snd_vibes: sv_suspend() aborts the playback channel with the record trigger (copy-paste) β playback DMA engine left enabled across suspend
Summary
sv_suspend aborts sc->pch with svrchan_trigger (the RECORD channel's trigger); its abort path clears only RECORD_ENABLE, so the playback engine never disables - it keeps bus-mastering across the suspend transition while the framework believes the channel quiesced. PM state-machine defect, no kernel memory-safety impact. One-token fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4553 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.3 KB | β raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| run.sh | β | 146 B | view raw | |
| env.txt | β | 418 B | view raw | |
| fix.diff | β | 352 B | view raw | |
| manifest.json | β | 831 B | view raw | |
| verdict.json | β | 2.1 KB | view raw |
DF-4553 β sv_suspend() aborts the playback channel with the record trigger (copy-paste): playback DMA engine left running across suspend
What this is
sys/dev/sound/pci/vibes.c:653, inside sv_suspend():
sc->rch.dma_was_active = sc->rch.dma_active;
svrchan_trigger(NULL, &sc->rch, PCMTRIG_ABORT); /* correct: rec */
sc->pch.dma_was_active = sc->pch.dma_active;
svrchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT); /* BUG: play channel
* aborted with the
* RECORD trigger */
svrchan_trigger()'s STOP/ABORT path (vibes.c:345-350) clears
SV_RECORD_ENABLE and stops DMAC β it never touches the playback
engine. Applied to sc->pch it does nothing to the playback DMA:
SV_PLAY_ENABLE stays set, so DMAA keeps bus-mastering the (still mapped
and armed) DMA buffer while the system suspends, and the record engine is
disabled twice. On sv_resume() the playback channel is then re-programmed
and restarted as if it had been cleanly stopped.
Consequences on real hardware: the S3 SonicVibes continues to master PCI
bus traffic into ch->buffer across the suspend transition β the driver
believes the channel is stopped. This is a suspend/resume state-machine
defect (upstream FreeBSD's driver uses svpchan_trigger for the playback
channel); security impact is bounded to device/PM misbehavior (continued
DMA, noise, corrupted stream state on resume), not kernel memory
corruption.
Reproduce
Needs an S3 SonicVibes (5333:ca00) machine playing audio:
cat /dev/dsp0 < /dev/zero &(playback running)acpiconf -z/ suspend-to-RAM- Observe (via the card's status register,
SV_CM_STATUS_AINTstill firing / audio path still live) that playback DMA was never disabled.
Expected after fix: playback engine disabled at suspend (SV_PLAY_ENABLE
cleared via svpchan_trigger).
What was run on the audit QEMU guest
No SonicVibes hardware (pciconf -l | grep 5333 β none; /dev/sndstat
empty with snd_vibes.ko loaded) β suspend/resume of this device cannot be
exercised. not_reproduced on this guest; the defect is visible by
inspection and is a one-token fix.
Verdict
not_reproduced β hardware absent. Source-level: certain.
DF-4553 VERDICT β not_reproduced (hardware absent); source-level: certain, one-token fix
Root cause
sv_suspend() (sys/dev/sound/pci/vibes.c:644-659) saves each channel's
dma_active state and aborts it. Line 653 aborts the playback channel
sc->pch with svrchan_trigger() β the record channel's trigger β
a copy-paste of the line above it. svrchan_trigger()'s
PCMTRIG_STOP/PCMTRIG_ABORT arm (vibes.c:345-350) clears
SV_RECORD_ENABLE only; the playback enable (SV_PLAY_ENABLE,
SV_REG_ENABLE bit) is left set, so DMAA remains armed and
bus-mastering while the machine suspends. The record engine gets disabled
twice (harmless) and the playback engine not at all.
sv_resume() (vibes.c:661-687) later re-runs svpchan_trigger(0, &sc->pch,
PCMTRIG_START) only if (sc->pch.dma_was_active) β i.e. it papers over
the stale-enable state by reprogramming, but between suspend entry and
resume the device is in a state the driver does not model (continued DMA
into a buffer the sound framework considers quiesced; continued interrupt
generation feeding chn_intr(sc->pch.channel) while the pcm layer is
suspended).
Why not reproduced here
The audit QEMU guest has no S3 SonicVibes (PCI 5333:ca00) device:
pciconf -l | grep 5333 empty; with snd_vibes.ko loaded, /dev/sndstat
reports zero installed devices (see DF-4552 run.log). Suspend/resume of the
device therefore cannot be driven. No kernel-memory impact is claimed; the
finding is a device state-machine / PM defect with a one-token fix.
Fix
vibes.c:653: svrchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT); β
svpchan_trigger(NULL, &sc->pch, PCMTRIG_ABORT); (matches upstream
FreeBSD, whose snd_vibes uses the playback trigger for the playback
channel in sv_suspend). See fix.diff.
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_testableNot testable: no SonicVibes hardware in the QEMU guest; fix is a one-token correction identical to upstream FreeBSD's driver
fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
vibes.c:653 svrchan_trigger on &sc->pch; svrchan_trigger STOP/ABORT arm at vibes.c:345-350 touches only SV_RECORD_ENABLE; contrast svpchan_trigger STOP/ABORT at vibes.c:422-427 which clears SV_PLAY_ENABLE
PoC changes
authored from scratch this pass (no seed; finding filed this pass)
Verified recommended fix
vibes.c:653: use svpchan_trigger for sc->pch in sv_suspend (see fix.diff)
Verdict
Copy-paste defect at vibes.c:653: sv_suspend() aborts sc->pch (playback) with svrchan_trigger (the RECORD trigger), which only clears SV_RECORD_ENABLE (vibes.c:345-350). The playback DMA engine (DMAA) is therefore never disabled at suspend and keeps bus-mastering while the system suspends; the record engine is disabled twice. Not reproduced on the audit guest: no 5333:ca00 PCI device exists there, so the device suspend path cannot be exercised. Security impact bounded to device/PM misbehavior (continued DMA across suspend, stale-enable state on resume); no kernel memory-safety impact.
No comments yet.