From: Cen Zhang <zzzccc427@gmail.com>
To: marcel@holtmann.org, luiz.dentz@gmail.com
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: Protect resolving-list lookups
Date: Thu, 22 Oct 2026 20:05:56 +0800 [thread overview]
Message-ID: <pm-bluetooth-objects-candidate-0159-v11-9bd4b4c3c1e56d9ba355@gmail.com> (raw)
The host resolving list is updated under hdev->lock, and each
bdaddr_list_with_irk entry must remain alive throughout a lookup.
hci_le_del_resolve_list_sync() and hci_le_add_resolve_list_sync()
traverse that list without taking the lock.
On an LE privacy-capable controller with a programmed entry, passive
scan reconciliation can reach hci_le_del_resolve_list_sync() while a
privileged HCI_RAW client sends LE Clear Resolving List. The raw
command does not take req_lock, and its successful completion runs
on the controller workqueue independently of request work:
Request work Raw HCI / event work
hci_le_del_resolve_list_sync()
lookup loads a list node
hci_sock_sendmsg()
queue LE Clear Resolving List
hci_cc_le_clear_resolv_list()
take hdev->lock
unlink and free the node
release hdev->lock
read the node's address/type
The clear can free the node after the lookup loads it and before its
address/type read, causing a use-after-free. The report below shows
this access with the delete helper on the faulting stack. The add
helper uses the same unprotected lookup.
Take hdev->lock around each resolving-list membership lookup and
retain only a boolean result. This serializes traversal with clear
completion and keeps entry pointers inside the protected section.
Release the lock before issuing a synchronous HCI command, whose
completion also needs the lock.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in
hci_bdaddr_list_lookup_with_irk+0x106/0x120
Read of size 1 at addr ffff88810b036e16 by task kworker/u17:0/495
CPU: 2 UID: 0 PID: 495 Comm: kworker/u17:0 Not tainted
7.2.0-rc6-pmb-bt-functional-v1+ #3 PREEMPT(lazy)
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix,
1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: hci0 hci_cmd_sync_work
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? hci_bdaddr_list_lookup_with_irk+0x106/0x120
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? hci_bdaddr_list_lookup_with_irk+0x106/0x120
kasan_report+0xe0/0x110
? hci_bdaddr_list_lookup_with_irk+0x106/0x120
hci_bdaddr_list_lookup_with_irk+0x106/0x120
hci_le_del_resolve_list_sync.isra.0+0xd6/0x3f0
? __pfx_hci_le_del_resolve_list_sync.isra.0+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
hci_le_del_accept_list_sync.isra.0+0x11c/0x290
? __pfx_hci_le_del_accept_list_sync.isra.0+0x10/0x10
? hci_passive_scan_sync+0x551/0x1e80
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x280
hci_passive_scan_sync+0x71c/0x1e80
? __pfx_hci_passive_scan_sync+0x10/0x10
? find_held_lock+0x2b/0x80
? hci_lookup_le_connect+0xe1/0x3c0
? srso_alias_return_thunk+0x5/0xfbef5
? find_held_lock+0x2b/0x80
? hci_update_passive_scan_sync+0x437/0x950
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x280
hci_update_passive_scan_sync+0x461/0x950
hci_cmd_sync_work+0x1b3/0x450
? srso_alias_return_thunk+0x5/0xfbef5
process_one_work+0x908/0x19c0
? __pfx_process_one_work+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? lock_is_held_type+0x8f/0x100
? srso_alias_return_thunk+0x5/0xfbef5
worker_thread+0x65c/0xe40
? __pfx_worker_thread+0x10/0x10
kthread+0x34f/0x460
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_kthread+0x10/0x10
ret_from_fork+0x659/0x940
? __pfx_ret_from_fork+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __switch_to+0x74f/0xf80
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Allocated by task 495:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
hci_bdaddr_list_add_with_irk+0x183/0x3e0
hci_cc_le_add_to_resolv_list+0x18c/0x240
hci_cmd_complete_evt+0x373/0xab0
hci_event_packet+0x4e8/0xc70
hci_rx_work+0x367/0xf00
process_one_work+0x908/0x19c0
worker_thread+0x65c/0xe40
kthread+0x34f/0x460
ret_from_fork+0x659/0x940
ret_from_fork_asm+0x1a/0x30
Freed by task 497:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
hci_bdaddr_list_clear+0x134/0x230
hci_cc_le_clear_resolv_list+0x13d/0x240
hci_cmd_complete_evt+0x373/0xab0
hci_event_packet+0x4e8/0xc70
hci_rx_work+0x367/0xf00
process_one_work+0x908/0x19c0
worker_thread+0x65c/0xe40
kthread+0x34f/0x460
ret_from_fork+0x659/0x940
ret_from_fork_asm+0x1a/0x30
The buggy address belongs to the object at ffff88810b036e00
which belongs to the cache kmalloc-64 of size 64
The buggy address is located 22 bytes inside of
freed 64-byte region [ffff88810b036e00, ffff88810b036e40)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
pfn:0x10b036
flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff8881000428c0 dead000000000100
dead000000000122
raw: 0000000000000000 0000000000200020 00000000f5000000
0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88810b036d00: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
ffff88810b036d80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff88810b036e00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
^
ffff88810b036e80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ffff88810b036f00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
==================================================================
Disabling lock debugging due to kernel taint
Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
Sashiko review follow-up: earlier accept-list patch
- Address the resolving-list lookup issue raised by Sashiko:
https://sashiko.dev/#/patchset/88963
- Protect both resolving-list membership lookups with hdev->lock.
Related accept-list membership fix:
https://lore.kernel.org/r/pm-bluetooth-objects-candidate-0118-v7-e6b713327ef914d6d02a@gmail.com
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -2448,15 +2448,17 @@
bdaddr_t *bdaddr, u8 bdaddr_type)
{
struct hci_cp_le_del_from_resolv_list cp;
- struct bdaddr_list_with_irk *entry;
+ bool exists;
if (!ll_privacy_capable(hdev))
return 0;
/* Check if the IRK has been programmed */
- entry = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list, bdaddr,
- bdaddr_type);
- if (!entry)
+ hci_dev_lock(hdev);
+ exists = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
+ bdaddr, bdaddr_type);
+ hci_dev_unlock(hdev);
+ if (!exists)
return 0;
cp.bdaddr_type = bdaddr_type;
@@ -2512,8 +2514,8 @@
{
struct hci_cp_le_add_to_resolv_list cp;
struct smp_irk *irk;
- struct bdaddr_list_with_irk *entry;
struct hci_conn_params *p;
+ bool exists;
if (!ll_privacy_capable(hdev))
return 0;
@@ -2536,10 +2538,11 @@
return 0;
/* Check if the IK has _not_ been programmed yet. */
- entry = hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
- ¶ms->addr,
- params->addr_type);
- if (entry)
+ hci_dev_lock(hdev);
+ exists = hci_bdaddr_list_lookup_with_irk(
+ &hdev->le_resolv_list, ¶ms->addr, params->addr_type);
+ hci_dev_unlock(hdev);
+ if (exists)
return 0;
cp.bdaddr_type = params->addr_type;
reply other threads:[~2026-10-22 12:06 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-0159-v11-9bd4b4c3c1e56d9ba355@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 \
/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®