# DF-1197 — emx 2-byte DMA heap overflow in RX buffer

## Verdict
**NOT REPRODUCED (source-confirmed; hardware-gated).** The overflow window is
real and is exactly as described, but the emx driver attaches only to Intel
82574 / 82583 / ICH8-10 LAN controllers; this QEMU/KVM guest uses virtio-net
for networking. No runtime trigger; validated by line-level source trace +
single-fix kernel build.

## Mechanism
`emx_newbuf` (`sys/dev/netif/emx/if_emx.c:2900`) sets up each RX mbuf cluster:

```c
m->m_len = m->m_pkthdr.len = MCLBYTES;              // 2916  -- MCLBYTES=2048
if (rdata->sc->hw.mac.max_frame_size <= MCLBYTES - ETHER_ALIGN)  // 2918
    m_adj(m, ETHER_ALIGN);                          // 2919  -- m_data += 2
```

`MCLBYTES` is `1<<MCLSHIFT` = `1<<11` = **2048** (`sys/sys/param.h:495-497`).
`ETHER_ALIGN` is 2 (`sys/net/ethernet.h:41`). After `m_adj`, the mbuf data
buffer spans `[m_data+2 .. m_data+2048)`, i.e. **2046 bytes** of usable DMA
space. `bus_dmamap_load_mbuf_segment` (line 2921) maps exactly those 2046
bytes and the descriptor's `paddr` is the post-adj base.

In `emx_init_rx_unit` (`if_emx.c:3106`), the RX control register is set up as:

```c
rctl |= E1000_RCTL_SZ_2048;            // 3293  -- HW buffer size class = 2048
if (ifp->if_mtu > ETHERMTU)
    rctl |= E1000_RCTL_LPE;             // 3295-3296  -- receive packets > 1522 B
```

The window opens when the MTU is in `(1500, 2028]`:

* `max_frame_size = MTU + ETHER_HDR_LEN + ETHER_CRC_LEN = MTU + 18` is in
  `(1518, 2046]`, so the `<=` at line 2918 is **true** and `m_adj` runs (buffer
  shrunk to 2046).
* `ifp->if_mtu > ETHERMTU` is also **true**, so `RCTL_LPE` is set (HW will
  receive frames > 1522 bytes).
* With `RCTL_SZ_2048`, the first descriptor of a multi-segment frame is
  **DMA-filled to 2048 bytes** — 2 bytes past the 2046-byte mapping.

A remote attacker on the same L2 segment sending a frame slightly larger than
2046 bytes (e.g. a 1500-IP + 14-eth + 4-FCS + ~610 of IP-options/payload =
~2128, or simply a 2050-byte VLAN-tagged frame) triggers a 2-byte heap
overwrite past the mbuf cluster, plus a 2-byte out-of-mapping stack read in
`emx_rxeof` (`if_emx.c:3401` `mp->m_len = len`).

## Why not triggered on this guest
`pciconf -l` shows `virtio_pci0 @ 0:3:0` (class=0x020000,
chip=0x10001af4 — virtio-net) for networking. The emx PCI attachment table
targets Intel 82574/82583/ICH8-10 (vendor 0x8086 specific device IDs); no such
device exists, so `emx_newbuf` is never called. Option (d).

## Recommended fix (in `fix.diff`)
Replace the frame-size predicate with an MTU predicate so that `ETHER_ALIGN`
is only applied when `emx_init_rx_unit` will also keep `RCTL_LPE` off:

```c
if (rdata->sc->arpcom.ac_if.if_mtu <= ETHERMTU)
    m_adj(m, ETHER_ALIGN);
```

When MTU is standard, frames are <= 1518 B (1522 with VLAN) which fit in the
2046-byte post-adj buffer; when MTU is jumbo, the full 2048-byte cluster is
available and the multi-segment first descriptor fits exactly. Note that the
alternative "extend the buffer instead" is not available because the mbuf
cluster is already at the MCLBYTES maximum.

## Build validation
Cumulative kernel build with all 5 fixes applied — `NK_DONE rc=0`. See
`fix_build.log`.

## Reproduce
```
./build.sh    # no-op (no PoC; driver-gated)
./run.sh      # no-op (no emx NIC on guest)
```
