| From 467e71ab672bd932ac97b42ca39d55f2dbaff6e0 Mon Sep 17 00:00:00 2001 |
| From: Al Viro <viro@zeniv.linux.org.uk> |
| Date: Wed, 10 Apr 2019 14:04:34 -0400 |
| Subject: apparmorfs: fix use-after-free on symlink traversal |
| |
| [ Upstream commit f51dcd0f621caac5380ce90fbbeafc32ce4517ae ] |
| |
| symlink body shouldn't be freed without an RCU delay. Switch apparmorfs |
| 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/apparmor/apparmorfs.c | 13 +++++++++---- |
| 1 file changed, 9 insertions(+), 4 deletions(-) |
| |
| diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c |
| index e09fe4d7307cd..40e3a098f6fb5 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) |
| return 0; |
| } |
| |
| -static void aafs_evict_inode(struct inode *inode) |
| +static void aafs_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 aafs_destroy_inode(struct inode *inode) |
| +{ |
| + call_rcu(&inode->i_rcu, aafs_i_callback); |
| } |
| |
| static const struct super_operations aafs_super_ops = { |
| .statfs = simple_statfs, |
| - .evict_inode = aafs_evict_inode, |
| + .destroy_inode = aafs_destroy_inode, |
| .show_path = aafs_show_path, |
| }; |
| |
| -- |
| 2.20.1 |
| |