DF-3712 / verdict.json
{ "finding_id": "DF-3712", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-certain, runtime hardware-gated: em_newbuf (sys/dev/netif/em/if_em.c:3376-3383) front-trims the posted MCLBYTES=2048 RX cluster by ETHER_ALIGN=2 whenever hw.mac.max_frame_size <= 2046, so the RX DMA map covers only 2046 bytes, while em_init_rx_unit (:3607-3632) programs RCTL_SZ_2048 (2048-byte hardware receive buffers; rx_buffer_len fixed at MCLBYTES since :684) and enables RCTL_LPE for any if_mtu > 1500 (:3629). For any MTU in (1500,2028] (SIOCSIFMTU :1225-1281 accepts up to 16110 on 8254x) trim and LPE coexist: the first descriptor of a multi-descriptor frame is DMA-filled with 2048 bytes at cluster+2, writing 2 attacker-controlled bytes past the 2048-byte mbuf cluster (heap corruption), and em_rxeof:3738 then sets m_len=2048 claiming 2 bytes past the cluster on the stack side. Identical pattern to DF-1197 (emx). Guest-executed bound-math harness proves the posting/fill arithmetic (MTU=2000: write span [2,2050) into a 2048-byte cluster; MTU=1500 and MTU=9000 both safe). Audit guest has no em hardware (vtnet only), so the on-hardware trigger cannot run.", "exploit_chain": "", "evidence": "findings/poc/DF-3712/VERDICT.md (root-cause trace); run.log (guest probe: no em device + harness section [A]: MTU=2000 -> 2-byte DMA overflow, negative configs safe); build.log; fix.diff (trim only when max_frame_size <= ETHER_MAX_LEN)", "kernel_refs": [ "sys/dev/netif/em/if_em.c:3376", "sys/dev/netif/em/if_em.c:3378", "sys/dev/netif/em/if_em.c:3379", "sys/dev/netif/em/if_em.c:3381", "sys/dev/netif/em/if_em.c:684", "sys/dev/netif/em/if_em.c:3607", "sys/dev/netif/em/if_em.c:3609", "sys/dev/netif/em/if_em.c:3629", "sys/dev/netif/em/if_em.c:3630", "sys/dev/netif/em/if_em.c:1269", "sys/dev/netif/em/if_em.c:1276", "sys/dev/netif/em/if_em.h:218" ], "poc_changes": "No seed PoC existed. Wrote em_bounds_harness.c (guest-executed userspace bound-math replica of em_newbuf posting + RCTL fill arithmetic with redzone checks); trigger.sh-style on-hardware procedure documented in README.md.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64", "runtime_sec": 90, "guest_dirty": 0, "build_cmd": "cc -O -o /root/em_bounds_harness /root/em_bounds_harness.c", "run_cmd": "vm.sh run_root ifconfig -l; pciconf -l; ...; harness/module per run.sh", "code_hash": "062bd0525775d326bb2d63520b01e5d5600be3d5f77de6e6832f262bf7aecb80", "notes": "2 attacker-controlled overflow bytes = frame bytes 2047-2048; corrupts the kernel heap object following the RX cluster. Requires admin-set MTU in (1500,2028], then a single unauthenticated L2 frame >2048 bytes. Module if_em.ko exists on guest but zero em interfaces (no 8086 NIC).", "recommended_fix": "Apply the ETHER_ALIGN front-trim only when max_frame_size <= ETHER_MAX_LEN so trim and RCTL_LPE never coexist.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored against the read-only sys/ tree (patch --dry-run clean); cannot be validated on a guest without em hardware.", "fix_evidence": "findings/poc/DF-3712/fix.diff" } |