# DF-3713 — VERDICT

**Status: source-certain, runtime hardware-gated (inconclusive on this guest — no em NIC).**

## Root cause

`em_rxeof()` (`sys/dev/netif/em/if_em.c:3661-3821`) reads the 16-bit length
field out of the legacy RX descriptor — a value **DMA-written by the device**
(`struct e1000_rx_desc`, `e1000_hw.h:410-417`, `__le16 length`):

- `:3692` `desc_len = le16toh(current_desc->length);` — no bound against the
  posted buffer (`adapter->rx_buffer_len`, = MCLBYTES = 2048, set at `:684`,
  never changed).
- `:3705` non-EOP fragment: `len = desc_len;` — a legitimate fragment is at
  most 2048; nothing rejects larger values.
- `:3701` EOP fragment: `len = desc_len - ETHER_CRC_LEN`.
- `:3738` `mp->m_len = len;` and `:3761` `adapter->fmp->m_pkthdr.len += len;`
  — the unbounded value becomes the mbuf's advertised data length and the
  packet's total length, handed to `ifp->if_input` at `:3808`.
- `:3715` error path: `last_byte = *(mtod(mp, caddr_t) + desc_len - 1);` —
  OOB probe at up to `cluster + 65534` (the `desc_len == 0` negative
  direction of this line is the already-filed DF-1188).
- `:3697-3699` + `:3754-3758`: if a previous non-EOP fragment had
  `m_len < 4` (e.g. desc_len 0..3), `prev_len_adj = ETHER_CRC_LEN - desc_len`
  subtracts up to 4 from it → **negative `m_len`** in the chain
  (`lmp->m_len -= prev_len_adj` with no floor).

A device-side length of 0xFFFF yields an mbuf claiming 65535/65531 bytes
inside a 2048-byte cluster: every downstream consumer (ether parsing,
`m_pullup`, BPF taps, forwarding, `m_copydata`) reads up to ~63.5KB past the
cluster — per descriptor, and compounded by the `m_pkthdr.len` accumulator
for multi-descriptor frames.

## Threat

Device-trust boundary: descriptor corruption, device fault/erratum, or a
malicious DMA source (PCIe device spoofing an e1000, flawed emulated e1000 —
the default QEMU NIC model, or SR-IOV style injected writes). Not reachable
by a network peer against well-behaved hardware. Same premise and severity
rationale as the accepted family findings DF-3604/DF-3639/DF-3663/DF-3667
(bce/bnx/bge/ix) and DF-3679 (igb).

## Verification

- Guest has no em hardware (`run.sh` probe: `vtnet0 lo0` only).
- Guest-executed bound-math harness (`run.harness.log`): desc_len=0xFFFF
  non-EOP → 63487-byte OOB claim; EOP → 63483-byte; error-path probe OOB;
  prev_len_adj → `lmp->m_len = -2` demonstrated. Honest frames (1500) safe.

## Fix

`fix.diff`: after reading `desc_len`, discard (whole frame chain) when
`desc_len == 0` (also closes DF-1188) or `desc_len > adapter->rx_buffer_len`.
Cannot be hardware-validated on this guest (`fix_status: not_testable`).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
