| From 13a25e5d57e08e09afcfb7854a984bf4aa567363 Mon Sep 17 00:00:00 2001 |
| From: Al Viro <viro@zeniv.linux.org.uk> |
| Date: Wed, 10 Apr 2019 14:03:45 -0400 |
| Subject: securityfs: fix use-after-free on symlink traversal |
| |
| [ Upstream commit 46c874419652bbefdfed17420fd6e88d8a31d9ec ] |
| |
| symlink body shouldn't be freed without an RCU delay. Switch securityfs |
| to ->destroy_inode() and use of call_rcu(); free both the inode and symlink |
| body in the callback. |
| |
| Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| security/inode.c | 13 +++++++++---- |
| 1 file changed, 9 insertions(+), 4 deletions(-) |
| |
| diff --git a/security/inode.c b/security/inode.c |
| index 8dd9ca8848e43..829f15672e01f 100644 |
| --- a/security/inode.c |
| +++ b/security/inode.c |
| @@ -26,17 +26,22 @@ |
| static struct vfsmount *mount; |
| static int mount_count; |
| |
| -static void securityfs_evict_inode(struct inode *inode) |
| +static void securityfs_i_callback(struct rcu_head *head) |
| { |
| - truncate_inode_pages_final(&inode->i_data); |
| - clear_inode(inode); |
| + struct inode *inode = container_of(head, struct inode, i_rcu); |
| if (S_ISLNK(inode->i_mode)) |
| kfree(inode->i_link); |
| + free_inode_nonrcu(inode); |
| +} |
| + |
| +static void securityfs_destroy_inode(struct inode *inode) |
| +{ |
| + call_rcu(&inode->i_rcu, securityfs_i_callback); |
| } |
| |
| static const struct super_operations securityfs_super_operations = { |
| .statfs = simple_statfs, |
| - .evict_inode = securityfs_evict_inode, |
| + .destroy_inode = securityfs_destroy_inode, |
| }; |
| |
| static int fill_super(struct super_block *sb, void *data, int silent) |
| -- |
| 2.20.1 |
| |