# DF-0752 — mbuf leak in mpls_forward on route-not-found

## Claim
`mpls_forward()` in `sys/netproto/mpls/mpls_input.c` leaks the input mbuf on
the route-not-found path: when `rtalloc(cache_rt)` leaves `cache_rt->ro_rt ==
NULL`, the function `return`s at line 202 without calling `m_freem(m)` (and
without bumping `mplss_cantforward`). Every other drop path in this file frees
the mbuf (lines 156, 164, 170, 218). An on-link remote attacker who can deliver
MPLS-framed Ethernet packets (ethertype 0x8847) with a label that has no
matching MPLS route causes one mbuf+cluster leak per packet → memory-exhaustion
DoS. Requires `options MPLS` in the kernel config (non-default; the X86_64_GENERIC
shipped kernel does NOT compile MPLS in).

## Reproduce
The bug is unreachable on default GENERIC (MPLS not compiled in). The harness
here therefore uses a kernel built with `options MPLS` (the documented
precondition of the finding) and delivers MPLS frames into the kernel via a
`tap(4)` interface from a root-run injector (simulating the on-link attacker).

1. `./build.sh`  — build the injector (`mpls_flood`)
2. On an `options MPLS` kernel: `sudo ifconfig tap0 create; sudo ifconfig tap0 up`
3. `sudo ./run.sh`  — flood 20000 unroutable-label MPLS frames into tap0,
   printing `netstat -m` mbuf counts before/after.

Expected on the UNPATCHED MPLS kernel: mbufs-in-use grows by ~20000 (leak).
Expected on the FIXED kernel: mbufs-in-use stays flat (m_freem now called).

## Files
- `mpls_flood.c`     — injector: writes N MPLS frames (label=1000, no route) to /dev/tap0
- `build.sh / run.sh` — exact build/run
- `fix.diff`         — adds `m_freem(m); mplsstat.mplss_cantforward++;` before `return;`
- `VERDICT.md`       — full narrative
- `manifest.json`    — artifact catalog
