[BUG] KASAN: wild-memory-access in device_release_driver_internal (mgdl) driver / uncancelled timer on unload [mgag200] [syzkaller]

Yang Zi <[email protected]>
Newsgroups org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hi,

While fuzzing the kernel v7.1 with syzkaller (KASAN), we hit a Wild Memory Access
in the device-release path, caused by the mgag200 driver not cancelling its timer 
before the device structures are torn down.

Reproducer summary (see attached report/log):

    BUG: KASAN: wild-memory-access in device_unbind_cleanup drivers/base/md.c:498 [inline]
    BUG: KASAN: wild-memory-access in __device_release_driver drivers/base/md.c:1357 [inline]
    BUG: KASAN: wild-memory-access in device_release_driver_internal+0x381/0x540 drivers/base/md.c:1375
    Read of size 8 at addr 0855e8e7894c0090 by task syz.0.5/824

    Oops: general protection fault, probably for non-canonical address 0x855e8e7894c0090: 0000 [#1] SMP KASAN NOPTI
    RIP: 0010:device_unbind_cleanup ... mov 0x90(%r15),%r13   <-- R15 = 0x855e8e7894c0000

The module table shows `mgag200(+) ... [last unloaded: mgag200]`: the driver is
loaded and unloaded in a loop. In `mgag200_pci_remove` -> `drm_dev_unregister`.
the associated timer is not cancelled (`del_timer_sync` missing). When the device
objects are destroyed the pending timer softirq still writes to the freed slab,
overwriting the `struct device` / devres pointer fields with a non-canonical
value (0x855e8e...). A subsequent device unbind (`device_release_driver_internal`
-> `device_unbind_cleanup`) dereferences that corrupted pointer and faults.

Root-cause: the driver-facing bug is the missing timer teardown on
remove/hot-unplug; the crash surfaces as a corrupted `struct device` in the
driver-core unbind path. This is a use-after-free spreading from the mg201000
timer into the device-driver model (taint shows BAD_PAGE after the first enjoy).

The crash report attached below:

BUG: KASAN: wild-memory-access in device_unbind_cleanup drivers/base/dd.c:599 [inline]
BUG: KASAN: wild-memory-access in __device_release_driver drivers/base/dd.c:1357 [inline]
BUG: KASAN: wild-memory-access in device_release_driver_internal+0x381/0x540 drivers/base/dd.c:1375
Read of size 8 at addr 0855e8e7894c0090 by task syz.0.5/824

CPU: 0 UID: 0 PID: 824 Comm: syz.0.5 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
 device_unbind_cleanup drivers/base/dd.c:599 [inline]
 __device_release_driver drivers/base/dd.c:1357 [inline]
 device_release_driver_internal+0x381/0x540 drivers/base/dd.c:1375
 device_unbind_cleanup drivers/base/dd.c:598 [inline]
 __device_release_driver drivers/base/dd.c:1357 [inline]
 device_release_driver_internal+0x369/0x540 drivers/base/dd.c:1375
 </IRQ>
 <TASK>
 </TASK>
==================================================================
Oops: general protection fault, probably for non-canonical address 0x855e8e7894c0090: 0000 [#1] SMP KASAN NOPTI
CPU: 0 UID: 0 PID: 824 Comm: syz.0.5 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:device_unbind_cleanup drivers/base/dd.c:599 [inline]
RIP: 0010:__device_release_driver drivers/base/dd.c:1357 [inline]
RIP: 0010:device_release_driver_internal+0x381/0x540 drivers/base/dd.c:1375
Code: 76 d8 fe eb 05 e8 6f 76 d8 fe 4c 89 f7 e8 47 ae 00 00 4c 89 e7 e8 0f 08 01 ff 4d 8b 7e 68 49 8d bf 90 00 00 00 e8 ff 07 01 ff <4d> 8b af 90 00 00 00 4d 85 ed 74 13 e8 3e 76 d8 fe 4c 89 f7 4d 89
RSP: 0018:ffff88806ce08df0 EFLAGS: 00010286
RAX: ffff8880171e9b01 RBX: 0000000000000100 RCX: ffff8880171e9b40
RDX: 0000000000000100 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: ffffffff863e0fe7 R09: 1ffffffff0c7c1fc
R10: dffffc0000000000 R11: fffffbfff0c7c1fd R12: ffff888017ddc8c0
R13: 0000000000000000 R14: ffffffff828422c9 R15: 0855e8e7894c0000
FS:  000055557f72d500(0000) GS:ffff8880e6a8d000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fbcbeece820 CR3: 000000001861d000 CR4: 00000000000006f0
Call Trace:
 <IRQ>
 device_unbind_cleanup drivers/base/dd.c:598 [inline]
 __device_release_driver drivers/base/dd.c:1357 [inline]
 device_release_driver_internal+0x369/0x540 drivers/base/dd.c:1375
 </IRQ>
 <TASK>
 </TASK>
Modules linked in: mgag200(+) 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 ppdev watchdog vga16fb vgastate parport_pc lpc_ich mfd_core parport 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) [last unloaded: mgag200]
---[ end trace 0000000000000000 ]---
RIP: 0010:device_unbind_cleanup drivers/base/dd.c:599 [inline]
RIP: 0010:__device_release_driver drivers/base/dd.c:1357 [inline]
RIP: 0010:device_release_driver_internal+0x381/0x540 drivers/base/dd.c:1375
Code: 76 d8 fe eb 05 e8 6f 76 d8 fe 4c 89 f7 e8 47 ae 00 00 4c 89 e7 e8 0f 08 01 ff 4d 8b 7e 68 49 8d bf 90 00 00 00 e8 ff 07 01 ff <4d> 8b af 90 00 00 00 4d 85 ed 74 13 e8 3e 76 d8 fe 4c 89 f7 4d 89
RSP: 0018:ffff88806ce08df0 EFLAGS: 00010286
RAX: ffff8880171e9b01 RBX: 0000000000000100 RCX: ffff8880171e9b40
RDX: 0000000000000100 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: ffffffff863e0fe7 R09: 1ffffffff0c7c1fc
R10: dffffc0000000000 R11: fffffbfff0c7c1fd R12: ffff888017ddc8c0
R13: 0000000000000000 R14: ffffffff828422c9 R15: 0855e8e7894c0000
FS:  000055557f72d500(0000) GS:ffff8880e6a8d000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fbcbeece820 CR3: 000000001861d000 CR4: 00000000000006f0
----------------
Code disassembly (best guess), 1 bytes skipped:
   0:	d8 fe                	fdivr  %st(6),%st
   2:	eb 05                	jmp    0x9
   4:	e8 6f 76 d8 fe       	call   0xfed87678
   9:	4c 89 f7             	mov    %r14,%rdi
   c:	e8 47 ae 00 00       	call   0xae58
  11:	4c 89 e7             	mov    %r12,%rdi
  14:	e8 0f 08 01 ff       	call   0xff010828
  19:	4d 8b 7e 68          	mov    0x68(%r14),%r15
  1d:	49 8d bf 90 00 00 00 	lea    0x90(%r15),%rdi
  24:	e8 ff 07 01 ff       	call   0xff010828
* 29:	4d 8b af 90 00 00 00 	mov    0x90(%r15),%r13 <-- trapping instruction
  30:	4d 85 ed             	test   %r13,%r13
  33:	74 13                	je     0x48
  35:	e8 3e 76 d8 fe       	call   0xfed87678
  3a:	4c 89 f7             	mov    %r14,%rdi
  3d:	4d                   	rex.WRB
  3e:	89                   	.byte 0x89


Regards,
Yang Zi
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.