oss-sec mailing list archives
Re: Linux kernel: UAF, null-ptr-deref and double-free vulnerabilities in nfcmrvl module
From: duoming () zju edu cn
Date: Thu, 9 Jun 2022 10:49:22 +0800 (GMT+08:00)
Hello, The cve-2022-1734 was assigned to this problem.
Hello there, There are double-free, use-after-free(write,read), null-ptr-deref vulnerabilities in drivers/nfc/nfcmrvl of linux that allow attacker to crash linux kernel by simulating nfc device from user-space. =*=*=*=*=*=*=*=*= Bug Details =*=*=*=*=*=*=*=*= There are destructive operations such as nfcmrvl_fw_dnld_abort and gpio_free in nfcmrvl_nci_unregister_dev. The resources such as firmware, gpio and so on could be destructed while the upper layer functions such as nfcmrvl_fw_dnld_start and nfcmrvl_nci_recv_frame is executing, which leads to double-free, use-after-free and null-ptr-deref bugs. There are three situations that could lead to double-free bugs. The first situation is shown below: (Thread 1) | (Thread 2) nfcmrvl_fw_dnld_start | ... | nfcmrvl_nci_unregister_dev release_firmware() | nfcmrvl_fw_dnld_abort kfree(fw) //(1) | fw_dnld_over | release_firmware ... | kfree(fw) //(2) | ... The second situation is shown below: (Thread 1) | (Thread 2) nfcmrvl_fw_dnld_start | ... | mod_timer | (wait a time) | fw_dnld_timeout | nfcmrvl_nci_unregister_dev fw_dnld_over | nfcmrvl_fw_dnld_abort release_firmware | fw_dnld_over kfree(fw) //(1) | release_firmware ... | kfree(fw) //(2) The third situation is shown below: (Thread 1) | (Thread 2) nfcmrvl_nci_recv_frame | if(..->fw_download_in_progress)| nfcmrvl_fw_dnld_recv_frame | queue_work | | fw_dnld_rx_work | nfcmrvl_nci_unregister_dev fw_dnld_over | nfcmrvl_fw_dnld_abort release_firmware | fw_dnld_over kfree(fw) //(1) | release_firmware | kfree(fw) //(2) The firmware struct is deallocated in position (1) and deallocated in position (2) again. What's more, there are also use-after-free and null-ptr-deref bugs in nfcmrvl_fw_dnld_start. One of the use-after-free bugs about firmware is shown below: (Use Thread) | (Free Thread ) nfcmrvl_fw_dnld_start | | nfcmrvl_nci_unregister_dev | nfcmrvl_fw_dnld_abort ... | fw_dnld_over | release_firmware | kfree(fw) //(1) priv->fw_dnld.fw->data;//(2)| ... One of the use-after-free bugs about gpio is shown below: (Use Thread) | (Free Thread ) nfcmrvl_fw_dnld_start | | nfcmrvl_nci_unregister_dev ... | ... | gpio_free //(1) nfcmrvl_chip_reset | ... gpio_set_value //(2) | One of the null-ptr-deref bugs about firmware is shown below: (Use Thread) | (Free Thread ) nfcmrvl_fw_dnld_start | | nfcmrvl_nci_unregister_dev | nfcmrvl_fw_dnld_abort ... | fw_dnld_over | priv->fw_dnld.fw = NULL;//(1) | priv->fw_dnld.fw->data;//(2)| ... If we deallocate firmware struct, gpio or set null to the members of priv->fw_dnld in position(1), then, we dereference firmware, gpio or the members of priv->fw_dnld in position(2), the UAF or NPD bugs will happen. =*=*=*=*=*=*=*=*= Bug Effects =*=*=*=*=*=*=*=*= We can successfully trigger the vulnerabilities to crash the linux kernel. (1) One of the backtraces caused by use-after-free(write) bug is shown below. [ 138.280382] BUG: KASAN: use-after-free in _request_firmware+0x52/0x690 [ 138.280382] Write of size 8 at addr ffff88800c114850 by task download/11174 [ 138.280382] Call Trace: [ 138.280382] <TASK> [ 138.280382] dump_stack_lvl+0x57/0x7d [ 138.280382] print_report.cold+0x5e/0x5db [ 138.280382] ? _request_firmware+0x52/0x690 [ 138.280382] kasan_report+0xbe/0x1c0 [ 138.280382] ? _request_firmware+0x52/0x690 [ 138.280382] _request_firmware+0x52/0x690 [ 138.280382] request_firmware+0x2d/0x50 [ 138.280382] nfcmrvl_fw_dnld_start+0x7a/0xb0 [ 138.280382] nfc_fw_download+0x92/0xe0 [ 138.280382] nfc_genl_fw_download+0x10b/0x170 [ 138.280382] ? nfc_genl_enable_se+0xa0/0xa0 [ 138.280382] ? __kasan_slab_alloc+0x2c/0x80 [ 138.280382] ? __nla_parse+0x22/0x30 [ 138.280382] ? genl_family_rcv_msg_attrs_parse.constprop.0+0xd3/0x130 [ 138.280382] genl_family_rcv_msg_doit+0x17a/0x200 [ 138.280382] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x130/0x130 [ 138.280382] ? mutex_lock_io_nested+0xb63/0xbd0 [ 138.280382] ? security_capable+0x48/0x60 [ 138.280382] genl_rcv_msg+0x18d/0x2c0 [ 138.280382] ? genl_get_cmd+0x1b0/0x1b0 [ 138.280382] ? rcu_read_lock_sched_held+0xd/0x70 [ 138.280382] ? nfc_genl_enable_se+0xa0/0xa0 [ 138.280382] ? rcu_read_lock_sched_held+0xd/0x70 [ 138.280382] ? lock_acquire+0xce/0x410 [ 138.280382] netlink_rcv_skb+0xc4/0x1f0 [ 138.280382] ? genl_get_cmd+0x1b0/0x1b0 [ 138.280382] ? netlink_ack+0x4d0/0x4d0 [ 138.280382] ? netlink_deliver_tap+0xf7/0x5a0 [ 138.280382] genl_rcv+0x1f/0x30 [ 138.280382] netlink_unicast+0x2d8/0x420 [ 138.280382] ? netlink_attachskb+0x430/0x430 [ 138.280382] netlink_sendmsg+0x3a9/0x6e0 [ 138.280382] ? netlink_unicast+0x420/0x420 [ 138.280382] ? netlink_unicast+0x420/0x420 [ 138.280382] sock_sendmsg+0x91/0xa0 [ 138.280382] __sys_sendto+0x168/0x200 [ 138.280382] ? __ia32_sys_getpeername+0x40/0x40 [ 138.280382] ? preempt_count_sub+0xf/0xb0 [ 138.280382] ? fd_install+0xfb/0x340 [ 138.280382] ? __sys_socket+0xf0/0x160 [ 138.280382] ? __x64_sys_clock_nanosleep+0x195/0x220 [ 138.280382] ? compat_sock_ioctl+0x410/0x410 [ 138.280382] __x64_sys_sendto+0x6f/0x80 [ 138.280382] do_syscall_64+0x3b/0x90 [ 138.280382] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 138.280382] RIP: 0033:0x7ff12ac0602c [ 138.280382] Code: 0a f8 ff ff 44 8b 4c 24 2c 4c 8b 44 24 20 89 c5 44 8b 54 2b [ 138.280382] RSP: 002b:00007ff12aa1ee00 EFLAGS: 00000293 ORIG_RAX: 0000000000c [ 138.280382] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007ff12ac0602c [ 138.280382] RDX: 000000000000002c RSI: 000055eab88030b0 RDI: 0000000000000000 [ 138.280382] RBP: 0000000000000000 R08: 00007ff12aa1ee7c R09: 000000000000000c [ 138.280382] R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffca74ba00e [ 138.280382] R13: 00007ffca74ba00f R14: 00007ff12aa1efc0 R15: 00007ff12aa1f700 (2) One of the backtraces caused by use-after-free(read) bug is shown below. [ 65.835462] BUG: KASAN: use-after-free in nci_fw_download+0x26/0x60 [ 65.840236] Read of size 8 at addr ffff88800c2f5008 by task download/160 [ 65.845755] Call Trace: [ 65.845755] <TASK> [ 65.845755] dump_stack_lvl+0x57/0x7d [ 65.845755] print_report.cold+0x5e/0x5db [ 65.845755] ? nci_fw_download+0x26/0x60 [ 65.845755] kasan_report+0xbe/0x1c0 [ 65.856061] ? nfc_driver_failure+0x90/0xa0 [ 65.856235] ? nci_fw_download+0x26/0x60 [ 65.856235] nci_fw_download+0x26/0x60 [ 65.856235] nfc_fw_download+0x99/0xe0 [ 65.856235] nfc_genl_fw_download+0x10b/0x170 [ 65.861189] ? nfc_genl_enable_se+0xa0/0xa0 [ 65.861189] ? __kasan_slab_alloc+0x2c/0x80 [ 65.861189] ? __nla_parse+0x22/0x30 [ 65.865988] ? genl_family_rcv_msg_attrs_parse.constprop.0+0xd3/0x130 [ 65.865988] genl_family_rcv_msg_doit+0x17a/0x200 [ 65.865988] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x130/0x130 [ 65.870892] ? asm_spurious_interrupt+0x3/0x30 [ 65.870892] ? security_capable+0x48/0x60 [ 65.870892] genl_rcv_msg+0x18d/0x2c0 [ 65.870892] ? genl_get_cmd+0x1b0/0x1b0 [ 65.870892] ? rcu_read_lock_sched_held+0xd/0x70 [ 65.875946] ? nfc_genl_enable_se+0xa0/0xa0 [ 65.875946] ? rcu_read_lock_sched_held+0xd/0x70 [ 65.875946] ? lock_acquire+0xce/0x410 [ 65.875946] netlink_rcv_skb+0xc4/0x1f0 [ 65.880842] ? genl_get_cmd+0x1b0/0x1b0 [ 65.881778] ? netlink_ack+0x4d0/0x4d0 [ 65.881778] ? netlink_deliver_tap+0xf7/0x5a0 [ 65.881778] genl_rcv+0x1f/0x30 [ 65.881778] netlink_unicast+0x2d8/0x420 [ 65.885734] ? netlink_attachskb+0x430/0x430 [ 65.887472] netlink_sendmsg+0x3a9/0x6e0 [ 65.887472] ? netlink_unicast+0x420/0x420 [ 65.887472] ? netlink_unicast+0x420/0x420 [ 65.887472] sock_sendmsg+0x91/0xa0 [ 65.891949] __sys_sendto+0x168/0x200 [ 65.893134] ? __ia32_sys_getpeername+0x40/0x40 [ 65.893134] ? lockdep_hardirqs_on_prepare+0xe/0x220 [ 65.893134] ? __schedule+0x5c5/0x1180 [ 65.893134] ? io_schedule_timeout+0xb0/0xb0 [ 65.897936] ? clockevents_program_event+0xd3/0x130 [ 65.897936] ? hrtimer_interrupt+0x332/0x350 [ 65.897936] __x64_sys_sendto+0x6f/0x80 [ 65.897936] do_syscall_64+0x3b/0x90 [ 65.897936] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 65.902930] RIP: 0033:0x7f96173ec02c [ 65.902930] 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> 3d 00 fb [ 65.908959] RSP: 002b:00007f9617204df0 EFLAGS: 00000293 ORIG_RAX: 000000000000002c [ 65.908959] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f96173ec02c [ 65.908959] RDX: 0000000000000034 RSI: 0000556fa2a030b0 RDI: 0000000000000003 [ 65.908959] RBP: 0000000000000000 R08: 00007f9617204e6c R09: 000000000000000c [ 65.915542] R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffde78477ee [ 65.916990] R13: 00007ffde78477ef R14: 00007f9617204fc0 R15: 00007f9617205700 (3) One of the backtraces caused by double-free bug is shown below. [ 122.640457] BUG: KASAN: double-free or invalid-free in fw_dnld_over+0x28/0xf0 [ 122.640457] Call Trace: [ 122.640457] <TASK> [ 122.640457] dump_stack_lvl+0x57/0x7d [ 122.640457] print_report.cold+0x5e/0x5db [ 122.640457] ? fw_dnld_over+0x28/0xf0 [ 122.640457] ? fw_dnld_over+0x28/0xf0 [ 1re22.640457] kasan_report_invalid_free+0x90/0x180 [ 122.640457] ? refcount_warn_saturate+0x40/0x110 [ 122.640457] ? fw_dnld_over+0x28/0xf0 [ 122.640457] __kasan_slab_free+0x152/0x170 [ 122.640457] ? fw_dnld_over+0x28/0xf0 [ 122.640457] kfree+0xb0/0x330 [ 122.640457] fw_dnld_over+0x28/0xf0 [ 122.640457] nfcmrvl_nci_unregister_dev+0x61/0x70 [ 122.640457] nci_uart_tty_close+0x87/0xd0 [ 122.640457] tty_ldisc_kill+0x3e/0x80 [ 122.640457] tty_ldisc_hangup+0x1b2/0x2c0 [ 122.640457] __tty_hangup.part.0+0x316/0x520 [ 122.640457] tty_release+0x200/0x670 [ 122.640457] __fput+0x110/0x410 [ 122.640457] ? _raw_spin_unlock_irq+0x1f/0x40 [ 122.640457] task_work_run+0x86/0xd0 [ 122.640457] exit_to_user_mode_prepare+0x1aa/0x1b0 [ 122.640457] syscall_exit_to_user_mode+0x19/0x50 [ 122.640457] do_syscall_64+0x48/0x90 [ 122.640457] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 122.640457] RIP: 0033:0x7f68433f6beb [ 122.640457] Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 84 [ 122.640457] RSP: 002b:00007f684320fee0 EFLAGS: 00000293 ORIG_RAX: 00000000003 [ 122.640457] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00007f68433f6beb [ 122.640457] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 [ 122.640457] RBP: 00007f684320ff00 R08: 0000000000000000 R09: 00007f6843210700 [ 122.640457] R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffd5d6f9fde [ 122.640457] R13: 00007ffd5d6f9fdf R14: 00007f684320ffc0 R15: 00007f6843210700 (4) One of the backtraces caused by null-ptr-deref bug is shown below. [ 80.495478] BUG: KASAN: null-ptr-deref in nfcmrvl_fw_dnld_start.cold+0x19/0x276 [ 80.498745] Read of size 8 at addr 0000000000000008 by task download/161 [ 80.502308] Call Trace: [ 80.502308] <TASK> [ 80.502308] dump_stack_lvl+0x57/0x7d [ 80.502308] kasan_report+0xbe/0x1c0 [ 80.502308] ? nfcmrvl_fw_dnld_start.cold+0x19/0x276 [ 80.502308] nfcmrvl_fw_dnld_start.cold+0x19/0x276 [ 80.508210] ? nfc_fw_download+0x79/0xe0 [ 80.508210] nfc_fw_download+0x99/0xe0 [ 80.508210] nfc_genl_fw_download+0x10b/0x170 [ 80.508210] ? nfc_genl_enable_se+0xa0/0xa0 [ 80.508210] ? __kasan_slab_alloc+0x2c/0x80 [ 80.508210] ? __nla_parse+0x22/0x30 [ 80.508210] ? genl_family_rcv_msg_attrs_parse.constprop.0+0xd3/0x130 [ 80.508210] genl_family_rcv_msg_doit+0x17a/0x200 [ 80.508210] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x130/0x130 [ 80.513085] ? mutex_lock_io_nested+0xb43/0xbd0 [ 80.513085] ? security_capable+0x48/0x60 [ 80.513085] genl_rcv_msg+0x18d/0x2c0 [ 80.513085] ? genl_get_cmd+0x1b0/0x1b0 [ 80.513085] ? rcu_read_lock_sched_held+0xd/0x70 [ 80.513085] ? nfc_genl_enable_se+0xa0/0xa0 [ 80.513085] ? rcu_read_lock_sched_held+0xd/0x70 [ 80.513085] ? lock_acquire+0xce/0x410 [ 80.513085] netlink_rcv_skb+0xc4/0x1f0 [ 80.513085] ? genl_get_cmd+0x1b0/0x1b0 [ 80.518420] ? netlink_ack+0x4d0/0x4d0 [ 80.518420] ? netlink_deliver_tap+0xf7/0x5a0 [ 80.518420] genl_rcv+0x1f/0x30 [ 80.518420] netlink_unicast+0x2d8/0x420 [ 80.518420] ? netlink_attachskb+0x430/0x430 [ 80.518420] netlink_sendmsg+0x3a9/0x6e0 [ 80.518420] ? netlink_unicast+0x420/0x420 [ 80.518420] ? netlink_unicast+0x420/0x420 [ 80.518420] sock_sendmsg+0x91/0xa0 [ 80.518420] __sys_sendto+0x168/0x200 [ 80.523005] ? __ia32_sys_getpeername+0x40/0x40 [ 80.523005] ? preempt_count_sub+0xf/0xb0 [ 80.523005] ? fd_install+0xfb/0x340 [ 80.523005] ? __sys_socket+0xf0/0x160 [ 80.523005] ? compat_sock_ioctl+0x410/0x410 [ 80.523005] __x64_sys_sendto+0x6f/0x80 [ 80.523005] do_syscall_64+0x3b/0x90 [ 80.523005] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 80.523005] RIP: 0033:0x7f30f54f402c [ 80.523005] 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 2b [ 80.528021] RSP: 002b:00007f30f530cdf0 EFLAGS: 00000293 ORIG_RAX: 000000000000002c [ 80.528021] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f30f54f402c [ 80.528021] RDX: 0000000000000034 RSI: 00005571766030b0 RDI: 0000000000000005 [ 80.533650] RBP: 0000000000000000 R08: 00007f30f530ce6c R09: 000000000000000c [ 80.533650] R10: 0000000000000000 R11: 0000000000000293 R12: 00007ffd9c6c6cee [ 80.533650] R13: 00007ffd9c6c6cef R14: 00007f30f530cfc0 R15: 00007f30f530d700 =*=*=*=*=*=*=*=*= Bug Fix =*=*=*=*=*=*=*=*= The patch that have been applied to mainline Linux kernel is shown below. https://github.com/torvalds/linux/commit/d270453a0d9ec10bb8a802a142fb1b3601a83098 =*=*=*=*=*=*=*=*= Timeline =*=*=*=*=*=*=*=*= 2022-05-01: commit d270453a0d9e accepted to mainline kernel 2022-06-05: send an email to secalert () redhat com in order to request CVE number =*=*=*=*=*=*=*=*= Credit =*=*=*=*=*=*=*=*= Duoming Zhou <duoming () zju edu cn>
Best Regards, Duoming Zhou
Current thread:
- Linux kernel: UAF, null-ptr-deref and double-free vulnerabilities in nfcmrvl module duoming (Jun 05)
- Re: Linux kernel: UAF, null-ptr-deref and double-free vulnerabilities in nfcmrvl module Salvatore Bonaccorso (Jun 05)
- Re: Linux kernel: UAF, null-ptr-deref and double-free vulnerabilities in nfcmrvl module duoming (Jun 09)