β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-1197

2-byte DMA heap overflow in RX buffer when ETHER_ALIGN applied with jumbo MTU

Summary

emx_newbuf at :2918-2919: m_adj(m,ETHER_ALIGN) applied when max_frame_size<=MCLBYTES-ETHER_ALIGN=2046 (MTU<=2028). DMA mapping shrunk to 2046 bytes. But emx_init_rx_unit at :3293 sets RCTL_SZ_2048 (HW buffer=2048) and :3295-3296 sets RCTL_LPE when MTU>1500. For MTU in (1500,2028]: both ETHER_ALIGN AND LPE active. Multi-segment RX fills first descriptor with 2048 bytes into 2046-byte mapping -> 2-byte heap overflow past mbuf cluster. emx_rxeof at :3401 sets m_len=2048, stack reads 2 bytes from overflow region. Attacker on same L2 segment sends >2050-byte frame. Fix: only apply ETHER_ALIGN when MTU<=ETHERMTU.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1197 Β· 9 files
FileTypeDescriptionSize
VERDICT.md verdict source-level analysis: 2-byte DMA heap overflow when ETHER_ALIGN applied with LPE 3.3 KB ↓ raw
fix.diff suggested-fix only apply ETHER_ALIGN when if_mtu <= ETHERMTU 922 B view raw
build.sh build-script no-op (no userspace PoC; hardware-gated) 444 B view raw
run.sh run-script no-op (no emx NIC on guest) 264 B view raw
fix_build.log build-log cumulative kernel build with all 5 fixes applied, NK_DONE rc=0 5.6 MB ↓ download
env.txt environment guest uname, PCI topology, target HW required 1.2 KB view raw
README.md readme human reproduce doc 897 B ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme human reproduce doc
↓ download raw

DF-1197 β€” emx 2-byte DMA heap overflow (build/run scripts)

Hardware-gated (Intel 82574/82583/ICH8-10 emx NIC). The guest uses virtio-net. See VERDICT.md for source-level confirmation.

Files

  • VERDICT.md β€” detailed source-level analysis
  • fix.diff β€” git-apply-able patch changing the m_adj predicate
  • env.txt β€” guest environment snapshot
  • fix_build.log β€” kernel-build output (cumulative batch)

build.sh

#!/bin/sh
echo 'build.sh: no userspace PoC for DF-1197 (hardware-gated driver bug).'
echo 'To validate the fix, apply fix.diff and build a kernel:'
echo '  cd /usr/src && patch -p1 < fix.diff && make -j6 nativekernel KERNCONF=X86_64_GENERIC'

run.sh

#!/bin/sh
echo 'run.sh: DF-1197 is hardware-gated (Intel 82574/82583 emx NIC).'
echo 'This guest uses virtio-net, not emx.'
echo 'See VERDICT.md for the source-level confirmation.'
VERDICT.md verdict source-level analysis: 2-byte DMA heap overflow when ETHER_ALIGN applied with LPE
↓ download raw

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:

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:

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).

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:

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)

Fix verification

not_testable

compile validated

nativekernel rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. emx 2B DMA heap overflow MTU window (1500,2028]. Remote L2 trigger. No emx NIC.