aureal: au_intr calls chn_intr(au->pch.channel) while the channel is NULL β NULL-deref panic in the snd_setup_intr-to-pcm_addchan window that au_testirq deliberately enables IRQs inside
Summary
pch.channel is NULL until pcm_addchan runs auchan_init, but au_intr is live from snd_setup_intr and au_testirq enables AU_IRQ_PCMOUT plus raises a test interrupt with DELAY(1s) - on PCMOUT, chn_intr derefs NULL. Misbehaving/crafted AU8820 hardware; healthy cards raise the test irq as UNKNOWN. NULL-guard + enable-after-addchan fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4727 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 604 B | β raw | |
| VERDICT.md | β | 2.8 KB | β raw | |
| fix.diff | β | 723 B | view raw | |
| verdict.json | β | 1.9 KB | view raw |
DF-4727 β PoC evidence pack
Finding: chn_intr(au->pch.channel) with NULL channel in the attach
window between snd_setup_intr (aureal.c:620) and pcm_addchan (:653);
au_testirq enables AU_IRQ_PCMOUT inside that window β NULL-deref panic.
Contents
VERDICT.mdβ path:line trace incl. chn_intr's unconditional lock deref.verdict.jsonβ machine verdict (status: untested; hw-gated).fix.diffβ NULL guard.
Reproduce / Expected
Requires the AU8820 card and a PCMOUT-sourced interrupt before the channel exists (spurious/crafted hardware). Not reproducible in QEMU.
DF-4727 β aureal: chn_intr(au->pch.channel) runs with NULL channel in the attach window before pcm_addchan β NULL-deref panic in interrupt context
File: sys/dev/sound/pci/aureal.c Β· Severity: Low Β· Bucket: base:dev Β· Confidence: likely
Root cause (path:line)
au->pch.channelis only assigned inauchan_init()(aureal.c:306-307), which runs whenpcm_addchan()(aureal.c:653) instantiates the play channel. Until then it is NULL (auisM_ZERO-allocated,aureal.c:564;struct au_chinfoembedded ataureal.c:85).- The interrupt handler is live much earlier:
snd_setup_intr(..., au_intr, au, &ih)ataureal.c:620. au_intr()(aureal.c:396-433) does, onintsrc & AU_IRQ_PCMOUT(AU_IRQ_PCMOUT = 0x0020,aureal.h:56):
if (intsrc & AU_IRQ_PCMOUT) { /* aureal.c:411 */
i = au_rd(...);
chn_intr(au->pch.channel); /* aureal.c:413 β NULL until :653 */
chn_intr()(sys/dev/sound/pcm/channel.c:683) immediately evaluatesCHN_LOCKOWNED(c)=lockstatus((c)->lock, ...)(channel.h:312) β unconditional dereference β NULL-pointer write/panic in hardirq context.
The window is real and interrupts are enabled inside it: au_testirq()
(aureal.c:625, body 528-537) writes AU_REG_IRQEN = 0x00001030
(aureal.c:531) β bit 5 = 0x0020 = AU_IRQ_PCMOUT enabled β and
deliberately pokes the chip to raise an interrupt ("this apparently generates
an irq", aureal.c:535), followed by DELAY(1000000) β a full second of
window. au_init() (aureal.c:627) then keeps IRQs globally on
(AU_REG_IRQGLOB |= AU_IRQ_ENABLE, aureal.c:505-506) through
AC97_CREATE/mixer_init/bus_dma_tag_create/pcm_register until
pcm_addchan at aureal.c:653.
Any spurious PCMOUT interrupt in this ~1s+ window (misbehaving or crafted
device, shared-IRQ noise after au_init state changes) panics the kernel.
Normal healthy hardware only raises the test interrupt as
AU_IRQ_UNKNOWN(0x1000) (also enabled by 0x1030), which is why this does not
fire on well-behaved cards β hence Low/likely rather than certain.
Verification
Hardware-gated (no AU8820 in QEMU). Source trace cross-checked against
channel.c:683/channel.h:312 (no NULL guard in chn_intr) and the
au_testirq enable mask.
Recommended fix
Guard the call: if (au->pch.channel != NULL) chn_intr(au->pch.channel);
(and ideally only enable AU_IRQ_PCMOUT after the channel exists). 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_testableFix not kernel-validated: requires physical AU8820 card and a spurious PCMOUT interrupt during attach.
fix.diff authored against read-only sys/.
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md path:line trace; fix.diff
PoC changes
n/a
Verified recommended fix
NULL-guard chn_intr(au->pch.channel) in au_intr; enable PCMOUT irq only after pcm_addchan
Verdict
au_intr (aureal.c:396-433) calls chn_intr(au->pch.channel) at :413 whenever intsrc & AU_IRQ_PCMOUT, but au->pch.channel is NULL until pcm_addchan (aureal.c:653) -> auchan_init (:306) assigns it; the IRQ is live from snd_setup_intr (aureal.c:620) and au_testirq (:625, body :528-537) explicitly enables AU_IRQ_PCMOUT (IRQEN 0x1030 includes 0x20) and raises an interrupt, leaving >1s of enabled-IRQ window; chn_intr (channel.c:683) unconditionally does CHN_LOCKOWNED(c) = lockstatus(c->lock) (channel.h:312) -> NULL-deref panic in interrupt context. Healthy hardware raises the test irq as AU_IRQ_UNKNOWN so the window normally passes quietly β Low/likely, hw-gated, not reproducible in QEMU.
No comments yet.