amr_pci_attach registers amr_pci_intr before the state it consumes exists: a shared-IRQ-line interrupt in the attach window dispatches through the still-NULL sc->amr_get_work -> boot/kldload panic (setup-side mirror of DF-1820)
Summary
bus_setup_intr connects the handler before amr_attach assigns the dispatch table, init locks, or DMA; the RF_SHAREABLE handler has no status check and no INTEN gate - it unconditionally calls amr_done whose first action is the indirect call through the NULL amr_get_work. Any co-line device interrupt in the millisecond window jumps to 0. Hardware-gated. Move-setup_intr-after-attach + INTEN-gate fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4706 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.4 KB | β raw | |
| VERDICT.md | β | 2.8 KB | β raw | |
| fix.diff | β | 1.9 KB | view raw | |
| verdict.json | β | 2.5 KB | view raw |
DF-4706 β amr_pci_attach registers amr_pci_intr before the state it
consumes exists β NULL function-pointer call from a shared-line IRQ
What
sys/dev/raid/amr/amr_pci.c:263-268 β bus_setup_intr(..., amr_pci_intr,
sc, ...) is called before everything the handler consumes exists:
sc->amr_get_workis assigned only insideamr_attach()(amr.c:206-216), which runs atamr_pci.c:346;- the softc locks are
lockinit'd atamr_pci.c:324-325; - the mailbox/sg/ccb DMA blocks are allocated at
amr_pci.c:326/334/338.
amr_pci_intr (amr_pci.c:461-470) does no interrupt-status check
and no state gate β it unconditionally calls amr_done(sc), whose
first action is the indirect call sc->amr_get_work(sc, &mbox)
(amr.c:1782). The IRQ was allocated RF_SHAREABLE
(amr_pci.c:257-258), so the handler is invoked for any device
sharing the line, not just the AMR card.
Consequence
Any interrupt on the shared IRQ line during the attach window
(bus_setup_intr β¦ amr_attach's pointer assignment) β e.g. a NIC on
the same legacy INTA line, or the card itself left asserting by
firmware/previous driver instance β executes amr_pci_intr β
amr_done β indirect call through the NULL sc->amr_get_work
β jump to address 0 β kernel panic at boot or kldload amr.
Distinct from known DF-1820 (teardown ordering: amr_pci_free tears
the interrupt down LAST while freeing DMA) β this is the setup side
of the same missing interrupt-lifecycle discipline: registered too
early, gated by nothing.
Reachability / gating
Requires LSI MegaRAID/amr PCI hardware (probe must match
amr_device_ids[]). The trigger is probabilistic (an unrelated
device's interrupt must land in a millisecond-scale window), or
deterministic with an amr card that asserts IRQ before INTEN.
QEMU does not emulate LSI MegaRAID β verified absent on the audit
guest (no 0x101e/0x1000:1960 PCI device, /dev/amr* absent), so this
is hw-gated inconclusive.
Conceptual trigger (needs hardware)
# device sharing the IRQ line with the amr card generates traffic; # repeat kldload in a loop to widen the window: while :; do kldload amr; kldunload amr; done # expected on hit: panic "Fatal trap 12/... calling 0x0" from # amr_pci_intr -> amr_done -> sc->amr_get_work
Fix
Register the interrupt AFTER amr_attach() succeeds (and/or gate the
handler on AMR_STATE_INTEN), see fix.diff.
VERDICT β DF-4706
status: inconclusive (hardware-gated; QEMU does not emulate LSI MegaRAID) Β· reproduced: 0 Β· analysis confidence: likely
Was it reproduced?
No β and it cannot be on this guest: pciconf -l shows no
0x101e/0x1000:1960 RAID controller and /dev/amr* does not exist, so
amr_pci_attach never runs (verified this run, see
../DF-4705/guest_session.log). kldload amr on the guest loads
nothing with a matching device. The defect is established by code
trace:
amr_pci_attachbzeros the softc (amr_pci.c:195) β every member NULL, including theamr_get_workfunction pointer (amrvar.h:254).- IRQ is allocated
RF_SHAREABLE|RF_ACTIVE(amr_pci.c:257-258) and the handler connected (amr_pci.c:263-265) β from this instant the ISR is live for any device asserting the shared line. amr_pci_intr(amr_pci.c:461-470) has no status check / noAMR_STATE_INTENgate; it callsamr_done(sc)unconditionally.amr_done(amr.c:1782) immediately dispatches throughsc->amr_get_workβ still NULL untilamr_attachassigns it (amr.c:206-216, reached only atamr_pci.c:346).- β indirect call to address 0 β fatal trap, boot-time or kldload-time panic.
Window: the three bus_dma_tag_creates + lockinits + three DMA
alloc/load rounds between amr_pci.c:278-340 β milliseconds, extended
under DMA32 memory pressure. The interrupt need not be the amr card's
own (RF_SHAREABLE) β any co-line device (NIC, USB controller) firing
in the window panics the machine.
Not a re-report of DF-1820: DF-1820 is the teardown half
(amr_pci_free ordering, intr torn down LAST while DMA is freed);
this finding is the setup half (intr registered FIRST, before the
dispatch table it calls exists). Different lines, different fix.
Also note the same unguarded handler is why DF-1820's teardown window
is exploitable β a complete fix gates amr_pci_intr on driver state
and fixes BOTH orderings; fix.diff here moves setup_intr after
amr_attach() and adds the AMR_STATE_INTEN gate.
Exploit chain
None beyond DoS (NULL function-pointer call β panic). The called
address is fixed (0), not attacker-chosen; no control over registers
at the call site beyond sc.
Fix validation
Impossible on this guest (no amr hardware β neither baseline nor
patched kernel can exercise the path). fix_status: not_testable.
Guest state
Guest untouched; stayed up the whole run.
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_testablefix validation impossible on this guest: amr_pci_attach never runs without MegaRAID hardware (absent); diff authored from the line-accurate ordering trace
fix.diff (setup_intr relocation + AMR_STATE_INTEN gate)
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md 5-step trace with amr_pci.c:195,257-268,324-346 and amr.c:1782,206-216; guest gate evidence in ../DF-4705/guest_session.log (no amr PCI device, /dev/amr* absent)
PoC changes
no seed; conceptual trigger in README (kldload loop) β requires hardware absent from the guest
Verified recommended fix
move bus_alloc_resource_any(SYS_RES_IRQ)+bus_setup_intr after amr_attach() succeeds and gate amr_pci_intr on AMR_STATE_INTEN (see fix.diff)
Verdict
amr_pci_attach (amr_pci.c:263-268) connects amr_pci_intr before anything the handler consumes exists: sc->amr_get_work is assigned only inside amr_attach (amr.c:206-216) reached at amr_pci.c:346, locks are lockinit'd at amr_pci.c:324-325, mailbox/sg/ccb DMA at 326-339. The IRQ is RF_SHAREABLE (amr_pci.c:257-258) and amr_pci_intr (461-470) has no status check and no AMR_STATE_INTEN gate, calling amr_done(sc) whose first action is the indirect call sc->amr_get_work(sc,&mbox) (amr.c:1782) β any co-line device interrupt in the attach window jumps to NULL: boot/kldload panic. Setup-side mirror of known DF-1820 (teardown-side); not a re-report. Cannot be exercised on the audit guest: no LSI MegaRAID PCI device exists in QEMU (verified: no 0x101e/0x1000:1960 device, /dev/amr* absent).
No comments yet.