All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: hci_core: Fix queuing rx_work after workqueue is drained
@ 2026-10-23 15:01 Shuai Liu
  2026-10-23 17:54 ` bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Shuai Liu @ 2026-10-23 15:01 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Marcel Holtmann, Luiz Augusto von Dentz, Shuai Liu,
	syzbot+2344fb8002f3ef5b1712

hci_recv_frame() and hci_recv_diag() queue hdev->rx_work unconditionally.
They can run from the driver RX path (e.g. vhci_write) while
hci_dev_close_sync() is draining hdev->workqueue (HCIDEVDOWN racing with
a driver write). Since that queue_work() is not chained work from the
rx_work worker itself, __queue_work() sees the queue marked __WQ_DRAINING,
warns "cannot queue %ps on wq %s", and drops the work:

  workqueue: cannot queue hci_rx_work on wq hci0
  WARNING: kernel/workqueue.c:2436 at __queue_work
  Call Trace:
   queue_work_on
   hci_recv_frame
   vhci_write

hci_dev_close_sync() already sets HCI_CMD_DRAIN_WORKQUEUE before
draining. Route the rx_work producers through the same guard via a
shared hci_sched_rx() helper, mirroring the existing hci_sched_tx()
fix for tx_work.

Fixes: 525daaea459f ("Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close")
Reported-by: syzbot+2344fb8002f3ef5b1712@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=2344fb8002f3ef5b1712
Signed-off-by: Shuai Liu <847807867@qq.com>
---
 net/bluetooth/hci_core.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 209244fd9391..dd6bc1628bca 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2892,6 +2892,17 @@ static u8 hci_dev_classify_pkt_type(struct hci_dev *hdev, struct sk_buff *skb)
 	return hci_skb_pkt_type(skb);
 }
 
+/* Queue hdev->rx_work, unless hdev->workqueue is being drained by
+ * hci_dev_close_sync(), which would otherwise WARN and drop the work.
+ */
+static void hci_sched_rx(struct hci_dev *hdev)
+{
+	rcu_read_lock();
+	if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
+		queue_work(hdev->workqueue, &hdev->rx_work);
+	rcu_read_unlock();
+}
+
 /* Receive frame from HCI drivers */
 int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
@@ -2945,7 +2956,7 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
 	__net_timestamp(skb);
 
 	skb_queue_tail(&hdev->rx_q, skb);
-	queue_work(hdev->workqueue, &hdev->rx_work);
+	hci_sched_rx(hdev);
 
 	return 0;
 }
@@ -2961,7 +2972,7 @@ int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb)
 	__net_timestamp(skb);
 
 	skb_queue_tail(&hdev->rx_q, skb);
-	queue_work(hdev->workqueue, &hdev->rx_work);
+	hci_sched_rx(hdev);
 
 	return 0;
 }
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-23 17:54 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-23 15:01 [PATCH] Bluetooth: hci_core: Fix queuing rx_work after workqueue is drained Shuai Liu
2026-10-23 17:54 ` bluez.test.bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.