* [PATCH] Bluetooth: msft: Lock failed probe cleanup against feature readers
@ 2026-10-06 14:41 Cen Zhang
0 siblings, 0 replies; only message in thread
From: Cen Zhang @ 2026-10-06 14:41 UTC (permalink / raw)
To: marcel, luiz.dentz
Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427
The MSFT data must remain allocated while msft_get_features() reads
its features. read_adv_mon_features() protects that access with
hdev->lock, but msft_do_open() clears hdev->msft_data and frees the
object without that lock when read_supported_features() fails.
After a successful probe, the data survives a normal close. A later
open can fail the probe while a management feature request is running.
hci_mgmt_cmd() permits requests during HCI_INIT, and the opener's
hdev->req_lock does not serialize the management reader:
Management feature request HCI open
hold hdev->req_lock
msft_do_open()
hold hdev->lock
msft_get_features(): save msft
read_supported_features() fails
hdev->msft_data = NULL
kfree(msft)
read msft->features
release hdev->lock release hdev->req_lock
The saved pointer then refers to freed memory, causing a use-after-free
read. Advertisement reporting through mgmt_device_found() also reads
the features with hdev->lock held.
Take hdev->lock around clearing and freeing msft_data in the failure
branch. An existing feature reader finishes before the free, while a
reader starting after cleanup sees NULL. Keep the synchronous probe
outside this critical section, following the existing req_lock to
hdev->lock ordering.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in msft_monitor_supported+0xa9/0xb0
Read of size 8 at addr ffff88811573ee00 by task mgmt-read-adv-m/532
CPU: 2 UID: 0 PID: 532 Comm: mgmt-read-adv-m 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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? msft_monitor_supported+0xa9/0xb0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? msft_monitor_supported+0xa9/0xb0
kasan_report+0xe0/0x110
? msft_monitor_supported+0xa9/0xb0
msft_monitor_supported+0xa9/0xb0
read_adv_mon_features+0xdf/0x640
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_read_adv_mon_features+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? do_raw_read_unlock+0x49/0xe0
? srso_alias_return_thunk+0x5/0xfbef5
? _raw_read_unlock+0x23/0x40
hci_sock_sendmsg+0x12b5/0x2270
? __pfx_hci_sock_sendmsg+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? selinux_socket_sendmsg+0x160/0x280
__sys_sendto+0x425/0x470
? __pfx_hci_sock_sendmsg+0x10/0x10
? __pfx___sys_sendto+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? __sys_setsockopt+0x119/0x180
__x64_sys_sendto+0xe5/0x1c0
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
? trace_hardirqs_on+0x18/0x160
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f9ceb04a687
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:00007ffe6ab96a70 EFLAGS: 00000202 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007f9ceafb8780 RCX: 00007f9ceb04a687
RDX: 0000000000000006 RSI: 00007ffe6ab96aea RDI: 0000000000000003
RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000003
R13: 00007ffe6ab96d50 R14: 00007f9ceb1f6000 R15: 00005625e427dd68
</TASK>
Allocated by task 506:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
msft_register+0x54/0x260
hci_register_dev+0x6b7/0xc80
__vhci_create_device+0x330/0x840
vhci_write+0x287/0x440
vfs_write+0x637/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 529:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
msft_do_open+0x604/0x9e0
hci_dev_open_sync+0x94a/0x2110
hci_dev_do_open+0x2f/0xb0
hci_dev_open+0x17d/0x300
hci_sock_ioctl+0x3c6/0x710
sock_do_ioctl+0x120/0x2b0
sock_ioctl+0x41b/0x670
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff88811573ee00
which belongs to the cache kmalloc-256 of size 256
The buggy address is located 0 bytes inside of
freed 256-byte region [ffff88811573ee00, ffff88811573ef00)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
pfn:0x11573e
head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x200000000000040(head|node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000040 ffff888100042b40 dead000000000100
dead000000000122
raw: 0000000000000000 0000000000100010 00000000f5000000
0000000000000000
head: 0200000000000040 ffff888100042b40 dead000000000100
dead000000000122
head: 0000000000000000 0000000000100010 00000000f5000000
0000000000000000
head: 0200000000000001 ffffffffffffff81 00000000ffffffff
00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff
0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88811573ed00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88811573ed80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88811573ee00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff88811573ee80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88811573ef00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================
Fixes: 5031ffcc79b8 ("Bluetooth: Keep MSFT ext info throughout a hci_dev's life cycle")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index d9dd722db3ebd5daf1a19fc50996c55e44494378..6f4b7c38a2474511062f38d20ccac6900035f322 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -654,8 +654,10 @@ void msft_do_open(struct hci_dev *hdev)
msft->features = 0;
if (!read_supported_features(hdev, msft)) {
+ hci_dev_lock(hdev);
hdev->msft_data = NULL;
kfree(msft);
+ hci_dev_unlock(hdev);
return;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-06 14:42 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-06 14:41 [PATCH] Bluetooth: msft: Lock failed probe cleanup against feature readers Cen Zhang
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®