# DF-0586 — PoC: lockless hci_pcb list UAF race

Two-thread race to exercise the `hci_mtap` `LIST_FOREACH` traversal against a
concurrent `hci_sdetach` → `kfree(pcb)`.

## Files

- `poc_race.c` — minimal reproducer (driver thread + closer thread).
- (added by per-PoC verifier) `build.sh`, `run.sh`, `build.log`, `run.log`,
  `VERDICT.md`, `manifest.json`, and — if escalation is developed — `exploit.c`
  plus slab-grooming recipe.

## Build & run (DragonFlyBSD guest)

```
cc -o poc_race poc_race.c -lpthread
./poc_race
```

## Expected first outcome

Kernel panic (`Fatal trap 12: page fault while in kernel mode`) with a
backtrace pinning the fault inside `hci_mtap` (sys/netbt/hci_socket.c:~935-1011)
or `sbappendaddr`, confirming the race.

## Notes for the per-PoC verifier

- Requires an SMP DragonFly guest with a Bluetooth controller present (or a
  loaded `ubt(4)` / `ng_ubt` module so the unit list is non-empty and
  `hci_mtap` actually taps). Verify with `dmesg | grep -i bt` and
  `kldstat | grep ubt`.
- The driver thread should `sendto()` an opcode allowed by
  `hci_security_check_opcode` for unprivileged sockets, otherwise
  `hci_output_cmd` will reject the frame before reaching `hci_mtap`.
- A reproduced panic is the minimum success criterion. The escalation variant
  requires a `sizeof(struct hci_pcb)` slab analysis and a grooming spray —
  document the chosen victim object in `VERDICT.md`.
- If `pru_send` and `pru_detach` for distinct HCI sockets happen to be
  serialized onto the same CPU message port, the race window collapses; in
  that case the verdict should reflect `cannot_reproduce_under_cpu_affinity`
  with the kernel-source trace to back it up, and the finding stays as a
  defence-in-depth concern.
