diff mbox series

Bluetooth: Fix use-after-free bug caused by hci_cmd_timeout

Message ID 20240408144302.105777-1-duoming@zju.edu.cn
State New
Headers show
Series Bluetooth: Fix use-after-free bug caused by hci_cmd_timeout | expand

Commit Message

Duoming Zhou April 8, 2024, 2:43 p.m. UTC
If we send a command and the command is timeout, the hci_cmd_timeout()
will run. Then we use hci_sock_ioctl() to inquiry the command, it will
deallocate the req_skb. But the req_skb could be dereferenced in the
hci_cmd_timeout(). As a result, the use-after-free bug will happen.
The detail is shown below:

     thread 1                       thread2
hci_sock_ioctl()             | hci_sock_sendmsg()
 hci_inquiry()               |  queue_work(...,&hdev->cmd_work)
  hci_req_sync()             |   hci_cmd_work()
   __hci_req_sync()          |    queue_delayed_work(...,&hdev->cmd_timer)
    kfree_skb(hdev->req_skb) |     hci_cmd_timeout()
                             |      hci_skb_opcode(hdev->req_skb)

The KASan report for such a POC is shown below:

 ==================================================================
 BUG: KASAN: slab-use-after-free in hci_cmd_timeout+0x3c/0x110
 Read of size 2 at addr ffff8880087a1c78 by task kworker/u21:0/131
 ...
 Workqueue: hci0 hci_cmd_timeout
 Call Trace:
  <TASK>
  dump_stack_lvl+0x84/0xc0
  print_address_description+0x78/0x440
  print_report+0x11b/0x220
  ? pfn_valid+0xe4/0x140
  ? __virt_addr_valid+0x7c/0x90
  ? hci_cmd_timeout+0x3c/0x110
  kasan_report+0xc7/0x100
  ? hci_cmd_timeout+0x3c/0x110
  hci_cmd_timeout+0x3c/0x110
  process_one_work+0x2df/0x610
  worker_thread+0x72f/0x870
  ? pr_cont_work+0x280/0x280
  kthread+0x18a/0x1b0
  ? kthread_blkcg+0x50/0x50
  ret_from_fork+0x34/0x50
  ? kthread_blkcg+0x50/0x50
  ret_from_fork_asm+0x11/0x20
  </TASK>

 Allocated by task 131 on cpu 1 at 45.611537s:
  kasan_save_track+0x32/0x90
  __kasan_slab_alloc+0x4b/0x60
  kmem_cache_alloc+0xcb/0x240
  skb_clone+0x117/0x170
  hci_cmd_work+0x19c/0x2a0
  process_one_work+0x2df/0x610
  worker_thread+0x72f/0x870
  kthread+0x18a/0x1b0
  ret_from_fork+0x34/0x50
  ret_from_fork_asm+0x11/0x20

 Freed by task 135 on cpu 2 at 47.671850s:
  kasan_save_track+0x32/0x90
  kasan_save_free_info+0x40/0x50
  poison_slab_object+0x118/0x180
  __kasan_slab_free+0x12/0x30
  kmem_cache_free+0x92/0x200
  __hci_req_sync+0x2e2/0x350
  hci_req_sync+0x73/0x90
  hci_inquiry+0x1c1/0x350
  sock_do_ioctl+0x50/0x1a0
  sock_ioctl+0x2ea/0x3b0
  __se_sys_ioctl+0x89/0xd0
  do_syscall_64+0xc4/0x1b0
  entry_SYSCALL_64_after_hwframe+0x62/0x6a
  ...

In order to mitigate the bug, add cancel_delayed_work_sync() in
__hci_req_sync() to cancel the cmd_timer before the req_skb is
deallocated.

Fixes: 9afee94939e3 ("Bluetooth: Fix memory leak at end of hci requests")
Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
---
 net/bluetooth/hci_request.c | 1 +
 1 file changed, 1 insertion(+)
diff mbox series

Patch

diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 00e02138003..06692c71093 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -179,6 +179,7 @@  int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
 		break;
 	}
 
+	cancel_delayed_work_sync(&hdev->cmd_timer);
 	kfree_skb(hdev->req_skb);
 	hdev->req_skb = NULL;
 	hdev->req_status = hdev->req_result = 0;