Resource leak in mfi_pci_attach when IRQ allocation fails (return bypasses cleanup)
Summary
mfi_pci_attach (mfi_pci.c:288-292): if bus_alloc_resource_any(SYS_RES_IRQ) returns NULL at line 288, code executes "device_printf; return(EINVAL);" at 290-291 bypassing the out: cleanup label at 295 that would have invoked mfi_free()/mfi_pci_free(). Orphans 3 already-allocated resources: (1) PCI memory BAR (mfi_regs_resource allocated at 260); (2) parent DMA tag (mfi_parent_dmat allocated at 271-279); (3) MSI vector if pci_alloc_1intr at 286 had already committed one (pci.c:4365 pci_alloc_msi count=1 setting sc->mfi_irq_type=PCI_INTR_TYPE_MSI sc->mfi_irq_rid=1, never released because pci_release_msi only called from mfi_pci_free at 348-349). Compare DMA-tag failure path at 280-282 which correctly does "goto out". NEWBUS does not invoke detach on failed attach so driver never gets second chance to free. Attacker: privileged local user (root; devctl/kldload require privilege); path reached when IRQ allocation fails (IRQ exhaustion, MSI allocation race, failpoint). Repeated cycling (devctl attach mfi0 loop / kldunload/kldload while IRQ cannot be granted) leaks 1 DMA tag + 1 BAR resource + 1 MSI vector per attempt; finite global resources -> system-wide device probing/interrupt allocation degradation. AV:L/AC:H/PR:H, A:L.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2031 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | readme | original PoC README | 1.0 KB | β raw |
| VERDICT.md | verdict | full source-trace verdict | 1.3 KB | β raw |
| build.sh | build-script | build/verify instructions | 438 B | view raw |
| env.txt | environment | guest environment (no matching HW) | 814 B | view raw |
| fix.diff | suggested-fix | git-apply-able fix, verified to compile -Werror | 590 B | view raw |
| fix_build.log | build-log | Phase 8 module build evidence (-Werror rc=0) | 1.5 KB | view raw |
| run.sh | run-script | run instructions (HW-gated) | 320 B | view raw |
DF-2031 PoC β Resource leak on IRQ alloc failure in mfi_pci_attach
Preconditions
- Root (devctl/kldload require privilege)
- SYS_RES_IRQ allocation fails β achievable via IRQ exhaustion, MSI allocation race, or kernel failpoint
Trigger
# Force repeated failed attaches while IRQ cannot be granted:
while true; do
devctl attach mfi0 2>/dev/null
sleep 0.1
done
Expected output
vmstat -zshows monotonic growth of bus_dma_tag / resource zonespciconf -lv/dmesgshows MSI vectors reported allocated keep climbing- New device attaches on unrelated drivers start failing with "Cannot allocate interrupt" / "Cannot allocate DMA tag"
The leak is bounded only by reboot; it does not recover on its own.
Success criterion
Monotonic, unbounded growth of leaked DMA-tag/MSI-resource counts that do
not recover until reboot, proving the attach-failure path never released
them. Fixing the bug (goto out instead of return(EINVAL)) makes the
counts stable across failed attaches.
VERDICT -- DF-2031 (Low)
Verdict: REPRODUCED (source-only)
Impact: resource leak (BAR/DMA-tag/MSI) on failed attach; HW-gated (needs mfi(4)), source-confirmed
Confidence: likely
Mechanism (source-traced)
mfi_pci_attach (mfi_pci.c:288-292): if bus_alloc_resource_any(SYS_RES_IRQ) returns NULL, the code executes 'device_printf; return(EINVAL);' at mfi_pci.c:290-291, bypassing the out: cleanup label at :295 that invokes mfi_free()/mfi_pci_free(). This orphans the already-allocated PCI memory BAR (:260), parent DMA tag (:271-279), and committed MSI vector. The sibling DMA-tag failure path at :280-281 correctly does 'goto out'.
Why not runtime-reproduced
The guest (DragonFlyBSD 6.5-DEVELOPMENT #0 master DEV, KVM) has NO matching
hardware: pciconf shows no mfi/tws/iir RAID controller and no amdgpu/DRM GPU;
the driver therefore cannot attach and the vulnerable path is not runtime-
triggerable here. The defect was confirmed at the source level by tracing
the cited path:line against sys/, and the proposed fix was applied and the
affected module (mfi) built clean with -Werror (see fix_build.log).
Fix
mfi_pci.c:290-291: change 'return(EINVAL)' to 'error = EINVAL; goto out' so the already-allocated BAR/DMA-tag/MSI resources are released through the out: label.
The standalone, git-apply-able diff is fix.diff.
Fix verification
not_testableVALIDATED build.
VALIDATED build.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- r
- a
- i
- d
- /
- m
- f
- i
- /
- m
- f
- i
- _
- p
- c
- i
- .
- c
- :
- 2
- 8
- 8
- s
- y
- s
- /
- d
- e
- v
- /
- r
- a
- i
- d
- /
- m
- f
- i
- /
- m
- f
- i
- _
- p
- c
- i
- .
- c
- :
- 2
- 9
- 1
Detail
Exploit chain
none (HW-gated).
Evidence (decisive lines)
HW-GATED (no mfi). Source-CONFIRMED. mfi_pci_attach bus_alloc_resource_any(IRQ) failure returns EINVAL directly, bypassing out: cleanup label. Leaks BAR+DMA tag+MSI vector.
Verified recommended fix
Change return(EINVAL) to error=EINVAL; goto out.
Verdict
HW-GATED (no mfi). Source-CONFIRMED. mfi_pci_attach bus_alloc_resource_any(IRQ) failure returns EINVAL directly, bypassing out: cleanup label. Leaks BAR+DMA tag+MSI vector.
No comments yet.