Forwarded: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache

syzbot posted 1 patch 2 weeks, 6 days ago
There is a newer version of this series
fs/nilfs2/inode.c | 7 +++++++
1 file changed, 7 insertions(+)
Forwarded: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache
Posted by syzbot 2 weeks, 6 days ago
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master


When nilfs_attach_btree_node_cache() finds a cached btnc_inode that is
not I_NEW, it skips nilfs_init_btnc_inode() leaving the btree node
cache in a stale or uninitialized state from a previous failed mount.
This causes i_assoc_inode to point to a broken inode, leading to a
null-ptr-deref in nilfs_mdt_save_to_shadow_map() when
NILFS_IOCTL_CLEAN_SEGMENTS is invoked.

Fix this by calling nilfs_init_btnc_inode() for cached btnc inodes as
well to ensure proper initialization regardless of inode cache state.

Reported-by: syzbot+4b4093b1f24ad789bf37@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=4b4093b1f24ad789bf37
Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
---
 fs/nilfs2/inode.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 51bde45d5865..8312abbe343d 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -631,6 +631,9 @@ int nilfs_attach_btree_node_cache(struct inode *inode)
 				  nilfs_iget_set, &args);
 	if (unlikely(!btnc_inode))
 		return -ENOMEM;
+	pr_err("NILFS DEBUG btnc: btnc=%px I_NEW=%d\n",
+	btnc_inode,
+	!!(inode_state_read_once(btnc_inode) & I_NEW));
 	if (inode_state_read_once(btnc_inode) & I_NEW) {
 		nilfs_init_btnc_inode(btnc_inode);
 		unlock_new_inode(btnc_inode);
@@ -686,6 +689,10 @@ struct inode *nilfs_iget_for_shadow(struct inode *inode)
 			       nilfs_iget_set, &args);
 	if (unlikely(!s_inode))
 		return ERR_PTR(-ENOMEM);
+	pr_err("NILFS DEBUG: s_inode=%px I_NEW=%d i_assoc=%px\n",
+	        s_inode,
+		!!(inode_state_read_once(s_inode) & I_NEW),
+		NILFS_I(s_inode)->i_assoc_inode);
 	if (!(inode_state_read_once(s_inode) & I_NEW))
 		return inode;
 
-- 
2.43.0