# DF-4107 — vge(4): `vge_rxeof` trusts the NIC-DMA'd 14-bit descriptor length with no MCLBYTES clamp — single-fragment path sets m_len up to 16379 on a 2048-byte cluster (and signed-underflows to -4 for len<4)

File: `sys/dev/netif/vge/if_vge.c` (pass 2)
Class: heap OOB read (CWE-125) via trusted DMA-written length —
DF-3604 (bce) / DF-4055 (et) / DF-4083 (sis) family instance.
Hardware gate: VT612x NIC (absent on the audit guest). Source-level certainty.

## The defect

if_vge.c:1268: `total_len = VGE_RXBYTES(cur_rx);` where
`VGE_RXBYTES(x) = ((le32toh((x)->vge_sts) & VGE_RDSTS_BUFSIZ) >> 16)`
(if_vgevar.h:55-56) and `VGE_RDSTS_BUFSIZ = 0x3FFF0000` (if_vgereg.h:676) —
a **14-bit NIC-DMA-written value: 0..16383**.

Single-fragment completion path (no SOF head chain), if_vge.c:1361-1363:

```c
} else {
        m->m_pkthdr.len = m->m_len = (total_len - ETHER_CRC_LEN);
}
```

No comparison against `MCLBYTES` (2048; the RX buffer is a single mbuf
cluster loaded at vge_newbuf:1131-1134). The NIC normally writes
BUFSIZ ≤ cluster size, but the value is device/DMA-written: a
malfunctioning or compromised NIC (PCIe DMA attack, bad FW, errata) sets
0x3FFF → `m_len = m_pkthdr.len = 16379` on a 2048-byte cluster → up to
**~14 KB heap OOB read** walked by ether_input/IP and duplicated to every
BPF listener.

Underflow sub-case: BUFSIZ=0 with RXOK set (hostile descriptor) gives
`m->m_pkthdr.len = m->m_len = -4` — negative length reaching if_input/BPF
(DF-3604's "unsigned underflow" analog; here m_len is `int`, so it
propagates as -4).

The multi-fragment path is partially protected by accident
(`m->m_len = total_len % (MCLBYTES - VGE_ETHER_ALIGN)` at 1342), but
`m_pkthdr.len = total_len - ETHER_CRC_LEN` (1360) is likewise unbounded
against the sum of the chain's mbuf lengths — a lying BUFSIZ desyncs
pkthdr.len from the chain, tripping later pullup/copy code.

## Build / Run
Hardware-gated; guest has virtio only. See VERDICT.md.

## Fix
Clamp before use:

```c
if (total_len > MCLBYTES - VGE_ETHER_ALIGN)
        total_len = MCLBYTES - VGE_ETHER_ALIGN;   /* or drop the frame */
```
(plus drop on total_len <= ETHER_CRC_LEN). See fix.diff.
