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

adw_pci_attach error unwinds leak the PCI register/IRQ resources (and the softc on the setup() path): adw_free() never calls bus_release_resource

Summary

Every error path after resource acquisition calls only adw_free (which never releases regs/irq) and the setup() failure returns with neither - permanent BAR/IRQ leaks per failed attach cycle with AdvanSys hardware present (driver in the default kernel). No UAF reachable (post-setup_intr failure provably dead). Legacy-bucket completeness. Release-on-every-path fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4969 Β· 8 files
FileTypeDescriptionSize
README.md β€” 1.9 KB ↓ raw
VERDICT.md β€” 3.5 KB ↓ raw
adw_static_check.sh β€” 1.5 KB view raw
run.log β€” 3.2 KB view raw
env.txt β€” 249 B view raw
fix.diff β€” 1.3 KB view raw
verdict.json β€” 3.5 KB view raw
manifest.json β€” 998 B view raw

DF-4969 β€” adw_pci_attach error unwinds leak the PCI register/IRQ resources (and the softc on the setup() path): adw_free() never calls bus_release_resource

File: sys/dev/disk/advansys/adw_pci.c:242-245,265-270,274-278,295-298,300-303 (+ adwcam.c:844-886) Class: boot/attach-time kernel resource leak (no unwind pairing) Severity: Low (requires AdvanSys PCI hardware present + an init failure; legacy driver) Bucket: legacy (advansys)

Reproduce (static trace β€” runtime needs AdvanSys hardware, absent on this guest)

sh adw_static_check.sh [srcdir]   # default /usr/src/sys/dev/disk/advansys

Prints the exact cited lines from the running kernel's source: every error path after regs = bus_alloc_resource(...) calls only adw_free(adw) β€” which frees the DMA hierarchy and the softc but never releases regs (or irq once allocated, and never tears down the interrupt), and the entry->setup() failure path at adw_pci.c:244-245 returns without even adw_free(adw), leaking the M_INTWAIT-allocated softc and the register resource.

Runtime preconditions (why untested here)

The driver is compiled into the default kernel (sys/config/X86_64_GENERIC:101 device adw) β€” but attach requires a PCI device with AdvanSys IDs (0x10CD). This guest (pciconf -l, see env.txt) has none, so probe never matches and no runtime trigger exists. On real hardware the leak fires whenever attach fails after regs is allocated: failed adw_find_signature (bogus/absent chip), failed bus_dma_tag_create, failed adw_init (bad EEPROM checksum / chip wedge β†’ adw_init_chip ENXIO), failed IRQ allocation, or failed bus_setup_intr. Flaky hardware or IRQ exhaustion (kldload after boot with the card present) makes repeat-probe leaks possible: each failed attach leaks one I/O or memory BAR resource + the softc, and the device can never attach cleanly afterwards (the resource stays rman-owned by the failed unit).

VERDICT.md
↓ download raw

VERDICT β€” DF-4969

Status: untested β€” the AdvanSys driver is compiled into the guest's default kernel (sys/config/X86_64_GENERIC:101) but the guest has no PCI device with an AdvanSys vendor ID (0x10CD) (pciconf -l, env.txt), so adw_pci_probe never matches, adw_pci_attach never runs, and no runtime trigger exists on this guest. The defect is certain by code inspection; the cited lines were printed verbatim from the guest's /usr/src by adw_static_check.sh (run.log).

The defect, path by path

Resource acquisition in sys/dev/disk/advansys/adw_pci.c:

  1. :211-225 β€” regs = bus_alloc_resource(dev, regs_type, &regs_id, ...) (active BAR resource owned by the driver).
  2. :227-229 β€” adw = adw_alloc(dev, regs, regs_type, regs_id) β€” adwcam.c:818-838 kmallocs the softc (M_INTWAIT, cannot fail) and stores regs in it.
  3. :291-298 β€” adw->irq = bus_alloc_resource(dev, SYS_RES_IRQ, ...).

Error unwinds after that:

  1. :235-238 signature failure β†’ adw_free(adw); return ENXIO.
  2. :242-245 entry->setup() failure β†’ bare return (error) β€” no adw_free, no release (latent: both in-tree setups return 0 unconditionally today, but the path is live code for any future setup that can fail).
  3. :265-270 dma-tag failure, :274-278 adw_init failure, :295-298 IRQ-alloc failure, :300-303 adw_attach failure β†’ all call only adw_free(adw).

adw_free (adwcam.c:844-886) unwinds the DMA hierarchy by init_level and kfrees adw->name/adw β€” it contains no bus_release_resource for regs/irq and no bus_teardown_intr (nothing in the driver ever calls either). Newbus does not auto-release driver resources on failed attach, so:

  • every failure path above leaks the active BAR resource permanently (and the IRQ resource once reached), and
  • path 5 additionally leaks the kmalloc'd softc + name.

Practical impact: with AdvanSys hardware present, any attach failure (bad signature, wedge β†’ adw_init_chip ENXIO (adwcam.c:1136-1137), tag/IRQ allocation failure, bus_setup_intr failure) permanently consumes the card's register resource; re-probing (driver re-register, kldload-style cycles) stacks one leaked resource per attempt. Resource leak only β€” no UAF is reachable today:

  • the adw_attach steps after bus_setup_intr (adwcam.c:1163-1180) cannot fail (cam_sim_alloc is M_INTWAIT, cam_sim.c:160-190; xpt_bus_register returns CAM_SUCCESS unconditionally, cam_xpt.c:1493+), so the handler is never left hooked into a freed softc;
  • bus_dma_tag_destroy(adw->parent_dmat) with the pre-incremented init_level (adw_pci.c:263-272) is NULL-safe (busdma_machdep.c:334-337).

Distinct from DF-4309 (per-ACB dma-map leak in adw_free): this finding is the bus resource side (regs/irq never released, setup-path softc leak).

Fix

fix.diff: release the acquired resources on every error path in adw_pci_attach (regs via the locals; irq via adw->irq before adw_free), and add the missing adw_free(adw) on the setup-failure path.

Fix validation

Not testable on this guest (no AdvanSys hardware β€” probe never matches).

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 not testable: no AdvanSys hardware on this guest, baseline and patched attach paths cannot be exercised. fix.diff adds the missing bus_release_resource/adw_free unwinds.

fix.diff; hardware absence documented in env.txt
↓ fix.diffper-fix-DF-4969

Confirmed kernel references

Detail

Evidence (decisive lines)

run.log (adw_static_check.sh output from the guest's /usr/src showing the exact cited lines); VERDICT.md (path-by-path trace); env.txt (no 0x10CD PCI device, 'device adw' at X86_64_GENERIC:101)

PoC changes

no runtime trigger possible (hardware absent); wrote a static line-trace reproducer runnable on any DF guest with /usr/src

Verified recommended fix

Release regs (and irq once allocated) on every adw_pci_attach error path and add the missing adw_free() on the entry->setup() failure path.

Verdict

Runtime untestable on this guest: the adw driver is compiled into the default kernel (sys/config/X86_64_GENERIC:101 'device adw') but no PCI device with AdvanSys vendor 0x10CD exists (pciconf -l, env.txt), so adw_pci_probe never matches and adw_pci_attach never runs. Defect certain by inspection and confirmed against the guest's verbatim /usr/src source by adw_static_check.sh: adw_pci_attach allocates an active BAR resource at adw_pci.c:211-225 and an IRQ resource at :291-298, but every error path calls only adw_free(adw) (which unwinds the DMA hierarchy and kfrees the softc but never calls bus_release_resource and never tears down the interrupt - adwcam.c:844-886), and the entry->setup() failure path at adw_pci.c:242-245 returns without even adw_free, leaking the softc as well. With AdvanSys hardware present, any attach failure (bad signature, chip-wedge ENXIO from adw_init_chip, tag/IRQ alloc failure, bus_setup_intr failure) permanently leaks the card's register resource (and IRQ once reached); repeat probes stack leaks. No UAF is reachable today: the post-bus_setup_intr steps cannot fail (cam_sim_alloc is M_INTWAIT, xpt_bus_register returns CAM_SUCCESS unconditionally), so the handler is never left hooked into freed memory. Distinct from DF-4309 (per-ACB dma-map leak): this is the bus-resource side.