DF-4304 / verdict.json
{ "finding_id": "DF-4304", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "Source-certain invariant break, runtime honestly inconclusive (hardware-gated). bfe_txeof (sys/dev/netif/bfe/if_bfe.c:1064-1083) and bfe_rxeof (:1106-1147) decode the DMA engines 12-bit current descriptor byte offset (BFE_STAT_CDMASK 0xfff, if_bfereg.h:69) into a descriptor index and use it directly as the walks termination target, with NO range validation and NO work bound. The fields encoding space maps to indices 0..511 (4095/8) but the rings hold 511 descriptors (valid 0..510, EOT at 510) and BFE_INC cycles software indices over 0..510 only - so any hardware-reported offset in [4088..4095] (index 511) makes while(current != cons)/while(i != chipidx) NON-TERMINATING in interrupt context while holding the ifnet serializer: bfe_rxeof spins allocating cluster mbufs and loading DMA maps forever (len=0-4 underflows into the error branch each pass); bfe_txeof spins the same way or trips KKASSERT(tx_cnt>0) (:1080) into a panic. The off-range encoding is architecturally used on this register interface - the driver itself programs 511*8=4088 into BFE_DMARX_PTR at if_bfe.c:549 - and the drivers error-reinit path (ISTAT_ERRORS -> bfe_init, :1176-1187) runs BEFORE bfe_rxeof (:1190) so it cannot rescue a walk begun with a bogus index. Guest index-space/loop-termination harness proves index 511 never terminates (run.log, HARN_RC=0); the guest has no Broadcom PCI device and QEMU provides no BCM4401 model (env.txt: NO_BROADCOM_PCI, hw.bfe unknown oid), so the instance cannot be fired - per family convention (DF-3761/DF-3715) recorded inconclusive. Availability only: software indices never leave 0..510, so no OOB memory access - no corruption, no uid=0 route.", "exploit_chain": "Precondition: bfe(4) hardware (BCM4401/4402) whose DMARX_STAT/DMATX_STAT current-descriptor field transiently or persistently reports byte offset 4088..4095 (post-EOT increment-before-wrap transient, DMA engine error state, or register corruption). The next RX/TX interrupt enters bfe_rxeof/bfe_txeof, the walk never terminates, one CPU pegs at interrupt priority holding the serializer, the interface and its ioctls/timers wedge permanently, and the rxeof variant additionally hammers the cluster allocator - system-wide livelock until reboot. No remote packet can set the register directly; the trigger is hardware-state-dependent.", "evidence": "run.log (harness output: index 511 is OUTSIDE the ring, current=511: walk NEVER TERMINATES, plus presence probes NO_BROADCOM_PCI / hw.bfe unknown oid / guest-src md5 == audited tree); build.log (cc clean); bfe_walk_harness.c (index-space enumeration + BFE_INC walk simulation); VERDICT.md (path:line trace + negative results incl. the killed DF-3604-family length-trust candidate); fix.diff (range guards in both walks, patch -p1 --dry-run clean)", "kernel_refs": [ "sys/dev/netif/bfe/if_bfe.c:1064", "sys/dev/netif/bfe/if_bfe.c:1070", "sys/dev/netif/bfe/if_bfe.c:1080", "sys/dev/netif/bfe/if_bfe.c:1106", "sys/dev/netif/bfe/if_bfe.c:1109", "sys/dev/netif/bfe/if_bfe.c:549", "sys/dev/netif/bfe/if_bfe.c:1176", "sys/dev/netif/bfe/if_bfe.c:1190", "sys/dev/netif/bfe/if_bfereg.h:69", "sys/dev/netif/bfe/if_bfereg.h:405", "sys/dev/netif/bfe/if_bfereg.h:426" ], "poc_changes": "No seed PoC. Authored bfe_walk_harness.c (userland index-space + loop-termination proof of the exact driver arithmetic) because the guest has no BCM4401 and QEMU cannot emulate one; plus guest-side presence probes.", "attempts": 1, "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": 30, "guest_dirty": 0, "build_cmd": "cc -o /root/bfe_walk_harness /root/bfe_walk_harness.c", "run_cmd": "vm.sh run_root /root/bfe_walk_harness; ifconfig -l; pciconf -l | grep -i -E \"14e4|broadcom\" || echo NO_BROADCOM_PCI; sysctl hw.bfe", "code_hash": "26a23d9c0b835cdd77a1e6ad69d671483e2b3862fcf609094e1ec68384d293bd", "notes": "Checklist items (a)/(b) result: the DF-3604-family length trust is KILLED (underflow caught by the len>ETHER_MAX_LEN+32 filter at :1121; max touch 1550+30=1580 < MCLBYTES 2048) and software TX invariants hold; the surviving defect is the unbounded, range-unvalidated completion walk (DF-3761/DF-3604 hybrid: register-trust + no work bound). The DF-3761 flood-livelock aspect is also unbounded here (no process_limit-style cap), though a 100Mbit NIC cannot sustain a line-rate walk overrun the way gigabit alc can.", "recommended_fix": "Range-validate the decoded index in both walks (return with a rate-limited error print if chipidx/current >= BFE_xX_LIST_CNT) and optionally cap iterations per interrupt; see fix.diff.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored against the read-only sys/ tree (patch -p1 --dry-run clean); cannot be runtime-validated without BCM4401 hardware.", "fix_evidence": "findings/poc/DF-4304/fix.diff" } |