Thread (2 messages) 2 messages, 2 authors, 8h ago
HOTtoday REVIEWED: 1 (0M)

[PATCH] Bluetooth: hci_event: Synchronously cancel timers in hci_cmd_complete_evt()

From: Sungwoo Kim <hidden>
Date: 2026-06-19 00:43:35
Also in: lkml
Subsystem: bluetooth subsystem, the rest · Maintainers: Marcel Holtmann, Luiz Augusto von Dentz, Linus Torvalds

RFC only.

hci_cmd_complete_evt() and hci_cmd_timeout can interleave, leading to
user-after-free access.

CPU1                  CPU2
hci_cmd_timeout()
                      hci_event_packet()
                      [snip]
                        hci_cmd_complete_evt()
                          handle_cmd_cnt_and_timer()
                            // this is asynchronous
                            cancel_delayed_work(&hdev->cmd_timer)
                        hci_cmd_sync_complete()
                          kfree_skb(hdev->req_skb); // free
  hci_skb_opcode(hdev->req_skb); // use-after-free

To fix this, make cancel_delayed_work() synchronous so it can wait for
the timeout handler.
However, this is not a complete fix because hci_cmd_timeout() resets the
device and queue a new command.
I would like to request for comments the better way to fix this issue.

KASAN splat:
BUG: KASAN: slab-use-after-free in hci_cmd_timeout+0x216/0x260 net/bluetooth/hci_core.c:1432
Read of size 2 at addr ffff88811605a7b8 by task syz.2.21760/74233

Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:94 [inline]
 dump_stack_lvl+0xba/0x110 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0x157/0x4c9 mm/kasan/report.c:482
 kasan_report+0xdf/0x1b0 mm/kasan/report.c:595
 hci_cmd_timeout+0x216/0x260 net/bluetooth/hci_core.c:1432
[snip]

Freed by task 4563:
[snip]
 kfree_skb include/linux/skbuff.h:1333 [inline]
 hci_cmd_sync_complete net/bluetooth/hci_sync.c:36 [inline]
 hci_cmd_sync_complete+0x152/0x370 net/bluetooth/hci_sync.c:24
 hci_event_packet+0x8fd/0xd20 net/bluetooth/hci_event.c:7863
 hci_rx_work+0x5c5/0xfa0 net/bluetooth/hci_core.c:4041
 process_one_work+0x93f/0x1810 kernel/workqueue.c:3316
[snip]

Fixes: ecb71f256667 ("Bluetooth: Fix race condition in handling NOP command")
Acked-by: Dave Tian <redacted>
Signed-off-by: Sungwoo Kim <redacted>
---
 net/bluetooth/hci_event.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index eea2f810aafa..3639aa896bc3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3765,14 +3765,14 @@ static void hci_remote_features_evt(struct hci_dev *hdev, void *data,
 	hci_dev_unlock(hdev);
 }
 
-static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd)
+static inline void handle_cmd_cnt_and_timer_sync(struct hci_dev *hdev, u8 ncmd)
 {
-	cancel_delayed_work(&hdev->cmd_timer);
+	cancel_delayed_work_sync(&hdev->cmd_timer);
 
 	rcu_read_lock();
 	if (!test_bit(HCI_RESET, &hdev->flags)) {
 		if (ncmd) {
-			cancel_delayed_work(&hdev->ncmd_timer);
+			cancel_delayed_work_sync(&hdev->ncmd_timer);
 			atomic_set(&hdev->cmd_cnt, 1);
 		} else {
 			if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
@@ -4304,7 +4304,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
 		*status = skb->data[0];
 	}
 
-	handle_cmd_cnt_and_timer(hdev, ev->ncmd);
+	handle_cmd_cnt_and_timer_sync(hdev, ev->ncmd);
 
 	hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
 			     req_complete_skb);
@@ -4418,7 +4418,7 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
 		}
 	}
 
-	handle_cmd_cnt_and_timer(hdev, ev->ncmd);
+	handle_cmd_cnt_and_timer_sync(hdev, ev->ncmd);
 
 	/* Indicate request completion if the command failed. Also, if
 	 * we're not waiting for a special event and we get a success
-- 
2.47.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help