[BUG] KASAN: slab-use-after-free in enqueue_timer (re-armed timer on freed skbuff) [mgag200] [syzkaller]

From: Yang Zi <hidden>
Date: 2026-08-09 01:58:23
Also in: dri-devel, lkml

Hi,

While fuzzing the kernel with syzkaller (KASAN), I triggered a
slab-use-after-free in the core timer wheel. A periodic (self-rearming) IPv6
addrconf `rs_timer` was fired in softirq after its host skbuff had already been
freed, and its `mod_timer()` wrote into the freed slab slot.

Reproducer summary :

    BUG: KASAN: slab-use-after-free in enqueue_timer+0x59/0x280 kernel/time/timer.c:616
    BUG: KASAN: slab-use-after-free in hlist_add_head include/linux/list.h:1075 [inline]
    Write of size 8 at addr ffff8880164ac28c8 by task syz.0.4/818
    Call trace:
      __run_timers -> expire_timers -> call_timer_fn
        addrconf_rs_timer  net/ipv6/addrconf.c:4061
        addrconf_mod_rs_timer  net/ipv6/addrconf.c:332
        __mod_timer -> enqueue_timer  kernel/time/timer.c:612
          hlist_add_head  list.h:1075   <-- UAF Write (8B)

The corrupted 704-byte object belongs to `skbuff_small_head` (offset 584,
i.e. the embedded timer_list region). It was allocated by an skb that mgag200's
uevent broadcast created during driver registration/probe, and released via
`consume_skb -> skb_free_head -> kfree`. The timer base still holds an active,
rearming RK/RS timer pointing into that freed object; when the softirq fires
it re-queues it, writing 8 bytes and corrupting the freed slab.

Root cause:  a device / driver with an active, self-rearming IPv6 `addrconf` RS
timer is torn down (device removed/unloaded - e.g. mgag200 remove path) without
first cancelling the timer with `del_timer_sync()`. Once the host object is
freed, the pending timer re-arms itself on freed memory (classic mode-B family:
“timer not removed on driver shutdown → cascade UAF”).

The crash stack trace shows below:

BUG: KASAN: slab-use-after-free in hlist_add_head include/linux/list.h:1075 [inline]
BUG: KASAN: slab-use-after-free in enqueue_timer+0x59/0x280 kernel/time/timer.c:616
Write of size 8 at addr ffff8880164288c8 by task syz.0.4/818

CPU: 0 UID: 0 PID: 818 Comm: syz.0.4 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:__orc_find arch/x86/kernel/unwind_orc.c:103 [inline]
RIP: 0010:orc_module_find arch/x86/kernel/unwind_orc.c:121 [inline]
RIP: 0010:orc_find arch/x86/kernel/unwind_orc.c:248 [inline]
RIP: 0010:unwind_next_frame+0x474/0x14a0 arch/x86/kernel/unwind_orc.c:510
Code: c1 f8 02 49 c1 ed 3f 49 01 c5 49 83 e5 fe 4b 8d 1c 6f 48 89 df e8 7c 8a 50 00 4b 63 04 6f 48 01 d8 4c 39 e0 76 bf 4b 8d 2c 6f <48> 83 c5 fc 49 39 ef 76 c3 48 8b 04 24 48 2b 44 24 30 48 c1 f8 02
RSP: 0018:ffff88800b91e5a0 EFLAGS: 00000202
RAX: ffffffffc002e234 RBX: ffffffffc0283d2c RCX: ffffffff81349f04
RDX: 0000000000000000 RSI: dffffc0000000000 RDI: ffffffffc0283d2c
RBP: ffffffffc0283d2c R08: 00000000000200ec R09: ffffffffffffffff
R10: dffffc0000000000 R11: ffffffff814fd3d0 R12: ffffffffc000f3d3
R13: 00000000000016ac R14: ffffffffc026ffac R15: ffffffffc0280fd4
 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
 poison_kmalloc_redzone mm/kasan/common.c:398 [inline]
 __kasan_kmalloc+0x72/0x90 mm/kasan/common.c:415
 kasan_kmalloc include/linux/kasan.h:263 [inline]
 __do_kmalloc_node mm/slub.c:5296 [inline]
 __kmalloc_noprof+0x237/0x6e0 mm/slub.c:5308
 <alloc::raw_vec::RawVecInner>::finish_grow+0x7d/0xb0 [kt_runtime]
 <alloc::raw_vec::RawVec<u8>>::grow_one+0x3f/0x70 [kt_runtime]
 __kerneltracker_log_integer_cmp_with_graph+0x174/0x590 [kt_runtime]
 mgag200_g200_init_registers drivers/gpu/drm/mgag200/mgag200_g200.c:48 [inline] [mgag200]
 mgag200_g200_device_create+0x55df/0x5a40 drivers/gpu/drm/mgag200/mgag200_g200.c:392 [mgag200]
 </TASK>

Allocated by task 814:
 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_node_noprof+0x1db/0x5e0 mm/slub.c:4951
 kmalloc_reserve net/core/skbuff.c:613 [inline]
 __alloc_skb+0x230/0x4a0 net/core/skbuff.c:713
 alloc_skb include/linux/skbuff.h:1385 [inline]
 alloc_uevent_skb+0x5c/0x120 lib/kobject_uevent.c:289
 uevent_net_broadcast_untagged lib/kobject_uevent.c:326 [inline]
 kobject_uevent_net_broadcast+0x23f/0x420 lib/kobject_uevent.c:410
 kobject_uevent_env+0x447/0x450 lib/kobject_uevent.c:611
 driver_register+0x1e2/0x220 drivers/base/driver.c:257
 drm_pci_register_driver_if_modeset+0x125/0xf20 drivers/gpu/drm/mgag200/mgag200_bmc.c:24 [mgag200]
 do_init_module+0x125/0x3f0 kernel/module/main.c:3106
 init_module_from_file kernel/module/main.c:3777 [inline]
 idempotent_init_module kernel/module/main.c:3789 [inline]
 __do_sys_finit_module kernel/module/main.c:3815 [inline]
 __se_sys_finit_module+0x2c7/0x410 kernel/module/main.c:3799
 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

Freed by task 135:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
 poison_slab_object mm/kasan/common.c:253 [inline]
 __kasan_slab_free+0x3a/0x60 mm/kasan/common.c:285
 kasan_slab_free include/linux/kasan.h:235 [inline]
 slab_free_hook mm/slub.c:2689 [inline]
 slab_free mm/slub.c:6251 [inline]
 kfree+0x1c1/0x550 mm/slub.c:6566
 skb_kfree_head net/core/skbuff.c:1075 [inline]
 skb_free_head net/core/skbuff.c:1087 [inline]
 skb_release_data+0x5a6/0x690 net/core/skbuff.c:1114
 skb_release_all net/core/skbuff.c:1189 [inline]
 __kfree_skb net/core/skbuff.c:1203 [inline]
 consume_skb+0x106/0x180 net/core/skbuff.c:1436
 netlink_recvmsg+0x3a9/0x570 net/netlink/af_netlink.c:1977
 sock_recvmsg_nosec net/socket.c:1138 [inline]
 sock_recvmsg+0x138/0x140 net/socket.c:1160
 ____sys_recvmsg+0xf5/0x280 net/socket.c:2919
 ___sys_recvmsg+0x117/0x300 net/socket.c:2961
 __sys_recvmsg net/socket.c:2994 [inline]
 __do_sys_recvmsg net/socket.c:3000 [inline]
 __se_sys_recvmsg net/socket.c:2997 [inline]
 __x64_sys_recvmsg+0xd5/0x170 net/socket.c:2997
 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

The buggy address belongs to the object at ffff888016428680
 which belongs to the cache skbuff_small_head of size 704
The buggy address is located 584 bytes inside of
 freed 704-byte region [ffff888016428680, ffff888016428940)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x16428
head: order:2 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x100000000000040(head|node=0|zone=1)
page_type: f5(slab)
raw: 0100000000000040 ffff888008b8adc0 dead000000000122 0000000000000000
raw: 0000000000000000 0000000800130013 00000000f5000000 0000000000000000
head: 0100000000000040 ffff888008b8adc0 dead000000000122 0000000000000000
head: 0000000000000000 0000000800130013 00000000f5000000 0000000000000000
head: 0100000000000002 ffffffffffffff01 00000000ffffffff 00000000ffffffff
head: ffff8880164291c0 0000000000000000 00000000ffffffff 0000000000000004
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff888016428780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff888016428800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888016428880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                              ^
 ffff888016428900: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
 ffff888016428980: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb

Regards,
Yang Zi
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help