| From cbbe5200ef168e7eca2542c6913d94da161dedd0 Mon Sep 17 00:00:00 2001 |
| From: Al Viro <viro@zeniv.linux.org.uk> |
| Date: Tue, 26 Mar 2019 01:39:50 +0000 |
| Subject: jffs2: fix use-after-free on symlink traversal |
| |
| [ Upstream commit 4fdcfab5b5537c21891e22e65996d4d0dd8ab4ca ] |
| |
| free the symlink body after the same RCU delay we have for freeing the |
| struct inode itself, so that traversal during RCU pathwalk wouldn't step |
| into freed memory. |
| |
| Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org> |
| --- |
| fs/jffs2/readinode.c | 5 ----- |
| fs/jffs2/super.c | 5 ++++- |
| 2 files changed, 4 insertions(+), 6 deletions(-) |
| |
| diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c |
| index 389ea53ea487..bccfc40b3a74 100644 |
| --- a/fs/jffs2/readinode.c |
| +++ b/fs/jffs2/readinode.c |
| @@ -1414,11 +1414,6 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) |
| |
| jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); |
| |
| - if (f->target) { |
| - kfree(f->target); |
| - f->target = NULL; |
| - } |
| - |
| fds = f->dents; |
| while(fds) { |
| fd = fds; |
| diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c |
| index bb6ae387469f..05d892c79339 100644 |
| --- a/fs/jffs2/super.c |
| +++ b/fs/jffs2/super.c |
| @@ -47,7 +47,10 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb) |
| static void jffs2_i_callback(struct rcu_head *head) |
| { |
| struct inode *inode = container_of(head, struct inode, i_rcu); |
| - kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); |
| + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
| + |
| + kfree(f->target); |
| + kmem_cache_free(jffs2_inode_cachep, f); |
| } |
| |
| static void jffs2_destroy_inode(struct inode *inode) |
| -- |
| 2.20.1 |
| |