From: Cen Zhang <zzzccc427@gmail.com>
To: marcel@holtmann.org, luiz.dentz@gmail.com, pav@iki.fi
Cc: linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org,
baijiaju1990@gmail.com, jjzuming@gmail.com, zzzccc427@gmail.com
Subject: [PATCH] Bluetooth: hci_sync: Drain LE timeouts before disconnecting
Date: Wed, 14 Oct 2026 00:31:55 +0800 [thread overview]
Message-ID: <pm-bluetooth-objects-candidate-0087-v9-625f001f92d657dbf938@gmail.com> (raw)
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
reply other threads:[~2026-10-13 16:32 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pm-bluetooth-objects-candidate-0087-v9-625f001f92d657dbf938@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=jjzuming@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
--cc=pav@iki.fi \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®