# 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`:

```c
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`:

```c
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:

```c
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_l2cap` module 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.
