* Forwarded: [PATCH] nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
@ 2026-03-17 3:40 ` syzbot
2026-03-17 4:25 ` Forwarded: [PATCH] nilfs2: fix wrong inode returned from nilfs_iget_for_shadow on cache hit syzbot
` (6 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: syzbot @ 2026-03-17 3:40 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
When nilfs_dat_read() is called a second time during rollback recovery
from a corrupted segment (checksum error), nilfs_iget_locked() returns
a cached DAT inode that is not I_NEW, causing the function to skip
nilfs_mdt_setup_shadow_map(). This leaves i_assoc_inode as NULL in the
DAT inode, which later causes a general protection fault in
nilfs_mdt_save_to_shadow_map() when NILFS_IOCTL_CLEAN_SEGMENTS is
invoked immediately after mount.
Fix this by redirecting the non-I_NEW path to a new reinit_shadow label
that calls nilfs_mdt_setup_shadow_map() if the shadow map has not been
initialized yet, ensuring i_assoc_inode is always valid before the
segment cleaner uses it.
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/dat.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 674380837ab9..c0b656e1c4ef 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -507,7 +507,7 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
if (unlikely(!dat))
return -ENOMEM;
if (!(inode_state_read_once(dat) & I_NEW))
- goto out;
+ goto reinit_shadow;
err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
if (err)
@@ -529,6 +529,14 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
goto failed;
unlock_new_inode(dat);
+ goto out;
+reinit_shadow:
+ di = NILFS_DAT_I(dat);
+ if (!di->mi.mi_shadow) {
+ err = nilfs_mdt_setup_shadow_map(dat, &di->shadow);
+ if (err)
+ goto failed;
+ }
out:
*inodep = dat;
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Forwarded: [PATCH] nilfs2: fix wrong inode returned from nilfs_iget_for_shadow on cache hit
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
2026-03-17 3:40 ` Forwarded: [PATCH] nilfs2: fix NULL i_assoc_inode dereference " syzbot
@ 2026-03-17 4:25 ` syzbot
2026-03-17 6:25 ` Forwarded: [PATCH] nilfs2: fix missing i_assoc_inode initialization in nilfs_iget_for_shadow syzbot
` (5 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: syzbot @ 2026-03-17 4:25 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] nilfs2: fix wrong inode returned from nilfs_iget_for_shadow on cache hit
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
nilfs_iget_for_shadow() returns the original inode instead of the
cached shadow inode when the shadow inode already exists (I_NEW not
set). This causes nilfs_mdt_setup_shadow_map() to store the original
inode as shadow->inode, so subsequent calls to
nilfs_mdt_save_to_shadow_map() dereference the wrong inode's
i_assoc_inode, which may be NULL, leading to a general protection
fault.
This can be triggered by mounting a corrupted NILFS2 image that causes
rollback recovery, followed immediately by NILFS_IOCTL_CLEAN_SEGMENTS.
During rollback, nilfs_dat_read() is called twice, causing
nilfs_iget_for_shadow() to hit the cached path and return the wrong
inode.
Fix this by returning s_inode instead of inode on the cache hit path.
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 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 51bde45d5865..1f9bc63eb295 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -687,7 +687,7 @@ struct inode *nilfs_iget_for_shadow(struct inode *inode)
if (unlikely(!s_inode))
return ERR_PTR(-ENOMEM);
if (!(inode_state_read_once(s_inode) & I_NEW))
- return inode;
+ return s_inode;
NILFS_I(s_inode)->i_flags = 0;
memset(NILFS_I(s_inode)->i_bmap, 0, sizeof(struct nilfs_bmap));
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Forwarded: [PATCH] nilfs2: fix missing i_assoc_inode initialization in nilfs_iget_for_shadow
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
2026-03-17 3:40 ` Forwarded: [PATCH] nilfs2: fix NULL i_assoc_inode dereference " syzbot
2026-03-17 4:25 ` Forwarded: [PATCH] nilfs2: fix wrong inode returned from nilfs_iget_for_shadow on cache hit syzbot
@ 2026-03-17 6:25 ` syzbot
2026-03-17 6:47 ` Forwarded: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache syzbot
` (4 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: syzbot @ 2026-03-17 6:25 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] nilfs2: fix missing i_assoc_inode initialization in nilfs_iget_for_shadow
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
When nilfs_iget_for_shadow() finds a cached shadow inode (I_NEW not
set), it returns the original inode instead of the cached shadow inode.
This causes nilfs_mdt_setup_shadow_map() to store the wrong inode as
shadow->inode, so subsequent calls to nilfs_mdt_save_to_shadow_map()
dereference the wrong inode's i_assoc_inode which may be NULL, leading
to a general protection fault.
Fix this by returning s_inode instead of inode on the cache hit path.
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 | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 51bde45d5865..60cfcc209cf7 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -686,6 +686,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
^ permalink raw reply related [flat|nested] 17+ messages in thread* Forwarded: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
` (2 preceding siblings ...)
2026-03-17 6:25 ` Forwarded: [PATCH] nilfs2: fix missing i_assoc_inode initialization in nilfs_iget_for_shadow syzbot
@ 2026-03-17 6:47 ` syzbot
2026-03-17 7:36 ` syzbot
` (3 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: syzbot @ 2026-03-17 6:47 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
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
^ permalink raw reply related [flat|nested] 17+ messages in thread* Forwarded: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
` (3 preceding siblings ...)
2026-03-17 6:47 ` Forwarded: [PATCH] nilfs2: fix uninitialized btree node cache in nilfs_attach_btree_node_cache syzbot
@ 2026-03-17 7:36 ` syzbot
2026-03-17 8:09 ` [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map Edward Adam Davis
` (2 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: syzbot @ 2026-03-17 7:36 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
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 +++++++
fs/nilfs2/mdt.c | 8 ++++++++
2 files changed, 15 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;
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 946b0d3534a5..968a5be834cc 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -551,6 +551,14 @@ int nilfs_mdt_save_to_shadow_map(struct inode *inode)
struct inode *s_inode = shadow->inode;
int ret;
+ if (!ii->i_assoc_inode) {
+ pr_err("NILFS DEBUG: ii->i_assoc_inode is NULL, attaching\n");
+ dump_stack();
+ ret = nilfs_attach_btree_node_cache(inode);
+ if (ret) {
+ pr_err("NILFS: failed to attach btree node cache: %d\n", ret);
+ }
+ }
ret = nilfs_copy_dirty_pages(s_inode->i_mapping, inode->i_mapping);
if (ret)
goto out;
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
` (4 preceding siblings ...)
2026-03-17 7:36 ` syzbot
@ 2026-03-17 8:09 ` Edward Adam Davis
2026-03-17 8:41 ` syzbot
2026-03-17 8:26 ` Forwarded: [PATCH] nilfs2: fix NULL i_assoc_inode dereference " syzbot
2026-03-17 8:29 ` [PATCH] nilfs2: no longer save to shadow map if the num of members is too small Edward Adam Davis
7 siblings, 1 reply; 17+ messages in thread
From: Edward Adam Davis @ 2026-03-17 8:09 UTC (permalink / raw)
To: syzbot+4b4093b1f24ad789bf37; +Cc: linux-kernel, syzkaller-bugs
#syz test
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 1491a4d4b1e1..7e0b24361d0b 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2518,9 +2518,11 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
nilfs_transaction_lock(sb, &ti, 1);
- err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
- if (unlikely(err))
- goto out_unlock;
+ if (argv[0].v_nmembs > 0) {
+ err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
+ if (unlikely(err))
+ goto out_unlock;
+ }
err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
if (unlikely(err)) {
^ permalink raw reply related [flat|nested] 17+ messages in thread* Forwarded: [PATCH] nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
` (5 preceding siblings ...)
2026-03-17 8:09 ` [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map Edward Adam Davis
@ 2026-03-17 8:26 ` syzbot
2026-03-17 8:29 ` [PATCH] nilfs2: no longer save to shadow map if the num of members is too small Edward Adam Davis
7 siblings, 0 replies; 17+ messages in thread
From: syzbot @ 2026-03-17 8:26 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
The DAT inode's btree node cache (i_assoc_inode) is initialized lazily
during btree operations. However, nilfs_mdt_save_to_shadow_map()
assumes i_assoc_inode is already initialized when copying dirty pages
to the shadow map during GC.
If NILFS_IOCTL_CLEAN_SEGMENTS is called immediately after mount before
any btree operation has occurred on the DAT inode, i_assoc_inode is
NULL leading to a general protection fault.
Fix this by calling nilfs_attach_btree_node_cache() on the DAT inode
in nilfs_dat_read() at mount time, ensuring i_assoc_inode is always
initialized before any GC operation can use it.
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/dat.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 674380837ab9..888dc1831c86 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -524,6 +524,9 @@ int nilfs_dat_read(struct super_block *sb, size_t entry_size,
if (err)
goto failed;
+ err = nilfs_attach_btree_node_cache(dat);
+ if (err)
+ goto failed;
err = nilfs_read_inode_common(dat, raw_inode);
if (err)
goto failed;
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-17 3:14 [syzbot] [nilfs?] general protection fault in nilfs_mdt_save_to_shadow_map syzbot
` (6 preceding siblings ...)
2026-03-17 8:26 ` Forwarded: [PATCH] nilfs2: fix NULL i_assoc_inode dereference " syzbot
@ 2026-03-17 8:29 ` Edward Adam Davis
2026-03-17 15:13 ` Deepanshu Kartikey
2026-03-17 15:15 ` Deepanshu Kartikey
7 siblings, 2 replies; 17+ messages in thread
From: Edward Adam Davis @ 2026-03-17 8:29 UTC (permalink / raw)
To: syzbot+4b4093b1f24ad789bf37
Cc: konishi.ryusuke, linux-kernel, linux-nilfs, slava, syzkaller-bugs
The value of argv0.v_nmembs passed from userspace is 0. This prevents
nilfs_iget_for_gc() from being called to initialize the gcinode during
the execution of nilfs_ioctl_move_blocks(). Consequently, this triggers
a null-ptr-deref involving ii->i_assoc_inode within the subsequent call
sequence: nilfs_clean_segments()->nilfs_mdt_save_to_shadow_map() [1].
A check for argv[0].v_nmembs has been added to nilfs_clean_segments()
to prevent this potential null-ptr-deref of ii->i_assoc_inode.
[1]
KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
Call Trace:
nilfs_clean_segments+0x162/0xa50 fs/nilfs2/segment.c:2521
nilfs_ioctl_clean_segments fs/nilfs2/ioctl.c:916 [inline]
nilfs_ioctl+0x261f/0x2780 fs/nilfs2/ioctl.c:1346
Reported-by: syzbot+4b4093b1f24ad789bf37@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=4b4093b1f24ad789bf37
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
fs/nilfs2/segment.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 1491a4d4b1e1..7e0b24361d0b 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2518,9 +2518,11 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
nilfs_transaction_lock(sb, &ti, 1);
- err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
- if (unlikely(err))
- goto out_unlock;
+ if (argv[0].v_nmembs > 0) {
+ err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
+ if (unlikely(err))
+ goto out_unlock;
+ }
err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
if (unlikely(err)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-17 8:29 ` [PATCH] nilfs2: no longer save to shadow map if the num of members is too small Edward Adam Davis
@ 2026-03-17 15:13 ` Deepanshu Kartikey
2026-03-17 15:15 ` Deepanshu Kartikey
1 sibling, 0 replies; 17+ messages in thread
From: Deepanshu Kartikey @ 2026-03-17 15:13 UTC (permalink / raw)
To: eadavis
Cc: konishi.ryusuke, linux-kernel, linux-nilfs, slava,
syzbot+4b4093b1f24ad789bf37, syzkaller-bugs
Hi Edward,
On Mon, 17 Mar 2026, Edward Adam Davis wrote:
> The value of argv0.v_nmembs passed from userspace is 0. This prevents
> nilfs_iget_for_gc() from being called to initialize the gcinode during
> the execution of nilfs_ioctl_move_blocks(). Consequently, this triggers
> a null-ptr-deref involving ii->i_assoc_inode within the subsequent call
> sequence: nilfs_clean_segments()->nilfs_mdt_save_to_shadow_map() [1].
This analysis is incorrect. The null-ptr-deref is not caused by
nilfs_iget_for_gc() not being called. The real problem is that
ns_dat->i_assoc_inode (the DAT inode's btree node cache) is never
initialized at mount time.
> A check for argv[0].v_nmembs has been added to nilfs_clean_segments()
> to prevent this potential null-ptr-deref of ii->i_assoc_inode.
This fixes the symptom but not the root cause. Also note that in
the original syzkaller reproducer:
argv[0].v_nmembs = 0xd = 13 > 0
Your check would NOT prevent the crash with the original reproducer.
The correct fix is to initialize the btnode cache eagerly in
nilfs_dat_read() at mount time, since i_assoc_inode is only
initialized lazily during btree operations. When
NILFS_IOCTL_CLEAN_SEGMENTS is called before any btree operation
has occurred, i_assoc_inode is NULL.
I have already submitted this fix and syzbot confirmed it as fixed:
https://lore.kernel.org/all/20260317090109.878401-1-kartikey406@gmail.com/T/
Regards,
Deepanshu Kartikey
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-17 8:29 ` [PATCH] nilfs2: no longer save to shadow map if the num of members is too small Edward Adam Davis
2026-03-17 15:13 ` Deepanshu Kartikey
@ 2026-03-17 15:15 ` Deepanshu Kartikey
2026-03-17 16:51 ` Ryusuke Konishi
1 sibling, 1 reply; 17+ messages in thread
From: Deepanshu Kartikey @ 2026-03-17 15:15 UTC (permalink / raw)
To: eadavis
Cc: konishi.ryusuke, linux-kernel, linux-nilfs, slava,
syzbot+4b4093b1f24ad789bf37, syzkaller-bugs
Hi Edward,
On Mon, 17 Mar 2026, Edward Adam Davis wrote:
> The value of argv0.v_nmembs passed from userspace is 0. This prevents
> nilfs_iget_for_gc() from being called to initialize the gcinode during
> the execution of nilfs_ioctl_move_blocks(). Consequently, this triggers
> a null-ptr-deref involving ii->i_assoc_inode within the subsequent call
> sequence: nilfs_clean_segments()->nilfs_mdt_save_to_shadow_map() [1].
This analysis is incorrect. The null-ptr-deref is not caused by
nilfs_iget_for_gc() not being called. The real problem is that
ns_dat->i_assoc_inode (the DAT inode's btree node cache) is never
initialized at mount time.
> A check for argv[0].v_nmembs has been added to nilfs_clean_segments()
> to prevent this potential null-ptr-deref of ii->i_assoc_inode.
This fixes the symptom but not the root cause. Also note that in
the original syzkaller reproducer:
argv[0].v_nmembs = 0xd = 13 > 0
Your check would NOT prevent the crash with the original reproducer.
The correct fix is to initialize the btnode cache eagerly in
nilfs_dat_read() at mount time, since i_assoc_inode is only
initialized lazily during btree operations. When
NILFS_IOCTL_CLEAN_SEGMENTS is called before any btree operation
has occurred, i_assoc_inode is NULL.
I have already submitted this fix and syzbot confirmed it as fixed:
https://lore.kernel.org/all/20260317090109.878401-1-kartikey406@gmail.com/T/
Regards,
Deepanshu Kartikey
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-17 15:15 ` Deepanshu Kartikey
@ 2026-03-17 16:51 ` Ryusuke Konishi
2026-03-17 23:00 ` Ryusuke Konishi
0 siblings, 1 reply; 17+ messages in thread
From: Ryusuke Konishi @ 2026-03-17 16:51 UTC (permalink / raw)
To: Deepanshu Kartikey
Cc: eadavis, linux-kernel, linux-nilfs, slava,
syzbot+4b4093b1f24ad789bf37, syzkaller-bugs
Hi Deepanshu and Edward,
On Wed, Mar 18, 2026 at 12:15 AM Deepanshu Kartikey wrote:
>
> Hi Edward,
>
> On Mon, 17 Mar 2026, Edward Adam Davis wrote:
>
> > The value of argv0.v_nmembs passed from userspace is 0. This prevents
> > nilfs_iget_for_gc() from being called to initialize the gcinode during
> > the execution of nilfs_ioctl_move_blocks(). Consequently, this triggers
> > a null-ptr-deref involving ii->i_assoc_inode within the subsequent call
> > sequence: nilfs_clean_segments()->nilfs_mdt_save_to_shadow_map() [1].
>
> This analysis is incorrect. The null-ptr-deref is not caused by
> nilfs_iget_for_gc() not being called. The real problem is that
> ns_dat->i_assoc_inode (the DAT inode's btree node cache) is never
> initialized at mount time.
>
> > A check for argv[0].v_nmembs has been added to nilfs_clean_segments()
> > to prevent this potential null-ptr-deref of ii->i_assoc_inode.
>
> This fixes the symptom but not the root cause. Also note that in
> the original syzkaller reproducer:
>
> argv[0].v_nmembs = 0xd = 13 > 0
>
> Your check would NOT prevent the crash with the original reproducer.
>
> The correct fix is to initialize the btnode cache eagerly in
> nilfs_dat_read() at mount time, since i_assoc_inode is only
> initialized lazily during btree operations. When
> NILFS_IOCTL_CLEAN_SEGMENTS is called before any btree operation
> has occurred, i_assoc_inode is NULL.
>
> I have already submitted this fix and syzbot confirmed it as fixed:
>
> https://lore.kernel.org/all/20260317090109.878401-1-kartikey406@gmail.com/T/
>
> Regards,
> Deepanshu Kartikey
Deepanshu's suggestion seems close to the answer, but I think there's
a slight leap in the root cause analysis.
When nilfs_dat_read() is in a b-tree configuration, it normally calls
nilfs_attach_btree_node_cache() via nilfs_read_inode_common() ->
nilfs_bmap_read() -> nilfs_btree_init().
Therefore, the problem seems to be one of the following two:
(1) nilfs_mdt_save_to_shadow_map(), called from a GC ioctl specifying
the dat, calls nilfs_copy_dirty_pages() assuming a b-tree node cache
exists, regardless of whether the DAT is direct mapping or b-tree
mapping.
(The DAT mapping method switching is not considered.)
(2) The DAT is in b-tree mapping mode, but nilfs_btree_init() is not
being called because the i_mode of the DAT inode is corrupt.
Both appear to be potential bugs, but their fixes are different.
Have you determined which of these is causing this bug?
Regards,
Ryusuke Konishi
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-17 16:51 ` Ryusuke Konishi
@ 2026-03-17 23:00 ` Ryusuke Konishi
2026-03-18 0:08 ` Edward Adam Davis
0 siblings, 1 reply; 17+ messages in thread
From: Ryusuke Konishi @ 2026-03-17 23:00 UTC (permalink / raw)
To: Deepanshu Kartikey
Cc: eadavis, linux-kernel, linux-nilfs, slava,
syzbot+4b4093b1f24ad789bf37, syzkaller-bugs
On Wed, Mar 18, 2026 at 1:51 AM Ryusuke Konishi wrote:
>
> Hi Deepanshu and Edward,
>
> On Wed, Mar 18, 2026 at 12:15 AM Deepanshu Kartikey wrote:
> >
> > Hi Edward,
> >
> > On Mon, 17 Mar 2026, Edward Adam Davis wrote:
> >
> > > The value of argv0.v_nmembs passed from userspace is 0. This prevents
> > > nilfs_iget_for_gc() from being called to initialize the gcinode during
> > > the execution of nilfs_ioctl_move_blocks(). Consequently, this triggers
> > > a null-ptr-deref involving ii->i_assoc_inode within the subsequent call
> > > sequence: nilfs_clean_segments()->nilfs_mdt_save_to_shadow_map() [1].
> >
> > This analysis is incorrect. The null-ptr-deref is not caused by
> > nilfs_iget_for_gc() not being called. The real problem is that
> > ns_dat->i_assoc_inode (the DAT inode's btree node cache) is never
> > initialized at mount time.
> >
> > > A check for argv[0].v_nmembs has been added to nilfs_clean_segments()
> > > to prevent this potential null-ptr-deref of ii->i_assoc_inode.
> >
> > This fixes the symptom but not the root cause. Also note that in
> > the original syzkaller reproducer:
> >
> > argv[0].v_nmembs = 0xd = 13 > 0
> >
> > Your check would NOT prevent the crash with the original reproducer.
> >
> > The correct fix is to initialize the btnode cache eagerly in
> > nilfs_dat_read() at mount time, since i_assoc_inode is only
> > initialized lazily during btree operations. When
> > NILFS_IOCTL_CLEAN_SEGMENTS is called before any btree operation
> > has occurred, i_assoc_inode is NULL.
> >
> > I have already submitted this fix and syzbot confirmed it as fixed:
> >
> > https://lore.kernel.org/all/20260317090109.878401-1-kartikey406@gmail.com/T/
> >
> > Regards,
> > Deepanshu Kartikey
>
> Deepanshu's suggestion seems close to the answer, but I think there's
> a slight leap in the root cause analysis.
>
> When nilfs_dat_read() is in a b-tree configuration, it normally calls
> nilfs_attach_btree_node_cache() via nilfs_read_inode_common() ->
> nilfs_bmap_read() -> nilfs_btree_init().
>
> Therefore, the problem seems to be one of the following two:
> (1) nilfs_mdt_save_to_shadow_map(), called from a GC ioctl specifying
> the dat, calls nilfs_copy_dirty_pages() assuming a b-tree node cache
> exists, regardless of whether the DAT is direct mapping or b-tree
> mapping.
> (The DAT mapping method switching is not considered.)
>
> (2) The DAT is in b-tree mapping mode, but nilfs_btree_init() is not
> being called because the i_mode of the DAT inode is corrupt.
>
> Both appear to be potential bugs, but their fixes are different.
> Have you determined which of these is causing this bug?
>
> Regards,
> Ryusuke Konishi
Okay, I'll do a few more checks to make sure it's alright, but I'm
going to pick Deepanshu's fix as the solution to this problem.
The reason is that pre-allocating the b-tree node cache inode to
i_assoc_inode, as nilfs_iget_for_shadow() does for shadow mapping, has
no side effects and seems like a comprehensive stabilization method
that covers both potential issues.
The nilfs_btree_node_cache() method, which detaches the b-tree node
cache inode, is currently only called from nilfs_clear_inode(), and
once allocated, it doesn't degrade regardless of whether the inode
uses direct mapping or b-tree mapping. Therefore, the approach of
pre-allocating the b-tree node cache inode is safe.
And also, this isn't overkill. The DAT file typically grows very
quickly, so it almost always uses b-tree mapping (which is why this
hasn't been found before). I think it's a good fix.
Thanks,
Ryusuke Konishi
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-17 23:00 ` Ryusuke Konishi
@ 2026-03-18 0:08 ` Edward Adam Davis
2026-03-18 0:54 ` Ryusuke Konishi
0 siblings, 1 reply; 17+ messages in thread
From: Edward Adam Davis @ 2026-03-18 0:08 UTC (permalink / raw)
To: konishi.ryusuke
Cc: eadavis, kartikey406, linux-kernel, linux-nilfs, slava,
syzbot+4b4093b1f24ad789bf37, syzkaller-bugs
Have you been following the path below? If the argv0.v_nmembs value
passed from userspace is greater than 0, everything will function normally.
nilfs_ioctl_clean_segments()->
nilfs_ioctl_move_blocks()->
nilfs_iget_for_gc()->
nilfs_init_gcinode()->
nilfs_attach_btree_node_cache()
Causing the mount to fail solely because the dat B-tree wasn't initialized
is an excessive fix.
BR,
Edward
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH] nilfs2: no longer save to shadow map if the num of members is too small
2026-03-18 0:08 ` Edward Adam Davis
@ 2026-03-18 0:54 ` Ryusuke Konishi
2026-03-18 1:16 ` Edward Adam Davis
0 siblings, 1 reply; 17+ messages in thread
From: Ryusuke Konishi @ 2026-03-18 0:54 UTC (permalink / raw)
To: Edward Adam Davis
Cc: kartikey406, linux-kernel, linux-nilfs, slava,
syzbot+4b4093b1f24ad789bf37, syzkaller-bugs
Hi Edward, thank you as always.
On Wed, Mar 18, 2026 at 9:08 AM Edward Adam Davis wrote:
>
> Have you been following the path below? If the argv0.v_nmembs value
> passed from userspace is greater than 0, everything will function normally.
>
> nilfs_ioctl_clean_segments()->
> nilfs_ioctl_move_blocks()->
> nilfs_iget_for_gc()->
> nilfs_init_gcinode()->
> nilfs_attach_btree_node_cache()
>
> Causing the mount to fail solely because the dat B-tree wasn't initialized
> is an excessive fix.
>
> BR,
> Edward
Are you perhaps confusing the regular inode's GC cache (gc inode) with
the DAT's shadow mapping inode?
Calling nilfs_attach_btree_node_cache() from nilfs_init_gcinode() does
not allocate the b-tree node cache for the DAT inode where the problem
is occurring in nilfs_mdt_save_to_shadow_map().
Therefore, it does not fix the root cause of the issue.
As can be seen from the call trace below, the issue arises when the
i_assoc_inode of the DAT inode (or potentially its shadow mapping
inode) in nilfs_mdt_save_to_shadow_map() is dereferenced.
RIP: 0010:nilfs_mdt_save_to_shadow_map+0x141/0x1c0 fs/nilfs2/mdt.c:559
Your fix eliminates the reproducibility conditions for the reproducer,
so it might pass the tests, but it doesn't fix the original problem,
does it?
The essential flaw is that it attempts to copy dirty pages from the
b-tree node cache to the shadow mapping, even though the DAT might not
have a btree node cache while remaining in direct mapping mode.
As I mentioned earlier, DAT usually grows quickly and switches to
btree mapping, so I don't think it's excessive to pre-allocate a btree
node cache as Deepanshu proposed.
Regards,
Ryusuke Konishi
^ permalink raw reply [flat|nested] 17+ messages in thread