# DF-0611 — PoC: ng_nat_rcvdata missing IP validation → OOB access

Remote adjacent-network DoS / OOB-read PoC (speculative on libalias
acceptance).

## Status

**LATENT — module does not build in the current tree.**
`sys/netinet/libalias/` is absent and `m_megapullup()` (referenced at
`ng_nat.c:692`) is defined nowhere, so `netgraph7_nat` cannot be compiled
or loaded. This PoC is a craft-and-send recipe, source-only, until
libalias / `m_megapullup` are reintroduced.

## Trigger frame (modulo libalias acceptance)

- `ip_v = 4`, `ip_hl = 0xF` (claims 60-byte IP header)
- `ip_p = IPPROTO_TCP` (6)
- `ip_off = 0` (so `(ip_off & IP_OFFMASK) == 0`)
- `ip_len = htons(80)` — 60 IP header + 20 TCP header, satisfies KASSERT
- `m_pkthdr.len == 80` — matches `ip_len` so the production KASSERT is a
  no-op
- body bytes 12..17 of the claimed TCP region set to non-zero so `th_x2`
  reads non-zero, forcing the write branch

Cycle `NGM_NAT_SET_MODE` through `flags=0, mask=0xffffffff` (lines
355-372) and toggle `NGM_NAT_REVERSE` to maximise the chance libalias
passes the frame through unchanged.

## Preconditions

- A configured `ng_nat` node with both hooks connected (`in`, `out`) and
  an alias address set via `NGM_NAT_SET_IPADDR`.
- The attacker delivers IP frames into `nat:in` via whatever peer node is
  connected (`ng_iface` over a tunneled interface, an `ether` node, etc.).
- The frame must pass libalias (`LibAliasIn`/`LibAliasOut` at lines
  707/714) — **this is the speculative element**; libalias sources are not
  in the tree so acceptance cannot be verified.

## Expected outcome

Kernel panic with a faulting RIP inside `in_delayed_cksum()` or
`in_cksum_skip()`; OR, on a debug kernel, the dmesg line
`delayed m_pullup, m->len: .. off: .. p: 6` from
`sys/netinet/ip_output.c:941` followed by a NULL-deref panic at the
`*(u_short *)(m->m_data + offset) = csum;` write.

## Notes for the per-PoC verifier

- Module must be buildable first — libalias + `m_megapullup` must exist.
- Primary verification task: determine whether libalias actually passes a
  malformed frame (large `ip_hl`, crafted `ip_len`) through to ng_nat's
  TCP-fixup block. If libalias always rejects, this is a pure latent bug
  and the finding should be downgraded to Info.
- The fix adds three guards: `m_pkthdr.len >= sizeof(struct ip)`,
  `ip_hl >= 5 && ip_len >= ip_hl<<2 && ip_len <= m_pkthdr.len`, and a
  TCP-header-fits check before the fixup block. Verify with
  `git apply findings/poc/DF-0611/fix.diff`.
