* [PATCH] Bluetooth: hci_sync: Protect resolving-list lookups
@ 2026-10-22 12:05 Cen Zhang
2026-10-22 13:06 ` bluez.test.bot
2026-10-23 22:10 ` [PATCH] " patchwork-bot+bluetooth
0 siblings, 2 replies; 3+ messages in thread
From: Cen Zhang @ 2026-10-22 12:05 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427
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;
^ permalink raw reply [flat|nested] 3+ messages in thread* RE: Bluetooth: hci_sync: Protect resolving-list lookups
2026-10-22 12:05 [PATCH] Bluetooth: hci_sync: Protect resolving-list lookups Cen Zhang
@ 2026-10-22 13:06 ` bluez.test.bot
2026-10-23 22:10 ` [PATCH] " patchwork-bot+bluetooth
1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-10-22 13:06 UTC (permalink / raw)
To: linux-bluetooth, zzzccc427
[-- Attachment #1: Type: text/plain, Size: 1605 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1191269/
---Test result---
Test Summary:
CheckPatch PASS 0.39 seconds
VerifyFixes PASS 0.07 seconds
VerifySignedoff PASS 0.07 seconds
GitLint PASS 0.18 seconds
SubjectPrefix PASS 0.28 seconds
BuildKernel PASS 19.57 seconds
CheckAllWarning PASS 22.69 seconds
CheckSparse PASS 24.74 seconds
BuildKernel32 PASS 20.13 seconds
CheckKernelLLVM PASS 21.58 seconds
TestRunnerSetup PASS 453.91 seconds
TestRunner_l2cap-tester PASS 12.92 seconds
TestRunner_iso-tester PASS 10.68 seconds
TestRunner_bnep-tester PASS 2.76 seconds
TestRunner_mgmt-tester PASS 80.29 seconds
TestRunner_rfcomm-tester PASS 4.04 seconds
TestRunner_sco-tester PASS 4.97 seconds
TestRunner_ioctl-tester PASS 5.68 seconds
TestRunner_mesh-tester PASS 5.02 seconds
TestRunner_smp-tester PASS 4.02 seconds
TestRunner_userchan-tester PASS 2.87 seconds
TestRunner_6lowpan-tester PASS 4.02 seconds
IncrementalBuild PASS 21.34 seconds
https://github.com/bluez/bluetooth-next/pull/978
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] Bluetooth: hci_sync: Protect resolving-list lookups
2026-10-22 12:05 [PATCH] Bluetooth: hci_sync: Protect resolving-list lookups Cen Zhang
2026-10-22 13:06 ` bluez.test.bot
@ 2026-10-23 22:10 ` patchwork-bot+bluetooth
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+bluetooth @ 2026-10-23 22:10 UTC (permalink / raw)
To: Cen Zhang
Cc: marcel, luiz.dentz, linux-bluetooth, linux-kernel, baijiaju1990,
jjzuming
Hello:
This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Thu, 22 Oct 2026 20:05:56 +0800 you wrote:
> 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:
>
> [...]
Here is the summary with links:
- Bluetooth: hci_sync: Protect resolving-list lookups
https://git.kernel.org/bluetooth/bluetooth-next/c/2a464ab1c5ac
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-23 22:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22 12:05 [PATCH] Bluetooth: hci_sync: Protect resolving-list lookups Cen Zhang
2026-10-22 13:06 ` bluez.test.bot
2026-10-23 22:10 ` [PATCH] " patchwork-bot+bluetooth
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox