Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
@ 2026-07-03  6:00 Cen Zhang
  2026-07-03  6:41 ` bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Cen Zhang @ 2026-07-03  6:00 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz
  Cc: linux-bluetooth, baijiaju1990, zzzccc427

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

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-03  6:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-03  6:00 [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx Cen Zhang
2026-07-03  6:41 ` bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox