Deadlock: callout_stop under pcb_lock while timeout callback requires pcb_lock
Summary
ng_btsocket_l2cap_untimeout(:2765-2775) asserts pcb_lock held, calls callout_stop under it. Timeout callback process_timeout(:2782-2786) acquires pcb_lock as first action. callout_init_mp(:1982) NOT callout_init_lk -> DragonFly callout_stop sync=1 blocks until callback done. Cycle: thread A holds pcb_lock sleeps in callout_stop waiting callback; softclock callback blocked on pcb_lock waiting A. Uninterruptible deadlock. Every untimeout caller under pcb_lock affected: detach(:2355) disconnect(:2411) all process_l2ca_* paths. Local user: AF_BLUETOOTH socket + close racing 300s ERTX timer.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0325 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-trace confirmed deadlock, no BT HW | 2.3 KB | β raw |
| README.md | readme | status explanation | 750 B | β raw |
| fix.diff | suggested-fix | use callout_stop_async instead of callout_stop | 850 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-0325 PoC β Bluetooth L2CAP callout deadlock
Status: REAL (source-trace confirmed), not testable on this guest
The deadlock is confirmed by tracing:
- ng_btsocket_l2cap_untimeout() holds pcb_lock then calls
callout_stop() (sync=1) which blocks until the callback finishes
- The callback ng_btsocket_l2cap_process_timeout() needs pcb_lock
as its first action
- Classic AB-BA deadlock
Not testable because:
- ng_btsocket_l2cap module is not loaded by default
- Not compiled into GENERIC kernel
- Requires Bluetooth hardware (none on guest)
- Loading requires kldload (root-only, invalidates unpriv chain)
Fix
See fix.diff β replaces callout_stop() with
callout_stop_async() to avoid the synchronous wait.
DF-0325 β Deadlock: callout_stop under pcb_lock while timeout callback needs pcb_lock
Verdict: REAL (source-trace confirmed) β not testable on this guest (no Bluetooth HW/module)
Mechanism
ng_btsocket_l2cap_untimeout() at
sys/netgraph7/bluetooth/socket/ng_btsocket_l2cap.c:2765-2775:
2767: KKASSERT(lockowned(&pcb->pcb_lock) != 0); // holds pcb_lock
2770: callout_stop(&pcb->timo); // blocks until callback done
ng_btsocket_l2cap_process_timeout() (the timeout callback) at
:2782-2786:
2786: lockmgr(&pcb->pcb_lock, LK_EXCLUSIVE); // needs pcb_lock
callout_init_mp(&pcb->timo) at :1982 uses the MP (non-lock)
variant. DragonFly's callout_stop() calls
_callout_cancel_or_stop(cc, CALLOUT_STOP, 1) with sync=1
(sys/kern/kern_timeout.c:1093), which at :910-921 enters a
ssleep() loop waiting for the callback to finish:
910: ++c->waiters;
911: for (;;) {
912: cpu_ccfence();
913: if ((c->flags & flags) == 0) break;
...
920: ssleep(c, &c->spin, 0, "costp", 0);
921: }
Deadlock cycle:
- Thread A: holds pcb_lock β sleeps in callout_stop waiting for
callback to finish
- Callback (softclock): tries to acquire pcb_lock β blocked waiting
for Thread A
Neither can make progress. The system deadlocks (one CPU stuck spinning on pcb_lock, another sleeping in callout_stop).
Privilege / testability
- The
ng_btsocket_l2capmodule is not loaded by default and is not compiled into the GENERIC kernel. - Loading it requires
kldload(root-only). - Even loaded, it requires Bluetooth hardware/stack to create L2CAP sockets.
- No Bluetooth hardware on this guest.
This is a valid hard blocker: the code path is dead code on this guest (no Bluetooth). The deadlock is confirmed via source trace.
Fix
fix.diff β use callout_stop_async() instead of callout_stop()
in ng_btsocket_l2cap_untimeout(). The async variant requests
cancellation without blocking, so the pcb_lock holder doesn't sleep.
The pcb->flags &= ~NG_BTSOCKET_L2CAP_TIMO immediately after makes
any in-flight callback a no-op when it eventually acquires the lock.
Impact
Local DoS (system deadlock/hang) if Bluetooth L2CAP sockets are available. Requires the bluetooth netgraph stack to be loaded and operational. No memory corruption β pure DoS.
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. callout_stop(sync) under pcb_lock vs timeout callback LK_EXCLUSIVE -> AB-BA deadlock. ng_btsocket not in GENERIC.
No comments yet.