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
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ 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] 6+ messages in thread

* RE: Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
  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
  2026-07-17 15:46 ` [PATCH] " Cen Zhang
  2026-08-07  2:59 ` Ali Ahmet Memis
  2 siblings, 0 replies; 6+ messages in thread
From: bluez.test.bot @ 2026-07-03  6:41 UTC (permalink / raw)
  To: linux-bluetooth, zzzccc427

[-- Attachment #1: Type: text/plain, Size: 1903 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1120897

---Test result---

Test Summary:
CheckPatch                    PASS      0.67 seconds
VerifyFixes                   PASS      0.10 seconds
VerifySignedoff               PASS      0.13 seconds
GitLint                       PASS      0.28 seconds
SubjectPrefix                 PASS      0.10 seconds
BuildKernel                   PASS      25.72 seconds
CheckAllWarning               PASS      29.69 seconds
CheckSparse                   PASS      28.42 seconds
BuildKernel32                 PASS      24.95 seconds
CheckKernelLLVM               SKIP      0.00 seconds
TestRunnerSetup               PASS      466.81 seconds
TestRunner_mgmt-tester        FAIL      207.37 seconds
TestRunner_mesh-tester        FAIL      25.91 seconds
IncrementalBuild              PASS      23.83 seconds

Details
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.237 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.743 seconds
Mesh - Send cancel - 2                               Timed out    1.987 seconds


https://github.com/bluez/bluetooth-next/pull/389

---
Regards,
Linux Bluetooth


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

* Re: [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
  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
@ 2026-07-17 15:46 ` Cen Zhang
  2026-07-17 15:50   ` Luiz Augusto von Dentz
  2026-08-07  2:59 ` Ali Ahmet Memis
  2 siblings, 1 reply; 6+ messages in thread
From: Cen Zhang @ 2026-07-17 15:46 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz; +Cc: linux-bluetooth, baijiaju1990

Hi Marcel, Luiz,

Gentle ping on this patch.

Could you please take a look when you have a chance?

Thanks!

Best regards,
Cen Zhang

Cen Zhang <zzzccc427@gmail.com> 于2026年7月3日周五 14:00写道:
>
> 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	[flat|nested] 6+ messages in thread

* Re: [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
  2026-07-17 15:46 ` [PATCH] " Cen Zhang
@ 2026-07-17 15:50   ` Luiz Augusto von Dentz
  2026-07-17 15:55     ` Cen Zhang
  0 siblings, 1 reply; 6+ messages in thread
From: Luiz Augusto von Dentz @ 2026-07-17 15:50 UTC (permalink / raw)
  To: Cen Zhang; +Cc: Marcel Holtmann, linux-bluetooth, baijiaju1990

Hi Cen,

On Fri, Jul 17, 2026 at 11:46 AM Cen Zhang <zzzccc427@gmail.com> wrote:
>
> Hi Marcel, Luiz,
>
> Gentle ping on this patch.
>
> Could you please take a look when you have a chance?

If you really want to bump it just resend it. Sending pings like this
won't retrigger the CI to pick it up and test it.

> Thanks!
>
> Best regards,
> Cen Zhang
>
> Cen Zhang <zzzccc427@gmail.com> 于2026年7月3日周五 14:00写道:
> >
> > 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



-- 
Luiz Augusto von Dentz

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

* Re: [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
  2026-07-17 15:50   ` Luiz Augusto von Dentz
@ 2026-07-17 15:55     ` Cen Zhang
  0 siblings, 0 replies; 6+ messages in thread
From: Cen Zhang @ 2026-07-17 15:55 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Marcel Holtmann, linux-bluetooth, baijiaju1990

Hi Luiz,

Luiz Augusto von Dentz <luiz.dentz@gmail.com> 于2026年7月17日周五 23:50写道:
>
> If you really want to bump it just resend it. Sending pings like this
> won't retrigger the CI to pick it up and test it.

Thanks for the clarification. I'll resend it next week.

Best regards,
Cen Zhang

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

* Re: [PATCH] Bluetooth: MGMT: dequeue queued mesh send before freeing canceled tx
  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
  2026-07-17 15:46 ` [PATCH] " Cen Zhang
@ 2026-08-07  2:59 ` Ali Ahmet Memis
  2 siblings, 0 replies; 6+ messages in thread
From: Ali Ahmet Memis @ 2026-08-07  2:59 UTC (permalink / raw)
  To: Cen Zhang
  Cc: Marcel Holtmann, Luiz Augusto von Dentz, linux-bluetooth,
	baijiaju1990

Hi Cen,

On Fri, Jul 3, 2026 at 14:00, Cen Zhang wrote:
> Dequeue any queued mesh_send_sync() for the target tx from send_cancel().

The analysis looks right to me, but the fix is scoped to send_cancel()
and there is a second path that frees a mgmt_mesh_tx while a queued
mesh_send_sync() still carries the pointer.

mgmt_cleanup(), called from hci_sock_release(), walks every controller
and completes the mesh entries belonging to the closing socket:

	list_for_each_entry(hdev, &hci_dev_list, list) {
		do {
			mesh_tx = mgmt_mesh_next(hdev, sk);

			if (mesh_tx)
				mesh_send_complete(hdev, mesh_tx, true);
		} while (mesh_tx);
	}

mesh_send_complete() reaches mgmt_mesh_remove(), which does the same
list_del() + sock_put() + kfree() your commit message describes, with no
hci_cmd_sync_dequeue() first. So closing the control socket right after
MGMT_OP_MESH_SEND, or while mesh_next() has queued the send for the next
tx, frees the object the queued mesh_send_sync() will dereference. That
is the same use-after-free, reached without MGMT_OP_MESH_SEND_CANCEL.

Separately, mgmt_cleanup() holds only hci_dev_list_lock, never
hdev->lock, while it traverses hdev->mesh_pending and removes entries
from it. mesh_send() inserts into that list under hci_dev_lock(hdev), so
the list itself is walked unsynchronised against insertion. Note this
one cannot be fixed by simply adding hci_dev_lock() there, since
hci_dev_list_lock is an rwlock and hci_dev_lock() is a mutex; it needs
the usual hci_dev_hold() and drop-the-list-lock dance.

Given both, an explicit owner reference on mgmt_mesh_tx may end up
simpler than dequeuing at each free site: the pending list holds one
reference, the queued cmd_sync entry holds another via a destroy
callback, and only the last put does sock_put() and kfree(). That would
cover send_cancel() and mgmt_cleanup() together, and would not need
every future caller to remember the dequeue.

To be clear about what I did and did not do: this is from reading the
code, I have not reproduced the socket-close variant, and I have not
tested your patch.

Regards,
Ali Ahmet Memis

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

end of thread, other threads:[~2026-08-07  2:59 UTC | newest]

Thread overview: 6+ 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
2026-07-17 15:46 ` [PATCH] " Cen Zhang
2026-07-17 15:50   ` Luiz Augusto von Dentz
2026-07-17 15:55     ` Cen Zhang
2026-08-07  2:59 ` Ali Ahmet Memis

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