# DF-0017 — PoC (REPRODUCED)

Unbounded recursion in `kdmsg_simulate_failure()` / `kdmsg_state_dying()`
(`sys/kern/kern_dmsg.c:1346` / `:1428`) overflows the 16 KB LWKT kernel
thread stack via a deep DMSG circuit-nesting chain.  See `VERDICT.md` for
the full analysis.

## Status

**REPRODUCED** — kernel stack-overflow DoS (double-fault panic) on
DragonFly master DEV `v6.5.0.1712.g89e6a-DEVELOPMENT`.  Prior
`inconclusive` (could not obtain a connected DMSG iocom fd) is resolved:
`trigger.c` performs the disk-open + socketpair + `DIOCRECLUSTER` setup
itself.

## Files

- `trigger.c` — **self-contained reproducer** (the one to use).  Opens
  `/dev/vbd0`, builds a socketpair, attaches one end to the kernel disk
  DMSG iocom via `DIOCRECLUSTER`, writes N chained CREATE messages
  (circuit nesting) + a root DELETE.  Includes a drain thread.
- `kdmsg_stackoverflow.c` — the original wire-format builder (retained as
  the minimal trigger reference; it expects the caller to supply the fd).
- `build.sh` / `run.sh` — one-command build + run (run.sh also frees the
  disk iocom by killing the boot-time hammer2 daemon — see below).
- `VERDICT.md` — full narrative + evidence.
- `build.log`, `run.log`, `panic.txt`, `env.txt` — untrimmed logs.

## Build (on the DragonFly guest, as root)

```
./build.sh        # cc -o trigger trigger.c -lpthread
```

## Run (as root)

```
# (once, to capture the panic on a headless guest)
echo 'console="comconsole"' >> /boot/loader.conf && reboot

./run.sh          # default depth 300; frees the disk iocom, then fires
# or:  ./run.sh 300
```

### Why run.sh kills the hammer2 daemon

On this image the userland hammer2 cluster daemon (pid "hammer2") connects
every disk iocom at boot via `DIOCRECLUSTER` (`sbin/hammer2/cmd_service.c:898`)
and relays peer DMSG traffic (TCP 987) into the kernel.  That leaves each
disk iocom's reader blocked in `fp_read()`, which deadlocks a follow-on
`DIOCRECLUSTER` in `kdmsg_iocom_reconnect()` (`kern_dmsg.c:141`).  Killing
the daemon breaks the pipes, the readers exit, and a fresh
`DIOCRECLUSTER` succeeds.  The root fs (hammer2 on vbd0s1d) has its own
kernel iocom and is unaffected.  `run.sh` does `pkill -9 -x hammer2` first.

## Expected output

- **Bug present:** kernel panic — `Fatal double fault` (total stack
  exhaustion, page-aligned `rsp`), guest freezes in DDB.  `vm.sh reset`
  to recover.
- **Control (`./run.sh 5`):** no panic, trigger exits 0 (shallow chain).
- **Fixed kernel (depth cap):** trigger exits 0, no panic at any depth.

## Reachability / impact

- **Local** (`DIOCRECLUSTER`): needs to open a raw disk node
  (`/dev/vbd0` is `root:operator crw-r-----`); unprivileged users are
  denied.  → root/operator.
- **Remote** (HAMMER2 cluster relay, TCP 987): `LNK_AUTH` unimplemented,
  receive-side CRC not checked → a network peer/MITM can forge the
  chain.  → unauthenticated DoS for HAMMER2-clustered deployments.
- No guard page on the LWKT stack → also an (uncontrolled) kernel
  memory-corruption primitive; realistically reliable impact = DoS.
