lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ