[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20260206080118.923439-1-ssp.nesin@crpt.ru>
Date: Fri, 6 Feb 2026 15:01:18 +0700
From: Rostislav Nesin <ssp.nesin@...t.ru>
To: Dave Kleikamp <shaggy@...nel.org>
Cc: Rostislav Nesin <ssp.nesin@...t.ru>,
Roman Smirnov <r.smirnov@....ru>,
Zheng Yu <zheng.yu@...thwestern.edu>,
Aditya Dutt <duttaditya18@...il.com>,
jfs-discussion@...ts.sourceforge.net,
linux-kernel@...r.kernel.org,
lvc-project@...uxtesting.org,
syzbot+8fe3b9efc02bf2d0b458@...kaller.appspotmail.com
Subject: [PATCH] jfs: fix out-of-bounds access in jfs_readdir
In jfs_readdir(), the stbl slot index validation uses a maximum value
of DTPAGEMAXSLOT (128). However, for root directory pages (bn == 0)
the maximum valid slot index is DTROOTMAXSLOT (9), not DTPAGEMAXSLOT
(128). This allows slot indices 9-127 to pass validation on root
pages, leading to out-of-bounds access when reading from p->slot[].
Similarly, the 'next' slot index in the directory entry name segment
chain is not validated. The 'next' field in struct ldtentry and
struct dtslot is read directly from disk (s8 next), and a corrupted
filesystem image could contain any value, causing out-of-bounds access
when following the segment chain via p->slot[next].
BUG: KASAN: slab-out-of-bounds in jfs_strfromUCS_le+0x28d/0x3b0 fs/jfs/jfs_unicode.c:40
Read of size 2 at addr ffff88807a187f72 by task syz.0.6/5913
CPU: 1 UID: 0 PID: 5913 Comm: syz.0.6 Not tainted 6.13.0-rc5-syzkaller-00012-g0bc21e701a6f #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:378 [inline]
print_report+0x169/0x550 mm/kasan/report.c:489
kasan_report+0x143/0x180 mm/kasan/report.c:602
jfs_strfromUCS_le+0x28d/0x3b0 fs/jfs/jfs_unicode.c:40
jfs_readdir+0x199d/0x3c50 fs/jfs/jfs_dtree.c:2975
wrap_directory_iterator+0x91/0xd0 fs/readdir.c:65
iterate_dir+0x571/0x800 fs/readdir.c:108
__do_sys_getdents64 fs/readdir.c:403 [inline]
__se_sys_getdents64+0x1e2/0x4b0 fs/readdir.c:389
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Fix this by validating stbl[i] and next against DTROOTMAXSLOT for root
directory pages (bn == 0).
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Reported-by: syzbot+8fe3b9efc02bf2d0b458@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=8fe3b9efc02bf2d0b458
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Rostislav Nesin <ssp.nesin@...t.ru>
---
This patch is prepared on top of the jfs-next branch of the maintainer's
repository (https://github.com/kleikamp/linux-shaggy.git).
fs/jfs/jfs_dtree.c | 13 +++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 9ab3f2fc61d1..a1b2c3d4e5f6 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -2902,7 +2902,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
stbl = DT_GETSTBL(p);
for (i = index; i < p->header.nextindex; i++) {
- if (stbl[i] < 0) {
+ if (stbl[i] < 0 || (bn == 0 && stbl[i] > DTROOTMAXSLOT)) {
jfs_err("JFS: Invalid stbl[%d] = %d for inode %ld, block = %lld",
i, stbl[i], (long)ip->i_ino, (long long)bn);
free_page(dirent_buf);
@@ -2970,6 +2970,11 @@ int jfs_readdir(struct file *file, struct dir_context *ctx)
/* copy name in the additional segment(s) */
next = d->next;
while (next >= 0) {
+ if (bn == 0 && next > DTROOTMAXSLOT) {
+ jfs_err("JFS: Invalid next %d for inode %ld, block = %lld",
+ next, (long)ip->i_ino, (long long)bn);
+ goto skip_one;
+ }
t = (struct dtslot *) & p->slot[next];
name_ptr += outlen;
d_namleft -= len;
--
2.34.1
Powered by blists - more mailing lists