aureal: BAR loop stores tags/handles for up to 6 BARs into au->st[3]/au->sh[3] β OOB kernel write over sh[], parent_dmat and lock at attach (crafted-PCI-device threat model)
Summary
The loop runs over PCI_MAXMAPS_0=6 but writes into size-3 arrays; a device advertising >=4 allocatable BARs overwrites sh[], parent_dmat, lock and x[0] with rman tags/handles - the corrupted parent_dmat is dereferenced by sndbuf_alloc on first open. Evil-peripheral/passthrough model; driver only uses map 0 so nothing legitimate needs slots 3+. Capacity-check-and-store-under-j fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4726 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 710 B | β raw | |
| VERDICT.md | β | 3.3 KB | β raw | |
| fix.diff | β | 930 B | view raw | |
| verdict.json | β | 1.8 KB | view raw |
DF-4726 β PoC evidence pack
Finding: aureal BAR loop stores bus tags/handles for up to 6 BARs into
au->st[3]/au->sh[3] β OOB kernel write over parent_dmat/lock/x[].
Contents
VERDICT.mdβ root cause, adjacency analysis, path:line.verdict.jsonβ machine verdict (status: untested; hw-gated).fix.diffβ capacity check + store under mapped-countj.
Reproduce / Expected
Requires a crafted PCI device with DID 0x000112eb advertising β₯4 allocatable
BARs (evil-peripheral / passthrough threat model) β not present in QEMU.
Static proof: sys/bus/pci/pcivar.h:44 (PCI_MAXMAPS_0 = 6) vs
aureal.c:76-77 (st[3], sh[3]) with write sites at aureal.c:592-593.
DF-4726 β aureal: BAR loop writes au->st[i]/au->sh[i] for up to 6 BARs into size-3 arrays β OOB kernel write of pointers at attach
File: sys/dev/sound/pci/aureal.c Β· Severity: Low Β· Bucket: memcorrupt Β· Confidence: certain
Root cause (path:line)
struct au_info { /* aureal.c:73-86 */
int unit;
bus_space_tag_t st[3]; /* 76 β THREE slots */
bus_space_handle_t sh[3]; /* 77 β THREE slots */
bus_dma_tag_t parent_dmat; /* 79 β adjacent */
struct lock *lock; /* 80 β adjacent */
u_int32_t x[32], y[128]; /* 82 β adjacent */
...
};
...
for (i=0; i<PCI_MAXMAPS_0; i++) { /* aureal.c:571 β 6 (sys/bus/pci/pcivar.h:44) */
regid[j] = PCIR_BAR(i);
...
if (reg[j]) {
au->st[i] = rman_get_bustag(reg[j]); /* aureal.c:592 β indexed by i, not j */
au->sh[i] = rman_get_bushandle(reg[j]); /* aureal.c:593 */
mapped++;
}
...
}
The arrays are indexed by the BAR index i (0..5) while the arrays hold
3 entries. A PCI device presenting β₯4 allocatable BARs under this driver's
PCI ID (0x12eb:0x0001) makes attach write:
st[3..5]β 24 bytes oversh[0..2](x86-64: tag = pointer)sh[3..5]β 24 bytes overparent_dmat(sh[3]),lock(sh[4]), and the low half ofx[0](sh[5]).
Written values are rman_get_bustag() / rman_get_bushandle() β for a memory
BAR the handle is the (attacker-chosen, via the crafted device's BAR
programming) bus address; the tag is a kernel pointer. Consequences:
parent_dmatcorrupted β the latersndbuf_alloc(ch->buffer, au->parent_dmat, ...)(aureal.c:310, viaauchan_init) runs the entirebus_dmamem_allocchain through a corruptedbus_dma_tag_tβ wild kernel pointer deref / memory corruption.lockcorrupted with a bus address β latent wild pointer in any future user.sh[0..2]corrupted by st[] overflow β all later au_rd/au_wr (the entire driver) operate on garbage handles β out-of-bounds device-memory access.
Note this is not hypothetical per-BAR handling: the real AU8820 has fewer BARs, so this is reachable only from a crafted/cloned PCI device advertising β₯4 BARs with this vendor/device ID (evil-peripheral / PCIe hotplug / VM PCI passthrough threat model).
Impact
OOB kernel write (CWE-787) of 24-48 bytes of semi-controlled data (kernel pointer + device-chosen physical addresses) into the driver softc at attach, leading to corrupted DMA tag / lock pointers β kernel memory corruption or panic on first use. Hardware-gated β Low.
Verification
Hardware-gated (needs a crafted PCI device); not reproducible in QEMU
(no Aureal emulation, no way to present extra BARs). Code-level proof:
sys/bus/pci/pcivar.h:44 (PCI_MAXMAPS_0 6) vs aureal.c:76-77 (st[3],
sh[3]), write sites aureal.c:592-593 indexed by i.
Recommended fix
Bound the loop's storable slots: for (i = 0; i < PCI_MAXMAPS_0; i++) with
if (j >= N(au->st)) break; before storing (or enlarge the arrays to 6).
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 crafted PCI hardware absent from the QEMU guest.
fix.diff authored against read-only sys/.
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (array sizes vs loop bound, adjacency analysis), fix.diff
PoC changes
n/a
Verified recommended fix
Cap stored slots at sizeof(au->st)/sizeof(au->st[0]) and index by the mapped count j, not the BAR index i
Verdict
au_pci_attach's BAR loop (aureal.c:571-605) iterates over all PCI_MAXMAPS_0=6 (sys/bus/pci/pcivar.h:44) BARs but stores rman_get_bustag/bushandle into au->st[i]/au->sh[i] (aureal.c:592-593) where st/sh are size-3 arrays (aureal.c:76-77): a PCI device under this driver's ID advertising >=4 allocatable BARs makes attach write 24-48 bytes past the arrays over sh[0..2], parent_dmat, lock and x[0] β OOB kernel write (CWE-787) that corrupts the bus_dma_tag later dereferenced by sndbuf_alloc (aureal.c:310). Hardware-gated (crafted/cloned PCI device, evil-peripheral threat model); not reproducible in QEMU.
No comments yet.