[BUG] KASAN: wild-memory-access in file_end_write after mgag200 unload — stale timer corrupts struct file [mgag200] [syzkaller]

From: Yang Zi

Date: Mon Aug 10 2026 - 03:22:17 EST


Hi,

While fuzzing the kernel v7.1.0 (KASAN), a user-space write syscall crashed
with a wild memory access in the VFS layer, one step removed from a mgag200
timer race.

Reproducer summary (attached report/log):

BUG: KASAN: wild-memory-access in file_end_write include/linux/fs.h:2742 [inline]
BUG: KASAN: wild-memory-access in vfs_write+0x6d7 /fs/read_write.c:696
Read of size 2 at addr 2788d6430cd06410 by task syz.0.1/807

Oops: general protection fault, probably for non-canonical address
0x8b4d9090504681d2gr ... Tainted: G B W O

The task `syz.0.1/807` ran `vfs_write() -> file_end_write() -> file_inode()`
and dereferenced RBX = 0x8b4d909050468a49, a non-canonical pointer with the
`file` object already overwritten by stray writes. `last unloaded: mgag200`
and `Tainted G B W O` (BAD_PAGE) indicate that memory corruption occurred at
the page level after the mgag200 module was removed.

Root-cause hypothesis: the kernel kept a per-device timer / net-side watchdog
pending while `mgag200_pci_remove` unloaded the device. The leftover timer
softirq subsequently wrote into a slab that had returned to the allocator and
been re-used (e.g. by an `struct file` / fd allocation); that write corrupted
the `file->f_inode` / `f_mode` fields to a non-canonical value. Later userland
`write()` on that recycled file dereferences the stale pointer and traps on a
wild 8-byte read. This is consistent with the family-wide mgag200 "timer not
cancelled before remove → write into freed memory → reused object corrupted"
pattern (mode B), earlier seen in id11/18/43 variants.

The crash report attached below:

BUG: KASAN: wild-memory-access in file_end_write include/linux/fs.h:2742 [inline]
BUG: KASAN: wild-memory-access in vfs_write+0x6d7/0x810 fs/read_write.c:696
Read of size 2 at addr 8b4d909050468949 by task syz.0.1/807

CPU: 0 UID: 0 PID: 807 Comm: syz.0.1 Tainted: G W O 7.1.0 #2 PREEMPT(lazy)
Tainted: [W]=WARN, [O]=OOT_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
Call Trace:
<IRQ>
dump_stack_lvl+0xa2/0xd0 lib/dump_stack.c:120
kasan_report+0x117/0x150 mm/kasan/report.c:595
file_end_write include/linux/fs.h:2742 [inline]
vfs_write+0x6d7/0x810 fs/read_write.c:696
</IRQ>
<TASK>
</TASK>
==================================================================
Oops: general protection fault, probably for non-canonical address 0x8b4d909050468949: 0000 [#1] SMP KASAN NOPTI
CPU: 0 UID: 0 PID: 807 Comm: syz.0.1 Tainted: G B W O 7.1.0 #2 PREEMPT(lazy)
Tainted: [B]=BAD_PAGE, [W]=WARN, [O]=OOT_MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
RIP: 0010:file_end_write include/linux/fs.h:2742 [inline]
RIP: 0010:vfs_write+0x6d7/0x810 fs/read_write.c:696
Code: d7 db af 04 48 8d bb d0 12 00 00 e8 a3 d6 fb ff 48 ff 83 d0 12 00 00 4c 89 f7 e8 94 d6 fb ff 49 8b 1e 48 89 df e8 c9 d3 fb ff <0f> bf 2b 0f b7 f5 bf 00 90 00 00 e8 a9 48 d3 ff 81 fd 00 90 ff ff
RSP: 0018:ffff88806ce08df0 EFLAGS: 00010286
RAX: ffff8880161d9b01 RBX: 8b4d909050468949 RCX: ffff8880161d9b40
RDX: 0000000000000100 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: ffffffff863e0fe7 R09: 1ffffffff0c7c1fc
R10: dffffc0000000000 R11: fffffbfff0c7c1fd R12: ffff8880189848c0
R13: ffffffff81508ef8 R14: ffffffff836d5fcb R15: 0000000000000140
FS: 000055557e5e4500(0000) GS:ffff8880e6a8d000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000056238de07430 CR3: 00000000525c2000 CR4: 00000000000006f0
Call Trace:
<IRQ>
</IRQ>
<TASK>
</TASK>
Modules linked in: gadgetfs udc_core sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan virt_wifi veth nlmon dummy team bonding tun rfuzzer_device(O) i2c_dev qrtr iTCO_wdt intel_pmc_bxt watchdog ppdev vga16fb vgastate mgag200 parport_pc lpc_ich parport mfd_core bochs mousedev serio_raw tpm_tis tpm_tis_core tpm dm_mod dax dmi_sysfs qemu_fw_cfg virtio_rng kt_runtime(O) uio_pci_kerneltracker_driver(O)
---[ end trace 0000000000000000 ]---
RIP: 0010:file_end_write include/linux/fs.h:2742 [inline]
RIP: 0010:vfs_write+0x6d7/0x810 fs/read_write.c:696
Code: d7 db af 04 48 8d bb d0 12 00 00 e8 a3 d6 fb ff 48 ff 83 d0 12 00 00 4c 89 f7 e8 94 d6 fb ff 49 8b 1e 48 89 df e8 c9 d3 fb ff <0f> bf 2b 0f b7 f5 bf 00 90 00 00 e8 a9 48 d3 ff 81 fd 00 90 ff ff
RSP: 0018:ffff88806ce08df0 EFLAGS: 00010286
RAX: ffff8880161d9b01 RBX: 8b4d909050468949 RCX: ffff8880161d9b40
RDX: 0000000000000100 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: ffffffff863e0fe7 R09: 1ffffffff0c7c1fc
R10: dffffc0000000000 R11: fffffbfff0c7c1fd R12: ffff8880189848c0
R13: ffffffff81508ef8 R14: ffffffff836d5fcb R15: 0000000000000140
FS: 000055557e5e4500(0000) GS:ffff8880e6a8d000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000056238de07430 CR3: 00000000525c2000 CR4: 00000000000006f0
----------------
Code disassembly (best guess):
0: d7 xlat %ds:(%rbx)
1: db af 04 48 8d bb fldt -0x4472b7fc(%rdi)
7: d0 12 rclb (%rdx)
9: 00 00 add %al,(%rax)
b: e8 a3 d6 fb ff call 0xfffbd6b3
10: 48 ff 83 d0 12 00 00 incq 0x12d0(%rbx)
17: 4c 89 f7 mov %r14,%rdi
1a: e8 94 d6 fb ff call 0xfffbd6b3
1f: 49 8b 1e mov (%r14),%rbx
22: 48 89 df mov %rbx,%rdi
25: e8 c9 d3 fb ff call 0xfffbd3f3
* 2a: 0f bf 2b movswl (%rbx),%ebp <-- trapping instruction
2d: 0f b7 f5 movzwl %bp,%esi
30: bf 00 90 00 00 mov $0x9000,%edi
35: e8 a9 48 d3 ff call 0xffd348e3
3a: 81 fd 00 90 ff ff cmp $0xffff9000,%ebp

<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>

Regards,
Yang Zi