# DF-0735 — PoC and evidence pack

**Finding:** ip_input/ip_output called from netgraph thread context
(`sys/netgraph7/ng_ipfw.c:245,248`). The `rcvdata` callback calls
`ip_output(m)` / `ip_input(m)` directly from the netgraph worker thread,
which is **not** a netisr thread, so the `ASSERT_NETISR_NCPUS(mycpuid)` at
`ip_input.c:460` / `ip_output.c:185` fires on default-GENERIC (INVARIANTS on)
and the kernel panics.

**Verdict:** REPRODUCED at source + harness level. The cited path is
**latent** — `ng_ipfw.c` doesn't compile on this tree (`netinet/ip_fw.h`
does not exist), has no in-kernel caller of its `ng_ipfw_input_p` function
pointer, and is neither in the default kernel nor in the netgraph7 module
SUBDIR. The harness demonstrates the assertion mechanism that the cited
call would trip if it were ever reached.

**Impact:** panic / DoS, **root-only reachability**, no escalation primitive.

## How to reproduce (on the DragonFly guest as root)

```sh
# 1. Build the three harness modules.
./build.sh

# 2. Run the two-phase demonstration (Phase A: fixed, no panic;
#    Phase B: buggy, PANIC -> guest wedges in DDB).
./run.sh
```

After Phase B the guest is wedged in DDB; reset it from the host with
`./dfbsd-qemu/vm.sh reset with-src`. The panic signature is in
`dfbsd-qemu/boot.log` and in `panic.txt`.

## Files

| file                    | purpose                                                       |
|-------------------------|---------------------------------------------------------------|
| `df735_trigger.c`       | sysctl trigger module: `ip_input(m)` direct (mirrors `ng_ipfw.c:248`) — PANICS |
| `df735_fixed.c`         | sysctl trigger module: `netisr_queue(NETISR_IP, m)` (mirrors the fix + `ng_ip_input.c:125`) — no panic |
| `ng_df735_poc.c`        | faithful netgraph node harness (mirrors `ng_ipfw_rcvdata`) — builds; netgraph7 ABI mismatch prevents `kldload` |
| `ng_df735_inject.c`     | userspace PF_NETGRAPH injector (for `ng_df735_poc`)           |
| `Makefile.ng_ipfw`      | Makefile template for building the real (unbuildable) `ng_ipfw.ko` from source |
| `trigger_df735.sh`      | alternative trigger via the real (unbuildable) `ng_ipfw.ko` + ipfw ngtee divert |
| `run_df735.sh`          | alternative trigger via the faithful netgraph node            |
| `build.sh`              | builds all three harness modules                              |
| `run.sh`                | runs Phase A (fixed, no panic) + Phase B (buggy, PANIC)       |
| `build.log`             | full compiler output of the final build                       |
| `run.log`               | full output of the decisive Phase B run (with panic signature) |
| `fix_run.log`           | full output of the Phase A (fixed) run (no panic)             |
| `panic.txt`             | panic signature excerpt from `dfbsd-qemu/boot.log`            |
| `env.txt`               | guest environment (uname, cc, kldstat, sysctls)               |
| `fix.diff`              | git-apply-able unified diff against `sys/netgraph7/ng_ipfw.c` |
| `VERDICT.md`            | full narrative verdict (mechanism, reachability, fix validation) |
| `manifest.json`         | machine-readable artifact catalog for the static-site renderer |
