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 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.