Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Date: Sun, 5 Jun 2022 09:20:35 +0800 (GMT+08:00)
From: duoming@....edu.cn
To: oss-security@...ts.openwall.com
Subject: CVE-2022-1974: Linux kernel: use-after-free caused by improper check
 device_is_registered() in nfc netlink related functions

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@....edu.cn>

Best Regards,
Duoming Zhou

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.