[BUG] KASAN: slab-use-after-free in mutex optimistic spin via dw_edma_pcie driver register [dw-edma-pcie] [syzkaller]

Yang Zi <[email protected]>
Newsgroups gmane.linux.kernel
Message-ID <[email protected]>
Hi,

While fuzzing v7.1 with syzkaller (KASAN), we triggered a slab-use-after-free in
the mutex optimistic-spin path: `owner_on_cpu()` read the `on_cpu` field of a
`task_struct` that had already been RCU-freed.

Reproducer summary:

    BUG: KASAN: slab-use-after-free in owner_on_cpu include/linux/sched.h:2351 [inline]
    BUG: KASAN: slab-use-after-free in mutex_can_spin_on_owner kernel/locking/mutex.c:442 [inline]
    BUG: KASAN: slab-use-after-free in mutex_optimistic_spin kernel/locking/mutex.c:485 [inline]
    BUG: KASAN: slab-use-after-free in __mutex_lock kernel/locking/mutex.c:820
    Read of size 4 at addr ffff88800c5ad1f4 by task syz.0.1/1163

    Call trace (syz.0.1/1163):
      __do_sys_finit_module  kernel/module/main.c:3815
      do_init_module         kernel/module/main.c:3106
      driver_register        drivers/base/driver.c:249
      bus_add_driver         drivers/base/bus.c:756
      bus_for_each_dev       drivers/base/bus.c:383
      __driver_attach        drivers/base/dd.c:1294
      device_lock
      __mutex_lock           kernel/locking/mutex.c:820
      mutex_optimistic_spin  kernel/locking/mutex.c:485
      owner_on_cpu           include/linux/sched.h:2351   <-- UAF Read (4B)

The victim is a `task_struct` (kmem_cache size 6720, offset 52 → `->on_cpu`)
whose holder was released via RCU (`call_rcu` → `rcu_do_batch` →
`kmem_cache_free`, triggered by `put_task_struct_rcu_user` on a usermodehelper
thread exit). `mutex_can_spin_on_owner()` reads `lock->owner` still pointing at
that freed task_struct; the optimistic-spin path dereferences `owner->on_cpu`
without holding a reference to `owner`.

Root cause: the mutex optimistic-spin path dereferences the `owner` task_struct
(the `owner_on_cpu()` READ) without any lifetime protection - no
`get_task_struct()` / refcount, no RCU read lock, no `task_lock` held for the
owner pointer taken by `__mutex_owner()` in `mutex_can_spin_on_owner()` /
`mutex_spin_on_owner()`.

The crash report shows below:

BUG: KASAN: slab-use-after-free in owner_on_cpu include/linux/sched.h:2351 [inline]
BUG: KASAN: slab-use-after-free in mutex_can_spin_on_owner kernel/locking/mutex.c:442 [inline]
BUG: KASAN: slab-use-after-free in mutex_optimistic_spin kernel/locking/mutex.c:485 [inline]
BUG: KASAN: slab-use-after-free in __mutex_lock_common kernel/locking/mutex.c:650 [inline]
BUG: KASAN: slab-use-after-free in __mutex_lock+0x196/0x1010 kernel/locking/mutex.c:820
Read of size 4 at addr ffff88800c5ad1f4 by task syz.0.1/1163

CPU: 0 UID: 0 PID: 1163 Comm: syz.0.1 Tainted: G      D W  O        7.1.0 #2 PREEMPT(lazy) 
Tainted: [D]=DIE, [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:
 <TASK>
 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
 owner_on_cpu include/linux/sched.h:2351 [inline]
 mutex_can_spin_on_owner kernel/locking/mutex.c:442 [inline]
 mutex_optimistic_spin kernel/locking/mutex.c:485 [inline]
 __mutex_lock_common kernel/locking/mutex.c:650 [inline]
 __mutex_lock+0x196/0x1010 kernel/locking/mutex.c:820
 device_lock include/linux/device.h:1040 [inline]
 __device_driver_lock drivers/base/dd.c:1174 [inline]
 __driver_attach+0x2ba/0x3b0 drivers/base/dd.c:1294
 bus_for_each_dev+0x182/0x1f0 drivers/base/bus.c:383
 bus_add_driver+0x253/0x430 drivers/base/bus.c:756
 driver_register+0x162/0x220 drivers/base/driver.c:249
 do_one_initcall+0x157/0x4a0 init/main.c:1392
 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
RIP: 0033:0x7f66f3ab93dd
Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fffa6323918 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
RAX: ffffffffffffffda RBX: 00007fffa6323bc0 RCX: 00007f66f3ab93dd
RDX: 0000000000000000 RSI: 00007fffa6323c90 RDI: 0000000000000003
RBP: 0000000000000003 R08: 0000000000000000 R09: 00007fffa6323a80
R10: 00007fffa6323a20 R11: 0000000000000246 R12: 00007fffa6323c80
R13: 00007fffa6323a20 R14: 000055558f24c4a8 R15: 00007fffa6323980
 </TASK>

Allocated by task 27:
 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
 alloc_task_struct_node kernel/fork.c:187 [inline]
 dup_task_struct+0x4c/0x3b0 kernel/fork.c:918
 copy_process+0x5ab/0x26d0 kernel/fork.c:2090
 kernel_clone+0x1bb/0x540 kernel/fork.c:2722
 user_mode_thread+0x6f/0xa0 kernel/fork.c:2798
 call_usermodehelper_exec_sync kernel/umh.c:132 [inline]
 call_usermodehelper_exec_work+0x7f/0x170 kernel/umh.c:163
 process_one_work kernel/workqueue.c:3314 [inline]
 process_scheduled_works+0x6f8/0xde0 kernel/workqueue.c:3397
 worker_thread+0x588/0x810 kernel/workqueue.c:3478
 kthread+0x284/0x2e0 kernel/kthread.c:436
 ret_from_fork+0x337/0x5f0 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Freed by task 1145:
 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]
 kmem_cache_free+0x1a4/0x560 mm/slub.c:6378
 rcu_do_batch kernel/rcu/tree.c:2617 [inline]
 rcu_core+0x6cc/0xfa0 kernel/rcu/tree.c:2869
 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
 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:697

Last potentially related work creation:
 kasan_save_stack+0x3e/0x60 mm/kasan/common.c:57
 kasan_record_aux_stack+0x99/0xb0 mm/kasan/generic.c:556
 __call_rcu_common kernel/rcu/tree.c:3131 [inline]
 call_rcu+0x4e/0x5d0 kernel/rcu/tree.c:3251
 rcu_do_batch kernel/rcu/tree.c:2617 [inline]
 rcu_core+0x6cc/0xfa0 kernel/rcu/tree.c:2869
 handle_softirqs+0x1a2/0x560 kernel/softirq.c:622
 run_ksoftirqd+0x2a/0x60 kernel/softirq.c:1076
 smpboot_thread_fn+0x447/0x680 kernel/smpboot.c:160
 kthread+0x284/0x2e0 kernel/kthread.c:436
 ret_from_fork+0x337/0x5f0 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Second to last potentially related work creation:
 kasan_save_stack+0x3e/0x60 mm/kasan/common.c:57
 kasan_record_aux_stack+0x99/0xb0 mm/kasan/generic.c:556
 __call_rcu_common kernel/rcu/tree.c:3131 [inline]
 call_rcu+0x4e/0x5d0 kernel/rcu/tree.c:3251
 put_task_struct_rcu_user kernel/exit.c:237 [inline]
 release_task+0xbd0/0xd30 kernel/exit.c:307
 wait_task_zombie kernel/exit.c:1281 [inline]
 wait_consider_task+0x10a8/0x1b00 kernel/exit.c:1508
 do_wait_pid kernel/exit.c:1647 [inline]
 __do_wait+0x2fa/0x4b0 kernel/exit.c:1682
 do_wait+0x179/0x2d0 kernel/exit.c:1723
 kernel_wait+0x51/0xc0 kernel/exit.c:1899
 call_usermodehelper_exec_sync kernel/umh.c:136 [inline]
 call_usermodehelper_exec_work+0xa1/0x170 kernel/umh.c:163
 process_one_work kernel/workqueue.c:3314 [inline]
 process_scheduled_works+0x6f8/0xde0 kernel/workqueue.c:3397
 worker_thread+0x588/0x810 kernel/workqueue.c:3478
 kthread+0x284/0x2e0 kernel/kthread.c:436
 ret_from_fork+0x337/0x5f0 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

The buggy address belongs to the object at ffff88800c5ad1c0
 which belongs to the cache task_struct of size 6720
The buggy address is located 52 bytes inside of
 freed 6720-byte region [ffff88800c5ad1c0, ffff88800c5aec00)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xc5a8
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
memcg:ffff88800c5aed01
flags: 0x100000000000040(head|node=0|zone=1)
page_type: f5(slab)
raw: 0100000000000040 ffff888008856640 dead000000000100 dead000000000122
raw: 0000000000000000 0000000800040004 00000000f5000000 ffff88800c5aed01
head: 0100000000000040 ffff888008856640 dead000000000100 dead000000000122
head: 0000000000000000 0000000800040004 00000000f5000000 ffff88800c5aed01
head: 0100000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000008
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff88800c5ad080: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
 ffff88800c5ad100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88800c5ad180: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb
                                                             ^
 ffff88800c5ad200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff88800c5ad280: 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.