FAILED: patch "[PATCH] nilfs2: reject invalid block index in GC ioctl" failed to apply to 6.1-stable tree

<[email protected]>
Newsgroups org.kernel.vger.stable
Message-ID <2026082454-equator-dexterous-7907@gregkh>
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x a1735eae55448bc79c2da6593455791e886f6ed8
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026082454-equator-dexterous-7907@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'

Possible dependencies:



thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From a1735eae55448bc79c2da6593455791e886f6ed8 Mon Sep 17 00:00:00 2001
From: Ryusuke Konishi <[email protected]>
Date: Fri, 3 Jul 2026 01:07:19 +0900
Subject: [PATCH] nilfs2: reject invalid block index in GC ioctl

Syzbot reported list corruption caused by a double list_add_tail() call on
bh->b_assoc_buffers within nilfs_lookup_dirty_data_buffers().

Analysis revealed that the root cause was the insertion of a page/folio
with a page index of ULONG_MAX into the page cache via the GC ioctl.
filemap_get_folios_tag(), called by nilfs_lookup_dirty_data_buffers(),
repeatedly detects a dirty folio with a page index of ULONG_MAX due to
index wrap-around, leading to duplicate processing of dirty buffers.

As a preparatory step, the GC ioctl loads the page/folio of the block to
be moved during GC and inserts it into the page cache based on information
in the nilfs_vdesc structure passed as an argument.  Normally, this does
not cause issues because the user-space GC library configures the
nilfs_vdesc structure properly.  However, since there is no range check on
the parameters determining the page index, a request with artificially
crafted parameters -- such as those generated by Syzbot -- can result in a
page/folio being inserted with a page index of ULONG_MAX, triggering the
above problem.

This resolves the issue by checking the ranges of 'vd_offset' and
'vd_vblocknr' in the nilfs_vdesc structure that determine the page index,
thereby preventing the invalid page/folio insertions.

Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=c37bed40868932d790e9
Fixes: 7942b919f732 ("nilfs2: ioctl operations")
Cc: wuyankun <[email protected]>
Cc: [email protected]
Signed-off-by: Ryusuke Konishi <[email protected]>
Signed-off-by: Viacheslav Dubeyko <[email protected]>

diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index b73f2c5d10f0..0957316e58b8 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -527,6 +527,7 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
  * Return: 0 on success, or one of the following negative error codes on
  * failure:
  * * %-EEXIST	- Block conflict detected.
+ * * %-EINVAL	- Invalid virtual block descriptor.
  * * %-EIO	- I/O error.
  * * %-ENOENT	- Requested block doesn't exist.
  * * %-ENOMEM	- Insufficient memory available.
@@ -536,15 +537,30 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode,
 					struct list_head *buffers)
 {
 	struct buffer_head *bh;
+	__u64 limit_blkidx = (__u64)inode->i_sb->s_maxbytes >> inode->i_blkbits;
 	int ret;
 
-	if (vdesc->vd_flags == 0)
+	/*
+	 * vblocknr 0 is reserved as an invalid pointer.  Also, limit_blkidx
+	 * ensures that the page index converted from vd_vblocknr never
+	 * overflows the page cache limit and respects the architecture's bmap
+	 * key width.
+	 */
+	if (unlikely(vdesc->vd_vblocknr == 0 ||
+			vdesc->vd_vblocknr >= limit_blkidx))
+		return -EINVAL;
+
+	if (vdesc->vd_flags == 0) {
+		if (unlikely(vdesc->vd_offset >= limit_blkidx))
+			return -EINVAL;
+
 		ret = nilfs_gccache_submit_read_data(
 			inode, vdesc->vd_offset, vdesc->vd_blocknr,
 			vdesc->vd_vblocknr, &bh);
-	else
+	} else {
 		ret = nilfs_gccache_submit_read_node(
 			inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
+	}
 
 	if (unlikely(ret < 0)) {
 		if (ret == -ENOENT)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.