Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fixes from Al Viro:

- a couple of ->i_link use-after-free fixes

- regression fix for wrong errno on absent device name in mount(2)
(this cycle stuff)

- ancient UFS braino in large GID handling on Solaris UFS images (bogus
cut'n'paste from large UID handling; wrong field checked to decide
whether we should look at old (16bit) or new (32bit) field)

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
ufs: fix braino in ufs_get_inode_gid() for solaris UFS flavour
Abort file_remove_privs() for non-reg. files
[fix] get rid of checking for absent device name in vfs_get_tree()
apparmorfs: fix use-after-free on symlink traversal
securityfs: fix use-after-free on symlink traversal

Changed files
+26 -16
fs
security
+7 -2
fs/inode.c
··· 1817 1817 int kill; 1818 1818 int error = 0; 1819 1819 1820 - /* Fast path for nothing security related */ 1821 - if (IS_NOSEC(inode)) 1820 + /* 1821 + * Fast path for nothing security related. 1822 + * As well for non-regular files, e.g. blkdev inodes. 1823 + * For example, blkdev_write_iter() might get here 1824 + * trying to remove privs which it is not allowed to. 1825 + */ 1826 + if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode)) 1822 1827 return 0; 1823 1828 1824 1829 kill = dentry_needs_remove_privs(dentry);
-5
fs/super.c
··· 1467 1467 struct super_block *sb; 1468 1468 int error; 1469 1469 1470 - if (fc->fs_type->fs_flags & FS_REQUIRES_DEV && !fc->source) { 1471 - errorf(fc, "Filesystem requires source device"); 1472 - return -ENOENT; 1473 - } 1474 - 1475 1470 if (fc->root) 1476 1471 return -EBUSY; 1477 1472
+1 -1
fs/ufs/util.h
··· 229 229 case UFS_UID_44BSD: 230 230 return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid); 231 231 case UFS_UID_EFT: 232 - if (inode->ui_u1.oldids.ui_suid == 0xFFFF) 232 + if (inode->ui_u1.oldids.ui_sgid == 0xFFFF) 233 233 return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid); 234 234 /* Fall through */ 235 235 default:
+9 -4
security/apparmor/apparmorfs.c
··· 123 123 return 0; 124 124 } 125 125 126 - static void aafs_evict_inode(struct inode *inode) 126 + static void aafs_i_callback(struct rcu_head *head) 127 127 { 128 - truncate_inode_pages_final(&inode->i_data); 129 - clear_inode(inode); 128 + struct inode *inode = container_of(head, struct inode, i_rcu); 130 129 if (S_ISLNK(inode->i_mode)) 131 130 kfree(inode->i_link); 131 + free_inode_nonrcu(inode); 132 + } 133 + 134 + static void aafs_destroy_inode(struct inode *inode) 135 + { 136 + call_rcu(&inode->i_rcu, aafs_i_callback); 132 137 } 133 138 134 139 static const struct super_operations aafs_super_ops = { 135 140 .statfs = simple_statfs, 136 - .evict_inode = aafs_evict_inode, 141 + .destroy_inode = aafs_destroy_inode, 137 142 .show_path = aafs_show_path, 138 143 }; 139 144
+9 -4
security/inode.c
··· 27 27 static struct vfsmount *mount; 28 28 static int mount_count; 29 29 30 - static void securityfs_evict_inode(struct inode *inode) 30 + static void securityfs_i_callback(struct rcu_head *head) 31 31 { 32 - truncate_inode_pages_final(&inode->i_data); 33 - clear_inode(inode); 32 + struct inode *inode = container_of(head, struct inode, i_rcu); 34 33 if (S_ISLNK(inode->i_mode)) 35 34 kfree(inode->i_link); 35 + free_inode_nonrcu(inode); 36 + } 37 + 38 + static void securityfs_destroy_inode(struct inode *inode) 39 + { 40 + call_rcu(&inode->i_rcu, securityfs_i_callback); 36 41 } 37 42 38 43 static const struct super_operations securityfs_super_operations = { 39 44 .statfs = simple_statfs, 40 - .evict_inode = securityfs_evict_inode, 45 + .destroy_inode = securityfs_destroy_inode, 41 46 }; 42 47 43 48 static int fill_super(struct super_block *sb, void *data, int silent)