All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: MGMT: Serialize power-on with power-off completion
@ 2026-10-13 16:28 Cen Zhang
  2026-10-13 20:19 ` bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Cen Zhang @ 2026-10-13 16:28 UTC (permalink / raw)
  To: marcel, luiz.dentz, padovan, johan.hedberg
  Cc: linux-bluetooth, linux-kernel, baijiaju1990, jjzuming, zzzccc427

mgmt_set_powered_complete() must only consume the pending command for
its own request. However, __mgmt_power_off() removes and frees the
SET_POWERED command before the request's destroy callback runs, and
mgmt_pending_valid() identifies outstanding commands only by address.

When a powered controller is switched off and another management socket
requests power-on, the allocator can reuse the old command's address:

  Power-off request worker          Power-on management handler
  ------------------------          ---------------------------
  __mgmt_power_off(): free cmd
  hci_dev_close_sync(): unlock
  set_powered_sync(): return
                                    set_powered(): lock hdev
                                    allocate and link replacement
  mgmt_pending_valid(): unlink
    replacement at old address
  read replacement's cp->val = 1
  wait for hdev->lock
                                    submit fails: remove/free cmd
                                    unlock hdev
  acquire hdev->lock
  read freed cmd->opcode

The old callback can respond through and free the new command instead of
completing its own request. If hci_cmd_sync_submit() fails to allocate
its work entry after the callback has unlinked the replacement,
set_powered() removes and frees it again while still holding hdev->lock.
The old callback then acquires that lock and reads the freed command.

Serialize power-on publication with the existing request mutex, which
hci_cmd_sync_work() holds across the request function and its destroy
callback. Hold it through submission and error cleanup so the
replacement cannot be published before the old callback finishes.
Acquire it before hdev->lock to preserve the worker's lock order.
Power-off retains its existing cancellation path.

KASAN report as below:

        BUG: KASAN: slab-use-after-free in
    mgmt_set_powered_complete+0x450/0x4d0
    Read of size 2 at addr ffff88810921ab10 by task kworker/u17:0/500

    Workqueue: hci0 hci_cmd_sync_work
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? mgmt_set_powered_complete+0x450/0x4d0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? mgmt_set_powered_complete+0x450/0x4d0
     kasan_report+0xe0/0x110
     ? mgmt_set_powered_complete+0x450/0x4d0
     mgmt_set_powered_complete+0x450/0x4d0
     ? __pfx_mgmt_set_powered_complete+0x10/0x10
     hci_cmd_sync_work+0x207/0x450
     ? __pfx_mgmt_set_powered_complete+0x10/0x10
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>

    Allocated by task 531:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_cache_noprof+0x251/0x610
     mgmt_pending_new+0x60/0x230
     mgmt_pending_add+0x3b/0x180
     set_powered+0x2a8/0x7e0
     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 531:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x307/0x580
     set_powered+0x336/0x7e0
     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

    The buggy address belongs to the object at ffff88810921ab00
                                                                which
                                belongs to the cache kmalloc-96 of size 96
    The buggy address is located 16 bytes inside of
                                                                freed
                                96-byte region [ffff88810921ab00,
                                ffff88810921ab60)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x10921a
    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:
     ffff88810921aa00: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
     ffff88810921aa80: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
    >ffff88810921ab00: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
                             ^
     ffff88810921ab80: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
     ffff88810921ac00: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
    ==================================================================

Fixes: eec8d2bcc841 ("Bluetooth: Add support for set_powered management command")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9f65863e7457d..d523ae2268be8 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1408,6 +1408,13 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
 		return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
 				       MGMT_STATUS_INVALID_PARAMS);
 
+	/*
+	 * Wait for the previous power-off completion before publishing a
+	 * new command that could reuse its freed pending-command address.
+	 */
+	if (cp->val)
+		hci_req_sync_lock(hdev);
+
 	hci_dev_lock(hdev);
 
 	if (!cp->val) {
@@ -1451,6 +1458,8 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
 
 failed:
 	hci_dev_unlock(hdev);
+	if (cp->val)
+		hci_req_sync_unlock(hdev);
 	return err;
 }
 

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

* RE: Bluetooth: MGMT: Serialize power-on with power-off completion
  2026-10-13 16:28 [PATCH] Bluetooth: MGMT: Serialize power-on with power-off completion Cen Zhang
@ 2026-10-13 20:19 ` bluez.test.bot
  0 siblings, 0 replies; 2+ messages in thread
From: bluez.test.bot @ 2026-10-13 20:19 UTC (permalink / raw)
  To: linux-bluetooth, zzzccc427

[-- Attachment #1: Type: text/plain, Size: 2807 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/series/1184931/

---Test result---

Test Summary:
CheckPatch                    PASS      0.60 seconds
VerifyFixes                   PASS      0.06 seconds
VerifySignedoff               PASS      0.06 seconds
GitLint                       PASS      11.67 seconds
SubjectPrefix                 PASS      1.12 seconds
BuildKernel                   PASS      30.33 seconds
CheckAllWarning               PASS      35.37 seconds
CheckSparse                   PASS      37.26 seconds
BuildKernel32                 PASS      29.76 seconds
CheckKernelLLVM               FAIL      23.97 seconds
TestRunnerSetup               PASS      729.63 seconds
TestRunner_mgmt-tester        PASS      87.68 seconds
TestRunner_mesh-tester        PASS      5.48 seconds
IncrementalBuild              PASS      27.87 seconds

Details
##############################
Test: CheckKernelLLVM - FAIL
Desc: Build kernel with LLVM + context analysis
Output:

net/bluetooth/mgmt.c:1418:2: error: mutex 'hdev->req_lock' is not held on every path through here [-Werror,-Wthread-safety-analysis]
 1418 |         hci_dev_lock(hdev);
      |         ^
./include/net/bluetooth/hci_core.h:1799:26: note: expanded from macro 'hci_dev_lock'
 1799 | #define hci_dev_lock(d)         mutex_lock(&d->lock)
      |                                 ^
net/bluetooth/mgmt.c:1416:3: note: mutex acquired here
 1416 |                 hci_req_sync_lock(hdev);
      |                 ^
./include/net/bluetooth/hci_sync.h:15:35: note: expanded from macro 'hci_req_sync_lock'
   15 | #define hci_req_sync_lock(hdev)   mutex_lock(&hdev->req_lock)
      |                                   ^
net/bluetooth/mgmt.c:1462:3: error: releasing mutex 'hdev->req_lock' that was not held [-Werror,-Wthread-safety-analysis]
 1462 |                 hci_req_sync_unlock(hdev);
      |                 ^
./include/net/bluetooth/hci_sync.h:16:35: note: expanded from macro 'hci_req_sync_unlock'
   16 | #define hci_req_sync_unlock(hdev) mutex_unlock(&hdev->req_lock)
      |                                   ^
2 errors generated.
make[4]: *** [scripts/Makefile.build:290: net/bluetooth/mgmt.o] Error 1
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [scripts/Makefile.build:551: net/bluetooth] Error 2
make[2]: *** [scripts/Makefile.build:551: net] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/home/runner/work/bluetooth-next/bluetooth-next/src/src/Makefile:2229: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2


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

---
Regards,
Linux Bluetooth


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

end of thread, other threads:[~2026-10-13 20:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 16:28 [PATCH] Bluetooth: MGMT: Serialize power-on with power-off completion Cen Zhang
2026-10-13 20:19 ` bluez.test.bot

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.