⬢ DragonFlyBSD Kernel Audit
DF-4079 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4079",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "REPRODUCED via the production-handler KLD dispatch rig (DF-4106/DF-4266 evidence class): the guest kernel ships `device oce`, so the rig binds the kernels OWN oce_rq_handler()/oce_alloc_rx_bufs()/ring-allocator as externs over a fabricated post-attach softc (BE3 flags, verbatim oce_rq_init DMA replay, real busdma rings, real posted clusters, MMIO BAR stand-ins) and dispatches it on firmware-shaped CQEs. Stock kernel: pkt_size=16383/num_fragments=1 delivered a 2048-byte chain claiming 16383 (14335 phantom bytes); pkt_size=16383/num_fragments=7 delivered 14336 bytes claiming 16383 (2047 phantom bytes \u2014 the max 7x2048<16383 trust-boundary gap); rx_bytes counted the phantom length. Panic mode: the cited stack offset-walker m_copydata (sys/kern/uipc_mbuf.c:1679 KASSERT, INVARIANTS kernel) panicked with backtrace m_copydata() <- df4079_input() <- oce_rx.isra.10() <- oce_rq_handler() \u2014 production oce_rx built the chain, production m_copydata died on it. Fix (residual-length drop in oce_rx) validated on a rebuilt+rebooted kernel: both crafted CQEs dropped (chains=0, violations=0, rx_pkts=0, FIX CONFIRMED) and the panic mode survives. Threat model unchanged: firmware/DMA-controlled CQE; not remotely reachable without the NIC.",
  "exploit_chain": "firmware/DMA-shaped RX CQE (pkt_size=16383, num_fragments=1..7) -> production oce_rq_handler/oce_rx builds a legal-RQ mbuf chain whose m_pkthdr.len exceeds its data by up to 2047 bytes -> if_input -> any offset-walking consumer (m_copydata/m_copym: forwarding, fragmentation, ICMP-error) reads past the chains real end -> KASSERT panic (demonstrated); with frame bytes also firmware-controlled, silent OOB reads of adjacent cluster data / TCP sequence desync are the same primitive short of the assert.",
  "evidence": "run.log (stock baseline: both CHAIN INVARIANT VIOLATION markers with per-mbuf m_len dumps); panic.txt (panic: m_copydata: offset > size of mbuf chain + backtrace oce_rx.isra.10 <- oce_rq_handler); fix_run.log (patched kernel: chains=0 violations=0 FIX CONFIRMED); fix_build.log (full 41592-line nativekernel build, BUILD_DONE_OK); panic_console_full.log (full serial console of the panic run)",
  "kernel_refs": [
    "sys/dev/netif/oce/oce_if.c:1260",
    "sys/dev/netif/oce/oce_if.c:1274",
    "sys/dev/netif/oce/oce_if.c:1290",
    "sys/dev/netif/oce/oce_if.c:1291",
    "sys/dev/netif/oce/oce_if.c:1299",
    "sys/dev/netif/oce/oce_if.c:1373",
    "sys/dev/netif/oce/oce_if.c:1381",
    "sys/dev/netif/oce/oce_hw.h:2531",
    "sys/dev/netif/oce/oce_hw.h:2549",
    "sys/kern/uipc_mbuf.c:1679"
  ],
  "poc_changes": "Seed pack had no PoC (marked hardware-gated/untested). Replaced with the production-handler KLD dispatch rig: extern-binds the kernels own oce_rq_handler + posting/ring helpers, fabricates the post-attach softc (verbatim oce_rq_init DMA replay), posts real clusters via REAL oce_alloc_rx_bufs, crafts CQEs in DMA memory, dispatches the real handler; if_input shim proves pkthdr.len > sum(m_len); panic mode dispatches the real m_copydata.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64 (reproduced) / #1: Thu Oct 15 13:06:11 UTC 2026 (fix validation)",
  "runtime_sec": 45,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df4079 && make -m /usr/src/share/mk   (sh build.sh)",
  "run_cmd": "kldload ./df4079_oce_poc.ko; sysctl -w kern.df4079.go=1   (baseline) | sysctl -w kern.df4079.panic=1 + go=1   (panic)",
  "code_hash": "c50f10aeaf68bd0fb396a786e0d67c947d6806d34abc8b11d324dddcd5e686a8",
  "notes": "Second baseline run produced byte-identical markers (deterministic). Handler address moved 0xffffffff805c9e50 -> 0xffffffff805c9e80 after the rebuild, proving the rig dispatches the patched kernels own code. mbuf pool balanced at teardown (oce_free_posted_rxbuf real). Guest reset to stock-source snapshot afterwards.",
  "recommended_fix": "In oce_rx, after the fragment loop, drop the chain when residual len != 0 (pkt_size exceeded num_fragments x frag_size); never set m_pkthdr.len above the chains real data.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (residual-length drop in oce_rx) applied to guest /usr/src, kernel rebuilt via make -j6 nativekernel KERNCONF=X86_64_GENERIC (full log fix_build.log) and rebooted (#1 Thu Oct 15 13:06:11 UTC 2026); identical rig re-dispatched against the patched kernels own oce_rq_handler: both crafted CQEs dropped (chains delivered=0, violations=0, rx_pkts=0, rx_bytes=0, FIX CONFIRMED) and panic mode SURVIVES. Every defective behavior gone.",
  "fix_evidence": "fix_run.log (FIX CONFIRMED markers on kernel #1); fix_build.log (BUILD_DONE_OK, kernel install completed 13:11:22); panic.txt vs fix survival (no second panic.txt exists \u2014 the patched panic-mode run completed with GO_RC=0)."
}