[BUG] ufs: UBSAN shift-out-of-bounds in ufs_fill_super() at fs/ufs/super.c:1181

From: Farhad Alemi

Date: Tue May 26 2026 - 17:48:48 EST


Hello Al and the linux-fsdevel team,

I am reporting a UFS crash found by syzkaller. fs/ufs has no named
M: entry in MAINTAINERS, so I'm routing by commit-history affinity.

Summary:
Mounting a crafted UFS image drives ufs_fill_super() through scalar
derivation from on-disk fields. At fs/ufs/super.c:1181:

uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift;

uspi->s_fpbshift is taken directly from the on-disk superblock
(usb1->fs_fragshift) and is not range-checked before being used as a
shift exponent. A crafted image with fs_fragshift = 0x08000000 reaches
this line and UBSAN reports the out-of-bounds shift; under panic_on_warn
this is promoted to a kernel panic.

This is distinct from the earlier UBSAN report in ubh_bread_uspi() at
fs/ufs/util.c:55 -- that one is on s_fshift; this one is on s_fpbshift.
Same general bug class (unvalidated on-disk shift exponent), different
code site.

Observed on:
- Linux v6.17.8 (where the bug was originally found) and verified still
present in linus/master at commit e8c2f9fdadee (v7.1-rc4-754-ge8c2f9fdadee),
x86_64, QEMU Q35
- UBSAN enabled; panic_on_warn set
- Trigger requires the ability to mount a crafted filesystem image,
normally CAP_SYS_ADMIN/root or an equivalent syzkaller test environment.
- The shift expression at fs/ufs/super.c:1181 is unchanged in linus/master
HEAD; bug remains reachable on current mainline.

Impact:
A crafted UFS image triggers a UBSAN shift-out-of-bounds during mount,
which panic_on_warn promotes to a kernel panic:

ufs: ufstype=old is supported read-only
UBSAN: shift-out-of-bounds in fs/ufs/super.c:1181:30
shift exponent 134217728 is too large for 32-bit type '__u32' (aka
'unsigned int')

Relevant stack:
__ubsan_handle_shift_out_of_bounds+0x385/0x410 lib/ubsan.c:494
ufs_fill_super+0x69a9/0x75c0 fs/ufs/super.c:1181
get_tree_bdev_flags+0x436/0x500 fs/super.c:1692
vfs_get_tree+0x94/0x2b0 fs/super.c:1815
do_new_mount+0x2a7/0xa00 fs/namespace.c:3816
__se_sys_mount+0x321/0x420 fs/namespace.c:4332

Expected behavior:
The crafted image should be rejected at mount with -EINVAL once
uspi->s_fpbshift is read from the superblock and found to be out of
range, before any shift expression consumes it.

Reproducer:
I attached the generated C reproducer as reproducer.c. I also attached the
syzkaller program as reproducer.syz and the console report as
crash-report.txt.

Novelty check:
I searched syzbot dashboard data across upstream, fixed, invalid, stable,
and Android namespaces, and searched lore.kernel.org for
"shift-out-of-bounds" + "ufs_fill_super", "fs/ufs/super.c:1181", and the
broader "UBSAN" + "fs/ufs/super.c". I did not find an exact match.

I appreciate your time and consideration.

Regards,
Farhad
mount -t ufs -o ufstype=sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...
>>>WARNING<<< Wrong ufstype may corrupt your filesystem, default is ufstype=old
ufs: ufstype=old is supported read-only
------------[ cut here ]------------
UBSAN: shift-out-of-bounds in fs/ufs/super.c:1181:30
shift exponent 134217728 is too large for 32-bit type '__u32' (aka 'unsigned int')
CPU: 0 UID: 0 PID: 3605 Comm: syz.2.17 Not tainted 6.17.8 #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+0x1a9/0x280 lib/dump_stack.c:120
ubsan_epilogue+0xa/0x30 lib/ubsan.c:233
__ubsan_handle_shift_out_of_bounds+0x385/0x410 lib/ubsan.c:494
ufs_fill_super+0x69a9/0x75c0 fs/ufs/super.c:1181
get_tree_bdev_flags+0x436/0x500 fs/super.c:1692
vfs_get_tree+0x94/0x2b0 fs/super.c:1815
do_new_mount+0x2a7/0xa00 fs/namespace.c:3816
do_mount fs/namespace.c:4144 [inline]
__do_sys_mount fs/namespace.c:4355 [inline]
__se_sys_mount+0x321/0x420 fs/namespace.c:4332
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xf0/0x390 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fd992df91be
Code: 0f 1f 40 00 48 c7 c2 b0 ff ff ff f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffef0ae8ed8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007ffef0ae8f70 RCX: 00007fd992df91be
RDX: 0000200000000080 RSI: 0000200000000580 RDI: 00007ffef0ae8f30
RBP: 0000200000000080 R08: 00007ffef0ae8f70 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000200000000580
R13: 00007ffef0ae8f30 R14: 0000000000000546 R15: 00002000000000c0
</TASK>
---[ end trace ]---

Attachment: reproducer.c
Description: Binary data

Attachment: reproducer.syz
Description: Binary data