oss-sec mailing list archives
CVE-2022-1974: Linux kernel: use-after-free caused by improper check device_is_registered() in nfc netlink related functions
From: duoming () zju edu cn
Date: Sun, 5 Jun 2022 09:20:35 +0800 (GMT+08:00)
Hello there, There are use-after-free vulnerabilities in /net/nfc/core.c of linux that allow attacker to crash linux kernel by simulating nfc device from user-space. =*=*=*=*=*=*=*=*= Bug Details =*=*=*=*=*=*=*=*= The device_is_registered() in nfc core is used to check whether nfc device is registered in netlink related functions such as nfc_fw_download(), nfc_dev_up() and so on. Although device_is_registered() is protected by device_lock, there is still a race condition between device_del() and device_is_registered(). The root cause is that kobject_del() in device_del() is not protected by device_lock. (cleanup task) | (netlink task) | nfc_unregister_device | nfc_fw_download device_del | device_lock ... | if (!device_is_registered)//(1) kobject_del//(2) | ... ... | device_unlock The device_is_registered() returns the value of state_in_sysfs and the state_in_sysfs is set to zero in kobject_del(). If we pass check in position (1), then set zero in position (2). As a result, the check in position (1) is useless. One of the use-after-free vulnerabilities caused by this problem is shown below: (Free) | (Use) nfc_unregister_device | nfc_dev_up rfkill_destroy //(1) | ... ... | device_del | device_lock ... | if (!device_is_registered) kobject_del | ... | rfkill_blocked | spin_lock_irqsave(&rfkill->lock,..);//(2) ... | device_unlock The rfkill is deallocated is position(1) and use in position(2), which leads to use-after-free bug. =*=*=*=*=*=*=*=*= Bug Effects =*=*=*=*=*=*=*=*= We can successfully trigger the vulnerabilities to crash the linux kernel. The backtrace caused by use-after-free bug is shown below. [ 97.540761] ================================================================== [ 97.541238] BUG: KASAN: use-after-free in do_raw_spin_lock+0x66/0x1a0 [ 97.541525] Read of size 4 at addr ffff888006e68004 by task example/635 [ 97.541525] CPU: 0 PID: 635 Comm: example Not tainted 5.18.0-rc3-00849-gfc06b2867f4c-dirty #167 [ 97.541525] Call Trace: [ 97.541525] <TASK> [ 97.541525] dump_stack_lvl+0x57/0x7d [ 97.541525] print_report.cold+0x5e/0x5db [ 97.541525] ? do_raw_spin_lock+0x66/0x1a0 [ 97.541525] kasan_report+0xbe/0x1c0 [ 97.541525] ? do_raw_spin_lock+0x66/0x1a0 [ 97.541525] do_raw_spin_lock+0x66/0x1a0 [ 97.541525] ? rwlock_bug.part.0+0x50/0x50 [ 97.541525] ? lock_release+0x450/0x450 [ 97.541525] _raw_spin_lock_irqsave+0x41/0x50 [ 97.541525] ? rfkill_blocked+0xc/0x40 [ 97.541525] rfkill_blocked+0xc/0x40 [ 97.541525] nfc_dev_up+0x4c/0x140 [ 97.541525] nfc_genl_dev_up+0x46/0x70 [ 97.541525] genl_family_rcv_msg_doit+0x17a/0x200 [ 97.541525] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x130/0x130 [ 97.541525] ? mutex_lock_io_nested+0xb63/0xbd0 [ 97.541525] ? security_capable+0x48/0x60 [ 97.541525] genl_rcv_msg+0x18d/0x2c0 [ 97.541525] ? genl_get_cmd+0x1b0/0x1b0 [ 97.541525] ? rcu_read_lock_sched_held+0xd/0x70 [ 97.541525] ? nfc_genl_dev_down+0x70/0x70 [ 97.541525] ? rcu_read_lock_sched_held+0xd/0x70 [ 97.541525] ? lock_acquire+0xce/0x410 [ 97.541525] netlink_rcv_skb+0xc4/0x1f0 [ 97.541525] ? genl_get_cmd+0x1b0/0x1b0 [ 97.541525] ? netlink_ack+0x4d0/0x4d0 [ 97.541525] ? netlink_deliver_tap+0xf7/0x5a0 [ 97.541525] genl_rcv+0x1f/0x30 [ 97.541525] netlink_unicast+0x2d8/0x420 [ 97.541525] ? netlink_attachskb+0x430/0x430 [ 97.541525] netlink_sendmsg+0x3a9/0x6e0 [ 97.541525] ? netlink_unicast+0x420/0x420 [ 97.541525] ? netlink_unicast+0x420/0x420 [ 97.541525] sock_sendmsg+0x91/0xa0 [ 97.541525] __sys_sendto+0x168/0x200 [ 97.541525] ? __ia32_sys_getpeername+0x40/0x40 [ 97.541525] ? preempt_count_sub+0xf/0xb0 [ 97.541525] ? fd_install+0xfb/0x340 [ 97.541525] ? __sys_socket+0xf0/0x160 [ 97.541525] ? kernel_fpu_begin_mask+0x160/0x160 [ 97.541525] ? compat_sock_ioctl+0x410/0x410 [ 97.541525] ? rwlock_bug.part.0+0x50/0x50 [ 97.541525] __x64_sys_sendto+0x6f/0x80 [ 97.541525] do_syscall_64+0x3b/0x90 [ 97.541525] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 97.541525] RIP: 0033:0x7f4d46a9102c [ 97.541525] Code: 0a f8 ff ff 44 8b 4c 24 2c 4c 8b 44 24 20 89 c5 44 8b 54 24 28 48 8b 54 24 18 b8 2c 00 00 00 48 8b 74 24 10 8b 7c 24 08 0f 05 <48> 3b [ 97.541525] RSP: 002b:00007f4d460a8e10 EFLAGS: 00000293 ORIG_RAX: 000000000000002c [ 97.541525] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f4d46a9102c [ 97.541525] RDX: 000000000000001c RSI: 0000558ad8003090 RDI: 000000000000009d [ 97.541525] RBP: 0000000000000000 R08: 00007f4d460a8e8c R09: 000000000000000c [ 97.541525] R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffded880efe [ 97.541525] R13: 00007ffded880eff R14: 00007f4d460a8fc0 R15: 00007f4d460a9700 [ 97.541525] </TASK> [ 97.541525] [ 97.541525] Allocated by task 159: [ 97.541525] kasan_save_stack+0x1e/0x40 [ 97.541525] __kasan_kmalloc+0x81/0xa0 [ 97.541525] rfkill_alloc+0x6a/0x170 [ 97.541525] nfc_register_device+0x8d/0x110 [ 97.541525] nci_register_device+0x515/0x5e0 [ 97.541525] nfcmrvl_nci_register_dev+0x143/0x170 [ 97.541525] nfcmrvl_nci_uart_open+0x147/0x240 [ 97.541525] nci_uart_tty_ioctl+0x1c3/0x270 [ 97.541525] tty_ioctl+0x5f0/0xc70 [ 97.541525] __x64_sys_ioctl+0xb4/0xf0 [ 97.541525] do_syscall_64+0x3b/0x90 [ 97.541525] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 97.541525] [ 97.541525] Freed by task 636: [ 97.541525] kasan_save_stack+0x1e/0x40 [ 97.541525] kasan_set_track+0x21/0x30 [ 97.541525] kasan_set_free_info+0x20/0x30 [ 97.541525] __kasan_slab_free+0x108/0x170 [ 97.541525] kfree+0xb0/0x330 [ 97.541525] device_release+0x54/0xe0 [ 97.541525] kobject_put+0xa5/0x120 [ 97.541525] nfc_unregister_device+0x51/0x100 [ 97.541525] nfcmrvl_nci_unregister_dev+0x45/0x70 [ 97.541525] nci_uart_tty_close+0x87/0xd0 [ 97.541525] tty_ldisc_kill+0x3e/0x80 [ 97.541525] tty_ldisc_hangup+0x1b2/0x2c0 [ 97.541525] __tty_hangup.part.0+0x316/0x520 [ 97.541525] tty_release+0x200/0x670 [ 97.541525] __fput+0x110/0x410 [ 97.541525] task_work_run+0x86/0xd0 [ 97.541525] exit_to_user_mode_prepare+0x1aa/0x1b0 [ 97.541525] syscall_exit_to_user_mode+0x19/0x50 [ 97.541525] do_syscall_64+0x48/0x90 [ 97.541525] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 97.541525] [ 97.541525] Last potentially related work creation: [ 97.541525] kasan_save_stack+0x1e/0x40 [ 97.541525] __kasan_record_aux_stack+0x97/0xa0 [ 97.541525] insert_work+0x28/0x110 [ 97.541525] __queue_work+0x357/0x830 [ 97.541525] queue_work_on+0x76/0x80 [ 97.541525] rfkill_register+0x37a/0x4a0 [ 97.541525] nfc_register_device+0xb3/0x110 [ 97.541525] nci_register_device+0x515/0x5e0 [ 97.541525] nfcmrvl_nci_register_dev+0x143/0x170 [ 97.541525] nfcmrvl_nci_uart_open+0x147/0x240 [ 97.541525] nci_uart_tty_ioctl+0x1c3/0x270 [ 97.541525] tty_ioctl+0x5f0/0xc70 [ 97.541525] __x64_sys_ioctl+0xb4/0xf0 [ 97.541525] do_syscall_64+0x3b/0x90 [ 97.541525] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 97.541525] [ 97.541525] The buggy address belongs to the object at ffff888006e68000 [ 97.541525] which belongs to the cache kmalloc-2k of size 2048 [ 97.541525] The buggy address is located 4 bytes inside of [ 97.541525] 2048-byte region [ffff888006e68000, ffff888006e68800) [ 97.541525] [ 97.541525] The buggy address belongs to the physical page: [ 97.541525] page:00000000949930bb refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6e68 [ 97.541525] head:00000000949930bb order:3 compound_mapcount:0 compound_pincount:0 [ 97.541525] flags: 0x100000000010200(slab|head|node=0|zone=1) [ 97.541525] raw: 0100000000010200 0000000000000000 dead000000000122 ffff888006042f00 [ 97.541525] raw: 0000000000000000 0000000080080008 00000001ffffffff 0000000000000000 [ 97.541525] page dumped because: kasan: bad access detected [ 97.541525] [ 97.541525] Memory state around the buggy address: [ 97.541525] ffff888006e67f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 97.541525] ffff888006e67f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 97.541525] >ffff888006e68000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 97.541525] ^ [ 97.541525] ffff888006e68080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 97.541525] ffff888006e68100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 97.541525] ================================================================== =*=*=*=*=*=*=*=*= Bug Fix =*=*=*=*=*=*=*=*= The patch that have been applied to mainline Linux kernel is shown below. https://github.com/torvalds/linux/commit/da5c0f119203ad9728920456a0f52a6d850c01cd =*=*=*=*=*=*=*=*= Timeline =*=*=*=*=*=*=*=*= 2022-05-01: commit da5c0f119203 accepted to mainline kernel 2022-06-03: CVE-2022-1974 is assigned =*=*=*=*=*=*=*=*= Credit =*=*=*=*=*=*=*=*= Duoming Zhou <duoming () zju edu cn> Best Regards, Duoming Zhou
Current thread:
- CVE-2022-1974: Linux kernel: use-after-free caused by improper check device_is_registered() in nfc netlink related functions duoming (Jun 05)