possible deadlock in add_ext_adv_params_complete

Status: moderation: reported on 2026/11/15 11:16
Subsystems: bluetooth
Labels: prio:low
[Documentation on labels]
Reported-by: syzbot+7aecdf521b41d5854686@syzkaller.appspotmail.com
First crash: 1h40m, last: 1h40m
✨ AI-generated root cause summary:

An ABBA circular locking dependency exists between hdev->lock and hdev->cmd_sync_work_lock in the Bluetooth subsystem. Callers holding hci_dev_lock(hdev) (such as MGMT command handlers and HCI event handlers) acquire hdev->cmd_sync_work_lock when enqueuing or looking up cmd_sync work via hci_cmd_sync_queue()/hci_cmd_sync_queue_once(). Conversely, hci_cmd_sync_clear() (and related cancellation paths in net/bluetooth/hci_sync.c) acquires hdev->cmd_sync_work_lock and calls _hci_cmd_sync_cancel_entry(), which invokes entry->destroy (e.g. add_ext_adv_params_complete) while still holding hdev->cmd_sync_work_lock. Because entry->destroy attempts to acquire hci_dev_lock(hdev), this inverts the lock hierarchy and causes a deadlock.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 6964ff21c5d8:

Root Cause Analysis

1. Components and Locks Involved

2. The Lock Dependency Cycle (ABBA Inversion)

Order 1: &hdev->lock $\rightarrow$ &hdev->cmd_sync_work_lock

Throughout net/bluetooth/mgmt.c and net/bluetooth/hci_event.c, operations acquire hci_dev_lock(hdev) before scheduling synchronous HCI commands:

Order 2: &hdev->cmd_sync_work_lock $\rightarrow$ &hdev->lock

During device deregistration or command cancellation (hci_unregister_dev() $\rightarrow$ hci_cmd_sync_clear(), net/bluetooth/hci_sync.c:682):

void hci_cmd_sync_clear(struct hci_dev *hdev)
{
    ...
    mutex_lock(&hdev->cmd_sync_work_lock);
    list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list)
        _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
    mutex_unlock(&hdev->cmd_sync_work_lock);
}

_hci_cmd_sync_cancel_entry() calls the entry's destroy callback while &hdev->cmd_sync_work_lock is held:

static void _hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
                                       struct hci_cmd_sync_work_entry *entry,
                                       int err)
{
    if (entry->destroy)
        entry->destroy(hdev, entry->data, err);

    list_del(&entry->list);
    kfree(entry);
}

When entry->destroy is add_ext_adv_params_complete() (or similar MGMT completion handlers such as add_advertising_complete()), it begins by acquiring hci_dev_lock(hdev) (net/bluetooth/mgmt.c:9253) to clean up advertising instances (hci_find_adv_instance, hci_remove_adv_instance).

3. Invariant Violation and Mechanism

Notice the contrast with standard worker execution in hci_cmd_sync_work() (net/bluetooth/hci_sync.c:321-342), where cmd_sync_work_lock is held only to detach entry from hdev->cmd_sync_work_list via list_del(&entry->list) and dropped before executing entry->func and entry->destroy.

In hci_cmd_sync_clear() (as well as _hci_cmd_sync_cancel_entry() and hci_cmd_sync_dequeue()), entry->destroy is invoked inside the critical section protected by cmd_sync_work_lock. Because callbacks can validly manage device resources protected by hdev->lock, invoking entry->destroy under cmd_sync_work_lock violates the established locking hierarchy and triggers the reported lockdep warning / circular deadlock.

▶ ▼ ✨ AI Jobs (1)
ID Workflow Result Correct Bug Created Started Finished Revision
29f58bce assessment-security DenialOfService: ✅ Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ possible deadlock in add_ext_adv_params_complete 2026/11/15 10:29 2026/11/15 10:29 2026/11/15 11:12 819ebe34

Sample crash report:
======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Not tainted
------------------------------------------------------
syz-executor/5634 is trying to acquire lock:
ffff8880298c40b8 (&hdev->lock){+.+.}-{4:4}, at: add_ext_adv_params_complete+0xd5/0x890 net/bluetooth/mgmt.c:9253

but task is already holding lock:
ffff8880298c47c0 (&hdev->cmd_sync_work_lock){+.+.}-{4:4}, at: hci_cmd_sync_clear+0xfb/0x3f0 net/bluetooth/hci_sync.c:682

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&hdev->cmd_sync_work_lock){+.+.}-{4:4}:
       __mutex_lock_common kernel/locking/mutex.c:646 [inline]
       __mutex_lock+0x197/0x15a0 kernel/locking/mutex.c:821
       hci_cmd_sync_lookup_entry net/bluetooth/hci_sync.c:869 [inline]
       hci_cmd_sync_queue_once+0x42/0x250 net/bluetooth/hci_sync.c:806
       hci_update_passive_scan+0x1bf/0x210 net/bluetooth/hci_sync.c:3518
       le_conn_complete_evt+0xee9/0x18d0 net/bluetooth/hci_event.c:6106
       hci_le_conn_complete_evt+0x187/0x470 net/bluetooth/hci_event.c:6117
       hci_event_func net/bluetooth/hci_event.c:8084 [inline]
       hci_event_packet+0x67a/0xf10 net/bluetooth/hci_event.c:8138
       hci_rx_work+0x2b4/0x1110 net/bluetooth/hci_core.c:4150
       process_one_work kernel/workqueue.c:3495 [inline]
       process_scheduled_works+0xc3d/0x1630 kernel/workqueue.c:3578
       worker_thread+0xa47/0xfb0 kernel/workqueue.c:3659
       kthread+0x38b/0x480 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #0 (&hdev->lock){+.+.}-{4:4}:
       check_prev_add kernel/locking/lockdep.c:3209 [inline]
       check_prevs_add kernel/locking/lockdep.c:3328 [inline]
       validate_chain kernel/locking/lockdep.c:3952 [inline]
       __lock_acquire+0x164c/0x2de0 kernel/locking/lockdep.c:5288
       lock_acquire+0x115/0x350 kernel/locking/lockdep.c:5942
       __mutex_lock_common kernel/locking/mutex.c:646 [inline]
       __mutex_lock+0x197/0x15a0 kernel/locking/mutex.c:821
       add_ext_adv_params_complete+0xd5/0x890 net/bluetooth/mgmt.c:9253
       _hci_cmd_sync_cancel_entry net/bluetooth/hci_sync.c:667 [inline]
       hci_cmd_sync_clear+0x1b4/0x3f0 net/bluetooth/hci_sync.c:684
       hci_unregister_dev+0x1b4/0x5c0 net/bluetooth/hci_core.c:2697
       vhci_release+0x16d/0x1c0 drivers/bluetooth/hci_vhci.c:704
       __fput+0x408/0xa40 fs/file_table.c:512
       fput_close_sync+0x11f/0x240 fs/file_table.c:618
       filp_close_sync+0x6e/0xa0 fs/open.c:1574
       close_files fs/file.c:572 [inline]
       put_files_struct+0x230/0x3c0 fs/file.c:584
       do_exit+0x6f0/0x2360 kernel/exit.c:977
       do_group_exit+0x22d/0x2f0 kernel/exit.c:1123
       get_signal+0x136a/0x1430 kernel/signal.c:3113
       arch_do_signal_or_restart+0xbb/0x860 arch/x86/kernel/signal.c:337
       __exit_to_user_mode_loop kernel/entry/common.c:66 [inline]
       exit_to_user_mode_loop+0x10e/0x770 kernel/entry/common.c:101
       __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [inline]
       syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:230 [inline]
       syscall_exit_to_user_mode include/linux/entry-common.h:343 [inline]
       do_syscall_64+0x32c/0x530 arch/x86/entry/syscall_64.c:107
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&hdev->cmd_sync_work_lock);
                               lock(&hdev->lock);
                               lock(&hdev->cmd_sync_work_lock);
  lock(&hdev->lock);

 *** DEADLOCK ***

locks held by syz-executor/5634: 1, on CPU#1:
 #0: ffff8880298c47c0 (&hdev->cmd_sync_work_lock){+.+.}-{4:4}, at: hci_cmd_sync_clear+0xfb/0x3f0 net/bluetooth/hci_sync.c:682

stack backtrace:
CPU: 1 UID: 0 PID: 5634 Comm: syz-executor Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/06/2026
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 print_circular_bug+0x2e2/0x300 kernel/locking/lockdep.c:2087
 check_noncircular+0x12f/0x150 kernel/locking/lockdep.c:2219
 check_prev_add kernel/locking/lockdep.c:3209 [inline]
 check_prevs_add kernel/locking/lockdep.c:3328 [inline]
 validate_chain kernel/locking/lockdep.c:3952 [inline]
 __lock_acquire+0x164c/0x2de0 kernel/locking/lockdep.c:5288
 lock_acquire+0x115/0x350 kernel/locking/lockdep.c:5942
 __mutex_lock_common kernel/locking/mutex.c:646 [inline]
 __mutex_lock+0x197/0x15a0 kernel/locking/mutex.c:821
 add_ext_adv_params_complete+0xd5/0x890 net/bluetooth/mgmt.c:9253
 _hci_cmd_sync_cancel_entry net/bluetooth/hci_sync.c:667 [inline]
 hci_cmd_sync_clear+0x1b4/0x3f0 net/bluetooth/hci_sync.c:684
 hci_unregister_dev+0x1b4/0x5c0 net/bluetooth/hci_core.c:2697
 vhci_release+0x16d/0x1c0 drivers/bluetooth/hci_vhci.c:704
 __fput+0x408/0xa40 fs/file_table.c:512
 fput_close_sync+0x11f/0x240 fs/file_table.c:618
 filp_close_sync+0x6e/0xa0 fs/open.c:1574
 close_files fs/file.c:572 [inline]
 put_files_struct+0x230/0x3c0 fs/file.c:584
 do_exit+0x6f0/0x2360 kernel/exit.c:977
 do_group_exit+0x22d/0x2f0 kernel/exit.c:1123
 get_signal+0x136a/0x1430 kernel/signal.c:3113
 arch_do_signal_or_restart+0xbb/0x860 arch/x86/kernel/signal.c:337
 __exit_to_user_mode_loop kernel/entry/common.c:66 [inline]
 exit_to_user_mode_loop+0x10e/0x770 kernel/entry/common.c:101
 __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [inline]
 syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:230 [inline]
 syscall_exit_to_user_mode include/linux/entry-common.h:343 [inline]
 do_syscall_64+0x32c/0x530 arch/x86/entry/syscall_64.c:107
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f35a9f69d0e
Code: Unable to access opcode bytes at 0x7f35a9f69ce4.
RSP: 002b:00007ffe3a7895f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
RAX: fffffffffffffe00 RBX: 00005555922b8500 RCX: 00007f35a9f69d0e
RDX: 0000000000000030 RSI: 00007ffe3a7896f0 RDI: 00000000000000f9
RBP: 00007ffe3a78969c R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000258
R13: 000000000000002b R14: 000000000006526d R15: 00007ffe3a7896f0
 </TASK>

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/15 10:29 net-next 6964ff21c5d8 819ebe34 .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-net-kasan-gce possible deadlock in add_ext_adv_params_complete
* Struck through repros no longer work on HEAD.