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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2031 Β· 7 files
FileTypeDescriptionSize
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
README.md readme original PoC README
↓ download raw

DF-2031 PoC β€” Resource leak on IRQ alloc failure in mfi_pci_attach

Preconditions

  1. Root (devctl/kldload require privilege)
  2. 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 -z shows monotonic growth of bus_dma_tag / resource zones
  • pciconf -lv / dmesg shows 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.md verdict full source-trace verdict
↓ download raw

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_testable
baseline reproduced→ patch + rebuild →patched clean

VALIDATED build.

VALIDATED build.
↓ fix.diffmfi.ko build rc=0 -Werror

Confirmed kernel references

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.