[PATCH RFC] jfs: validate BT_ROOT flag in xt_getpage and DT_GETPAGE

23 views
Skip to first unread message

syzbot

unread,
Jun 26, 2026, 6:14:56 PMJun 26
to syzkaller-upst...@googlegroups.com, syz...@lists.linux.dev
A corrupted JFS image can trick the kernel into calling release_metapage()
on a pseudo-metapage embedded within the inode, leading to an out-of-bounds
memory access and a spinlock crash.

When operating on the root page of an xtree or dtree (which is stored
inline within the inode), JFS doesn't use a real struct metapage. Instead,
BT_GETPAGE() sets the metapage pointer to the address of
JFS_IP(ip)->bxflag. Because this is a pseudo-metapage, it does not have a
valid wait_queue_head_t wait field. Accessing mp->wait reads out-of-bounds
memory in struct jfs_inode_info.

In xt_getpage(), the code validates nextindex and maxentry, but it fails to
verify that the BT_ROOT flag is set in p->header.flag for the root page (bn
== 0). If the inline xtree root page has a corrupted header.flag where
BT_ROOT is missing, xtTruncate() will mistakenly treat the root page as a
regular leaf page and call discard_metapage(mp).

Unlike XT_PUTPAGE() which safely checks !BT_IS_ROOT(mp) before releasing,
discard_metapage() calls release_metapage(mp) directly. This assumes mp is
a real metapage and calls unlock_metapage(mp), which executes
wake_up(&mp->wait), accessing garbage memory and resulting in a spinlock
bad magic BUG or UBSAN out-of-bounds array access.

Fix this by enforcing the invariant that the BT_ROOT flag is set if and
only if bn == 0 in both xt_getpage() and DT_GETPAGE().

BUG: spinlock bad magic on CPU#0, syz-executor/6066
lock: 0xffff888120999b48, .magic: ffffffff, .owner: <...>/-1902340672,
.owner_cpu: 768
CPU: 0 UID: 0 PID: 6066 Comm: syz-executor Not tainted syzkaller #1
PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
1.16.3-debian-1.16.3-2 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
spin_bug kernel/locking/spinlock_debug.c:78 [inline]
debug_spin_lock_before kernel/locking/spinlock_debug.c:86 [inline]
do_raw_spin_lock+0x1e5/0x2f0 kernel/locking/spinlock_debug.c:115
__raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock_irqsave+0x4c/0x60 kernel/locking/spinlock.c:166
__wake_up_common_lock+0x30/0x1f0 kernel/sched/wait.c:124
unlock_metapage fs/jfs/jfs_metapage.c:40 [inline]
release_metapage+0x131/0xa60 fs/jfs/jfs_metapage.c:872
xtTruncate+0xeaa/0x2eb0 fs/jfs/jfs_xtree.c:-1
jfs_free_zero_link+0x35b/0x4c0 fs/jfs/namei.c:760
jfs_evict_inode+0x356/0x430 fs/jfs/inode.c:159
evict+0x624/0xb50 fs/inode.c:841
__dentry_kill+0x206/0x700 fs/dcache.c:718
shrink_kill+0xa9/0x2c0 fs/dcache.c:1195
shrink_dentry_list+0x2e0/0x5e0 fs/dcache.c:1222
shrink_dcache_tree+0xe9/0x5d0 fs/dcache.c:-1
do_one_tree+0x28/0xe0 fs/dcache.c:1721
shrink_dcache_for_umount+0xa0/0x170 fs/dcache.c:1738
generic_shutdown_super+0x6f/0x2d0 fs/super.c:624
kill_block_super+0x44/0x90 fs/super.c:1725
deactivate_locked_super+0xbc/0x130 fs/super.c:476
cleanup_mnt+0x3d3/0x460 fs/namespace.c:1312
task_work_run+0x1d9/0x270 kernel/task_work.c:233
resume_user_mode_work include/linux/resume_user_mode.h:50 [inline]
__exit_to_user_mode_loop kernel/entry/common.c:67 [inline]
exit_to_user_mode_loop+0xf3/0x4f0 kernel/entry/common.c:98
__exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [inline]
syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:230
[inline]
syscall_exit_to_user_mode include/linux/entry-common.h:318 [inline]
do_syscall_64+0x33e/0x560 arch/x86/entry/syscall_64.c:100
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Gemini:gemini-3.1-pro-preview syzbot
Reported-by: syzbot+e38044...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e380443eaa59bfb75a84
Link: https://syzkaller.appspot.com/ai_job?id=b075f2b7-e5d3-4157-9efa-ee28c166187b
To: <jfs-dis...@lists.sourceforge.net>
To: "Dave Kleikamp" <sha...@kernel.org>
Cc: "Arnd Bergmann" <ar...@arndb.de>
Cc: <linux-...@vger.kernel.org>
Cc: "Suchit Karunakaran" <suchitka...@gmail.com>
Cc: "Yun Zhou" <yun....@windriver.com>
Cc: "Zheng Yu" <zhen...@northwestern.edu>

---
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ac0f79faf..bbb157daf 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -111,19 +111,26 @@ struct dtsplit {
#define DT_PAGE(IP, MP) BT_PAGE(IP, MP, dtpage_t, i_dtroot)

/* get page buffer for specified block address */
-#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
-do { \
- BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
- if (!(RC)) { \
- if ((BN) && !check_dtpage(P)) { \
- BT_PUTPAGE(MP); \
- jfs_error((IP)->i_sb, \
- "DT_GETPAGE: dtree page corrupt\n"); \
- MP = NULL; \
- RC = -EIO; \
- } \
- } \
-} while (0)
+#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
+ do { \
+ BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
+ if (!(RC)) { \
+ if (((BN) == 0) != !!((P)->header.flag & BT_ROOT)) { \
+ BT_PUTPAGE(MP); \
+ jfs_error( \
+ (IP)->i_sb, \
+ "DT_GETPAGE: dtree root page corrupt\n"); \
+ MP = NULL; \
+ RC = -EIO; \
+ } else if ((BN) && !check_dtpage(P)) { \
+ BT_PUTPAGE(MP); \
+ jfs_error((IP)->i_sb, \
+ "DT_GETPAGE: dtree page corrupt\n"); \
+ MP = NULL; \
+ RC = -EIO; \
+ } \
+ } \
+ } while (0)

/* for consistency */
#define DT_PUTPAGE(MP) BT_PUTPAGE(MP)
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 28c3cf960..6d960dd96 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -118,10 +118,11 @@ static inline xtpage_t *xt_getpage(struct inode *ip, s64 bn, struct metapage **m
if (rc)
return ERR_PTR(rc);
if ((le16_to_cpu(p->header.nextindex) < XTENTRYSTART) ||
- (le16_to_cpu(p->header.nextindex) >
- le16_to_cpu(p->header.maxentry)) ||
- (le16_to_cpu(p->header.maxentry) >
- ((bn == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE))) {
+ (le16_to_cpu(p->header.nextindex) >
+ le16_to_cpu(p->header.maxentry)) ||
+ (le16_to_cpu(p->header.maxentry) >
+ ((bn == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE)) ||
+ ((bn == 0) != !!(p->header.flag & BT_ROOT))) {
jfs_error(ip->i_sb, "xt_getpage: xtree page corrupt\n");
BT_PUTPAGE(*mp);
*mp = NULL;


base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
--
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzk...@googlegroups.com.

Kusaram Devineni

unread,
Jul 8, 2026, 11:04:34 AM (7 days ago) Jul 8
to syzkaller-upstream-moderation
keep the current fix direction. The BT_ROOT invariant checks in both xt_getpage() and DT_GETPAGE() are correct.
preserve local indentation/style in `DT_GETPAGE()` and `xt_getpage()`. do not reindent the whole DT_GETPAGE() macro or existing xt_getpage() condition block. add only the minimal new condition/branch.
in DT_GETPAGE(), prefer the existing error message: "DT_GETPAGE: dtree page corrupt\n" instead of: "DT_GETPAGE: dtree root page corrupt\n" or explain why the new string is desirable despite the check being bidirectional. i.e. the invariant is bidirectional and also catches non-root pages incorrectly carrying BT_ROOT.

-kusaram

Kusaram Devineni

unread,
Jul 9, 2026, 3:09:10 AM (7 days ago) Jul 9
to syzbot, syzkaller-upst...@googlegroups.com, syz...@lists.linux.dev
On 27-06-2026 03:44 am, syzbot wrote:
> A corrupted JFS image can trick the kernel into calling release_metapage()
> on a pseudo-metapage embedded within the inode, leading to an out-of-bounds
> memory access and a spinlock crash.
>
> When operating on the root page of an xtree or dtree (which is stored
> inline within the inode), JFS doesn't use a real struct metapage. Instead,
> BT_GETPAGE() sets the metapage pointer to the address of
> JFS_IP(ip)->bxflag. Because this is a pseudo-metapage, it does not have a
> valid wait_queue_head_t wait field. Accessing mp->wait reads out-of-bounds
> memory in struct jfs_inode_info.
>
> In xt_getpage(), the code validates nextindex and maxentry, but it fails to
> verify that the BT_ROOT flag is set in p->header.flag for the root page (bn
> == 0). If the inline xtree root page has a corrupted header.flag where
> BT_ROOT is missing, xtTruncate() will mistakenly treat the root page as a
> regular leaf page and call discard_metapage(mp).
>
> Unlike XT_PUTPAGE() which safely checks !BT_IS_ROOT(mp) before releasing,
> discard_metapage() calls release_metapage(mp) directly. This assumes mp is
> a real metapage and calls unlock_metapage(mp), which executes
> wake_up(&mp->wait), accessing garbage memory and resulting in a spinlock
> bad magic BUG or UBSAN out-of-bounds array access.
>
> Fix this by enforcing the invariant that the BT_ROOT flag is set if and
> only if bn == 0 in both xt_getpage() and DT_GETPAGE().
>

keep the current fix direction. The BT_ROOT invariant checks in both
xt_getpage() and DT_GETPAGE() are correct.

in DT_GETPAGE(), prefer the existing error message: "DT_GETPAGE: dtree
page corrupt\n" instead of: "DT_GETPAGE: dtree root page corrupt\n" or
explain why the new string is desirable despite the check being
bidirectional. i.e. the invariant is bidirectional and also catches
non-root pages incorrectly carrying BT_ROOT.

> /* for consistency */
> #define DT_PUTPAGE(MP) BT_PUTPAGE(MP)
> diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
> index 28c3cf960..6d960dd96 100644
> --- a/fs/jfs/jfs_xtree.c
> +++ b/fs/jfs/jfs_xtree.c
> @@ -118,10 +118,11 @@ static inline xtpage_t *xt_getpage(struct inode *ip, s64 bn, struct metapage **m
> if (rc)
> return ERR_PTR(rc);
> if ((le16_to_cpu(p->header.nextindex) < XTENTRYSTART) ||
> - (le16_to_cpu(p->header.nextindex) >
> - le16_to_cpu(p->header.maxentry)) ||
> - (le16_to_cpu(p->header.maxentry) >
> - ((bn == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE))) {
> + (le16_to_cpu(p->header.nextindex) >
> + le16_to_cpu(p->header.maxentry)) ||
> + (le16_to_cpu(p->header.maxentry) >
> + ((bn == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE)) ||
> + ((bn == 0) != !!(p->header.flag & BT_ROOT))) {
> jfs_error(ip->i_sb, "xt_getpage: xtree page corrupt\n");
> BT_PUTPAGE(*mp);
> *mp = NULL;
>
>
> base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6

preserve local indentation/style in `DT_GETPAGE()` and `xt_getpage()`.
do not reindent the whole DT_GETPAGE() macro or existing xt_getpage()
condition block. add only the minimal new condition/branch.

-kusaram

syzbot

unread,
Jul 9, 2026, 4:20:29 AM (7 days ago) Jul 9
to syzkaller-upst...@googlegroups.com, syz...@lists.linux.dev
A corrupted JFS image can trick the kernel into calling release_metapage()
on a pseudo-metapage embedded within the inode, leading to an out-of-bounds
memory access and a spinlock crash.

When operating on the root page of an xtree or dtree (which is stored
inline within the inode), JFS doesn't use a real struct metapage. Instead,
BT_GETPAGE() sets the metapage pointer to the address of
JFS_IP(ip)->bxflag. Because this is a pseudo-metapage, it does not have a
valid wait_queue_head_t wait field. Accessing mp->wait reads out-of-bounds
memory in struct jfs_inode_info.

In xt_getpage(), the code validates nextindex and maxentry, but it fails to
verify that the BT_ROOT flag is set in p->header.flag for the root page (bn
== 0). If the inline xtree root page has a corrupted header.flag where
BT_ROOT is missing, xtTruncate() will mistakenly treat the root page as a
regular leaf page and call discard_metapage(mp).

Unlike XT_PUTPAGE() which safely checks !BT_IS_ROOT(mp) before releasing,
discard_metapage() calls release_metapage(mp) directly. This assumes mp is
a real metapage and calls unlock_metapage(mp), which executes
wake_up(&mp->wait), accessing garbage memory and resulting in a spinlock
bad magic BUG or UBSAN out-of-bounds array access.

Fix this by enforcing the invariant that the BT_ROOT flag is set if and
only if bn == 0 in both xt_getpage() and DT_GETPAGE().

BUG: spinlock bad magic on CPU#1, syz-executor/6074
lock: 0xffff8881f71d1b48, .magic: ffffffff, .owner: /-1902340672,
.owner_cpu: 768
CPU: 1 UID: 0 PID: 6074 Comm: syz-executor Not tainted syzkaller #1
RIP: 0033:0x7fbf84d9e097
</TASK>
------------[ cut here ]------------
UBSAN: array-index-out-of-bounds in kernel/locking/qspinlock.h:68:9
index 8945 is out of range for type 'unsigned long[8]'
CPU: 1 UID: 0 PID: 6074 Comm: syz-executor Not tainted syzkaller #1
PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
1.16.3-debian-1.16.3-2 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
ubsan_epilogue+0xa/0x30 lib/ubsan.c:233
__ubsan_handle_out_of_bounds+0xe8/0xf0 lib/ubsan.c:455
decode_tail kernel/locking/qspinlock.h:68 [inline]
__pv_queued_spin_lock_slowpath+0xaf3/0xbc0 kernel/locking/qspinlock.c:285
pv_queued_spin_lock_slowpath arch/x86/include/asm/paravirt-spinlock.h:35
[inline]
queued_spin_lock_slowpath arch/x86/include/asm/paravirt-spinlock.h:66
[inline]
queued_spin_lock include/asm-generic/qspinlock.h:114 [inline]
do_raw_spin_lock+0x26c/0x2f0 kernel/locking/spinlock_debug.c:116
__raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock_irqsave+0x4c/0x60 kernel/locking/spinlock.c:166
__wake_up_common_lock+0x30/0x1f0 kernel/sched/wait.c:124
unlock_metapage fs/jfs/jfs_metapage.c:40 [inline]
release_metapage+0x131/0xa60 fs/jfs/jfs_metapage.c:872
xtTruncate+0xeaa/0x2eb0 fs/jfs/jfs_xtree.c:-1
</TASK>

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot
Link: https://syzkaller.appspot.com/ai_job?id=755ca394-6f1f-4a09-8e45-1a3c045336ed
To: <jfs-dis...@lists.sourceforge.net>
To: "Dave Kleikamp" <sha...@kernel.org>
Cc: "Arnd Bergmann" <ar...@arndb.de>
Cc: <linux-...@vger.kernel.org>
Cc: "Suchit Karunakaran" <suchitka...@gmail.com>
Cc: "Yun Zhou" <yun....@windriver.com>
Cc: "Zheng Yu" <zhen...@northwestern.edu>

---
v2:
- Combined the BT_ROOT flag validation with the existing page integrity check in DT_GETPAGE.
- Unified the error message in DT_GETPAGE for both root and leaf page corruption.

v1:
https://lore.kernel.org/all/65efb3d8-bbf9-4f4b...@mail.kernel.org/T/
---
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ac0f79faf..2b6bdea1f 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -111,19 +111,20 @@ struct dtsplit {
#define DT_PAGE(IP, MP) BT_PAGE(IP, MP, dtpage_t, i_dtroot)

/* get page buffer for specified block address */
-#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
-do { \
- BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
- if (!(RC)) { \
- if ((BN) && !check_dtpage(P)) { \
- BT_PUTPAGE(MP); \
- jfs_error((IP)->i_sb, \
- "DT_GETPAGE: dtree page corrupt\n"); \
- MP = NULL; \
- RC = -EIO; \
- } \
- } \
-} while (0)
+#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
+ do { \
+ BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
+ if (!(RC)) { \
+ if ((((BN) == 0) != !!((P)->header.flag & BT_ROOT)) || \
+ ((BN) && !check_dtpage(P))) { \
+ BT_PUTPAGE(MP); \
+ jfs_error((IP)->i_sb, \
+ "DT_GETPAGE: dtree page corrupt\n"); \
+ MP = NULL; \
+ RC = -EIO; \
+ } \
+ } \
+ } while (0)

/* for consistency */
#define DT_PUTPAGE(MP) BT_PUTPAGE(MP)
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 28c3cf960..6d960dd96 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -118,10 +118,11 @@ static inline xtpage_t *xt_getpage(struct inode *ip, s64 bn, struct metapage **m
if (rc)
return ERR_PTR(rc);
if ((le16_to_cpu(p->header.nextindex) < XTENTRYSTART) ||
- (le16_to_cpu(p->header.nextindex) >
- le16_to_cpu(p->header.maxentry)) ||
- (le16_to_cpu(p->header.maxentry) >
- ((bn == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE))) {
+ (le16_to_cpu(p->header.nextindex) >
+ le16_to_cpu(p->header.maxentry)) ||
+ (le16_to_cpu(p->header.maxentry) >
+ ((bn == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE)) ||
+ ((bn == 0) != !!(p->header.flag & BT_ROOT))) {
jfs_error(ip->i_sb, "xt_getpage: xtree page corrupt\n");
BT_PUTPAGE(*mp);
*mp = NULL;


base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6

Kusaram Devineni

unread,
Jul 10, 2026, 2:05:33 AM (6 days ago) Jul 10
to syzbot, syzkaller-upst...@googlegroups.com, syz...@lists.linux.dev
- checkpatch.pl considers the line above "------------[ cut here
]------------" that is added inside the commit message as "ERROR:
Invalid commit separator". remove it.
- change v2 changelog wording from “root and leaf page corruption” to
“root/non-root invariant failures and non-root dtpage integrity
failures.”, as check_dtpage() is for non-root dtpage integrity
generally, not leaf-only.
- limit the formatting changes to only the lines, block, or branch being
modified. in DT_GETPAGE() and xt_getpage(), avoid reindenting the
surrounding existing code; add only the new BT_ROOT invariant condition
and keep the local style unchanged.

>
> base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6

-kusaram

syzbot

unread,
11:28 AM (8 hours ago) 11:28 AM
to syzkaller-upst...@googlegroups.com, syz...@lists.linux.dev
A corrupted JFS image can trick the kernel into calling release_metapage()
on a pseudo-metapage embedded within the inode, leading to an out-of-bounds
memory access and a spinlock crash.

When operating on the root page of an xtree or dtree (which is stored
inline within the inode), JFS doesn't use a real struct metapage. Instead,
BT_GETPAGE() sets the metapage pointer to the address of
JFS_IP(ip)->bxflag. Because this is a pseudo-metapage, it does not have a
valid wait_queue_head_t wait field. Accessing mp->wait reads out-of-bounds
memory in struct jfs_inode_info.

In xt_getpage(), the code validates nextindex and maxentry, but it fails to
verify that the BT_ROOT flag is set in p->header.flag for the root page (bn
== 0). If the inline xtree root page has a corrupted header.flag where
BT_ROOT is missing, xtTruncate() will mistakenly treat the root page as a
regular leaf page and call discard_metapage(mp).

Unlike XT_PUTPAGE() which safely checks !BT_IS_ROOT(mp) before releasing,
discard_metapage() calls release_metapage(mp) directly. This assumes mp is
a real metapage and calls unlock_metapage(mp), which executes
wake_up(&mp->wait), accessing garbage memory and resulting in a spinlock
bad magic BUG or UBSAN out-of-bounds array access.

Fix this by enforcing the invariant that the BT_ROOT flag is set if and
only if bn == 0 in both xt_getpage() and DT_GETPAGE().

BUG: spinlock bad magic on CPU#1, syz-executor/6078
lock: 0xffff8881f55f1b48, .magic: ffffffff, .owner: /-1902340672,
.owner_cpu: 768
CPU: 1 UID: 0 PID: 6078 Comm: syz-executor Not tainted syzkaller #1
PREEMPT(full)
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
spin_bug kernel/locking/spinlock_debug.c:78 [inline]
debug_spin_lock_before kernel/locking/spinlock_debug.c:86 [inline]
do_raw_spin_lock+0x1e5/0x2f0 kernel/locking/spinlock_debug.c:115
__raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock_irqsave+0x4c/0x60 kernel/locking/spinlock.c:166
__wake_up_common_lock+0x30/0x1f0 kernel/sched/wait.c:124
unlock_metapage fs/jfs/jfs_metapage.c:40 [inline]
release_metapage+0x131/0xa60 fs/jfs/jfs_metapage.c:872
xtTruncate+0xeaa/0x2eb0 fs/jfs/jfs_xtree.c:-1
jfs_free_zero_link+0x35b/0x4c0 fs/jfs/namei.c:760
jfs_evict_inode+0x356/0x430 fs/jfs/inode.c:159
evict+0x624/0xb50 fs/inode.c:841
...
</TASK>

UBSAN: array-index-out-of-bounds in kernel/locking/qspinlock.h:68:9
index 8945 is out of range for type 'unsigned long[8]'
CPU: 1 UID: 0 PID: 6078 Comm: syz-executor Not tainted syzkaller #1
PREEMPT(full)
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
ubsan_epilogue+0xa/0x30 lib/ubsan.c:233
__ubsan_handle_out_of_bounds+0xe8/0xf0 lib/ubsan.c:455
decode_tail kernel/locking/qspinlock.h:68 [inline]
__pv_queued_spin_lock_slowpath+0xaf3/0xbc0 kernel/locking/qspinlock.c:285
pv_queued_spin_lock_slowpath arch/x86/include/asm/paravirt-spinlock.h:35
[inline]
queued_spin_lock_slowpath arch/x86/include/asm/paravirt-spinlock.h:66
[inline]
queued_spin_lock include/asm-generic/qspinlock.h:114 [inline]
do_raw_spin_lock+0x26c/0x2f0 kernel/locking/spinlock_debug.c:116
__raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock_irqsave+0x4c/0x60 kernel/locking/spinlock.c:166
__wake_up_common_lock+0x30/0x1f0 kernel/sched/wait.c:124
unlock_metapage fs/jfs/jfs_metapage.c:40 [inline]
release_metapage+0x131/0xa60 fs/jfs/jfs_metapage.c:872
xtTruncate+0xeaa/0x2eb0 fs/jfs/jfs_xtree.c:-1
...
</TASK>

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot
Reported-by: syzbot+e38044...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e380443eaa59bfb75a84
Link: https://syzkaller.appspot.com/ai_job?id=20a14f45-b85b-4c13-8896-26c43b87a29b
To: <jfs-dis...@lists.sourceforge.net>
To: "Dave Kleikamp" <sha...@kernel.org>
Cc: "Arnd Bergmann" <ar...@arndb.de>
Cc: <linux-...@vger.kernel.org>
Cc: "Yun Zhou" <yun....@windriver.com>
Cc: "Zheng Yu" <zhen...@northwestern.edu>

---
v3:
- Validated root/non-root invariant failures and non-root dtpage integrity failures.
- Removed '------------[ cut here ]------------' from the commit message.

v2:
- Combined the BT_ROOT flag validation with the existing page integrity check in DT_GETPAGE.
- Unified the error message in DT_GETPAGE for both root and leaf page corruption.
https://lore.kernel.org/all/b94e1523-acdb-4470...@mail.kernel.org/T/
Reply all
Reply to author
Forward
0 new messages