adw_free() never destroys the per-ACB buffer DMA maps β attach/detach asymmetry leaks up to 253 bus_dmamaps and destroys their tag while live
Summary
adwallocacbs creates one buffer dmamap per ACB but adw_free's teardown switch never destroys them and tears down the tag with all maps live - every detach/kldunload/failed-attach leaks them. Destroy-loop fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4309 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | β | 1.7 KB | β raw | |
| README.md | β | 347 B | β raw | |
| fix.diff | β | 2.7 KB | view raw | |
| manifest.json | β | 195 B | view raw | |
| verdict.json | β | 2.1 KB | view raw |
DF-4309 evidence pack
Source-level finding against sys/dev/disk/advansys/adwcam.c β hardware-gated (guest/QEMU has no Advansys HBA; pciconf shows no vendor 10cd). No runnable PoC exists without the device. See VERDICT.md for the full path:line proof and fix.diff for the validated-shape fix (patch -p1 apply-verified, never applied to sys/).
DF-4309 β adw_free() never destroys the per-ACB buffer DMA maps (attach/detach asymmetry)
File: sys/dev/disk/advansys/adwcam.c β severity Info (resource leak /
cleanup asymmetry), bucket base:dev, confidence certain (source).
Root cause
adwallocacbs() creates one buffer DMA map per ACB:
error = bus_dmamap_create(adw->buffer_dmat, /*flags*/0,
&next_acb->dmamap); /* adwcam.c:205-206 */
adw_free() (adwcam.c:843-886) unwinds init levels 9β1: it frees the sg
maps (case 9), unloads/frees the acb array (cases 8/7) and destroys
buffer_dmat itself (case 2, adwcam.c:878) β but never destroys the
next_acb->dmamap maps (up to ADW_DEF_MAX_HOST_QNG = 253 of them,
adwlib.h:54). Every adw_free() β driver detach / kldunload / failed
attach β leaks all per-ACB bus_dma map structures and destroys their tag
while the maps are still live.
Impact: kernel resource leak only (repeatable by privileged module load/unload); no direct memory-safety consequence. Filed as Info hardening found by the pass-2 attach-error-path lens.
Reproduction
Hardware-gated (needs Advansys HBA for adw_init to reach adwallocacbs).
Guest has none (pciconf -l | grep 10cd β empty). Status untested.
Fix
fix.diff β destroy the per-ACB maps in adw_free() case 9 (before the
buffer tag is torn down in case 2). patch -p1 apply-verified.
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 against the read-only sys/ tree (patch -p1 apply-verified); cannot be runtime-tested without Advansys hardware.
findings/poc/DF-4309/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
findings/poc/DF-4309/VERDICT.md; creation adwcam.c:205-206; teardown switch adwcam.c:846-883 (no per-acb dmamap destroy); tag destroyed at adwcam.c:878
PoC changes
No seed PoC (finding new in pass 2). Hardware-gated.
Verified recommended fix
Destroy the per-ACB buffer maps in adw_free() case 9 before the tag teardown β see fix.diff.
Verdict
Source-certain, hardware-gated. adwallocacbs() creates one bus_dmamap per ACB (bus_dmamap_create(adw->buffer_dmat, &next_acb->dmamap), adwcam.c:205-206) but adw_free() (adwcam.c:843-886) never destroys them: case 9 frees the sg maps, cases 8/7 free the acb array, case 2 destroys buffer_dmat itself (adwcam.c:878) with all per-ACB maps still live. Every adw_free() (detach, kldunload, failed attach) leaks up to ADW_DEF_MAX_HOST_QNG=253 dma maps and destroys their tag out from under them. Resource-leak / cleanup-asymmetry only (privileged repeat path), no direct memory-safety impact β Info severity. Guest has no Advansys HBA, so no runtime reproduction.
No comments yet.