adv_pci_attach leaves the active IRQ resource allocated when bus_setup_intr() fails after bus_alloc_resource(SYS_RES_IRQ) succeeded
Summary
The setup_intr-failure unwind releases only the IOPORT - the RF_ACTIVE IRQ stays pinned forever (failed attach means no detach). adv twin of DF-4969 (adw_pci). Replay harness mode 2: IRQ=0 releases - leak proven; patched clean.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5043 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| run.log | run-log | both modes; mode-2 section shows IRQ=0 releases + LEAK PROVEN marker | 2.4 KB | view raw |
| run.2.log | run-log | patched replay: IRQ=1 released, unwind clean | 2.2 KB | view raw |
| fix.diff | suggested-fix | same diff as DF-5042 (IRQ-release hunk is this finding's fix) | 1.1 KB | view raw |
| VERDICT.md | verdict | full narrative | 2.9 KB | β raw |
| ../DF-5042/ | harness | shared verbatim-replay kld (wrapper.c/advansys_shim.c/fkdecl.h/Makefile/build.sh) | 4.0 KB | β download |
DF-5043 β VERDICT
Verdict: REPRODUCED (runtime replay of verbatim driver code; HW-gated natural trigger) Class: resource leak (CWE-772) Impact ceiling: none (pinned IRQ resource per failed attach) Confidence: certain
Reproduction
Same harness as DF-5042 (see ../DF-5042/VERDICT.md for the technique).
Mode 2 (kenv df5042.irqfail=1): the verbatim adv_pci_attach() reaches the
interrupt stage; fk_bus_alloc_resource hands out a fake IRQ resource and
records it; fk_bus_setup_intr returns failure; the adv_pci.c:289-294 unwind
calls adv_free() and bus_release_resource(dev, SYS_RES_IOPORT, ...) only.
Observed in run.log:
FK: bus_alloc_resource(IRQ) -> fake irq resource 0xffffffff82606820 FK: bus_setup_intr -> scripted FAILURE FK: bus_release_resource(IOPORT) DF5042: bus_release_resource: IOPORT=1 IRQ=0; bus_setup_intr calls=1 DF5042: *** IRQ resource NEVER RELEASED on the bus_setup_intr failure unwind -- DF-5043 LEAK PROVEN ***
Mechanism (source-confirmed)
adv_pci.c:287-294:
irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &irqrid, 0, ~0, 1,
RF_SHAREABLE | RF_ACTIVE);
if (irqres == NULL ||
bus_setup_intr(dev, irqres, 0, adv_intr, adv, &ih, NULL)) {
adv_free(adv);
bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); /* only IOPORT */
return ENXIO;
}
When bus_alloc_resource succeeded but bus_setup_intr failed, irqres is
never released (SYS_RES_IRQ, rid 0, RF_ACTIVE). Because the attach fails,
newbus (device_doattach, sys/kern/subr_bus.c:2115-2124) unbinds the driver
without invoking any detach method β nothing ever releases the resource. The
device is left in DS_NOTPRESENT with an active rman IRQ reservation against
it; re-probes of the device continue to work only because rman re-grants the
same owner, but the reservation (and its interrupt vector bookkeeping for MSI
systems) persists. This is the adv twin of DF-4969 (adw_pci error unwinds).
Fix validation (runtime A/B)
The IRQ-release hunk of fix.diff (identical file as DF-5042's pack; the
diff covers both unwind defects) adds:
if (irqres != NULL)
bus_release_resource(dev, SYS_RES_IRQ, irqrid, irqres);
Patched replay (run.2.log): bus_release_resource: IOPORT=1 IRQ=1,
"unwind clean (fix effective?)". Baseline vs patched on the same guest, same
scripted chip, same verbatim driver code.
Gating precondition
AdvanSys 0x10CD PCI HBA whose attach passes DMA/chip init but fails
bus_setup_intr (IRQ exhaustion, msix setup failure), or a VFIO endpoint
engineered to do so. Availability hygiene only; no escalation path.
Exploit chain
Not applicable.
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
fixedBaseline: IRQ resource released 0 times (marker printed). Patched (fix.diff applied to the adv_pci.c copy the kld compiles): 'bus_release_resource: IOPORT=1 IRQ=1', 'unwind clean (fix effective?)'. Runtime A/B on the same guest/kernel, no hardware.
run.log (baseline mode 2: IRQ=0 + LEAK PROVEN); run.2.log (patched: IRQ=1, unwind clean); fix_build.log
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log mode-2 section ('FK: bus_alloc_resource(IRQ) -> fake irq resource', 'FK: bus_setup_intr -> scripted FAILURE', 'DF5042: bus_release_resource: IOPORT=1 IRQ=0', '*** IRQ resource NEVER RELEASED ... DF-5043 LEAK PROVEN ***'); run.2.log patched ('IOPORT=1 IRQ=1', 'unwind clean'); fix.diff; VERDICT.md
PoC changes
Uses the DF-5042 harness unchanged; this finding is mode 2 (kenv df5042.irqfail=1) of the same kld.
Verified recommended fix
In the bus_setup_intr failure unwind, release the IRQ resource when it was allocated: if (irqres != NULL) bus_release_resource(dev, SYS_RES_IRQ, irqrid, irqres); (see the second hunk of fix.diff)
Verdict
When bus_alloc_resource(SYS_RES_IRQ) succeeds but bus_setup_intr() fails, the adv_pci.c:289-294 unwind calls adv_free() and releases only the IOPORT resource - the active IRQ resource is never bus_release_resource'd, and since the attach fails, newbus (device_doattach, subr_bus.c:2115-2124) unbinds the driver without running any detach, so nothing ever releases it. Reproduced at runtime on the guest with the DF-5042 verbatim-replay harness in mode 2 (kenv df5042.irqfail=1): 'bus_release_resource: IOPORT=1 IRQ=0' and the harness's ' IRQ resource NEVER RELEASED ... DF-5043 LEAK PROVEN ' marker. Natural trigger HW-gated (AdvanSys 0x10CD HBA; none on guest). Impact is a pinned rman IRQ reservation per failed attach - availability hygiene, no corruption/disclosure. The IRQ-release hunk of fix.diff validated by runtime A/B: patched replay shows 'IOPORT=1 IRQ=1', 'unwind clean'. adv twin of DF-4969 (adw_pci).
No comments yet.