β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4726

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4726 Β· 4 files
FileTypeDescriptionSize
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-count j.

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.

VERDICT.md
↓ download raw

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 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.

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_testable
baseline no→ patch + rebuild →patched clean

Fix not kernel-validated: requires crafted PCI hardware absent from the QEMU guest.

fix.diff authored against read-only sys/.
↓ fix.diffper-fix-DF-4726

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.