β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-5614

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5614 Β· 2 files
FileTypeDescriptionSize
README.md file 812 B ↓ raw
verdict.json file 3.4 KB view raw
README.md file
↓ download 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_testable
baseline no→ patch + rebuild →patched clean

not applicable: latent protocol violation, no runtime trigger exists on this platform to validate against

per-fix-DF-5614

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.