From: Chengfeng Ye <nicoyip.dev@gmail.com>
To: Marcel Holtmann <marcel@holtmann.org>,
Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org, Chengfeng Ye <nicoyip.dev@gmail.com>
Subject: [PATCH v2] Bluetooth: hci_sync: Fix accept list UAF during suspend
Date: Sat, 1 Aug 2026 15:05:24 +0800 [thread overview]
Message-ID: <20260801070524.3547883-1-nicoyip.dev@gmail.com> (raw)
hci_update_event_filter_sync() walks hdev->accept_list while sending a
synchronous HCI command for each remote-wakeup device. The suspend path
holds hdev->req_lock, but accept-list updates are serialized by hdev->lock.
Consequently, remove_device() can free the current list entry during the
controller wait.
The following interleaving causes the use-after-free:
hci_update_event_filter_sync() remove_device()
fetch accept-list entry
hci_set_event_filter_sync()
wait for controller response hci_dev_lock()
list_del()
kfree()
hci_dev_unlock()
read the freed list.next
KASAN reported:
BUG: KASAN: slab-use-after-free in hci_suspend_sync+0x835/0x910
Read of size 8 at addr ffff88810bec8440 by task kworker/0:1/10
Workqueue: events vhci_suspend_work
Call Trace:
hci_suspend_sync+0x835/0x910
hci_suspend_dev+0x182/0x450
process_one_work+0x661/0x1090
worker_thread+0x45b/0xd10
Allocated by task 86:
hci_bdaddr_list_add_with_flags+0x1a8/0x400
add_device+0x381/0x820
hci_sock_sendmsg+0x1033/0x1ea0
Freed by task 91:
kfree+0x131/0x3c0
remove_device+0x429/0xb70
hci_sock_sendmsg+0x1033/0x1ea0
Snapshot the remote-wakeup addresses under hdev->lock. Release the lock
before sending HCI commands. Clear the controller event filter before
building the snapshot, and skip allocation and the second list traversal
when there are no matching entries. This preserves the original filter
and scan-state updates without retaining an accept-list node across a
controller wait.
Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/linux-bluetooth/20260730092331.2069741-1-nicoyip.dev@gmail.com/
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
Changes in v2:
- Clear the event filter before taking the accept-list snapshot.
- Skip allocation and the second list walk when there are no matching entries.
Link: https://lore.kernel.org/linux-bluetooth/20260730092331.2069741-1-nicoyip.dev@gmail.com/ [v1]
net/bluetooth/hci_sync.c | 46 ++++++++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index c8d14128c363..8ccc3b22ef5b 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -6313,6 +6313,8 @@ static int hci_pause_discovery_sync(struct hci_dev *hdev)
static int hci_update_event_filter_sync(struct hci_dev *hdev)
{
struct bdaddr_list_with_flags *b;
+ bdaddr_t *accept_list;
+ size_t i, num_entries = 0;
u8 scan = SCAN_DISABLED;
bool scanning = test_bit(HCI_PSCAN, &hdev->flags);
int err;
@@ -6329,23 +6331,49 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev)
/* Always clear event filter when starting */
hci_clear_event_filter_sync(hdev);
- list_for_each_entry(b, &hdev->accept_list, list) {
- if (!(b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP))
- continue;
+ hci_dev_lock(hdev);
+
+ list_for_each_entry(b, &hdev->accept_list, list)
+ if (b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP)
+ num_entries++;
+
+ if (!num_entries) {
+ hci_dev_unlock(hdev);
+ goto update_scan;
+ }
+
+ accept_list = kmalloc_array(num_entries, sizeof(*accept_list),
+ GFP_KERNEL);
+ if (!accept_list) {
+ hci_dev_unlock(hdev);
+ return -ENOMEM;
+ }
+
+ i = 0;
+ list_for_each_entry(b, &hdev->accept_list, list)
+ if (b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP)
+ bacpy(&accept_list[i++], &b->bdaddr);
+
+ hci_dev_unlock(hdev);
- bt_dev_dbg(hdev, "Adding event filters for %pMR", &b->bdaddr);
+ for (i = 0; i < num_entries; i++) {
+ bt_dev_dbg(hdev, "Adding event filters for %pMR",
+ &accept_list[i]);
- err = hci_set_event_filter_sync(hdev, HCI_FLT_CONN_SETUP,
- HCI_CONN_SETUP_ALLOW_BDADDR,
- &b->bdaddr,
- HCI_CONN_SETUP_AUTO_ON);
+ err = hci_set_event_filter_sync(hdev, HCI_FLT_CONN_SETUP,
+ HCI_CONN_SETUP_ALLOW_BDADDR,
+ &accept_list[i],
+ HCI_CONN_SETUP_AUTO_ON);
if (err)
bt_dev_err(hdev, "Failed to set event filter for %pMR",
- &b->bdaddr);
+ &accept_list[i]);
else
scan = SCAN_PAGE;
}
+ kfree(accept_list);
+
+update_scan:
if (scan && !scanning)
hci_write_scan_enable_sync(hdev, scan);
else if (!scan && scanning)
--
2.43.0
next reply other threads:[~2026-08-01 7:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-01 7:05 Chengfeng Ye [this message]
2026-08-01 8:03 ` [v2] Bluetooth: hci_sync: Fix accept list UAF during suspend bluez.test.bot
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=20260801070524.3547883-1-nicoyip.dev@gmail.com \
--to=nicoyip.dev@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
--cc=stable@vger.kernel.org \
/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 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.