⬢ DragonFlyBSD Kernel Audit
DF-3639 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3639",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Source-level certain: bnx_rxeof (sys/dev/netif/bnx/if_bnx.c:2848) sets m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN directly from the NIC-DMAd return-ring descriptor with no MCLBYTES bound anywhere on the path \u2014 a faulty or malicious BCM5717/5719/5720/577xx can hand the stack an mbuf describing up to 65531 bytes in a 2048-byte cluster (2046 usable after m_adj(ETHER_ALIGN), if_bnx.c:816-822). ether_inputs ETHER_BPF_MTAP (sys/net/if_ethersubr.c:1512) then copies the bogus length out of the cluster to bpf listeners => kernel heap OOB read / info disclosure of up to ~63.5KB; bge_len < 18 gives a negative m_len which if_ethersubr.c:1499-1503 drops harmlessly (no underflow panic, unlike bce DF-3604). Runtime verification honestly inconclusive: the audit guest has virtio-net only; bnx is compiled into the running kernel (kldstat -v: pci/if_bnx) but no Broadcom PCI device exists, so bnx_attach/bnx_rxeof are unreachable (run.log: NO_BROADCOM_DEVICE, ifconfig=vtnet0 lo0, sysctl hw.bnx unknown oid). Guest /usr/src if_bnx.c md5 49a18c4b7642b9b2ebd1d02ad11542e4 is byte-identical to the audited tree.",
  "exploit_chain": "On real hardware: (1) device DMAs an RX return-ring BD with bge_len=65535 and error flag clear; (2) driver hands the stack an mbuf with m_len=65531 in a 2048B cluster; (3) unprivileged user with a bpf listener on bnx0 reads up to ~63.5KB of adjacent kernel heap (info leak); IP-stack parsing of the same OOB range can also fault (panic/DoS). No write primitive from this bug alone (NIC DMA write is bounded by the posted BD len).",
  "evidence": "run.log (guest proof: driver in kernel, zero Broadcom devices, no attach, src md5 match), VERDICT.md (full path:line trace incl. the benign underflow path), trigger.c (annotated hardware-precondition trigger, builds clean -O -Wall), fix.diff (drop-frame clamp bounded by the mbufs own posted length)",
  "kernel_refs": [
    "sys/dev/netif/bnx/if_bnx.c:2848",
    "sys/dev/netif/bnx/if_bnx.c:2842",
    "sys/dev/netif/bnx/if_bnx.c:816",
    "sys/dev/netif/bnx/if_bnx.c:821",
    "sys/dev/netif/bnx/if_bnx.c:843",
    "sys/dev/netif/bnx/if_bnx.c:1348",
    "sys/dev/netif/bnx/if_bnx.c:3620",
    "sys/dev/netif/bnx/if_bnx.c:2881",
    "sys/dev/netif/bge/if_bgereg.h:2327",
    "sys/net/if_ethersubr.c:1499",
    "sys/net/if_ethersubr.c:1512"
  ],
  "poc_changes": "No seed existed (new pass-2 finding); trigger written as an annotated hardware-precondition skeleton per the DF-3604 precedent, built and executed on the guest to prove the code path is unreachable there.",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 140,
  "guest_dirty": 0,
  "build_cmd": "cc -O -Wall -o trigger trigger.c (guest)",
  "run_cmd": "./run.sh via dfbsd-qemu/vm.sh run_root (kldstat/pciconf/ifconfig/sysctl hw.bnx/md5 of if_bnx.c + trigger)",
  "code_hash": "ea827491551f529398e0ddeeeff59e9a39f0506132a2224a02b5031e2862fc52",
  "notes": "Pass-2 calibration: identical NIC-trust-length pattern filed Medium in pass 1 for my(DF-1478), vr(DF-1481), tx(DF-1490), ste(DF-1514), lge(DF-1519), pcn(DF-1562), and Medium for the bce sibling DF-3604; no bnx RX-length finding existed (DB-verified) so this is not a re-report. Hardware-layer bounds (BD len 2046, RX_MTU 1522, RCB 1536) are all device-side and thus not a defense against the defecting device this check guards against.",
  "recommended_fix": "In bnx_rxeof, drop the frame (ierrors++ + m_freem) when cur_rx->bge_len is outside [ETHER_HDR_LEN + ETHER_CRC_LEN, m->m_len + ETHER_CRC_LEN] before using it (see fix.diff).",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff adds the clamp using the mbufs own posted length as the bound (correct even if BNX_FLAG_JUMBO is ever enabled). Cannot be runtime-validated: the guest has no BCM5717+ device so neither baseline nor patched behavior is exercisable (same reason the PoC is inconclusive). The patch touches only existing symbols on an already-compiled path and mirrors the error-drop idiom used at if_bnx.c:2836-2841.",
  "fix_evidence": "fix.diff; baseline absence proof in run.log (NO_BROADCOM_DEVICE, sysctl hw.bnx unknown oid)"
}