# 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)

```c
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 over `sh[0..2]` (x86-64: tag = pointer)
- `sh[3..5]` → 24 bytes over `parent_dmat` (`sh[3]`), `lock` (`sh[4]`), and
  the low half of `x[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_dmat` corrupted → the later `sndbuf_alloc(ch->buffer, au->parent_dmat, ...)`
  (`aureal.c:310`, via `auchan_init`) runs the entire `bus_dmamem_alloc` chain
  through a corrupted `bus_dma_tag_t` — wild kernel pointer deref / memory
  corruption.
- `lock` corrupted 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.
