From: Cen Zhang <zzzccc427@gmail.com>
To: Marcel Holtmann <marcel@holtmann.org>,
Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: linux-bluetooth@vger.kernel.org, baijiaju1990@gmail.com,
zzzccc427@gmail.com
Subject: [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
Date: Fri, 3 Jul 2026 14:00:24 +0800 [thread overview]
Message-ID: <20260703060024.570535-1-zzzccc427@gmail.com> (raw)
mesh_next() queues mesh_send_sync() with a raw mgmt_mesh_tx pointer after
a previous mesh send completes. MGMT_OP_MESH_SEND_CANCEL can already be
queued on the same hci_cmd_sync_work list. If cancel runs before the queued
send, it can remove and free the same mgmt_mesh_tx while mesh_send_sync()
still carries that pointer as callback data.
The buggy scenario involves two paths, with each column showing the order
within that path:
mesh completion path: cancel command path:
1. mesh_send_done_sync() returns 1. send_cancel is already queued
2. mesh_next() selects next_tx 2. send_cancel finds next_tx
3. mesh_next() queues 3. send_cancel frees next_tx
mesh_send_sync(next_tx)
4. mesh_send_sync() later
dereferences next_tx
Validation reproduced this kernel report:
BUG: KASAN: slab-use-after-free in mesh_send_sync+0x5a/0x1c0 [bluetooth]
Read of size 1 at addr ffff88811a01d13b by task kworker/u17:0/562
Workqueue: hci0 hci_cmd_sync_work [bluetooth]
Call Trace:
<TASK>
dump_stack_lvl+0x66/0xa0
print_report+0xce/0x5f0
? mesh_send_sync+0x5a/0x1c0 [bluetooth]
? __virt_addr_valid+0x19f/0x330
? mesh_send_sync+0x5a/0x1c0 [bluetooth]
kasan_report+0xe0/0x110
? mesh_send_sync+0x5a/0x1c0 [bluetooth]
? __pfx_mesh_send_sync+0x10/0x10 [bluetooth]
mesh_send_sync+0x5a/0x1c0 [bluetooth]
? mesh_send_sync+0x9/0x1c0 [bluetooth]
? __pfx_mesh_send_sync+0x10/0x10 [bluetooth]
hci_cmd_sync_work+0x187/0x210 [bluetooth]
process_one_work+0x4fd/0xbc0
worker_thread+0x2d8/0x570
kthread+0x1ad/0x1f0
ret_from_fork+0x3c9/0x540
ret_from_fork_asm+0x1a/0x30
Allocated by task 602:
kasan_save_stack+0x33/0x60
kasan_save_track+0x17/0x60
__kasan_kmalloc+0xaa/0xb0
mgmt_mesh_add+0x41/0x1a0 [bluetooth]
mesh_send+0x197/0x3a0 [bluetooth]
hci_sock_sendmsg+0x96b/0xf80 [bluetooth]
__sys_sendto+0x2bc/0x2d0
__x64_sys_sendto+0x76/0x90
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 562:
kasan_save_stack+0x33/0x60
kasan_save_track+0x17/0x60
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x313/0x590
send_cancel+0x1d8/0x210 [bluetooth]
hci_cmd_sync_work+0x187/0x210 [bluetooth]
process_one_work+0x4fd/0xbc0
worker_thread+0x2d8/0x570
kthread+0x1ad/0x1f0
ret_from_fork+0x3c9/0x540
ret_from_fork_asm+0x1a/0x30
Dequeue any queued mesh_send_sync() for the target tx from send_cancel().
When a queued send is found, the dequeue path invokes
mesh_send_start_complete(), which completes and frees the tx; send_cancel()
must not complete it again.
Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
net/bluetooth/mgmt.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 733a4b70e10c..ac4922cb39b5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2416,17 +2416,28 @@ static int send_cancel(struct hci_dev *hdev, void *data)
struct mgmt_mesh_tx *mesh_tx;
if (!cancel->handle) {
- do {
+ for (;;) {
mesh_tx = mgmt_mesh_next(hdev, cmd->sk);
- if (mesh_tx)
- mesh_send_complete(hdev, mesh_tx, false);
- } while (mesh_tx);
+ if (!mesh_tx)
+ break;
+
+ /* Dequeue any queued send before freeing the tx. */
+ if (hci_cmd_sync_dequeue(hdev, mesh_send_sync, mesh_tx,
+ mesh_send_start_complete))
+ continue;
+
+ mesh_send_complete(hdev, mesh_tx, false);
+ }
} else {
mesh_tx = mgmt_mesh_find(hdev, cancel->handle);
- if (mesh_tx && mesh_tx->sk == cmd->sk)
- mesh_send_complete(hdev, mesh_tx, false);
+ if (mesh_tx && mesh_tx->sk == cmd->sk) {
+ /* Dequeue any queued send before freeing the tx. */
+ if (!hci_cmd_sync_dequeue(hdev, mesh_send_sync, mesh_tx,
+ mesh_send_start_complete))
+ mesh_send_complete(hdev, mesh_tx, false);
+ }
}
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,
--
2.43.0
next reply other threads:[~2026-07-03 6:00 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 6:00 Cen Zhang [this message]
2026-07-03 6:41 ` Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx bluez.test.bot
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=20260703060024.570535-1-zzzccc427@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=linux-bluetooth@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