cs4281_pci_detach() releases the BA0/BA1 register mappings before bus_teardown_intr - live ISR reads released mappings (shared-IRQ use-after-release window)
Summary
Detach releases the register windows before tearing down the interrupt; the ISR bus_space-reads HISR/HDSR through exactly those mappings on every dispatch on a shareable IRQ. An interrupt in the window dispatches into released rman resources (panic); the bad: unwind repeats the inverted order. Sibling es137x does it correctly. Teardown-intr-first fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4538 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.6 KB | β raw | |
| VERDICT.md | β | 2.4 KB | β raw | |
| cs4281_probe.c | β | 2.0 KB | view raw | |
| build.sh | β | 133 B | view raw | |
| run.sh | β | 138 B | view raw | |
| build.log | β | 94 B | view raw | |
| run.log | β | 428 B | view raw | |
| env.txt | β | 604 B | view raw | |
| wedge_episode.txt | β | 777 B | view raw | |
| fix.diff | β | 793 B | view raw | |
| manifest.json | β | 975 B | view raw | |
| verdict.json | β | 3.1 KB | view raw |
DF-4538 β cs4281_pci_detach() releases the BA0/BA1 register mappings before tearing down the interrupt handler that reads them
What this is
cs4281_pci_detach() (cs4281.c:878-901) releases the BA0 register window
(cs4281.c:893) and the BA1 memory window (cs4281.c:894) before
bus_teardown_intr() (cs4281.c:895). The interrupt handler
(cs4281_intr, registered at cs4281.c:812, shared-IRQ capable per
cs4281.c:806 RF_SHAREABLE) reads CS4281PCI_HISR/HDSR through those
mappings (cs4281_rd, cs4281.c:146-150) on every line assertion, and
pcm_unregister() does not unregister the handler. During the window
between the two releases and the teardown, an interrupt (its own or a
shared line level) dispatches into bus_space reads of already-released
rman resources β use-after-release of the register mapping, typically a
kernel panic.
Sibling drivers get the order right (es137x.c:1917-1919 tears down the
interrupt before releasing IRQ and registers); cs4281 (and its bad:
unwind at cs4281.c:867-870, which has the same inverted order) does not.
Trigger: root unloading snd_cs4281 (kldunload) while the device
raises or shares an interrupt. Unprivileged users cannot reach this;
severity Low.
Build / run
./build.sh # guest build of the environment probe ./run.sh # documents: no CS4281 hardware on this guest (detach path unreachable)
Fix
fix.diff moves bus_teardown_intr() + IRQ release ahead of the BA0/BA1
register releases in cs4281_pci_detach(), matching es137x.c:1917-1919.
git apply --check clean; never applied to sys/.
DF-4538 VERDICT β untested (hardware-gated), analysis certain
Source chain
snd_setup_intr(dev, sc->irq, 0, cs4281_intr, sc, &sc->ih)at cs4281.c:812 installs the ISR; the IRQ resource was allocatedRF_SHAREABLE(cs4281.c:805-806).cs4281_intr(cs4281.c:512-533) immediately readscs4281_rd(sc, CS4281PCI_HISR)(cs4281.c:517) β i.e. a bus_space read throughsc->st/sc->sh, the BA0 mapping β before deciding whether the interrupt is ours (there is no early filter/ITHREAD filter separation here).cs4281_pci_detach(cs4281.c:878-901) first callspcm_unregister(cs4281.c:884) β which stops channels/mixer but does not unregister the ISR β then releases the BA0 register resource (cs4281.c:893) and BA1 memory (cs4281.c:894), and only then runsbus_teardown_intr(cs4281.c:895).- In the window between (3)'s releases and the teardown, any interrupt
on the (shared) line dispatches
cs4281_intrinto reads of released rman-backed mappings β use-after-release; typical outcome panic. - The
bad:attach-unwind has the same inverted order (cs4281.c:867-870:bus_teardown_intrafter the twobus_release_resourcecalls), though reaching it additionally requires an attach failure. - Correct ordering exists in the sibling es137x driver (es137x.c:1917-1919: teardown_intr, release IRQ, release regs).
Why untested
Requires a real CS4281 PCI function to exist (so attach succeeded and
detach can run) plus root (kldunload snd_cs4281) plus an interrupt
arrival inside the release window. The audit guest has no vendor-1013
function (env.txt, run.log) β the detach path cannot execute here at
all. Static chain verified line-by-line; classification untested,
confidence certain, no unprivileged impact (root-gated) β Low.
Fix validation
fix.diff reorders detach to teardown_intr β IRQ release β BA0/BA1
release. git apply --check clean. Not observable on this guest (no
CS4281 hardware) β fix_status not_testable.
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.diff moves bus_teardown_intr() and the IRQ release ahead of the BA0/BA1 register releases in cs4281_pci_detach(); git apply --check is clean. Not observable on the audit guest (no CS4281 hardware), so baseline vs patched cannot be compared.
findings/poc/DF-4538/fix.diff; correct sibling order at es137x.c:1917-1919
Confirmed kernel references
Detail
Evidence (decisive lines)
findings/poc/DF-4538/VERDICT.md; cs4281.c:812 snd_setup_intr, cs4281.c:805-806 RF_SHAREABLE, cs4281.c:517/523/528 ISR register reads, cs4281.c:893-895 inverted release order, cs4281.c:867-870 same order in bad:, es137x.c:1917-1919 correct sibling order; run.log/env.txt (no vendor-1013 PCI function on guest)
PoC changes
no seed; environment probe shared with DF-4537 (same trigger-hardware absence)
Verified recommended fix
In cs4281_pci_detach (and the bad: unwind), call bus_teardown_intr and release the IRQ before releasing the BA0/BA1 register resources, matching es137x.c:1917-1919
Verdict
cs4281_pci_detach() (cs4281.c:878-901) releases the BA0 register window (cs4281.c:893) and BA1 memory window (cs4281.c:894) before bus_teardown_intr() (cs4281.c:895), while cs4281_intr -- installed at cs4281.c:812 on a shareable IRQ (cs4281.c:805-806) -- bus_space-reads HISR/HDSR through exactly those mappings on every dispatch (cs4281.c:517,523,528) and pcm_unregister() (cs4281.c:884) does not unregister it. An interrupt arriving in the release window dispatches into released rman mappings: use-after-release, typical outcome panic. The bad: attach-unwind repeats the same inverted order (cs4281.c:867-870). Sibling es137x.c:1917-1919 demonstrates the correct teardown-first order. Untested: executing detach at all requires a CS4281 PCI function (absent on the audit guest, env.txt) and root (kldunload); the race window needs an interrupt arrival. Root-gated, hardware-gated: Low, analysis certain.
No comments yet.