# DF-0533 — bt3c hard-ISR vs SWI unsynchronized inq/outq race (UAF)

**Verdict:** LATENT on this guest (source bug real; not runtime-exercisable).
**Fix authored** (`fix.diff`, applies cleanly; `not_testable` — no PCMCIA HW).

## Bug
`ng_bt3c_pccard.c` registers a hard ISR (`bt3c_intr` → `bt3c_receive`) that does
`IF_ENQUEUE(&sc->inq, …)` (`:939`) and an SWI handler (`bt3c_swi_intr` →
`bt3c_forward`) that does `IF_DEQUEUE(&sc->inq, …)` (`:1017`). `IF_*QUEUE` macros
(`net/if_var.h:484-510`) are **lock-free** linked-list ops, and `attach`
initialises **no lock** for `inq`/`outq`. A hard IRQ landing mid-`IF_DEQUEUE`
corrupts the list → dangling `ifq_head`/`ifq_tail` → UAF. Same shape on `outq`
(`:566` vs `:1060/:1081`).

## Reachability
**Latent on this guest.** The driver is `optional netgraph7_bluetooth_bt3c`
(`sys/conf/files:1669`); there is no `ng_bt3c.ko` shipped, no `bt3c` symbols in
the running kernel, **no PCMCIA/pccard bus** in QEMU, and the 3Com 3CRWB6095
card it drives is absent. So the race is dead code here — a real defect that
would manifest on real hardware.

## Fix
`fix.diff` adds a `struct spinlock sc_lock` to `bt3c_softc`
(`ng_bt3c_var.h`), `spin_init`s it in `attach`, and wraps every
`IF_ENQUEUE/IF_DEQUEUE/IF_PREPEND` site (inq + outq) with
`spin_lock/spin_unlock`, serialising the ISR producer against the SWI/netgraph
consumers. Applies cleanly; not build-validated (needs PCMCIA headers/HW).

See `VERDICT.md` for the full line-cited trace.
