# DF-0039 — PoC

`pts_race.c` — exercises the `ptsopen` check-then-use TOCTOU race on
`dev->si_drv1` from the unprivileged `maxx` account.

## The bug (source-level)

`ptsopen` (`sys/kern/tty_pty.c:313-317`) tests `dev->si_drv1 == NULL` (`:313`)
then re-reads `pti = dev->si_drv1` (`:315`) with no lock; a concurrent
`ptcclose()`→`pti_done()` nulls `si_drv1` (`:279`) between the two unlocked
loads, so `lwkt_gettoken(&pti->pt_tty.t_token)` (`:317`) would dereference
NULL → panic. `ptcopen` (`:571-573`) uses the safe single-read pattern.

## Verdict (this run)

**NOT REPRODUCED on the master DEV kernel** (certain).  GCC 8.3 at `-O2`
CSE-fuses the two source-level reads of `dev->si_drv1` into a single
`mov 0x98(%r14),%r12`, identical to the safe `ptcopen` pattern.  The race
window the finding describes does not exist in the compiled kernel.  34
million race attempts (42 500 iterations × 4 × 200 opens) produced no
panic.  See `VERDICT.md` and `ptsopen.kernel.asm` for the full proof.

The bug is still worth fixing in source as defense-in-depth — a different
compiler/version/flags would resurrect the two-load form.  See `fix.diff`.

## Build & run (unprivileged, disposable VM)

```
./build.sh           # cc -pthread -O2 -o pts_race pts_race.c
./run.sh             # races for 60 s; prints iter count, no panic expected
```

## Expected output

On the current master DEV kernel: a stream of `[pts_race] iter=N (no panic)`
lines, then exit.  Guest stays up.

On a hypothetical kernel where the race is reachable: kernel panic
(NULL deref in `ptsopen`).

## Files

- `pts_race.c` — race PoC (rewritten from the original to actually build
  and run on DragonFly).
- `ptsopen.kernel.asm` / `ptcopen.kernel.asm` / `pti_done.kernel.asm` —
  objdump of the shipped `/boot/kernel/kernel` showing the CSE-fused
  single load in `ptsopen` (the proof).
- `build.log` / `run.log` — full build and decisive 60 s run output.
- `env.txt` — guest uname, compiler, sysctls.
- `fix.diff` — `git apply`-able single-read fix matching `ptcopen`.
- `VERDICT.md` — full narrative.
- `manifest.json` — artifact catalog.
