[BUG] KASAN: slab-use-after-free in owner_on_cpu via iava_remove (mutex optimistic spin) [iavf] [syzkaller]

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

While fuzzing the kernel v7.1 with syzkaller (KASAN) we hit a slab-use-after-free on
the mutex optimistic-spin path during iava driver removal. The crash is a
Read of size 4 on the `on_cpu` field of a freed `task_struct`.

Reproducer summary:

    BUG: KASAN: slab-use-after-free in owner_on_cpu include/linux/sched.h:2257 [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_lock+0x129c/0x13a0 kernel/locking/mutex.c:820
    Read of size 4 at addr ffff88800a260034 by task syz.2.655/1932

Call trace:
  delete_module -> pci_unregister_driver -> __device_release_driver
   -> iava_remove -> netdev_lock() -> __mutex_lock -> mutex_optimistic_spin
   -> owner_on_cpu include/linux/sched.h:2257

The visited `task_struct` was released via RCU (see "Freed by ..." in the
report). `mutex_can_spin_on_owner()` reads `lock->owner` which still points at
the recycled task_struct; the optimistic-spin path does not hold a reference
on the owner, so the `READ_ONCE(owner->on_cpu)` can touch memory already
returned to the `task_struct` slab.

Root-cause hypothesis: the optimistic-spin owner pointer has no lifetime
protection (no `get_task_struct()` / RCU-read-side held while reading
`owner->on_cpu`). This matches the classic UAF race in the mutex spin path.

The crash report attached 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+0x129c/0x13a0 kernel/locking/mutex.c:820
Read of size 4 at addr ffff88800a260034 by task syz.2.665/1932

CPU: 0 UID: 0 PID: 1932 Comm: syz.2.665 Tainted: G      D             7.1.0 #1 PREEMPT(lazy) 
Tainted: [D]=DIE
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+0x129c/0x13a0 kernel/locking/mutex.c:820
 netdev_lock include/linux/netdevice.h:2818 [inline] [iavf]
 iavf_remove+0x103/0xf10 drivers/net/ethernet/intel/iavf/iavf_main.c:5523 [iavf]
 pci_device_remove+0x9d/0x240 drivers/pci/pci-driver.c:512
 device_remove drivers/base/dd.c:619 [inline]
 __device_release_driver drivers/base/dd.c:1352 [inline]
 device_release_driver_internal+0x48b/0x880 drivers/base/dd.c:1375
 driver_detach+0x1f3/0x2d0 drivers/base/dd.c:1438
 bus_remove_driver+0x21c/0x280 drivers/base/bus.c:825
 pci_unregister_driver+0x2d/0x140 drivers/pci/pci-driver.c:1502
 __do_sys_delete_module kernel/module/main.c:863 [inline]
 __se_sys_delete_module+0x285/0x420 kernel/module/main.c:804
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x143/0x470 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f7c72dec12d
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 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 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffdf2deced8 EFLAGS: 00000246 ORIG_RAX: 00000000000000b0
RAX: ffffffffffffffda RBX: 00007ffdf2ded010 RCX: 00007f7c72dec12d
RDX: 0000000000667661 RSI: 0000000000000000 RDI: 00007ffdf2ded020
RBP: 00007ffdf2ded2c0 R08: 000000000000001e R09: 00007ffdf2decf00
R10: 00007ffdf2ded2b0 R11: 0000000000000246 R12: 00007ffdf2ded2a0
R13: 00007ffdf2ded020 R14: 000000000000001e R15: 000000000000154c
 </TASK>

Allocated by task 41:
 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+0x1cc/0x5d0 mm/slub.c:4951
 alloc_task_struct_node kernel/fork.c:187 [inline]
 dup_task_struct+0x4e/0x5f0 kernel/fork.c:918
 copy_process+0x748/0x3db0 kernel/fork.c:2090
 kernel_clone+0x21e/0x730 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+0x9c/0x230 kernel/umh.c:163
 process_one_work kernel/workqueue.c:3314 [inline]
 process_scheduled_works+0x90f/0x12f0 kernel/workqueue.c:3397
 worker_thread+0x9f6/0xf50 kernel/workqueue.c:3478
 kthread+0x385/0x470 kernel/kthread.c:436
 ret_from_fork+0x390/0x7a0 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Freed by task 1879:
 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+0x175/0x5a0 mm/slub.c:6378
 rcu_do_batch kernel/rcu/tree.c:2617 [inline]
 rcu_core+0x6f1/0x1200 kernel/rcu/tree.c:2869
 handle_softirqs+0x21c/0x7a0 kernel/softirq.c:622
 __do_softirq kernel/softirq.c:656 [inline]
 invoke_softirq kernel/softirq.c:496 [inline]
 __irq_exit_rcu+0xb1/0x1c0 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+0x7d/0x870 kernel/rcu/tree.c:3251
 rcu_do_batch kernel/rcu/tree.c:2617 [inline]
 rcu_core+0x6f1/0x1200 kernel/rcu/tree.c:2869
 handle_softirqs+0x21c/0x7a0 kernel/softirq.c:622
 __do_softirq kernel/softirq.c:656 [inline]
 invoke_softirq kernel/softirq.c:496 [inline]
 __irq_exit_rcu+0xb1/0x1c0 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

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+0x7d/0x870 kernel/rcu/tree.c:3251
 put_task_struct_rcu_user kernel/exit.c:237 [inline]
 release_task+0x1099/0x1490 kernel/exit.c:307
 wait_task_zombie kernel/exit.c:1281 [inline]
 wait_consider_task+0x18b8/0x2d30 kernel/exit.c:1508
 do_wait_pid kernel/exit.c:1647 [inline]
 __do_wait+0x524/0x720 kernel/exit.c:1682
 do_wait+0x1c8/0x4b0 kernel/exit.c:1723
 kernel_wait+0x51/0xf0 kernel/exit.c:1899
 call_usermodehelper_exec_sync kernel/umh.c:136 [inline]
 call_usermodehelper_exec_work+0xbe/0x230 kernel/umh.c:163
 process_one_work kernel/workqueue.c:3314 [inline]
 process_scheduled_works+0x90f/0x12f0 kernel/workqueue.c:3397
 worker_thread+0x9f6/0xf50 kernel/workqueue.c:3478
 kthread+0x385/0x470 kernel/kthread.c:436
 ret_from_fork+0x390/0x7a0 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 ffff88800a260000
 which belongs to the cache task_struct of size 6720
The buggy address is located 52 bytes inside of
 freed 6720-byte region [ffff88800a260000, ffff88800a261a40)

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

Memory state around the buggy address:
 ffff88800a25ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff88800a25ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88800a260000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                     ^
 ffff88800a260080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff88800a260100: 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.