Hi,

While fuzzing with syzkaller (KASAN) we hit a use-after-free in the timer
subsystem while unloading the mgag200 DRM driver.

Reproducer summary:

    BUG: KASAN: use-after-free in enqueue_timer kernel/time/timer.c:616
    [inline] hlist_add_head include/linux/list.h:1075
    BUG: KASAN: use-after-free in enqueue_timer+0x59/0x280
    Write of size 8 at addr ffff8880192808c8 by task (udev-worker)/829

Call chain (IRQ softirq):

    run_timer_softirq -> expire_timers -> call_timer_fn
       addrconf_rs_timer net/ipv6/addrconf.c:4061
       addrconf_mod_rs_timer addrconf.c:332
       __mod_timer -> enqueue_timer -> hlist_add_head   (Write 8B to freed page)

Root cause: the periodic IPv6 `addrconf_rs_timer` (re-armed in softirq via
`mod_timer`) is not cancelled when the device/interface that owns the timer
is released during mgag200 module removal. Once the object page is released
(refcount:0, KASAN shadow all 0xff), the softirq callback keeps re-queuing
the timer into a released page, causing the UAF, which then cascades into
scheduling-while-atomic / invalid opcode / NULL deref in VFS.

The crash report shows below:

BUG: KASAN: use-after-free in hlist_add_head include/linux/list.h:1075 [inline]
BUG: KASAN: use-after-free in enqueue_timer+0x59/0x280 kernel/time/timer.c:616
Write of size 8 at addr ffff8880192808c8 by task (udev-worker)/829

CPU: 0 UID: 0 PID: 829 Comm: (udev-worker) 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
 print_address_description+0x77/0x200 mm/kasan/report.c:378
 print_report+0x58/0x70 mm/kasan/report.c:482
 kasan_report+0x117/0x150 mm/kasan/report.c:595
 hlist_add_head include/linux/list.h:1075 [inline]
 enqueue_timer+0x59/0x280 kernel/time/timer.c:616
 __mod_timer+0x625/0x840 kernel/time/timer.c:-1
 addrconf_mod_rs_timer+0x36/0xd0 net/ipv6/addrconf.c:332
 addrconf_rs_timer+0x280/0x320 net/ipv6/addrconf.c:4061
 call_timer_fn+0xfb/0x2c0 kernel/time/timer.c:1748
 expire_timers kernel/time/timer.c:1799 [inline]
 __run_timers kernel/time/timer.c:2374 [inline]
 __run_timer_base+0x4ad/0x6d0 kernel/time/timer.c:2386
 run_timer_base kernel/time/timer.c:2395 [inline]
 run_timer_softirq+0x32/0x70 kernel/time/timer.c:2405
 handle_softirqs+0x1a2/0x560 kernel/softirq.c:622
 __do_softirq kernel/softirq.c:656 [inline]
 invoke_softirq kernel/softirq.c:496 [inline]
 __irq_exit_rcu+0xa7/0x180 kernel/softirq.c:735
 irq_exit_rcu+0x9/0x20 kernel/softirq.c:752
 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1061 [inline]
 sysvec_apic_timer_interrupt+0x6e/0x80 arch/x86/kernel/apic/apic.c:1061
 </IRQ>
 <TASK>
 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:697
RIP: 0010:bytes_is_nonzero mm/kasan/generic.c:98 [inline]
RIP: 0010:memory_is_nonzero mm/kasan/generic.c:115 [inline]
RIP: 0010:memory_is_poisoned_n mm/kasan/generic.c:140 [inline]
RIP: 0010:memory_is_poisoned mm/kasan/generic.c:172 [inline]
RIP: 0010:check_region_inline mm/kasan/generic.c:191 [inline]
RIP: 0010:kasan_check_range+0x97/0x2c0 mm/kasan/generic.c:200
Code: 00 fc ff df 4d 8d 34 19 4d 89 f4 4d 29 dc 49 83 fc 10 7f 29 4d 85 e4 0f 
84 3d 01 00 00 4c 89 cb 48 f7 d3 4c 01 fb 41 80 3b 00 <0f> 85 9e 01 00 00 49 ff 
c3 48 ff c3 75 ee e9 1d 01 00 00 44 89 dd
RSP: 0018:ffff88800bf6f9e8 EFLAGS: 00000246
RAX: ffffffff854d4501 RBX: ffffffffffffffff RCX: ffffffff81349e22
RDX: 0000000000000000 RSI: 0000000000000002 RDI: ffffffff854d45d8
RBP: ffffffff85123ea0 R08: ffffffff854d45d9 R09: 1ffffffff0a9a8bb
R10: dffffc0000000000 R11: fffffbfff0a9a8bb R12: 0000000000000001
R13: 0000000000000002 R14: fffffbfff0a9a8bc R15: 1ffffffff0a9a8bb
 unwind_next_frame+0x382/0x14a0 arch/x86/kernel/unwind_orc.c:520
 arch_stack_walk+0x131/0x160 arch/x86/kernel/stacktrace.c:25
 stack_trace_save+0x45/0x70 kernel/stacktrace.c:122
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 unpoison_slab_object mm/kasan/common.c:340 [inline]
 __kasan_slab_alloc+0x4b/0x60 mm/kasan/common.c:366
 kasan_slab_alloc include/linux/kasan.h:253 [inline]
 slab_post_alloc_hook mm/slub.c:4570 [inline]
 slab_alloc_node mm/slub.c:4899 [inline]
 kmem_cache_alloc_noprof+0x17d/0x5c0 mm/slub.c:4906
 alloc_filename fs/namei.c:142 [inline]
 do_getname+0x2e/0x1c0 fs/namei.c:182
 getname include/linux/fs.h:2526 [inline]
 class_filename_constructor include/linux/fs.h:2553 [inline]
 do_sys_openat2+0x60/0x130 fs/open.c:1363
 do_sys_open fs/open.c:1370 [inline]
 __do_sys_openat fs/open.c:1386 [inline]
 __se_sys_openat fs/open.c:1381 [inline]
 __x64_sys_openat+0xf2/0x120 fs/open.c:1381
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x14b/0x490 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fbfd40d52e2
Code: 00 48 89 45 c8 31 c0 f6 c2 40 75 44 89 d0 45 31 d2 f7 d0 a9 00 00 41 00 
74 36 80 3d 67 fd 0e 00 00 74 51 b8 01 01 00 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 
8a 00 00 00 48 8b 55 c8 64 48 2b 14 25 28
RSP: 002b:00007ffe785a8c90 EFLAGS: 00000202 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 00007ffe785a905c RCX: 00007fbfd40d52e2
RDX: 00000000002a0000 RSI: 00005654b37462b0 RDI: 0000000000000015
RBP: 00007ffe785a8d00 R08: 0000000000000000 R09: 0000000000000007
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000
R13: 0000000000000014 R14: 00005654b37462b0 R15: 0000000000000000
 </TASK>

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888019283a80 
pfn:0x19280
flags: 0x100000000000000(node=0|zone=1)
raw: 0100000000000000 ffffea00004fd408 ffff88806ce3d4c0 0000000000000000
raw: ffff888019283a80 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888019280780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
 ffff888019280800: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff888019280880: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
                                              ^
 ffff888019280900: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
 ffff888019280980: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Regards,
Yang Zi

Reply via email to