# DF-2949 — cttyclose() vref() races terminal vrele() of concurrent ctty teardown (refcount corruption / KASSERT panic / UAF on stock)

## Build

On the DragonFly guest (any user; unprivileged):

    cc -O2 -o /tmp/ctty_race_hammer /tmp/ctty_race_hammer.c
    cc -O2 -o /tmp/ctty_race_sweep  /tmp/ctty_race_sweep.c   # alignment sweep / oracle
    cc -O2 -o /tmp/diag_timing     /tmp/diag_timing.c        # latency diagnostics

## Run

Two rigs in parallel (unprivileged):

    /tmp/ctty_race_hammer 100000000 700 > /tmp/h1.log 2>&1 &
    /tmp/ctty_race_hammer 100000000 800 > /tmp/h2.log 2>&1 &

Alignment/oracle sweep (produces the benign-overlap evidence):

    /tmp/ctty_race_sweep 600 100 900
    # then: dmesg | grep -c "cttyclose: race avoided"
    #       awk long-duration closes in /tmp/diag.log (dur=... > 200us)

## Expected

- Benign overlap (always, within a few hundred iterations):
  `Warning: cttyclose: race avoided` on console/dmesg, and victim close()
  durations of 200-1500 us in /tmp/diag.log (blocked at tty_tty.c:160
  through the leader-exit ttyclosesession teardown).
- Panic (the finding): `panic: vref: bad refcnt 00000000 ...` from
  vfs_lock.c:269-270 when a victim is descheduled between the unlocked
  VCTTYISOPEN read (tty_tty.c:155) and the vref (tty_tty.c:159) and
  resumes after the leader's terminal vrele() (tty.c:379). Guest goes
  down into DDB; `dfbsd-qemu/vm.sh status` => down.

The panic window is nanosecond-scale (two adjacent instructions, stretched
to ~1 us only by cache-coherence traffic on the vnode's v_flag/v_refcnt
lines): the hammer reproduces the contended interleaving deterministically,
the preempt-in-window hit is a lottery (see VERDICT.md for the measured
rates and honest status).
