# DF-3426 — netmap generic TX pool mbuf UAF / double-free (VERIFIED)

## What this is
The production netmap KLD (verbatim `sys/net/netmap/` sources) rebuilt in a
copied tree with two infrastructure port shims (the stock module does not
compile on this tree), loaded on the stock 6.5-DEVELOPMENT INVARIANTS guest,
and driven through the real `/dev/netmap` userspace ABI.

The two port shims (no logic under audit is touched):
- `wna_shim.[ch]` — pointer-sized WNA side table (this tree's `struct ifnet`
  has no `if_unused7`; `netmap_kern.h:747`)
- `rig_port2.patch` — `dev_open_args.a_fp` → `*a_fpp` (`netmap_freebsd.c:387`)
- `rig_trace.patch` — RIG_TRACE kprintf diagnostics only

## Build (guest, as root, files scp'd to /root/df3426)
    ./build.sh                 # -> netmap-src/netmap.ko + ./trigger

## Run (guest, as root)
    ./run.sh probe             # sanity: register/unregister, counters flat
    ./run.sh unreg 8           # 8 double frees, counter-exact, guest ALIVE
    ./run.sh uaf 512 4096 16384  # UAF reuse -> Fatal trap 12 panic
    ./run.sh evt               # ring exhaustion + unregister -> 2^64-767

Prerequisite state (run.sh sets it up): `kldload if_tap`;
`ifconfig tap0 create && ifconfig tap0 up`; `kldload ./netmap-src/netmap.ko`.
tap0 has no reader, so `tapifstart()->ifsq_purge()` frees every dispatched
mbuf synchronously inside `ifq_dispatch()` — a deterministic stand-in for
driver TX completion.

## Expected output
- `unreg 8`: rc=0; `netstat -m` "mbuf clusters in use" drops 256 → 248
  (exactly −8 = the 8 double frees).  Guest stays up.
- `uaf 512 4096 16384`: kernel prints both `RIG: txsync enter:` laps, then
  `RIG: ring exhausted`, `RIG: generic_set_tx_event`,
  `RIG: generic_mbuf_destructor CALLED`, then
  **"Fatal trap 12: page fault while in kernel mode"** and the guest dies
  in DDB (run.log / panic_uaf_run2_serial.txt).
- `evt`: rc=0 but `netstat -m` shows
  `18446744073709550849/33552 mbuf clusters in use` (counter underflow).

## Fix validation (fix.diff)
    cd netmap-src && patch < ../fix3426-rig.diff && make   # fixed module
    # then re-run the exact same PoC matrix -> no panic, counters flat,
    # set_tx_event arms on NULL (mbuf=0) and returns early
See fix_validation.log / fix_validation27.log, VERDICT.md.

## Verdict
reproduced (impact: panic — kernel memory corruption gated on root/wheel
for /dev/netmap access, as filed).  Full narrative: VERDICT.md.
