[BUG] efs: divide error in efs_iget() on mount of crafted image
From: Farhad Alemi
Date: Fri May 29 2026 - 13:54:26 EST
Hello Christian and the linux-fsdevel team,
I am reporting a divide-by-zero (#DE) on mount of a crafted SGI EFS
image, found by syzkaller as part of research at the SEFCOM Lab at
ASU. EFS is marked "S: Orphan" in MAINTAINERS (F: fs/efs/), so I am
routing this to you as the VFS maintainer who shepherded the recent
fs/efs changes, plus linux-fsdevel.
Summary:
efs_iget() computes the on-disk block of an inode by dividing by
sb->inode_blocks at fs/efs/inode.c:85-87:
block = sb->fs_start + sb->first_block +
(sb->group_size * (inode_index / sb->inode_blocks)) +
(inode_index % sb->inode_blocks);
sb->inode_blocks is taken directly from the on-disk superblock in
efs_validate_super() at fs/efs/super.c:234, with no non-zero check:
sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
efs_validate_super() only rejects a bad magic (returns -1 at
fs/efs/super.c:226); a crafted image with fs_cgisize = 0 passes
validation, and the first inode lookup -- the root inode that
efs_fill_super() loads via efs_iget(s, EFS_ROOTINODE) at
fs/efs/super.c:305 -- divides by zero. The crash RIP is the
inode_index % sb->inode_blocks at fs/efs/inode.c:87.
Observed on:
- Linux v7.1-rc3-200-g70eda68668d1-dirty (where the bug was found),
x86_64, QEMU Q35
- KASAN enabled; PREEMPT(full)
- Crash context: Comm: syz.1.794, PID 15915, UID 0
- Reach (full call trace in crash-report.txt): __se_sys_mount ->
do_new_mount -> vfs_get_tree -> get_tree_bdev_flags ->
efs_fill_super -> efs_iget
- The only local dirty file in my tree is
drivers/tty/serial/serial_core.c, a ttyS0 console guard for the
fuzzing harness, unrelated to fs/efs/.
- Source inspection of linus/master at commit e8c2f9fdadee
(v7.1-rc4-754-ge8c2f9fdadee) shows the structure is unchanged:
fs/efs/inode.c:85-87 still divides by sb->inode_blocks, and
efs_validate_super() at fs/efs/super.c:234 still assigns
sb->inode_blocks = be16_to_cpu(super->fs_cgisize) with no
non-zero check. I have re-confirmed by source inspection only; I
have not re-run the reproducer against e8c2f9fdadee.
Impact:
A mount(2) of the crafted image divides by zero and kills the kernel:
Oops: divide error: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:efs_iget+0x172/0x12f0 fs/efs/inode.c:87
The full register dump and call trace are in crash-report.txt.
Expected behavior:
efs_validate_super() should reject a superblock with
sb->inode_blocks == 0 (it already returns -1 on a magic mismatch, so
the reject path exists).
Reproducer:
Attached: reproducer.c (syzkaller-generated C) and reproducer.syz.
The reproducer uses syz_mount_image$efs with the crafted EFS image
embedded inline. The console report is attached as crash-report.txt.
Novelty check:
I searched the syzbot dashboard's upstream open, fixed, stable, and
invalid (fs subsystem) namespaces; the Android dashboard; the
marc.info linux-fsdevel archive; and lore, for
"efs_iget", "divide error in efs", and "fs/efs/inode.c:87". I did
not find a prior report.
I appreciate your time and consideration, and I'm grateful for your
work on this subsystem. I'd be glad to test any candidate patches.
Regards,
loop1: detected capacity change from 0 to 16
Oops: divide error: 0000 [#1] SMP KASAN NOPTI
CPU: 1 UID: 0 PID: 15915 Comm: syz.1.794 Not tainted 7.1.0-rc3-00200-g70eda68668d1-dirty #1 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:efs_iget+0x172/0x12f0 fs/efs/inode.c:87
Code: 0f 85 2b 0d 00 00 41 8b 5e 10 49 83 c6 1c 4c 89 f0 48 c1 e8 03 42 0f b6 04 00 84 c0 0f 85 37 0d 00 00 41 0f b7 0e 44 89 f8 99 <f7> f9 41 89 c7 44 0f af fb 01 d5 4c 8d 76 28 4c 89 f0 48 c1 e8 03
RSP: 0018:ffffc90001edfae0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 0000000000000064 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff88812e2d3920 RDI: ffff888164899a50
RBP: 0000000000000002 R08: dffffc0000000000 R09: 1ffff11027045930
R10: ffffc90001edf860 R11: fffff520003dbf21 R12: 0000000000000002
R13: ffff88813822c000 R14: ffff888164899a5c R15: 0000000000000000
FS: 00007f95e52776c0(0000) GS:ffff8882ab7b6000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f95dce58000 CR3: 0000000155ce1000 CR4: 0000000000750ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600
PKRU: 80000000
Call Trace:
<TASK>
efs_fill_super+0xd82/0x14c0 fs/efs/super.c:305
get_tree_bdev_flags+0x436/0x500 fs/super.c:1694
vfs_get_tree+0x97/0x2b0 fs/super.c:1754
fc_mount fs/namespace.c:1193 [inline]
do_new_mount_fc fs/namespace.c:3758 [inline]
do_new_mount+0x346/0xd30 fs/namespace.c:3834
do_mount fs/namespace.c:4167 [inline]
__do_sys_mount fs/namespace.c:4383 [inline]
__se_sys_mount+0x322/0x420 fs/namespace.c:4360
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0x560 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f95e68291be
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:00007f95e5276e28 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007f95e5276ec0 RCX: 00007f95e68291be
RDX: 0000200000000380 RSI: 00002000000000c0 RDI: 00007f95e5276e80
RBP: 0000200000000380 R08: 00007f95e5276ec0 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00002000000000c0
R13: 00007f95e5276e80 R14: 0000000000000065 R15: 0000200000000340
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:efs_iget+0x172/0x12f0 fs/efs/inode.c:87
Code: 0f 85 2b 0d 00 00 41 8b 5e 10 49 83 c6 1c 4c 89 f0 48 c1 e8 03 42 0f b6 04 00 84 c0 0f 85 37 0d 00 00 41 0f b7 0e 44 89 f8 99 <f7> f9 41 89 c7 44 0f af fb 01 d5 4c 8d 76 28 4c 89 f0 48 c1 e8 03
RSP: 0018:ffffc90001edfae0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 0000000000000064 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff88812e2d3920 RDI: ffff888164899a50
RBP: 0000000000000002 R08: dffffc0000000000 R09: 1ffff11027045930
R10: ffffc90001edf860 R11: fffff520003dbf21 R12: 0000000000000002
R13: ffff88813822c000 R14: ffff888164899a5c R15: 0000000000000000
FS: 00007f95e52776c0(0000) GS:ffff8882ab6b6000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fc069d60a10 CR3: 0000000155ce1000 CR4: 0000000000750ef0
PKRU: 80000000
----------------
Code disassembly (best guess):
0: 0f 85 2b 0d 00 00 jne 0xd31
6: 41 8b 5e 10 mov 0x10(%r14),%ebx
a: 49 83 c6 1c add $0x1c,%r14
e: 4c 89 f0 mov %r14,%rax
11: 48 c1 e8 03 shr $0x3,%rax
15: 42 0f b6 04 00 movzbl (%rax,%r8,1),%eax
1a: 84 c0 test %al,%al
1c: 0f 85 37 0d 00 00 jne 0xd59
22: 41 0f b7 0e movzwl (%r14),%ecx
26: 44 89 f8 mov %r15d,%eax
29: 99 cltd
* 2a: f7 f9 idiv %ecx <-- trapping instruction
2c: 41 89 c7 mov %eax,%r15d
2f: 44 0f af fb imul %ebx,%r15d
33: 01 d5 add %edx,%ebp
35: 4c 8d 76 28 lea 0x28(%rsi),%r14
39: 4c 89 f0 mov %r14,%rax
3c: 48 c1 e8 03 shr $0x3,%rax
<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>
Attachment:
reproducer.syz
Description: Binary data
Attachment:
reproducer.c
Description: Binary data