dcons_crom_detach half-clears the global dcons state: dcons_conf->dma_map is left dangling over the map freed two lines below and the module-static dcons_paddr is never reset β a re-attached dcons_crom takes dmamap_cb's 'already set' early-return and can never re-wire dcons_conf, silently disabling DMA sync; memory safety rests solely on the incidental dma_tag!=NULL guards in dcons_os.c
Summary
Only dma_tag is cleared on detach while dma_map dangles and dcons_paddr stays non-NULL - re-attach hits the paddr!=0 early-return leaving dma_tag NULL forever (all bus_dmamap_syncs silently skipped, coherency lost) with the dangling map one refactor away from UAF. Clear-both-globals fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5118 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 599 B | β raw | |
| VERDICT.md | β | 2.9 KB | β raw | |
| trigger.sh | β | 875 B | view raw | |
| env.txt | β | 1.0 KB | view raw | |
| fix.diff | β | 520 B | view raw | |
| verdict.json | β | 2.6 KB | view raw |
DF-5118 evidence pack
Finding: dcons_crom_detach half-clears global state β only
dcons_conf->dma_tag is NULLed; dcons_conf->dma_map is left dangling (map
freed two lines later) and dcons_paddr is never reset, so a re-attach takes
dmamap_cb's "already set" early-return (dcons_crom.c:139-143) and can never
re-wire dcons_conf. Memory safety today rests solely on the
dma_tag != NULL guards in dcons_os.c:176-206.
Status: untested / Info β needs FireWire hardware (guest has none).
Contents: VERDICT.md, trigger.sh (hardware-gated), env.txt, fix.diff (2-line detach fix).
DF-5118 β dcons_crom detach half-clears the global dcons state: dcons_conf->dma_map left dangling, dcons_paddr stale forever, re-attach can never re-wire
Verdict: UNTESTED (needs FireWire hardware) β Info/hardening. The state-machine defect is certain in code; memory safety today is only preserved by an unrelated NULL-guard.
Where
sys/dev/misc/dcons/dcons_crom.c:190-207(dcons_crom_detach)sys/dev/misc/dcons/dcons_crom.c:139-146(dmamap_cbβ the early-return and the global wiring)- Consumers:
sys/dev/misc/dcons/dcons_os.c:176-206(dcons_os_getc/checkc/putcguard everybus_dmamap_syncwithdg.dma_tag != NULL;dg.dma_mapis used unguarded inside those blocks)
The defect
/* XXX */
if (dcons_conf->dma_tag == sc->dma_tag)
dcons_conf->dma_tag = NULL; /* tag cleared ... */
/* ... but dma_map NOT */
bus_dmamap_unload(sc->dma_tag, sc->dma_map);
bus_dmamap_destroy(sc->dma_tag, sc->dma_map); /* map freed */
bus_dma_tag_destroy(sc->dma_tag);
After detach:
dcons_conf->dma_mapis a dangling pointer to freed map memory, whiledcons_conf->dma_tagis NULL. Today the only thing preventing a UAF is theif (dg.dma_tag != NULL)guards in dcons_os.c:176-206 β one refactor that reorders those checks away from a NULL tag makes every console getc/putc callbus_dmamap_sync(NULL-tag, freed-map).- The module-static
dcons_paddr(dcons_crom.c:63) is never reset, anddmamap_cbearly-returns when it is already set (dcons_crom.c:139-143): a re-attach of dcons_crom (device re-added under a live firewire bus without module unload) skipsdcons_conf->dma_tag/dma_map = ...(:144-145) entirely β the dcons core stays withdma_tag == NULLforever βbus_dmamap_synccoherency silently disabled β whilepost_busresetkeeps publishing the staledcons_paddrinto the ROM (:120-121). On x86 the stale physical address happens to still denote the same contigmalloc'd buffer (no IOMMU translation), so it is latent rather than actively corrupting; on any translated busdma backend it would advertise a dead mapping.
Fix
Clear both globals and dcons_paddr together in detach β fix.diff. With
dcons_paddr = 0, the re-attach path re-wires dcons_conf correctly and the
early-return retains its intended second-controller semantics.
Why no PoC run
Requires a FireWire controller for dcons_crom to instantiate
(guest has none β env.txt). Pure state-machine 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 (2-line detach fix); cannot be validated on this guest - dcons_crom never instantiates without FireWire hardware.
fix.diff; VERDICT.md
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (state trace across detach/re-attach); env.txt (no FireWire hardware on guest)
PoC changes
n/a - no FireWire controller on the guest; trigger.sh documents the hardware-gated sequence
Verified recommended fix
In dcons_crom_detach, clear dcons_conf->dma_map and reset dcons_paddr alongside dcons_conf->dma_tag so re-attach re-wires the globals instead of running on stale state.
Verdict
State-machine defect is certain in code: dcons_crom_detach (dcons_crom.c:199-204) clears only dcons_conf->dma_tag, leaving dcons_conf->dma_map dangling (the map is destroyed two lines below) and the module-static dcons_paddr stale. Because dmamap_cb early-returns when dcons_paddr != 0 (dcons_crom.c:139-143), a re-attach of dcons_crom (device re-added without module unload) never re-wires dcons_conf->dma_tag/dma_map - the dcons core runs with dma_tag==NULL forever (bus_dmamap_sync silently skipped, dcons_os.c:176-206) while post_busreset keeps publishing the stale dcons_paddr into the ConfigROM (dcons_crom.c:120-121). Memory safety today is preserved solely by the dma_tag!=NULL guards in dcons_os.c:176-206 sitting in front of the unguarded dma_map use - a fragile invariant one refactor away from a UAF. Filed as Info hardening; untested because the guest has no FireWire controller (env.txt).
No comments yet.