# DF-2712 — evidence pack

Finding: `sys/kern/usched_bsd4.c:1590-1615` — `bsd4_kick_helper()` issues
`lwkt_send_ipiq()`/`wakeup()` while the caller still holds the global
`bsd4_spin`, so a FIFO-full `lwkt_send_ipiq3()` liveloop (which enables
interrupts and spins, `lwkt_ipiq.c:240-277`) executes with the scheduler
spinlock held — claimed to enable a same-cpu schedclock recursion and a
cross-cpu mutual whole-system wedge, unprivileged, when `usched_bsd4` is
the active user scheduler.

## What is in here

| file | what |
|---|---|
| `df2712_rig.c` | kernel-compiled hard-IRQ watchdog (1 Hz systimer per cpu; per-cpu beats / gd_spinlocks / td_critcount / max outgoing ipiq FIFO depth; frozen-beat wedge marker). Compiled INTO the guest kernel because runtime kldload GPFs on this guest. |
| `df2712_storm.c` | unpinned unpriv yield storm (v1) — negative control: no kicks |
| `df2712_storm2.c` | pinned victim/sender yield storm via `lwp_setaffinity(0,-1,mask)` (unpriv-legal self-affinity, `kern_usched.c:423`) |
| `df2712_storm3.c`, `df2712_storm4.c` | priority-shape variants (sleep-interleaved victims / interactive victims) |
| `df2712_storm5.c` | pulsed fresh-wave bursts (the burst is where all kick traffic lives) |
| `df2712_bench.c` | scheduler sanity microbench (yield rate, fork64, pipe RT) |
| `build.sh` | push rig+storm, compile rig into kernel (`make nativekernel`), install, set `kern.user_scheduler=bsd4` in loader.conf, reboot |
| `run.sh` | experiment runner with host-side sampling |
| `run.e*.{pre,sampler,post,console}.txt` | full logs per experiment |
| `env.txt` | guest/kernel/scheduler state (bsd4 ACTIVE, rig armed) |
| `fix.diff` | deferred-kick patch (+ queue_checks clamp) |
| `VERDICT.md`, `manifest.json`, `verdict.json` | the verdict |

## Reproduce (summary)

1. `./build.sh` — boots guest into a rig kernel with `kern.user_scheduler="bsd4"`.
2. Confirm: `sysctl debug.df2712.armed` = 1, `kern.usched_bsd4.kicks` moves
   under load (bsd4 active; stock boots dfly so the loader switch is required).
3. Smoke (the primitive, 8 s, unprivileged):
   `vm.sh run_root 'su -m maxx -c "/tmp/storm2 5 60 30 8"'`
   then `sysctl lwkt.ipiq_fifofull` — rose from 0 to 1+ on the stock-bsd4
   kernel (48 total across all our runs): spin-held FIFO-full liveloops
   entered. Each drained < 1 s (no `tgt not draining` console lines).
4. Wedge attempt (did NOT wedge): `su -m maxx -c "/tmp/storm5 5 180 12 3 15"`.
5. Full battery + fix A/B: see `VERDICT.md`.

## Expected output (what we actually observed)

- `kern.usched_bsd4.kicks`: 4 -> 238,005 under unprivileged storms.
- `lwkt.ipiq_fifofull`: 0 -> 48 (spin-held liveloop entries, all transient).
- max outgoing FIFO depth seen by the 1 Hz watchdog sampler: 20 of the
  128 (MAXCPUFIFO/2, `lwkt_ipiq.c:225`) entries needed to enter the liveloop
  (253 applies to the nested case only).
- ssh/serial starvation > 60 s, load average 30-71, storm cycles stretched
  from 6 s nominal to 2-4 min — severe recoverable DoS.
- NO permanent wedge: watchdog beats never froze >= 5 s
  (`debug.df2712.wmarks` = 0), zero `send_ipiq ... tgt not draining` lines.
