Forwarded: Re: [syz] KASAN: slab-out-of-bounds Write in diWrite

syzbot posted 1 patch 1 month, 2 weeks ago
fs/jfs/jfs_imap.c | 10 ++++++++++
1 file changed, 10 insertions(+)
Forwarded: Re: [syz] KASAN: slab-out-of-bounds Write in diWrite
Posted by syzbot 1 month, 2 weeks ago
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: Re: [syz] KASAN: slab-out-of-bounds Write in diWrite
Author: tristmd@gmail.com

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

>From b49fd6df859312590dfffd12e3dad87914f88c9c Mon Sep 17 00:00:00 2001
From: Tristan Madani <tristan@talencesecurity.com>
Date: Thu, 30 Apr 2026 23:01:32 +0000
Subject: [PATCH] jfs: validate lv bounds in diWrite to prevent
 slab-out-of-bounds

diWrite() copies btree root data from the in-memory inode to the
on-disk dinode using lv->offset and lv->length from the transaction
lock without bounds checking.  When a corrupted JFS filesystem image
provides inconsistent dtree or xtree metadata, the transaction log
entries can reference slots beyond the root node boundaries
(DTROOTMAXSLOT or XTROOTMAXSLOT), causing a slab-out-of-bounds write
in the subsequent memcpy.

For example, with a crafted directory inode where the dtree metadata
produces lv->offset + lv->length > DTROOTMAXSLOT (9), the memcpy in
the dtree copy loop writes 32 bytes past the dinode boundary into
adjacent slab memory.

Add bounds validation before each memcpy in both the xtree and dtree
copy loops to ensure lv->offset + lv->length does not exceed
XTROOTMAXSLOT (18) or DTROOTMAXSLOT (9) respectively.

Reported-by: syzbot+aa6df9d3b383bf5f047f@syzkaller.appspotmail.com
Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
 fs/jfs/jfs_imap.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index b84ba4d7dfb44..70d6a33597273 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -726,6 +726,11 @@ int diWrite(tid_t tid, struct inode *ip)
 		xp = &dp->di_xtroot;
 		lv = ilinelock->lv;
 		for (n = 0; n < ilinelock->index; n++, lv++) {
+			if (lv->offset + lv->length > XTROOTMAXSLOT) {
+				jfs_err("diWrite: xtree lv out of bounds");
+				release_metapage(mp);
+				return -EIO;
+			}
 			memcpy(&xp->xad[lv->offset], &p->xad[lv->offset],
 			       lv->length << L2XTSLOTSIZE);
 		}
@@ -750,6 +755,11 @@ int diWrite(tid_t tid, struct inode *ip)
 		xp = (dtpage_t *) & dp->di_dtroot;
 		lv = ilinelock->lv;
 		for (n = 0; n < ilinelock->index; n++, lv++) {
+			if (lv->offset + lv->length > DTROOTMAXSLOT) {
+				jfs_err("diWrite: dtree lv out of bounds");
+				release_metapage(mp);
+				return -EIO;
+			}
 			memcpy(&xp->slot[lv->offset], &p->slot[lv->offset],
 			       lv->length << L2DTSLOTSIZE);
 		}
--
2.47.3