[BUG] KASAN: use-after-free in mutex optimistic spin (owner_on_cpu) via sysfs uevent_show [bna] [syzkaller]

Yang Zi <[email protected]>
Newsgroups gmane.linux.kernel
Message-ID <[email protected]>
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
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.