# DF-5707 — Global MINSTD state broadcast: unprivileged-oracle recovery of `randseed`

**File audited (pass 2):** `sys/libkern/random.c`
**Class:** state-recovery oracle / cross-domain PRNG coupling (CWE-200/CWE-340)
**Severity:** Medium · **Confidence:** certain (mechanism, triple-verified on guest)

## What this pack proves (all on the QEMU guest, DragonFly 6.5-DEVELOPMENT x86_64)

1. **Calibrated consumer model** (`calib7-10.log`): under ipfw rule
   `prob 0.5 deny icmp from any to any icmptypes 8 via lo0`
   (`O_PROB` at `sys/net/ipfw/ip_fw2.c:3952-3955`, threshold encoding at
   `sbin/ipfw/ipfw2.c:3396-3402`), every echo request consumes exactly:
   - 1 draw (`<T`) → `sendto: Permission denied`   ("D")
   - 2 draws (`≥T,<T`) → silent loss                ("T")
   - 4 draws (`≥T,≥T`) → reply                      ("R")

2. **Full state recovery** (`recover1.log`, `attack2.log`, `attack3.log`,
   `landmark4.log`): a 60-packet burst (unprivileged-observable decisions)
   plus a 6-thread exhaustive scan of the 2^31-1 MINSTD space recovers the
   kernel's global `randseed` in ~4 s. **Four independent recoveries, each
   bit-exact against the `/dev/mem` control read** (`MATCH start ==
   RS-before-burst` in `attack2/attack3`, `landmark4`; `end→RS1 dist=1`
   in `verify1.log`).

3. **Cross-subsystem prediction** (`attack3.log` + `finalgen.log` +
   `strike3.log` + `rawgen.log`): from the recovered state alone, the
   on-disk UFS inode generation number of a file created *after* the burst
   is predicted exactly (`PREDICTED-IGEN … k=19:0x359714fe` == on-disk
   `di_gen = 0x359714fe` for ino 10). i_gen is the NFS file-handle
   unguessability component (`ffs_alloc.c:641-642`, `ffs_vfsops.c:1174-1175`).
   Draw↔gen mapping verified bit-exact on three pairs: zero-gen path
   stores `draw/2+2` (vget assigns `/2+1`, valloc's `++i_gen` adds 1),
   wrap path stores `draw/2+1`.

4. **Ambient characterization** (`rate.log`, `ambient*.log`, `bisect.log`):
   idle draw rate 1.23/s = 6 per-CPU loadav callouts
   (`kern_synch.c:1425-1432`); DF-2250 races observed live twice
   (documented in VERDICT.md).

## Build

    ./build.sh            # cc on the guest (gcc 8.3, base system)

## Run (summary; full choreography in run.sh / VERDICT.md)

    # as root (oracle setup only):
    kldload ipfw
    ipfw -q add 65000 allow ip from any to any
    ipfw -q add 50 skipto 65000 ip from any to any not via lo0
    ipfw -q add 100 prob 0.5 deny icmp from any to any icmptypes 8 via lo0
    ./attack <bootsec> 8      # burst -> recover -> strike -> predict

## Expected decisive output (attack3.log)

    RECOVERED start=998920631 end=781784740      (== RS-before-burst)
    STRIKE file=/mnt/final ino=10 ...
    CONTROL ra-to-rb dist=1 (1 expected: the i_gen draw)
    → on-disk di_gen(ino10) = 0x359714fe == attacker-table k=19 prediction

## Contents

- `attack.c`      flagship PoC (observe→recover→strike→predict), fork-free
- `probe.c`       burst generator + outcome classifier
- `recover2.c`    2^31 exhaustive state recovery (pthreads)
- `minstd.c`      step/ainv/dist/igen/backseed2 utilities
- `devmem.c`      /dev/mem read/write control tool (root-side only)
- `strike2/3.c`, `zerogen.c`, `mkstate.c`, `watch.c`, `probe2.c` supporting
- `logs/`         full untrimmed guest logs for every phase
- `fix.diff`      consumer-migration fix (never applied to sys/)
