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

iir_pci_attach error paths: BAR0 resource never released (release commented out, rid clobbered) and bus_setup_intr failure skips iir_free()/XPT teardown β€” leaked DMA state + /dev/iirN + live registered CAM SIMs with no interrupt (CCBs hang forever)

Summary

Every failure path after the BAR0 map leaks the memory resource (the io release is commented out and would use the rid clobbered to 0 by the IRQ alloc - disabled rather than fixed); a bus_setup_intr failure occurs AFTER iir_init/iir_attach fully armed the controller (gdt softcs, DMA tags/pool, /dev/iirN, XPT-registered SIMs, shutdown handler) - none unwound, and the registered SIMs immediately consume CAM scan traffic whose completions can never be delivered (iir_timeout empty per DF-4176). Admin/hw-triggered resource leak + CAM wedge. Full-teardown + save-rid fix (git-apply verified).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4888 Β· 5 files
FileTypeDescriptionSize
README.md β€” 1.0 KB ↓ raw
VERDICT.md β€” 4.1 KB ↓ raw
fix.diff β€” 2.8 KB view raw
verdict.json β€” 2.8 KB view raw
env.txt β€” 636 B view raw

DF-4888

iir_pci_attach error-path unwind: BAR0 (io) never released on any attach failure (release commented out at iir_pci.c:349-352 and rid clobbered), and bus_setup_intr failure (iir_pci.c:336-341) skips iir_free()/XPT teardown β€” leaving leaked DMA state, a live /dev/iirN, registered CAM SIMs with no interrupt (CCBs hang forever; iir_timeout is empty per DF-4176) and a stale shutdown handler.

Hardware-gated finding (needs the Intel SRCZCRX / ICP RAID PCI card present with a failing attach) β€” PoC not runnable on the audit guest: no such controller exists there (pciconf -lv shows 6 devices, none 0x8086:0x0600 / 0x1119; see env.txt). The driver is compiled into the guest kernel (kldstat -v β†’ 100 pci/iir).

Status: untested per the DF-4175 hardware-gated convention; code path verified by inspection end-to-end (attach at iir_pci.c:176-354; unwind semantics of iir_init/iir_free/ iir_attach at iir.c:182-518).

Source citations in the pass-2 result block; full narrative in VERDICT.md; fix in fix.diff.

VERDICT.md
↓ download raw

DF-4888 β€” iir_pci_attach error-path unwind: BAR resource never released; bus_setup_intr failure leaves XPT sims + /dev/iirN + pools live with no interrupt

Status: untested (hardware-gated β€” no Intel SRC / ICP RAID controller on the audit guest, code-certain by inspection). Severity: Low. Class: improper resource shutdown / error-path lifetime (CWE-404).

Root cause (two distinct unwinding gaps in sys/dev/raid/iir/iir_pci.c)

(a) The DPMEM BAR resource io is never released on ANY attach failure

iir_pci_attach allocates BAR0 at iir_pci.c:186-192 (rid = PCI_DPMEM; io = bus_alloc_resource_any(...)), then overwrites rid to 0 for the IRQ allocation (iir_pci.c:195-197). Every failure path after that (DPMEM magic mismatch :225-231, DEINIT timeout :253-261, protocol mismatch :267-271, init-error timeout :290-298, dma tag create :314-323, iir_init failure :326-330, bus_setup_intr failure :336-341) jumps to err:, which releases only irq. The io release is commented out β€” and would be wrong anyway, because rid no longer holds the memory rid:

346: err:
347:     if (irq)
348:         bus_release_resource( dev, SYS_RES_IRQ, 0, irq );
349: /*
350:     if (io)
351:         bus_release_resource( dev, SYS_RES_MEMORY, rid, io );
352: */
353:     return (error);

Because attach failed, newbus will never call a detach (the driver has none), so the rman resource for BAR0 leaks permanently. Each failed re-probe (devctl rescan, kldload after flaky-card failure, hot-plug flap) leaks another one β€” rman pool exhaustion eventually blocks other devices on the bus from mapping their BARs.

(b) bus_setup_intr failure skips ALL higher-level teardown

iir_init(gdt) (iir_pci.c:326) and iir_attach(gdt) (iir_pci.c:333) have already, by the time bus_setup_intr runs at iir_pci.c:336:

  • inserted gdt into the global gdt_softcs TAILQ (iir.c:199),
  • created DMA tags, the ccb pool and GDT_MAXCMDS dmamaps (iir.c:202-268),
  • created the control device /dev/iirN (iir.c:272),
  • registered GDT_MAXBUS CAM SIMs with the XPT and wildcard paths (iir.c:490-511),
  • registered a shutdown_post_sync handler (iir.c:514).

When bus_setup_intr fails (iir_pci.c:336-341) the code jumps to err: releasing only the IRQ β€” iir_free() is never called, the SIMs are never deregistered. Result on a live system:

  1. Permanent leak of sc_parent_dmat, sc_buffer_dmat, sc_gcscratch_dmat, sc_gcscratch, sc_gccbs, and the /dev/iirN cdev.
  2. The XPT-registered SIMs are immediately used by CAM's bus scan; iir_action queues commands to a board whose completions can never be delivered (no interrupt handler, and iir_timeout is an empty handler β€” DF-4176). All scanned CCBs hang forever, wedging the CAM rescan thread.
  3. The shutdown_post_sync handler stays registered against a controller that was never enabled (gdt_pci_enable_intr at iir_pci.c:343 is skipped), leaving a shutdown-time hazard.

Contrast: the author did unwind iir_init on its own failure (iir_pci.c:326-330 calls iir_free), proving the omission at :336-341 is an oversight, not a design decision.

Threat model

Requires the Intel SRCZCRX / ICP vortex RAID PCI hardware (vendor 0x8086 dev 0x0600, or 0x1119 0x0100-0x02ff/0x0300 β€” iir_pci.c:160-171) to be present AND attach to fail at the specific late stage (IRQ registration failure / flaky DPMEM). No unprivileged-user trigger; impact is resource exhaustion and I/O wedge on the host (admin/hardware-triggered DoS). Same trigger surface and severity band as the sibling iir findings DF-4173/DF-4175/DF-4176.

Fix

See fix.diff (saves the memory rid and releases io on every error path; on bus_setup_intr failure deregisters the XPT paths/SIMs that iir_attach created, drops the shutdown handler, and calls iir_free()).

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.diff authored post-verification against the read-only sys/ tree; not build-validated (no controller hardware to attach the patched kernel to)

findings/poc/DF-4888/fix.diff
↓ fix.diffper-fix-DF-4888

Confirmed kernel references

Detail

Evidence (decisive lines)

findings/poc/DF-4888/VERDICT.md (full path:line trace); findings/poc/DF-4888/fix.diff; guest hardware-absence proof in findings/poc/DF-4888/env.txt

PoC changes

no runnable PoC (hardware absent); evidence pack documents the trace and fix

Verified recommended fix

Save the memory rid and release io on every error path; on bus_setup_intr failure deregister XPT paths/SIMs, drop the shutdown handler and call iir_free() (see fix.diff)

Verdict

Source-verified, hardware-gated: every iir_pci_attach error path leaks the BAR0 resource (release commented out at sys/dev/raid/iir/iir_pci.c:349-352, and the saved rid was clobbered to 0 at :195), and a bus_setup_intr failure after successful iir_init()/iir_attach() (:336-341) releases only the IRQ - no iir_free(), no XPT/sim/shutdown-handler teardown - leaving leaked pools plus live registered SIMs whose completions can never be delivered (CCBs hang; iir_timeout is empty per DF-4176). Not runnable on the audit guest: no Intel 0x8086:0x0600 / ICP controller exists in pciconf (env.txt); driver is compiled in (kldstat -v: '100 pci/iir') so the code path is live on any host with the card.