# DF-0401 PoC — VALE bridge heap overflow via unchecked slot->len

## Verdict

**NOT REPRODUCED (latent bug).** The source-level defect is real and severe
(a missing bounds check on `slot->len` in `nm_bdg_preflush` that would allow
a 63488-byte heap overflow), but the entire netmap subsystem is dead code on
DragonFlyBSD master DEV `6cc80ee9`: `struct ifnet` no longer has the
`if_unused7` member that netmap's `WNA` macro requires, so `netmap.ko`
cannot be compiled, loaded, or instantiated, `/dev/netmap` does not exist,
and the VALE forwarding path cannot be entered live. See `VERDICT.md` for
the full source-level proof and the unreachability evidence.

## Build

```
./build.sh
```

Builds the self-contained `reachability_probe` (succeeds) and attempts to
build the intended `poc` (fails: netmap userland headers are not installed
and netmap.ko cannot be built).

## Run

```
./run.sh        # as the unprivileged user (maxx)
```

Expected output (this is the actual result on this guest):

```
DF-0401 reachability probe
--------------------------
[UNREACHABLE] /dev/netmap does not exist: No such file or directory
[UNREACHABLE] netmap subsystem is not loaded/available.
[UNREACHABLE] The VALE forwarding path (nm_bdg_preflush/
              nm_bdg_flush) cannot be entered live.
REACHABILITY_PROBE_RC=2
...
ls: /dev/netmap: No such file or directory
no netmap.ko shipped in /boot/kernel
```

## How the bug would work (if netmap were loadable)

1. `open("/dev/netmap")` and `NIOCREGIF` a VALE port (e.g. `vale1:0`).
2. `mmap` the shared ring memory.
3. Set `txring->slot[idx].len = 65535` (the buffer is only 2048 bytes).
4. Fill the buffer with a controlled pattern.
5. `ioctl(fd, NIOCTXSYNC)` triggers `nm_bdg_preflush` → `nm_bdg_flush`.
6. `nm_bdg_preflush` (`netmap_vale.c:988`) stores the unchecked `slot->len`
   into `ft[].ft_len` — **no bounds check** (unlike `netmap.c:748`).
7. `nm_bdg_flush` (`netmap_vale.c:1330`) computes `len = (65535 + 63) & ~63 = 65536`
   and calls `pkt_copy(src, dst, 65536)` into the 2048-byte `dst` buffer
   (`BDG_NMB`) → **63488-byte heap overflow with attacker-controlled
   content and length**.

The sibling checks that DO exist (and that the VALE path omits):
- `netmap.c:748`  — `if (slot->len < 14 || slot->len > NETMAP_BDG_BUF_SIZE(...))`
- `netmap.c:1124` — `else if (len > NETMAP_BDG_BUF_SIZE(...))`
- `netmap.c:2017` — `if (len > NETMAP_BDG_BUF_SIZE(...))`

## Fix

`fix.diff` adds the missing check at `netmap_vale.c:988`, mirroring
`netmap.c:748`. It applies cleanly to both the host `sys/` tree and the
in-guest `/usr/src` tree. A full boot-test is not possible because the
netmap subsystem does not compile on this master (see
`netmap_build_attempt.log`).

## Reproduce from scratch

```
scp -r findings/poc/DF-0401 dfbsd-maxx:/tmp/
ssh dfbsd-maxx 'cd /tmp/DF-0401 && ./build.sh && ./run.sh'
# To inspect the netmap build failure (proof the subsystem is dead):
ssh dfbsd 'cd /usr/src/sys/net/netmap && make obj && make 2>&1 | grep if_unused7 | head'
```
