mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: hci_sync: Drain LE timeouts before disconnecting
@ 2026-10-13 16:31 Cen Zhang
  0 siblings, 0 replies; only message in thread
From: Cen Zhang @ 2026-10-13 16:31 UTC (permalink / raw)
  To: marcel, luiz.dentz, pav
  Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427

A pending LE peripheral connection can be deleted by power-off while its
le_conn_timeout callback is running on hdev->workqueue. The callback uses
a raw hci_conn pointer and waits for hdev->lock before calling
hci_conn_failed(). On the request workqueue, hci_disconnect_all_sync() can
abort the same connection first. hci_conn_del() cancels the timeout
without waiting for a running callback, and the walker's final
hci_conn_put() can free the connection before the timeout resumes. The
subsequent conn->hdev read in hci_conn_failed() is a use-after-free.

Disable and drain le_conn_timeout in hci_disconnect_all_sync() before
hci_abort_conn_sync(), while the walker's existing reference still keeps
the connection alive. Do this outside RCU and before taking hdev->lock so
the callback can finish, and prevent the timeout from being requeued
during teardown. If the callback removes the connection, the existing
hash check in hci_abort_conn_sync() avoids deleting it again.

A matching KASAN report from an instrumented kernel showed:
 BUG: KASAN: slab-use-after-free in hci_conn_failed+0x3f8/0x410
    Read of size 8 at addr ffff888119e391b0 by task
    Workqueue: hci0 le_conn_timeout
    [...]
    hci_conn_failed+0x3f8/0x410
    le_conn_timeout+0x286/0x360
    [...]
    Freed by task 509:
    [...]
    bt_link_release+0x87/0x180
    [...]
    put_device+0x24/0x30
    hci_disconnect_all_sync.constprop.0+0x163/0x460
    hci_set_powered_sync+0x48f/0x680
    [...]

Fixes: 94d9ba9f9888 ("Bluetooth: hci_sync: Fix UAF in hci_disconnect_all_sync")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index efbd2e5387c0b..ba573aeebba88 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -6083,6 +6083,15 @@ static int hci_disconnect_all_sync(struct hci_dev *hdev, u8 reason)
 		/* Make sure the connection is not freed while unlocking */
 		conn = hci_conn_get(conn);
 		rcu_read_unlock();
+
+		/*
+		 * The LE timeout takes hdev->lock, so drain it before
+		 * deleting the connection. The reference above keeps it
+		 * alive while waiting.
+		 */
+		if (conn->type == LE_LINK)
+			disable_delayed_work_sync(&conn->le_conn_timeout);
+
 		/* Disregard possible errors since hci_conn_del shall have been
 		 * called even in case of errors had occurred since it would
 		 * then cause hci_conn_failed to be called which calls

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

only message in thread, other threads:[~2026-10-13 16:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13 16:31 [PATCH] Bluetooth: hci_sync: Drain LE timeouts before disconnecting Cen Zhang

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®