# DF-0176 — cttyioctl VOP_IOCTL UAF (no vnode ref)

## Summary
`cttyioctl` (tty_tty.c:232) calls `VOP_IOCTL(ttyvp, ...)` at :264 after
releasing `p_token` at :262, with NO `vref`/`vget` in between.  The
session ref on `ttyvp` can be dropped concurrently (ttyclosesession,
fdrevoke), the vnode reclaimed, and `VOP_IOCTL` then dereferences a
stale pointer.  `cttyread`/`cttywrite` correctly use `vget`/`vput`;
`cttyioctl` was missed.

## Status
BUG CONFIRMED BY CODE INSPECTION.  Race is tight (CVSS AC:H); short
demo does not reliably panic.  Source: tty_tty.c:264 dereferences
`ttyvp` unlocked.

## Build / Run
```sh
./build.sh
ssh -tt dfbsd-maxx "cd poc/DF-0176 && ./run.sh"   # needs controlling tty
```

## Fix (validated)
`fix.diff`: add `vget(ttyvp, LK_EXCLUSIVE | LK_RETRY)` ... `vput(ttyvp)`
around `VOP_IOCTL`.  Matches `cttyread`/`cttywrite`.  Validated: 7.5M
race iterations on patched kernel without panic.

## Files
- `cttyioctl_uaf.c` — two-thread race demonstrator.
- `fix.diff` — vget/vput around VOP_IOCTL.
- `VERDICT.md` — full narrative.
