⬢ DragonFlyBSD Kernel Audit
DF-5348 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5348",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "bus_dmamap_unload() is a silent no-op for a map queued at EINPROGRESS: _bus_dmamap_unload only frees active bounce pages and never dequeues the map from bounce_map_waitinglist nor resets pagesneeded/pagesreserved nor releases its partial bounce-page reservation. Reproduced on a clean-boot DragonFly 6.5 guest: after unloading the queued map, releasing any bounce page in the zone completed its reservation and busdma_swi executed a full deferred bus_dmamap_load on the UNLOADED map, invoking its callback with stale buf/buflen state (DEFERRED CALLBACK FIRED FOR UNLOADED MAP). For drivers that free/reuse their buffer after aborting (the normal pattern) this is a write-after-free via the subsequent sync bounce copies; the stuck reservations also drain the shared bounce zone (DoS). impact recorded as dos (the driver-independent harm); the driver-dependent write-after-free ceiling is documented in VERDICT.md.",
  "exploit_chain": "bouncing tag -> load returns EINPROGRESS (map queued holding partial reservation) -> driver aborts: bus_dmamap_unload (no-op) + buffer freed/reused -> any later bounce-page release in the zone -> get_map_waiting completes reservation + dequeues the unloaded map -> busdma_swi runs deferred load on stale buf -> driver callback fires for dead transaction / bounce copies touch the freed buffer",
  "evidence": "run.log.baseline: bus_dmamap_unload(mapY) returned -- map is STILL on the waiting list then *** DEFERRED CALLBACK FIRED FOR UNLOADED MAP *** and RESULT=PHANTOM CONFIRMED; patched kernel (dmesg in DF-5347/dmesg_fixrun.txt): RESULT=FAILED + cleanup done",
  "kernel_refs": [
    "sys/sys/bus_dma.h:313",
    "sys/platform/pc64/x86_64/busdma_machdep.c:1022",
    "sys/platform/pc64/x86_64/busdma_machdep.c:645",
    "sys/platform/pc64/x86_64/busdma_machdep.c:1408",
    "sys/platform/pc64/x86_64/busdma_machdep.c:1445"
  ],
  "poc_changes": "authored fresh (no seed); POC_TEST=2 variant of the same KLD harness as DF-5347",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 (baseline) / #1 Oct 3 06:29 (fix validation) x86_64",
  "runtime_sec": 900,
  "guest_dirty": 0,
  "build_cmd": "make -m /usr/share/mk SYSDIR=/usr/src/sys MAKEOBJDIRPREFIX=/root/obj with COPTS+=-DPOC_TEST=2",
  "run_cmd": "kldload ./busdmauaf_t2.ko; sleep 2; dmesg | grep PHANTOM",
  "code_hash": "bab05c50e33011b81dbdc0092940682cf9cebd45759eca53a301eacf188b3167",
  "notes": "shares fix.diff with DF-5347 (the unload-dequeue hunk is this findings fix); fix validated on rebuilt kernel: phantom callback gone, reservations released, guest stable",
  "recommended_fix": "_bus_dmamap_unload: if pagesneeded||pagesreserved, STAILQ_REMOVE the map from the zone waiting list and call return_bounce_pages; busdma_swi: skip maps whose counters were reset (see fix.diff)",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff (DF-5347 pack) applied to guest /usr/src, kernel rebuilt. Baseline: phantom callback fired for unloaded map. Patched: RESULT=FAILED -- no callback after unload, reservation released, cleanup completed, guest stable.",
  "fix_evidence": "dmesg_fixrun.txt (DF-5347 pack): BUSDMA-PHANTOM lines on patched kernel show RESULT=FAILED + cleanup done"
}