mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: hci_core: Fix queuing disc_work while workqueue is drained
       [not found] <20261020145320.115333-1-deaner92.ref@yahoo.com>
@ 2026-10-20 14:53 ` Jeremy Dean Clifton
  0 siblings, 0 replies; only message in thread
From: Jeremy Dean Clifton @ 2026-10-20 14:53 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz
  Cc: linux-bluetooth, linux-kernel, Hillf Danton, Jeremy Dean Clifton,
	syzbot+5897b3c764f5989ea942

hci_conn_drop() queues conn->disc_work on hdev->workqueue unconditionally
when the last reference to a connection is dropped. It can run from the
socket connect path while hci_dev_close_sync() is draining
hdev->workqueue (e.g. HCIDEVDOWN racing with an SCO connect). Since that
queue_delayed_work() is not chained from a work item already running on
the queue, __queue_work() sees the queue marked __WQ_DRAINING, warns and
drops the work:

  workqueue: cannot queue hci_conn_timeout on wq hci4
  WARNING: kernel/workqueue.c:2352 at __queue_work+0xdb7/0x1370
  Call Trace:
   __queue_delayed_work kernel/workqueue.c:2617
   queue_delayed_work_on kernel/workqueue.c:2669
   hci_conn_drop include/net/bluetooth/hci_core.h:1729 [inline]
   hci_connect_sco net/bluetooth/hci_conn.c:1881
   sco_connect net/bluetooth/sco.c:375 [inline]
   sco_sock_connect net/bluetooth/sco.c:764
   __sys_connect_file net/socket.c:2166
   __sys_connect net/socket.c:2183
   __x64_sys_connect net/socket.c:2186

hci_dev_close_sync() already sets HCI_CMD_DRAIN_WORKQUEUE and calls
synchronize_rcu() before draining, and keeps the flag set until the
device is fully closed. Skip queuing disc_work while the flag is set,
checking it under rcu_read_lock().

hci_conn_hash_flush(), called from hci_dev_close_sync(),
deletes the remaining connections.

Fixes: 525daaea459f ("Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close")
Reported-by: syzbot+5897b3c764f5989ea942@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5897b3c764f5989ea942
Tested-by: syzbot+5897b3c764f5989ea942@syzkaller.appspotmail.com
Suggested-by: Hillf Danton <hdanton@sina.com>
Assisted-by: LLM
Signed-off-by: Jeremy Dean Clifton <deaner92@yahoo.com>
---

Notes:
    Testing:
    
    syzbot ran its reproducer for this bug on upstream 90201351a862:
      - without this patch, the warning reproduces:
        https://syzkaller.appspot.com/x/report.txt?x=17940305580000
      - with this patch, the reproducer does not trigger any issue:
        https://syzkaller.appspot.com/x/bisect.txt?x=1714618e580000
    
    The evidence is the pair of runs on
    90201351a862, where the same kernel crashed without this patch and
    did not crash with it. syzbot's own retest on
    58161ead29e5 (Oct 17) still reproduces the warning without this
    patch.
    
    This patch is based on bluetooth-next (185c11232d5f). I built
    net/bluetooth and hci_vhci for arm64 with CONFIG_PROVE_LOCKING=y
    with no new warnings, and the same change also builds on x86-64
    against v7.3. I could not run the reproducer locally; all runtime
    testing above is syzbot's.
    
    Hillf Danton tested an equivalent hci_conn_drop() check in February,
    together with a hci_dev_close_sync() change that is now upstream via
    525daaea459f:
    https://lore.kernel.org/all/694c9ee9.050a0220.35954c.0030.GAE@google.com/T/
    
    Tool use: An LLM helped me analyse the syzbot
    report, compare hci_conn_drop() with the existing
    HCI_CMD_DRAIN_WORKQUEUE checks, draft the changelog and prepare the
    syzbot test requests.
    
    I made the code change myself and checked the
    locking: the RCU read section pairs with synchronize_rcu() in
    hci_dev_close_sync(), and hci_conn_hash_flush() later deletes the
    remaining connections, so not queuing disc_work loses nothing.

 include/net/bluetooth/hci_core.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8f32c860d492..c8cc25d35195 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1775,8 +1775,11 @@ static inline void hci_conn_drop(struct hci_conn *conn)
 		}
 
 		cancel_delayed_work(&conn->disc_work);
-		queue_delayed_work(conn->hdev->workqueue,
-				   &conn->disc_work, timeo);
+		rcu_read_lock();
+		if (!hci_dev_test_flag(conn->hdev, HCI_CMD_DRAIN_WORKQUEUE))
+			queue_delayed_work(conn->hdev->workqueue,
+					   &conn->disc_work, timeo);
+		rcu_read_unlock();
 	}
 }
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-20 14:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20261020145320.115333-1-deaner92.ref@yahoo.com>
2026-10-20 14:53 ` [PATCH] Bluetooth: hci_core: Fix queuing disc_work while workqueue is drained Jeremy Dean Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®