DF-5614 / verdict.json
{ "finding_id": "DF-5614", "status": "untested", "reproduced": false, "impact": "none demonstrated (latent): garbage/stale fwdma bus_addr programmed into OHCI registers on any bus_dmamap_load failure -> hardware DMA against a wild physical address; unreachable on the current x86_64 busdma because loads of bus_dmamem_allocd memory cannot fail there", "confidence": "certain", "verdict": "Code-certain bus_dma protocol violation, runtime-latent on this platform (not PoC-verified -- Low severity, below the verification threshold). fwdma_map_cb (fwdma.c:53-62) prints the error but unconditionally writes *baddr = segs->ds_addr, reading segs[0] that is uninitialized when _bus_dmamap_load_buffer failed before filling segments; both load call sites ignore the return value (fwdma.c:102-103, 127-128). On this platform bus_dmamap_load RETURNS 0 even when the load failed -- the error reaches only the callback (sys/platform/pc64/x86_64/busdma_machdep.c:804-806) -- so the callbacks error parameter is the ONLY error channel and fwdma discards it. The result (dma->bus_addr / seg->bus_addr stale-uninitialized or garbage) is consumed as a hardware DMA base address (fwohci.c:664-700 config_rom/sid_buf; fwohci.c:1232 fwdma_bus_addr into descriptor rings). The correct contract is implemented 40 lines away in the tree: _bus_dmamem_coherent_cb checks if (error) return; and KASSERTs nseg==1 (sys/kern/subr_busdma.c:42-51), and bus_dmamem_coherent checks the load return and unwinds (subr_busdma.c:79-93). Today the failure paths (bounce-page reserve ENOMEM / EINPROGRESS, busdma_machdep.c:638-657) cannot trigger for bus_dmamem_allocd memory (<=PAGE kmalloc or contigmalloc below lowaddr both satisfy the tag), so impact is latent/portability-hazard, not a live bug: hence Low and no runtime PoC.", "exploit_chain": "", "evidence": "source citations in verdict; no runtime artifacts (Low/latent, verification skipped per contract)", "kernel_refs": [ "sys/bus/firewire/fwdma.c:53", "sys/bus/firewire/fwdma.c:58", "sys/bus/firewire/fwdma.c:61", "sys/bus/firewire/fwdma.c:102", "sys/bus/firewire/fwdma.c:127", "sys/kern/subr_busdma.c:42", "sys/kern/subr_busdma.c:79", "sys/platform/pc64/x86_64/busdma_machdep.c:804", "sys/platform/pc64/x86_64/busdma_machdep.c:638" ], "poc_changes": "", "attempts": 0, "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": 0, "guest_dirty": 0, "build_cmd": "", "run_cmd": "", "code_hash": "", "notes": "Low/latent hardening finding -- PoC skipped (untestable in practice: no code path on the current x86_64 busdma can make this load fail for bus_dmamem_allocd memory). Filed for portability/future-proofing: any future busdma change (deferred loads, bounce-on-demand for kmallocd memory) turns this into silent wild-address hardware DMA.", "recommended_fix": "Make fwdma_map_cb follow the _bus_dmamem_coherent_cb contract (return without touching segs when error != 0, KASSERT nseg == 1) and have fwdma_malloc/fwdma_malloc_size check bus_dmamap_loads return, unwinding (bus_dmamem_free + bus_dma_tag_destroy) on failure.", "fix_status": "not_testable", "fix_baseline_reproduced": false, "fix_patched_reproduced": false, "fix_verdict": "not applicable: latent protocol violation, no runtime trigger exists on this platform to validate against", "fix_evidence": "" } |