* [PATCH 0/2] Bluetooth: SMP: Serialize root channel updates
@ 2026-10-30 14:43 Cen Zhang
2026-10-30 14:43 ` [PATCH 1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes Cen Zhang
2026-10-30 14:43 ` [PATCH 2/2] Bluetooth: SMP: Serialize root channel replacement Cen Zhang
0 siblings, 2 replies; 4+ messages in thread
From: Cen Zhang @ 2026-10-30 14:43 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427
The SMP root channels in hdev->smp_data and hdev->smp_bredr_data are
used by HCI event processing under hdev->lock and by SMP receive
callbacks on hdev->workqueue. Power-off already removes them under
hdev->lock in hci_dev_close_sync(). Two other writers do not serialize
with these users:
1/2 The force_bredr_smp debugfs switch creates and removes the BR/EDR
root without hdev->lock. A connection confirmation can see a root
whose operations are not set yet, and a disable can race with
power-off and release the channel twice. Take hdev->lock in the
writer, and skip the deletion when power-off already emptied the
slot.
2/2 smp_register() replaces both roots when management powers on a
controller that is already up with HCI_AUTO_OFF set, while HCI
event processing and SMP receive callbacks can still be using the
old roots. Run the registration on hdev->workqueue, where it ran
before commit 2ff13894cfb8 ("Bluetooth: Perform HCI update for
power on synchronously"), and hold hdev->lock while it replaces
the roots. The caller waits for the work without holding
hdev->lock, which HCI event processing on that workqueue takes.
smp_register() still warns when it replaces the channels on that path.
This series only makes the replacement safe.
Cen Zhang (2):
Bluetooth: SMP: Serialize forced BR/EDR channel changes
Bluetooth: SMP: Serialize root channel replacement
net/bluetooth/hci_debugfs.c | 2 ++
net/bluetooth/smp.c | 38 +++++++++++++++++++++++++++++++++++--
net/bluetooth/smp.h | 3 ++-
3 files changed, 40 insertions(+), 3 deletions(-)
---
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes
2026-10-30 14:43 [PATCH 0/2] Bluetooth: SMP: Serialize root channel updates Cen Zhang
@ 2026-10-30 14:43 ` Cen Zhang
2026-10-30 16:41 ` Bluetooth: SMP: Serialize root channel updates bluez.test.bot
2026-10-30 14:43 ` [PATCH 2/2] Bluetooth: SMP: Serialize root channel replacement Cen Zhang
1 sibling, 1 reply; 4+ messages in thread
From: Cen Zhang @ 2026-10-30 14:43 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427
The force_bredr_smp debugfs switch creates and removes the BR/EDR SMP
root channel in hdev->smp_bredr_data without holding hdev->lock. The
other users of that channel hold the lock: l2cap_connect_cfm() looks up
fixed channels during HCI event processing, and hci_dev_close_sync()
removes the root through smp_unregister().
Enabling the switch can let a connection confirmation use a root that
is not fully initialized. smp_add_cid() publishes the channel through
l2cap_chan_create() and sets BT_LISTEN before it assigns the channel
operations and the parent lock nesting level:
Debugfs writer HCI receive worker
smp_add_cid()
l2cap_chan_create()
l2cap_add_scid()
chan->state = BT_LISTEN
hci_dev_lock(hdev)
l2cap_connect_cfm()
l2cap_global_fixed_chan()
l2cap_chan_lock(root)
l2cap_new_connection()
root->ops->new_connection()
chan->ops = &smp_root_chan_ops
Disabling the switch can race with power-off, which releases the same
channel:
Debugfs writer Power-off
smp_force_bredr(hdev, false)
chan = hdev->smp_bredr_data
hci_dev_lock(hdev)
smp_unregister(hdev)
smp_del_chan(chan), chan is freed
hci_dev_unlock(hdev)
smp_del_chan(chan)
reads chan->data after the free
Hold hdev->lock around smp_force_bredr() in the debugfs writer and
annotate that requirement. smp_unregister() leaves HCI_FORCE_BREDR_SMP
set, so after power-off the slot is empty while the switch still reads
as enabled. Disabling it then passes NULL to smp_del_chan() even without
a race; skip the deletion in that case and only clear the flag.
Both reports below come from test kernels with scheduling hooks that
widen these windows. In the enable case lockdep also reported recursive
locking just before the oops, because the root still had the default
nesting level.
Oops report as below:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
CPU: 1 UID: 0 PID: 497 Comm: kworker/u17:0 Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #1 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: hci1 hci_rx_work
RIP: 0010:l2cap_new_connection+0x16c/0x320
Code: c1 ea 03 80 3c 02 00 0f 85 70 01 00 00 4c 8b a5 a8 04 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d 7c 24 08 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 6d 01 00 00 4d 8b 64 24 08 4d 85 e4 74 19 e8 2b
RSP: 0018:ffff88810dd57928 EFLAGS: 00010212
RAX: dffffc0000000000 RBX: ffff888108959000 RCX: ffffffff85b5ff24
RDX: 0000000000000001 RSI: 0000000000000008 RDI: 0000000000000008
RBP: ffff88810895a000 R08: 0000000000000000 R09: 0000000000000000
R10: ffffffff893d2f57 R11: 0000000000000000 R12: 0000000000000000
R13: ffff8881089594b0 R14: ffff888100d59800 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff8881fd852000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000563a39fc8768 CR3: 00000001069d8004 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
l2cap_connect_cfm+0x46c/0xe60
? __pfx_l2cap_connect_cfm+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
hci_remote_ext_features_evt+0x67d/0xbd0
? __pfx_l2cap_connect_cfm+0x10/0x10
? __pfx_hci_remote_ext_features_evt+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
hci_event_packet+0x894/0xc70
? __pfx_hci_remote_ext_features_evt+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_hci_event_packet+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? free_zapped_rcu+0xd0/0x1e0
? srso_alias_return_thunk+0x5/0xfbef5
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
hci_rx_work+0x367/0xf00
? 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>
Modules linked in:
---[ end trace 0000000000000000 ]---
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in smp_del_chan+0xd2/0xe0
Read of size 8 at addr ffff888112a2e4a0 by task sh/493
CPU: 1 UID: 0 PID: 493 Comm: sh Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #2 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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? smp_del_chan+0xd2/0xe0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? smp_del_chan+0xd2/0xe0
kasan_report+0xe0/0x110
? smp_del_chan+0xd2/0xe0
smp_del_chan+0xd2/0xe0
smp_force_bredr+0xda/0x200
force_bredr_smp_write+0xc9/0x130
? __pfx_force_bredr_smp_write+0x10/0x10
? __entry_text_end+0x1020f5/0x1020f9
? lock_acquire+0x17b/0x2f0
? ksys_write+0x111/0x200
full_proxy_write+0x11f/0x180
vfs_write+0x25a/0x1010
? __pfx_full_proxy_write+0x10/0x10
? __pfx_vfs_write+0x10/0x10
ksys_write+0x111/0x200
? __pfx_ksys_write+0x10/0x10
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f4692518687
Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
RSP: 002b:00007ffd467e8b10 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f4692486780 RCX: 00007f4692518687
RDX: 0000000000000002 RSI: 0000555ac2951a80 RDI: 0000000000000001
RBP: 0000555ac2951a80 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000001
R13: 0000000000000002 R14: 0000000000000000 R15: 0000555abc0f2988
</TASK>
Allocated by task 493:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
l2cap_chan_create+0x47/0x930
smp_add_cid+0x309/0x4f0
smp_force_bredr+0x17d/0x200
force_bredr_smp_write+0xc9/0x130
full_proxy_write+0x11f/0x180
vfs_write+0x25a/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 496:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
l2cap_chan_put+0x273/0x3a0
smp_unregister+0x59/0xe0
hci_dev_close_sync+0x4c9/0x1150
hci_set_powered_sync+0x4a7/0x680
set_powered_sync+0xaa/0x150
hci_cmd_sync_work+0x1b3/0x450
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 ffff888112a2e000
which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 1184 bytes inside of
freed 2048-byte region [ffff888112a2e000, ffff888112a2e800)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x112a28
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x200000000000040(head|node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000040 ffff888100042f00 dead000000000100 dead000000000122
raw: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
head: 0200000000000040 ffff888100042f00 dead000000000100 dead000000000122
head: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
head: 0200000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888112a2e380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888112a2e400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888112a2e480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff888112a2e500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888112a2e580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
Fixes: 300acfdec916 ("Bluetooth: Introduce force_bredr_smp debugfs option for testing")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
Assisted-by: LLM
net/bluetooth/hci_debugfs.c | 2 ++
net/bluetooth/smp.c | 2 +-
net/bluetooth/smp.h | 3 ++-
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
index cd5ef398f2382..f513731053d28 100644
--- a/net/bluetooth/hci_debugfs.c
+++ b/net/bluetooth/hci_debugfs.c
@@ -525,7 +525,9 @@ static ssize_t force_bredr_smp_write(struct file *file,
if (err)
return err;
+ hci_dev_lock(hdev);
err = smp_force_bredr(hdev, enable);
+ hci_dev_unlock(hdev);
if (err)
return err;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 984b2d0b5e3e9..0e442cc2a35da 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -3356,7 +3356,7 @@ int smp_force_bredr(struct hci_dev *hdev, bool enable)
return PTR_ERR(chan);
hdev->smp_bredr_data = chan;
- } else {
+ } else if (hdev->smp_bredr_data) {
struct l2cap_chan *chan;
chan = hdev->smp_bredr_data;
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index c86c463890078..13fe40c0cb244 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -193,7 +193,8 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa);
int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]);
-int smp_force_bredr(struct hci_dev *hdev, bool enable);
+int smp_force_bredr(struct hci_dev *hdev, bool enable)
+ __must_hold(&hdev->lock);
int smp_register(struct hci_dev *hdev);
void smp_unregister(struct hci_dev *hdev);
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] Bluetooth: SMP: Serialize root channel replacement
2026-10-30 14:43 [PATCH 0/2] Bluetooth: SMP: Serialize root channel updates Cen Zhang
2026-10-30 14:43 ` [PATCH 1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes Cen Zhang
@ 2026-10-30 14:43 ` Cen Zhang
1 sibling, 0 replies; 4+ messages in thread
From: Cen Zhang @ 2026-10-30 14:43 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427
smp_register() replaces the SMP root channels when they are still
registered from an earlier power-on. This happens when management
powers on a controller that is already up with HCI_AUTO_OFF set:
hci_power_on_sync() clears the flag and runs hci_powered_update_sync()
again, which registers SMP so that the channels use the identity address
chosen for this power-on. The WARN_ON() in smp_register() fires on this
path, and the old channels and their SMP data are freed while two kinds
of users can still hold them.
HCI event handlers read hdev->smp_data under hdev->lock, for example
smp_irk_matches() when resolving the target of a directed advertising
report:
HCI receive worker Power-on request
hci_dev_lock(hdev)
smp_irk_matches()
chan = hdev->smp_data
hci_powered_update_sync()
smp_register()
smp_del_chan(chan), chan freed
reads chan->data
SMP receive callbacks run on hdev->workqueue without hdev->lock and use
the ECDH transform of the root, for example smp_cmd_public_key():
HCI receive worker (SMP) Power-on request
smp_cmd_public_key()
tfm = root's tfm_ecdh
smp_register()
smp_del_chan()
crypto_free_kpp(tfm)
compute_ecdh_secret(tfm, ...)
Before commit 2ff13894cfb8 ("Bluetooth: Perform HCI update for power on
synchronously") moved it to the request worker, registration ran from the
completion callback of the power-on request in the HCI receive worker,
which serialized it with both users.
Run the registration on hdev->workqueue again and hold hdev->lock while
it replaces the channels. smp_register() waits for the work and returns
its result. Its callers hold the request lock but not hdev->lock, and no
work on hdev->workqueue takes the request lock; hci_dev_close_sync()
already drains this workqueue with the request lock held. Users that run
under the request lock, such as smp_generate_rpa(), stay serialized by
that lock.
The reports below come from test kernels with scheduling hooks that
widen these windows. The WARN_ON() in smp_register() was printed before
each of them.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in smp_irk_matches+0x2fb/0x310
Read of size 8 at addr ffff88810c35f4a0 by task kworker/u17:0/520
CPU: 0 UID: 0 PID: 520 Comm: kworker/u17:0 Tainted: G W 7.2.0-rc6-pmb-bt-functional-v1+ #6 PREEMPT(lazy)
Tainted: [W]=WARN
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_rx_work
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? smp_irk_matches+0x2fb/0x310
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? smp_irk_matches+0x2fb/0x310
kasan_report+0xe0/0x110
? smp_irk_matches+0x2fb/0x310
smp_irk_matches+0x2fb/0x310
? __pfx_smp_irk_matches+0x10/0x10
? __mutex_lock+0x182c/0x2590
? hci_le_direct_adv_report_evt+0xe4/0x4c0
? srso_alias_return_thunk+0x5/0xfbef5
process_adv_report.part.0+0x2ce/0x1680
? __pfx_process_adv_report.part.0+0x10/0x10
? __pfx_pmbd_probe_hit_cookie+0x10/0x10
hci_le_direct_adv_report_evt+0x2f8/0x4c0
? __pfx_hci_le_direct_adv_report_evt+0x10/0x10
hci_le_meta_evt+0x30c/0x5c0
hci_event_packet+0x4e8/0xc70
? __pfx_hci_le_meta_evt+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_hci_event_packet+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? free_zapped_rcu+0xd0/0x1e0
? srso_alias_return_thunk+0x5/0xfbef5
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
hci_rx_work+0x367/0xf00
? 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 522:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
l2cap_chan_create+0x47/0x930
smp_add_cid+0x120/0x4f0
smp_register+0xa7/0x400
hci_powered_update_sync+0x88/0x720
hci_dev_open_sync+0xae0/0x2060
hci_set_powered_sync+0x2a9/0x720
set_powered_sync+0xaa/0x150
hci_cmd_sync_work+0x1b3/0x450
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 522:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
l2cap_chan_put+0x273/0x3a0
smp_del_chan+0x9f/0x170
smp_register+0x2e8/0x400
hci_powered_update_sync+0x88/0x720
hci_set_powered_sync+0x5e5/0x720
set_powered_sync+0xaa/0x150
hci_cmd_sync_work+0x1b3/0x450
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 ffff88810c35f000
which belongs to the cache kmalloc-2k of size 2048
The buggy address is located 1184 bytes inside of
freed 2048-byte region [ffff88810c35f000, ffff88810c35f800)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10c358
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x200000000000040(head|node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000040 ffff888100042f00 dead000000000100 dead000000000122
raw: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
head: 0200000000000040 ffff888100042f00 dead000000000100 dead000000000122
head: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000
head: 0200000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88810c35f380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88810c35f400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88810c35f480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff88810c35f500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88810c35f580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in compute_ecdh_secret+0x856/0xa50
Read of size 4 at addr ffff8881071f4f00 by task kworker/u17:2/500
CPU: 0 UID: 0 PID: 500 Comm: kworker/u17:2 Tainted: G W 7.2.0-rc6-pmb-bt-functional-v1+ #2 PREEMPT(lazy)
Tainted: [W]=WARN
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: hci1 hci_rx_work
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? compute_ecdh_secret+0x856/0xa50
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? compute_ecdh_secret+0x856/0xa50
kasan_report+0xe0/0x110
? compute_ecdh_secret+0x856/0xa50
compute_ecdh_secret+0x856/0xa50
? __pfx_pmbd_hold_maybe+0x10/0x10
? __pfx_compute_ecdh_secret+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
smp_recv_cb+0x3acf/0x93b0
? __pfx_smp_recv_cb+0x10/0x10
? __pfx___might_resched+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __mutex_lock+0x182c/0x2590
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_sched_clock_cpu+0x10/0x10
? __pfx___mutex_lock+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_l2cap_chan_hold_unless_zero+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? l2cap_recv_frame+0x13cc/0x8830
? __pfx_smp_recv_cb+0x10/0x10
l2cap_recv_frame+0x13cc/0x8830
? srso_alias_return_thunk+0x5/0xfbef5
? __mutex_lock+0x182c/0x2590
? __pfx_l2cap_recv_frame+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? find_held_lock+0x2b/0x80
? l2cap_recv_acldata+0x1eb/0x10e0
? __pfx___mutex_lock+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __mutex_unlock_slowpath+0x147/0x920
? __pfx_l2cap_conn_hold_unless_zero+0x10/0x10
? __pfx_hci_conn_enter_active_mode+0x10/0x10
? l2cap_recv_acldata+0x13d/0x10e0
? srso_alias_return_thunk+0x5/0xfbef5
l2cap_recv_acldata+0xe9f/0x10e0
? srso_alias_return_thunk+0x5/0xfbef5
hci_rx_work+0x5a6/0xf00
? 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
? srso_alias_return_thunk+0x5/0xfbef5
? __kthread_parkme+0x175/0x220
? srso_alias_return_thunk+0x5/0xfbef5
? __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 497:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_node_noprof+0x2f2/0x7b0
crypto_create_tfm_node+0x92/0x390
crypto_alloc_tfm_node+0xf5/0x220
smp_add_cid+0xc1/0x4f0
smp_register+0x9d/0x430
hci_powered_update_sync+0x82/0x680
hci_set_powered_sync+0x4f4/0x750
set_powered_sync+0xb8/0x210
hci_cmd_sync_work+0x1b3/0x450
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
crypto_destroy_tfm+0xdd/0x230
smp_del_chan+0x8b/0x180
smp_register+0x29d/0x430
hci_powered_update_sync+0x82/0x680
hci_set_powered_sync+0x4f4/0x750
set_powered_sync+0xb8/0x210
hci_cmd_sync_work+0x1b3/0x450
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 ffff8881071f4f00
which belongs to the cache kmalloc-128 of size 128
The buggy address is located 0 bytes inside of
freed 128-byte region [ffff8881071f4f00, ffff8881071f4f80)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff8881071f4e00 pfn:0x1071f4
flags: 0x200000000000200(workingset|node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000200 ffff888100042a00 ffffea00041c77d0 ffffea00041c7bd0
raw: ffff8881071f4e00 000000000010000b 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff8881071f4e00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff8881071f4e80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff8881071f4f00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff8881071f4f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff8881071f5000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
Fixes: 2ff13894cfb8 ("Bluetooth: Perform HCI update for power on synchronously")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
Assisted-by: LLM
net/bluetooth/smp.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 0e442cc2a35da..552b6b3713c3a 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -3369,7 +3369,8 @@ int smp_force_bredr(struct hci_dev *hdev, bool enable)
return 0;
}
-int smp_register(struct hci_dev *hdev)
+static int __smp_register(struct hci_dev *hdev)
+ __must_hold(&hdev->lock)
{
struct l2cap_chan *chan;
@@ -3419,6 +3420,39 @@ int smp_register(struct hci_dev *hdev)
return 0;
}
+struct smp_register_work {
+ struct work_struct work;
+ struct hci_dev *hdev;
+ int err;
+};
+
+static void smp_register_func(struct work_struct *work)
+{
+ struct smp_register_work *reg =
+ container_of(work, struct smp_register_work, work);
+ struct hci_dev *hdev = reg->hdev;
+
+ hci_dev_lock(hdev);
+ reg->err = __smp_register(hdev);
+ hci_dev_unlock(hdev);
+}
+
+int smp_register(struct hci_dev *hdev)
+{
+ struct smp_register_work reg = { .hdev = hdev };
+
+ /* HCI event handlers use the root channels under hdev->lock, and
+ * SMP receive callbacks use them from hdev->workqueue. Replace the
+ * channels from that workqueue while holding hdev->lock.
+ */
+ INIT_WORK_ONSTACK(®.work, smp_register_func);
+ queue_work(hdev->workqueue, ®.work);
+ flush_work(®.work);
+ destroy_work_on_stack(®.work);
+
+ return reg.err;
+}
+
void smp_unregister(struct hci_dev *hdev)
{
struct l2cap_chan *chan;
^ permalink raw reply related [flat|nested] 4+ messages in thread
* RE: Bluetooth: SMP: Serialize root channel updates
2026-10-30 14:43 ` [PATCH 1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes Cen Zhang
@ 2026-10-30 16:41 ` bluez.test.bot
0 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-10-30 16:41 UTC (permalink / raw)
To: linux-bluetooth, zzzccc427
[-- Attachment #1: Type: text/plain, Size: 7090 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/1197223/
---Test result---
Test Summary:
CheckPatch FAIL 1.92 seconds
VerifyFixes PASS 0.10 seconds
VerifySignedoff PASS 0.10 seconds
GitLint FAIL 0.57 seconds
SubjectPrefix PASS 0.19 seconds
BuildKernel PASS 26.32 seconds
CheckAllWarning PASS 29.35 seconds
CheckSparse PASS 30.87 seconds
BuildKernel32 PASS 26.63 seconds
CheckKernelLLVM PASS 26.68 seconds
TestRunnerSetup PASS 604.48 seconds
TestRunner_l2cap-tester FAIL 12.24 seconds
TestRunner_iso-tester PASS 9.92 seconds
TestRunner_bnep-tester PASS 2.91 seconds
TestRunner_mgmt-tester PASS 85.26 seconds
TestRunner_rfcomm-tester PASS 4.15 seconds
TestRunner_sco-tester PASS 5.23 seconds
TestRunner_ioctl-tester PASS 4.34 seconds
TestRunner_mesh-tester PASS 6.72 seconds
TestRunner_smp-tester PASS 4.26 seconds
TestRunner_userchan-tester PASS 2.92 seconds
TestRunner_6lowpan-tester PASS 4.14 seconds
IncrementalBuild PASS 26.88 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#176:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
total: 0 errors, 1 warnings, 0 checks, 26 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/home/runner/work/bluetooth-next/bluetooth-next/src/patch/14927653.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
[2/2] Bluetooth: SMP: Serialize root channel replacement
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#281:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10c358
total: 0 errors, 1 warnings, 0 checks, 48 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/home/runner/work/bluetooth-next/bluetooth-next/src/patch/14927654.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes
53: B1 Line exceeds max length (116>80): " Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI"
55: B1 Line exceeds max length (107>80): " CPU: 1 UID: 0 PID: 497 Comm: kworker/u17:0 Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)"
56: B1 Line exceeds max length (119>80): " 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"
59: B1 Line exceeds max length (203>80): " Code: c1 ea 03 80 3c 02 00 0f 85 70 01 00 00 4c 8b a5 a8 04 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d 7c 24 08 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 6d 01 00 00 4d 8b 64 24 08 4d 85 e4 74 19 e8 2b"
119: B1 Line exceeds max length (96>80): " CPU: 1 UID: 0 PID: 493 Comm: sh Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #2 PREEMPT(lazy)"
120: B1 Line exceeds max length (119>80): " 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"
147: B1 Line exceeds max length (203>80): " Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff"
[2/2] Bluetooth: SMP: Serialize root channel replacement
59: B1 Line exceeds max length (125>80): " CPU: 0 UID: 0 PID: 520 Comm: kworker/u17:0 Tainted: G W 7.2.0-rc6-pmb-bt-functional-v1+ #6 PREEMPT(lazy)"
61: B1 Line exceeds max length (119>80): " 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"
185: B1 Line exceeds max length (125>80): " CPU: 0 UID: 0 PID: 500 Comm: kworker/u17:2 Tainted: G W 7.2.0-rc6-pmb-bt-functional-v1+ #2 PREEMPT(lazy)"
187: B1 Line exceeds max length (119>80): " 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"
299: B1 Line exceeds max length (94>80): " page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff8881071f4e00 pfn:0x1071f4"
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
Sanitizer errors:
==35==ERROR: AddressSanitizer: heap-use-after-free on address 0x7c24aa8e33d0 at pc 0x55dc41eebe8e bp 0x7ffd90feee80 sp 0x7ffd90feee70
READ of size 4 at 0x7c24aa8e33d0 thread T0
#0 0x55dc41eebe8d in timeout_callback src/shared/timeout-mainloop.c:33
#1 0x55dc41eecb75 in timeout_callback src/shared/mainloop.c:270
#2 0x55dc41eedaa6 in mainloop_run src/shared/mainloop.c:124
#3 0x55dc41ef03fa in mainloop_run_with_signal src/shared/mainloop-notify.c:196
#4 0x55dc41ef564b in tester_run src/shared/tester.c:1223
#5 0x55dc41e1f17d in main tools/l2cap-tester.c:3918
#6 0x7fe4ab80d600 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:59
#7 0x7fe4ab80d717 in __libc_start_main_impl ../csu/libc-start.c:360
#8 0x55dc41e25c84 in _start (/home/runner/work/bluetooth-next/bluetooth-next/src/bluez/tools/l2cap-tester+0x16cc84) (BuildId: 91c9d49e9766c394468e27ffa29b05e7d348169f)
0x7c24aa8e33d0 is located 0 bytes inside of 40-byte region [0x7c24aa8e33d0,0x7c24aa8e33f8)
freed by thread T0 here:
#0 0x7fe4ac14b3ff in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:51
#1 0x55dc41eec36a in timeout_destroy src/shared/mainloop.c:251
previously allocated by thread T0 here:
#0 0x7fe4ac14c60f in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:67
#1 0x55dc41ed62d5 in util_malloc src/shared/util.c:46
SUMMARY: AddressSanitizer: heap-use-after-free src/shared/timeout-mainloop.c:33 in timeout_callback
No test result found
https://github.com/bluez/bluetooth-next/pull/1033
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-30 16:41 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30 14:43 [PATCH 0/2] Bluetooth: SMP: Serialize root channel updates Cen Zhang
2026-10-30 14:43 ` [PATCH 1/2] Bluetooth: SMP: Serialize forced BR/EDR channel changes Cen Zhang
2026-10-30 16:41 ` Bluetooth: SMP: Serialize root channel updates bluez.test.bot
2026-10-30 14:43 ` [PATCH 2/2] Bluetooth: SMP: Serialize root channel replacement Cen Zhang
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.