[PATCH] jffs2: fix kfree uninitialized pointer in jffs2_i_callback

From: Huaijie Yi
Date: Fri Dec 20 2019 - 02:08:33 EST


commit 4fdcfab5b553 ("jffs2: fix use-after-free on
symlink traversal") move free operation of f->target
to jffs2_i_callback().

But when destroy an jffs2 inode in iget_locked(), jffs2_inode_info
was not initialized. which results in destroy_inode() calling
jffs2_i_callback() to kfree the uninitialized pointer f->target
and then BUG_ON. So move the initialization from jffs2_init_inode_info()
to jffs2_alloc_inode().

The stack likes following:
[19700101000004]kernel BUG at mm/slub.c:3824!
[19700101000004]Internal error: Oops - BUG: 0 [#1] SMP ARM
[19700101000004]CPU: 2 PID: 9 Comm: rcuos/0 Tainted: P O 4.4.185 #1
[19700101000004]PC is at kfree+0xfc/0x264
[19700101000004]LR is at jffs2_i_callback+0x10/0x28 [jffs2]
......
[20191219102226][<ffffff80083630a4>] kfree+0xd4/0x2ac
[20191219102226][<ffffff80008a0ae4>] jffs2_i_callback+0x24/0x40 [jffs2]
[20191219102226][<ffffff800828a908>] rcu_process_callbacks+0x524/0x61c
[20191219102226][<ffffff8008229cf8>] __do_softirq+0x1e0/0x3bc
[20191219102226][<ffffff800822a19c>] irq_exit+0xa0/0x124
[20191219102226][<ffffff800825074c>] msa_irq_exit+0x138/0x1c4
[20191219102226][<ffffff800827aaf8>] __handle_domain_irq+0xf0/0x1a4
[20191219102226][<ffffff8008200944>] gic_handle_irq+0xac/0x140

Reported-by: Guohua Zhong <zhongguohua1@xxxxxxxxxx>
Signed-off-by: Huaijie Yi <yihuaijie@xxxxxxxxxx>
Signed-off-by: zhangyi (F) <yi.zhang@xxxxxxxxxx>
Signed-off-by: chenjie <chenjie6@xxxxxxxxxx>
Signed-off-by: fangxinwei <fangxinwei@xxxxxxxxxx>
---
fs/jffs2/os-linux.h | 1 -
fs/jffs2/super.c | 2 ++
2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index ef1cfa61549e..625c4da3246d 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -54,7 +54,6 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
f->fragtree = RB_ROOT;
f->metadata = NULL;
f->dents = NULL;
- f->target = NULL;
f->flags = 0;
f->usercompr = 0;
}
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 0e6406c4f362..d76ed98057a1 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -42,6 +42,8 @@ static struct inode *jffs2_alloc_inode(struct super_block *sb)
f = kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
if (!f)
return NULL;
+ f->target = NULL;
+
return &f->vfs_inode;
}

--
2.12.3