[PATCH] fs: jfs: fix UBSAN in jfs_statfs
From: Hoi Pok Wu
Date: Sun Nov 20 2022 - 10:00:41 EST
The reason for the following undefined behaviour is the shifting is
larger than the amounts of bit of 's64'. Given that the shifting is the
only use case of the variable im_l2nbperiext, I wonder if it is a good
idea to guard the value thus it is smaller than 64.
I am not sure the actual meaning of the variable, so there maybe better
ways. Still, I would send this patch as a suggestion. Thank you.
loop0: detected capacity change from 0 to 32768
================================================================================
UBSAN: shift-out-of-bounds in fs/jfs/super.c:140:14
shift exponent 1749508610 is too large for 64-bit type 's64' (aka 'long long')
CPU: 0 PID: 3634 Comm: syz-executor222 Not tainted 6.1.0-rc5-syzkaller-00241-gab290eaddc4c #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106
ubsan_epilogue lib/ubsan.c:151 [inline]
__ubsan_handle_shift_out_of_bounds+0x33d/0x3b0 lib/ubsan.c:322
jfs_statfs+0x503/0x510 fs/jfs/super.c:140
statfs_by_dentry fs/statfs.c:66 [inline]
vfs_statfs+0x136/0x310 fs/statfs.c:90
user_statfs fs/statfs.c:105 [inline]
__do_sys_statfs fs/statfs.c:195 [inline]
__se_sys_statfs fs/statfs.c:192 [inline]
__x64_sys_statfs+0x120/0x230 fs/statfs.c:192
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f0501ab8f79
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffffd945308 EFLAGS: 00000246 ORIG_RAX: 0000000000000089
RAX: ffffffffffffffda RBX: 0030656c69662f2e RCX: 00007f0501ab8f79
RDX: 00007f0501a77473 RSI: 0000000000000000 RDI: 0000000020004c80
RBP: 00007f0501a78740 R08: 0000555555fe32c0 R09: 0000000000000000
R10: 00007ffffd9451d0 R11: 0000000000000246 R12: 0a0a0a0a0a0a0a0a
R13: 0000000000000000 R14: 00083878000000f8 R15: 0000000000000000
</TASK>
================================================================================
Reported-by: syzbot+3424c9550a49659f1704@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Hoi Pok Wu <wuhoipok@xxxxxxxxx>
---
fs/jfs/jfs_imap.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 390cbfce391f..093f2ecd92ac 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -124,6 +124,13 @@ int diMount(struct inode *ipimap)
atomic_set(&imap->im_numfree, le32_to_cpu(dinom_le->in_numfree));
imap->im_nbperiext = le32_to_cpu(dinom_le->in_nbperiext);
imap->im_l2nbperiext = le32_to_cpu(dinom_le->in_l2nbperiext);
+
+ /* 63 is the maximum shift amounts for type s64 */
+ if (imap->im_l2nbperiext >= 64) {
+ release_metapage(mp);
+ return -EINVAL;
+ }
+
for (index = 0; index < MAXAG; index++) {
imap->im_agctl[index].inofree =
le32_to_cpu(dinom_le->in_agctl[index].inofree);
--
2.38.1