fwdma_map_cb and both fwdma load call sites discard the bus_dmamap_load error β stale/garbage bus_addr would be programmed into OHCI DMA registers (latent protocol violation)
Summary
The callback prints the error but unconditionally executes *baddr = segs->ds_addr reading uninitialized segs[0] on failure, and both malloc paths ignore bus_dmamap_load's return - on this platform load returns 0 even on failure so the discarded callback error is the ONLY failure channel. A failed load leaves bus_addr stale/garbage, consumed as hardware DMA base addresses (config_rom, descriptor rings) -> device DMA against a wild physical address. Latent on x86_64 (dmamem loads cannot fail there); any busdma change or port activates it. The tree's own correct contract is 40 lines away in subr_busdma.c. early-return+check fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5614 Β· 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | file | 812 B | β raw | |
| verdict.json | file | 3.4 KB | view raw |
DF-5614 β fwdma_map_cb / fwdma load call sites ignore the bus_dmamap_load error contract (latent wild bus_addr)
fwdma.c:53-62 writes *baddr = segs->ds_addr even when the callback's
error != 0 (and segs[0] may be uninitialized), and fwdma.c:102-103 /
:127-128 ignore bus_dmamap_load's return β which on this platform is 0
even on failure (busdma_machdep.c:804-806 passes the error only to the
callback). The stale/garbage bus_addr is then programmed into OHCI
registers (fwohci.c:664-700) as a hardware DMA base. Latent today (loads
of bus_dmem_alloc'd memory cannot fail on x86_64 busdma); the correct
contract to copy is subr_busdma.c:42-51 + :79-93.
Low / latent β no runtime PoC (verification skipped per contract). Details: verdict.json; finding text: findings/DF-5614-*.md (orchestrator).
Fix verification
not_testablenot applicable: latent protocol violation, no runtime trigger exists on this platform to validate against
Confirmed kernel references
Detail
Evidence (decisive lines)
source citations in verdict; no runtime artifacts (Low/latent, verification skipped per contract)
Verified 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_load's return, unwinding (bus_dmamem_free + bus_dma_tag_destroy) on failure.
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 callback's 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_alloc'd 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.
No comments yet.