[BUG] KASAN: use-after-free in mutex optimistic spin (owner_on_cpu) via sysfs uevent_show [bna] [syzkaller]
From: Yang Zi
Date: Sun Aug 09 2026 - 00:23:01 EST
Hi,
While fuzzing v5.15.212 with syzkaller (KASAN), we hit a use-after-free in the mutex
optimistic-spin path. Reading the `uevent` sysfs attribute of a bna NIC device takes
`device_lock()`; the spin can read the `on_cpu` field of a `task_struct`
that has already been RCU-freed.
Reproducer summary:
BUG: KASAN: use-after-free in owner_on_cpu include/linux/sched.h [inline]
BUG: KASAN: use-after-free in mutex_can_spin_on_owner kernel/locking/mutex.c:401 [inline]
BUG: KASAN: use-after-free in mutex_optimistic_spin+0x102/0x210 kernel/locking/mutex.c:445
Read of size 4 at addr ffff8880077c34 by task systemd-journal/5284
Call trace (systemd-journal/5284):
ksys_read -> vfs_read -> seq_read_iter -> sysfs_kf_seq_show
dev_attr_show drivers/base/core.c:2110
uevent_show drivers/base/core.c:2408
device_lock
__mutex_lock_common kernel/locking/mutex.c:599
mutex_optimistic_spin kernel/locking/mutex.c:445
mutex_can_spin_on_owner kernel/locking/mutex.c:401 <-- UAF Read (4B)
The victim is a `task_struct` (kmem_cache size 6400, offset 52 → `->on_cpu`)
freed via RCU by ksoftirqd (task 11, `rcu_do_batch->kmem_cache_free`) after a
usermodehelper thread exited (`put_task_struct_rcu_user` →
`wait_task_zombie`). `mutex_can_spin_on_owner()` still dereferences the stale
`lock->owner` pointer.
Root cause is identical to the known "mutex optimistic-spin owner lifetime"
issue: the optimistic-spin fast path reads `owner->on_cpu` with no
`get_task_struct()` / RCU-read-lock / `task_lock` protecting the owner pointer.
The crash report attached below:
BUG: KASAN: use-after-free in mutex_can_spin_on_owner kernel/locking/mutex.c:401 [inline]
BUG: KASAN: use-after-free in mutex_optimistic_spin+0x102/0x210 kernel/locking/mutex.c:445
Read of size 4 at addr ffff888007611a34 by task systemd-journal/5284
CPU: 0 PID: 5284 Comm: systemd-journal Tainted: G D W O 5.15.212 #1
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xa5/0xf0 lib/dump_stack.c:106
print_address_description+0x75/0x2b0 mm/kasan/report.c:248
__kasan_report mm/kasan/report.c:434 [inline]
kasan_report+0x106/0x160 mm/kasan/report.c:451
mutex_can_spin_on_owner kernel/locking/mutex.c:401 [inline]
mutex_optimistic_spin+0x102/0x210 kernel/locking/mutex.c:445
__mutex_lock_common+0x11f/0x1220 kernel/locking/mutex.c:599
__mutex_lock kernel/locking/mutex.c:729 [inline]
mutex_lock_nested+0x17/0x20 kernel/locking/mutex.c:743
device_lock include/linux/device.h:809 [inline]
uevent_show+0x103/0x220 drivers/base/core.c:2408
dev_attr_show+0x38/0xa0 drivers/base/core.c:2110
sysfs_kf_seq_show+0x1f1/0x310 fs/sysfs/file.c:61
seq_read_iter+0x2f9/0x910 fs/seq_file.c:230
call_read_iter include/linux/fs.h:2167 [inline]
new_sync_read fs/read_write.c:404 [inline]
vfs_read+0x651/0x780 fs/read_write.c:485
ksys_read+0xd9/0x190 fs/read_write.c:623
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x53/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6c/0xd6
RIP: 0033:0x7eff9fbdba61
Code: 00 48 8b 15 b9 73 0e 00 f7 d8 64 89 02 b8 ff ff ff ff eb bd e8 40 c4 01 00 f3 0f 1e fa 80 3d e5 f5 0e 00 00 74 13 31 c0 0f 05 <48> 3d 00 f0 ff ff 77 4f c3 66 0f 1f 44 00 00 55 48 89 e5 48 83 ec
RSP: 002b:00007ffd76160d18 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
RAX: ffffffffffffffda RBX: 0000000000001008 RCX: 00007eff9fbdba61
RDX: 0000000000001008 RSI: 000055b3db74fdb0 RDI: 0000000000000014
RBP: 00007ffd76160e20 R08: 00007eff9fcc3b20 R09: 0000000000000000
R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000014
R13: 0000000000001008 R14: ffffffffffffffff R15: 000055b3db74fdb0
</TASK>
Allocated by task 3073:
kasan_save_stack mm/kasan/common.c:38 [inline]
kasan_set_track mm/kasan/common.c:46 [inline]
set_alloc_info mm/kasan/common.c:434 [inline]
__kasan_slab_alloc+0x92/0xd0 mm/kasan/common.c:467
kasan_slab_alloc include/linux/kasan.h:254 [inline]
slab_post_alloc_hook+0x50/0x380 mm/slab.h:519
slab_alloc_node mm/slub.c:3225 [inline]
kmem_cache_alloc_node+0x140/0x260 mm/slub.c:3261
alloc_task_struct_node kernel/fork.c:173 [inline]
dup_task_struct+0x60/0x470 kernel/fork.c:896
copy_process+0x3e0/0x2250 kernel/fork.c:2122
kernel_clone+0x168/0x640 kernel/fork.c:2681
kernel_thread+0x66/0x90 kernel/fork.c:2733
call_usermodehelper_exec_sync kernel/umh.c:135 [inline]
call_usermodehelper_exec_work+0x7a/0x170 kernel/umh.c:166
process_one_work+0x5f6/0x980 kernel/workqueue.c:2310
worker_thread+0x54f/0xa30 kernel/workqueue.c:2457
kthread+0x295/0x2d0 kernel/kthread.c:334
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:287
Freed by task 11:
kasan_save_stack mm/kasan/common.c:38 [inline]
kasan_set_track+0x4b/0x80 mm/kasan/common.c:46
kasan_set_free_info+0x1f/0x40 mm/kasan/generic.c:360
____kasan_slab_free+0xfd/0x140 mm/kasan/common.c:366
kasan_slab_free include/linux/kasan.h:230 [inline]
slab_free_hook mm/slub.c:1710 [inline]
slab_free_freelist_hook+0xf3/0x180 mm/slub.c:1736
slab_free mm/slub.c:3504 [inline]
kmem_cache_free+0xab/0x210 mm/slub.c:3520
rcu_do_batch kernel/rcu/tree.c:2523 [inline]
rcu_core+0x5a1/0xc00 kernel/rcu/tree.c:2763
handle_softirqs+0x2b2/0x520 kernel/softirq.c:576
run_ksoftirqd+0x45/0x90 kernel/softirq.c:943
smpboot_thread_fn+0x2d9/0x410 kernel/smpboot.c:164
kthread+0x295/0x2d0 kernel/kthread.c:334
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:287
Last potentially related work creation:
kasan_save_stack+0x35/0x60 mm/kasan/common.c:38
kasan_record_aux_stack+0xb2/0xe0 mm/kasan/generic.c:348
__call_rcu kernel/rcu/tree.c:3011 [inline]
call_rcu+0x7d/0x650 kernel/rcu/tree.c:3091
wait_task_zombie kernel/exit.c:1183 [inline]
wait_consider_task+0x1071/0x1ad0 kernel/exit.c:1410
do_wait_pid kernel/exit.c:1541 [inline]
do_wait+0x432/0x6e0 kernel/exit.c:1583
kernel_wait+0x4e/0xc0 kernel/exit.c:1770
call_usermodehelper_exec_sync kernel/umh.c:139 [inline]
call_usermodehelper_exec_work+0x9c/0x170 kernel/umh.c:166
process_one_work+0x5f6/0x980 kernel/workqueue.c:2310
worker_thread+0x54f/0xa30 kernel/workqueue.c:2457
kthread+0x295/0x2d0 kernel/kthread.c:334
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:287
Second to last potentially related work creation:
kasan_save_stack+0x35/0x60 mm/kasan/common.c:38
kasan_record_aux_stack+0xb2/0xe0 mm/kasan/generic.c:348
__call_rcu kernel/rcu/tree.c:3011 [inline]
call_rcu+0x7d/0x650 kernel/rcu/tree.c:3091
wait_task_zombie kernel/exit.c:1183 [inline]
wait_consider_task+0x1071/0x1ad0 kernel/exit.c:1410
do_wait_pid kernel/exit.c:1541 [inline]
do_wait+0x432/0x6e0 kernel/exit.c:1583
kernel_wait+0x4e/0xc0 kernel/exit.c:1770
call_usermodehelper_exec_sync kernel/umh.c:139 [inline]
call_usermodehelper_exec_work+0x9c/0x170 kernel/umh.c:166
process_one_work+0x5f6/0x980 kernel/workqueue.c:2310
worker_thread+0x54f/0xa30 kernel/workqueue.c:2457
kthread+0x295/0x2d0 kernel/kthread.c:334
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:287
The buggy address belongs to the object at ffff888007611a00
which belongs to the cache task_struct of size 6400
The buggy address is located 52 bytes inside of
6400-byte region [ffff888007611a00, ffff888007613300)
The buggy address belongs to the page:
page:0000000025818919 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x7610
head:0000000025818919 order:3 compound_mapcount:0 compound_pincount:0
memcg:ffff88800d92ef81
flags: 0x100000000010200(slab|head|node=0|zone=1)
raw: 0100000000010200 dead000000000100 dead000000000122 ffff888006c00500
raw: 0000000000000000 0000000000040004 00000001ffffffff ffff88800d92ef81
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888007611900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888007611980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff888007611a00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff888007611a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888007611b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
Regards,
Yang Zi