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

dmamap_cb continues after bus_dmamap_load error: uninitialized-stack segments[0].ds_addr is stored into dcons_paddr and published to FireWire peers via the ConfigROM, the stack bytes are printed to console, and dcons_conf is wired for a map whose load failed β€” while dcons_crom_attach ignores all three bus_dma return values and reports success

Summary

DF busdma invokes the callback even on error with uninit stack segments; the callback prints, wires globals, publishes the garbage address into the ConfigROM. Practically unreachable on DF/amd64 (WAITOK forced over a valid contig buffer) - hardening. Early-return + check-the-three-returns fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5117 Β· 6 files
FileTypeDescriptionSize
README.md β€” 817 B ↓ raw
VERDICT.md β€” 3.0 KB ↓ raw
trigger.sh β€” 757 B view raw
env.txt β€” 1.0 KB view raw
fix.diff β€” 1.6 KB view raw
verdict.json β€” 2.9 KB view raw

DF-5117 evidence pack

Finding: dmamap_cb (dcons_crom.c:126-153) continues after a bus_dmamap_load error β€” stores uninitialized-stack segments[0].ds_addr into dcons_paddr, prints those kernel-stack bytes to console, wires dcons_conf globals for a failed map, and the garbage address is published into the FireWire ConfigROM (dcons_crom.c:120-121). Attach ignores all three bus_dma return values. DF's bus_dmamap_load calls the callback even on error (busdma_machdep.c:804).

Status: untested / Info β€” precondition (load failure on a valid contig buffer with WAITOK forced) is unreachable on DF/amd64; no FireWire hardware on the guest. Hardening only.

Contents: VERDICT.md (trace), trigger.sh (documents unreachable precondition), env.txt (guest), fix.diff (error return + checked attach).

VERDICT.md
↓ download raw

DF-5117 β€” dcons_crom dmamap_cb continues after bus_dmamap_load error: garbage physical address published to the FireWire ConfigROM + uninitialized stack bytes printed to console

Verdict: UNTESTED (and practically unreachable on this platform) β€” Info/hardening. The defect is certain in code; the triggering load failure is ~impossible on DF/amd64 for this buffer.

Where

The defect

    if (error)
        kprintf("dcons_dmamap_cb: error=%d\n", error);   /* prints... */

    sc = (struct dcons_crom_softc *)arg;
    sc->bus_addr = segments[0].ds_addr;   /* ...but DOES NOT RETURN */
    ...
    dcons_conf->dma_tag = sc->dma_tag;    /* wires globals for a failed map */
    dcons_conf->dma_map = sc->dma_map;
    dcons_paddr = sc->bus_addr;           /* garbage published */

On a load error the callback:

  1. reads segments[0].ds_addr β€” uninitialized kernel stack β€” and both prints it to the console (bus_addr 0x%jx, dcons_crom.c:137-138: an 8-byte kernel-stack disclosure to dmesg) and stores it into the module global dcons_paddr;
  2. that garbage dcons_paddr is then published into the local ConfigROM by dcons_crom_post_busreset (dcons_crom.c:120-121, DCONS_CSR_KEY_HI/LO) for any FireWire peer β€” the peer's dcons client then reads/writes the wrong physical address;
  3. dcons_conf->dma_tag/dma_map are wired for a map whose load failed β€” bus_dmamap_sync on an unloaded map (silent coherency loss or, with bpages, wrong bounce handling);
  4. attach still returns 0 β€” the driver claims healthy.

dcons_crom_attach (dcons_crom.c:171-185) ignores the return of bus_dma_tag_create, bus_dmamap_create and bus_dmamap_load; on DF/amd64 the tag create is M_INTWAIT/ALLOCNOW-backed and bus_dmamap_load forces WAITOK (:782-783) over a valid contigmalloc buffer, so failure needs pathological conditions β€” hence Info, not higher.

Fix

Early-return on error in dmamap_cb and check/propagate the three returns in attach (fail the attach with unwind) β€” fix.diff.

Why no PoC run

Requires a FireWire controller (none on the guest β€” env.txt) and a bus_dmamap_load failure that current DF busdma cannot produce for this buffer. Pure hardening.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

fix.diff authored statically (error return in callback + checked/unwound attach); cannot be validated on this guest - no FireWire controller and the failure precondition is unreachable on DF/amd64 busdma.

fix.diff; VERDICT.md
↓ fix.diffper-fix-DF-5117

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (line-by-line continuation trace + busdma callback semantics); env.txt (no FireWire hardware on guest); trigger.sh documents the unreachable precondition

PoC changes

n/a - precondition (load failure) unreachable on the guest (no FireWire controller) and on the platform (WAITOK forced)

Verified recommended fix

dmamap_cb: return immediately on error before touching segments[] or the globals; dcons_crom_attach: check bus_dma_tag_create/bus_dmamap_create/bus_dmamap_load and fail attach with unwind.

Verdict

Code defect is certain: dmamap_cb (dcons_crom.c:126-153) prints a bus_dmamap_load error but does not return - DF's bus_dmamap_load invokes the callback even on failure (busdma_machdep.c:804) with segments[] backed by uninitialized stack (cache_segments, :771) - so the callback stores garbage into sc->bus_addr, prints those 8 uninitialized kernel-stack bytes to the console (dcons_crom.c:137-138), wires dcons_conf->dma_tag/dma_map for a failed map (:144-145), and publishes the garbage as dcons_paddr into the local ConfigROM (post_busreset :120-121) for FireWire peers, while dcons_crom_attach (:171-185) ignores all three bus_dma return values and returns success. Practical reachability is ~nil on DF/amd64: bus_dmamap_load forces WAITOK (:782-783) over a valid contigmalloc'd buffer and the tag/map creation paths are M_INTWAIT - so this is filed as Info hardening, not a demonstrable leak.