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)
PoC verification
Evidence pack
findings/poc/DF-5117 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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).
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
sys/dev/misc/dcons/dcons_crom.c:126-153(dmamap_cb)sys/dev/misc/dcons/dcons_crom.c:171-185(dcons_crom_attachβ all three bus_dma return values ignored)- DF bus_dma semantics:
sys/platform/pc64/x86_64/busdma_machdep.c:766-807βbus_dmamap_loadinvokes the callback at :804 even whenerror != 0(only EINPROGRESS defers), withsegmentspointing at the caller's uninitializedcache_segments[]stack buffer (:771) andnsegsmerely initialized to 1 (:774).
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:
- 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 globaldcons_paddr; - that garbage
dcons_paddris then published into the local ConfigROM bydcons_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; dcons_conf->dma_tag/dma_mapare wired for a map whose load failed βbus_dmamap_syncon an unloaded map (silent coherency loss or, with bpages, wrong bounce handling);- 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_testablefix.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
Confirmed kernel references
- sys/dev/misc/dcons/dcons_crom.c:130
- sys/dev/misc/dcons/dcons_crom.c:134
- sys/dev/misc/dcons/dcons_crom.c:137
- sys/dev/misc/dcons/dcons_crom.c:146
- sys/dev/misc/dcons/dcons_crom.c:171
- sys/dev/misc/dcons/dcons_crom.c:182
- sys/platform/pc64/x86_64/busdma_machdep.c:804
- sys/platform/pc64/x86_64/busdma_machdep.c:771
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.
No comments yet.