# DF-3273 — Remote peer one-frame kernel panic via CONF-NAK/REJ with h->len < 4

## What
`sppp_cp_input()` clamps `len = min(m->m_pkthdr.len, ntohs(h->len))` and only
re-validates `len < 4` for CONF_REQ (if_spppsubr.c:1417).  CONF_NAK/CONF_REJ
are dispatched to the `RCN_nak`/`RCN_rej` handlers with `len ∈ {0,1,2,3}`
(if_spppsubr.c:1541-1544).  Every handler starts with

```c
len -= 4;
buf = kmalloc(len, M_TEMP, M_INTWAIT);   /* len is now -4..-1 */
```

`kmalloc((size_t)-4)` reaches the oversized path in kern_slaballoc.c,
`round_page(0xFFFFFFFFFFFFFFFC)` **wraps to 0**, and the degenerate zero-length
`kmem_slab_alloc()` corrupts the kernel map — instant panic:

```
panic: vm_map_entry_link: dup addr map 0xffffffff8159eea0 ent 0xffffffff81604448
kmem_slab_alloc() at kmem_slab_alloc+0x145
_kmalloc() at _kmalloc+0x5be
```

The only gate is `h->ident == sp->confid[cp->protoidx]`; `confid[]` is 0 from
attach until the first CONF-REQ, and is otherwise readable off the wire, so an
unauthenticated PPP peer needs exactly ONE frame.

## Files
- `poc_3273.c`   — the trigger (injects one 8-byte LCP CONF-NAK, h->len=0)
- `sppp_harness.c` — PoC harness module (models the sync-PPP driver: allocates
  a real `struct sppp`, attaches via `sppp_attach()`, feeds frames to
  `sppp_input()` via /dev/spppinj0, exactly like ng_sppp.c does)
- `panic.txt`    — serial-console panic from the baseline run
- `env.txt`      — guest uname etc.
- `fix.diff`     — the len<4 guard in sppp_cp_input (also fixes DF-3272)

## Build / run (inside the guest, as root)
```sh
# harness module (needs /usr/src kernel source)
cd /root/poc
cat > Makefile <<'EOF'
KMOD= sppp_harness
SRCS= sppp_harness.c
KMODDIR= /root/poc
.include <bsd.kmod.mk>
EOF
make
cc -O2 -o poc_3273 poc_3273.c
kldload /root/poc/sppp_harness.ko     # pulls in stock sppp.ko
/root/poc/poc_3273                    # -> kernel panics (ssh dies)
```

## Expected
Baseline (stock sppp.ko): instant panic, `vm.sh status` => down (DDB).
With fix.diff applied to if_spppsubr.c and sppp.ko rebuilt+installed:
"write returned 8 / kernel still alive" — frame rejected, no panic.
