* [PATCH] Bluetooth: mgmt: Remove mesh cleanup from the socket destructor
@ 2026-10-12 1:58 Cen Zhang
0 siblings, 0 replies; only message in thread
From: Cen Zhang @ 2026-10-12 1:58 UTC (permalink / raw)
To: marcel, luiz.dentz, brian.gix
Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427
mgmt_mesh_add() takes a socket reference before linking a mesh
transmission, and mgmt_mesh_remove() unlinks it before dropping that
reference. A socket reaching hci_sock_destruct() therefore cannot own
any entries in mesh_pending. Nevertheless, the destructor calls
mgmt_cleanup(), which scans every controller's mesh_pending list without
protecting the entries against request completion.
With mesh enabled on an LE controller, a pending transmission owned by
socket B can complete while an unrelated socket A is being destroyed.
For a successful send, mesh_send_start_complete() schedules
mesh_send_done(), which queues mesh_send_done_sync() on the controller's
request workqueue. While the controller remains registered, the paths
can interleave as follows:
1. A enters hci_sock_destruct() -> mgmt_cleanup(), and mgmt_mesh_next()
obtains a pointer to B's linked mesh_tx.
2. B's worker runs mesh_send_done_sync() -> mesh_send_complete() ->
mgmt_mesh_remove(), unlinks mesh_tx, drops B's socket reference and
frees the entry.
3. A reads mesh_tx->sk to compare it with A's socket, accessing freed
memory.
The hci_dev_list_lock held by A protects controller membership, but B's
completion does not acquire it and can free the entry before A's read.
The socket reference held by the entry keeps B alive, but does not keep
B's mesh_tx alive for A's traversal. Start-error completion can remove
the same entry through mesh_send_start_complete() as well.
Remove the destructor's mesh cleanup call. The existing socket
references ensure that all of that socket's mesh entries are unlinked
before destruction. Mesh completion and cancellation already manage
the entries' lifetime, so the destructor need only purge its queues.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in mgmt_mesh_next+0x119/0x140
Read of size 8 at addr ffff88810c25cf20 by task python3/490
CPU: 3 UID: 0 PID: 490 Comm: python3 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
? mgmt_mesh_next+0x119/0x140
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? mgmt_mesh_next+0x119/0x140
kasan_report+0xe0/0x110
? mgmt_mesh_next+0x119/0x140
? __pfx_sock_close+0x10/0x10
mgmt_mesh_next+0x119/0x140
mgmt_cleanup+0x6c/0xe0
? __pfx_hci_sock_destruct+0x10/0x10
hci_sock_destruct+0x1a/0x50
__sk_destruct+0x85/0x790
? __pfx_sock_close+0x10/0x10
sk_destruct+0xb3/0xd0
__sk_free+0xdd/0x370
sk_free+0x51/0x80
hci_sock_release+0x339/0x550
__sock_release+0xb8/0x270
sock_close+0x21/0x30
__fput+0x39f/0xa60
fput_close_sync+0xff/0x200
? __pfx_fput_close_sync+0x10/0x10
? dnotify_flush+0x22/0x4b0
__x64_sys_close+0x8c/0xf0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f057299a687
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:00007fffcf66d4a0 EFLAGS: 00000202 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 00007f0572906780 RCX: 00007f057299a687
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000005
RBP: 0000000000000005 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000a83590
R13: 0000000000a83590 R14: 0000000000000000 R15: 00007f0572744188
</TASK>
Allocated by task 490:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
mgmt_mesh_add+0x5d/0x3e0
mesh_send+0x22d/0x6c0
hci_sock_sendmsg+0x128b/0x22e0
__sys_sendto+0x425/0x470
__x64_sys_sendto+0xe5/0x1c0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 492:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
mesh_send_done_sync+0x115/0x180
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 ffff88810c25cf00
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 32 bytes inside of
freed 96-byte region [ffff88810c25cf00, ffff88810c25cf60)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
pfn:0x10c25c
flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff888100042280 dead000000000100
dead000000000122
raw: 0000000000000000 0000000000200020 00000000f5000000
0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88810c25ce00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff88810c25ce80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
>ffff88810c25cf00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff88810c25cf80: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff88810c25d000: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
==================================================================
Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index b26f065d0c18ff3a7cd4b2be1f3fc44d1d2a0605..24cfa6db7654255e5192be75fad49478db251817 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -2186,7 +2186,6 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname,
static void hci_sock_destruct(struct sock *sk)
{
- mgmt_cleanup(sk);
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&sk->sk_error_queue);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-12 1:58 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-12 1:58 [PATCH] Bluetooth: mgmt: Remove mesh cleanup from the socket destructor 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®