diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-05 12:28:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-05 12:28:45 -0400 |
commit | 51987affd626b8e4ce9f4c65e1950cb9159f0f58 (patch) | |
tree | 9c10c7f5accd7cf6717597af815d6f80d4efbfd5 | |
parent | 6203838dec05352bc357625b1e9ba0a10d3bca35 (diff) | |
parent | 4e9036042fedaffcd868d7f7aa948756c48c637d (diff) |
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
-rw-r--r-- | fs/inode.c | 9 | ||||
-rw-r--r-- | fs/super.c | 5 | ||||
-rw-r--r-- | fs/ufs/util.h | 2 | ||||
-rw-r--r-- | security/apparmor/apparmorfs.c | 13 | ||||
-rw-r--r-- | security/inode.c | 13 |
5 files changed, 26 insertions, 16 deletions
diff --git a/fs/inode.c b/fs/inode.c index e9d97add2b36..9a453f3637f8 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1817,8 +1817,13 @@ int file_remove_privs(struct file *file) | |||
1817 | int kill; | 1817 | int kill; |
1818 | int error = 0; | 1818 | int error = 0; |
1819 | 1819 | ||
1820 | /* Fast path for nothing security related */ | 1820 | /* |
1821 | if (IS_NOSEC(inode)) | 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 | return 0; | 1827 | return 0; |
1823 | 1828 | ||
1824 | kill = dentry_needs_remove_privs(dentry); | 1829 | kill = dentry_needs_remove_privs(dentry); |
diff --git a/fs/super.c b/fs/super.c index 583a0124bc39..2739f57515f8 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -1467,11 +1467,6 @@ int vfs_get_tree(struct fs_context *fc) | |||
1467 | struct super_block *sb; | 1467 | struct super_block *sb; |
1468 | int error; | 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 | if (fc->root) | 1470 | if (fc->root) |
1476 | return -EBUSY; | 1471 | return -EBUSY; |
1477 | 1472 | ||
diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 1fd3011ea623..7fd4802222b8 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h | |||
@@ -229,7 +229,7 @@ ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode) | |||
229 | case UFS_UID_44BSD: | 229 | case UFS_UID_44BSD: |
230 | return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid); | 230 | return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid); |
231 | case UFS_UID_EFT: | 231 | case UFS_UID_EFT: |
232 | if (inode->ui_u1.oldids.ui_suid == 0xFFFF) | 232 | if (inode->ui_u1.oldids.ui_sgid == 0xFFFF) |
233 | return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid); | 233 | return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid); |
234 | /* Fall through */ | 234 | /* Fall through */ |
235 | default: | 235 | default: |
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index fefee040bf79..b9298d2e8165 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c | |||
@@ -123,17 +123,22 @@ static int aafs_show_path(struct seq_file *seq, struct dentry *dentry) | |||
123 | return 0; | 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); | 128 | struct inode *inode = container_of(head, struct inode, i_rcu); |
129 | clear_inode(inode); | ||
130 | if (S_ISLNK(inode->i_mode)) | 129 | if (S_ISLNK(inode->i_mode)) |
131 | kfree(inode->i_link); | 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 | static const struct super_operations aafs_super_ops = { | 139 | static const struct super_operations aafs_super_ops = { |
135 | .statfs = simple_statfs, | 140 | .statfs = simple_statfs, |
136 | .evict_inode = aafs_evict_inode, | 141 | .destroy_inode = aafs_destroy_inode, |
137 | .show_path = aafs_show_path, | 142 | .show_path = aafs_show_path, |
138 | }; | 143 | }; |
139 | 144 | ||
diff --git a/security/inode.c b/security/inode.c index b7772a9b315e..421dd72b5876 100644 --- a/security/inode.c +++ b/security/inode.c | |||
@@ -27,17 +27,22 @@ | |||
27 | static struct vfsmount *mount; | 27 | static struct vfsmount *mount; |
28 | static int mount_count; | 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); | 32 | struct inode *inode = container_of(head, struct inode, i_rcu); |
33 | clear_inode(inode); | ||
34 | if (S_ISLNK(inode->i_mode)) | 33 | if (S_ISLNK(inode->i_mode)) |
35 | kfree(inode->i_link); | 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 | static const struct super_operations securityfs_super_operations = { | 43 | static const struct super_operations securityfs_super_operations = { |
39 | .statfs = simple_statfs, | 44 | .statfs = simple_statfs, |
40 | .evict_inode = securityfs_evict_inode, | 45 | .destroy_inode = securityfs_destroy_inode, |
41 | }; | 46 | }; |
42 | 47 | ||
43 | static int fill_super(struct super_block *sb, void *data, int silent) | 48 | static int fill_super(struct super_block *sb, void *data, int silent) |