# DF-4724 — aureal: attach failure after mixer_init() leaves live 0666 /dev/mixerN over freed `au` (mixer-UAF family, 15th instance)

**File:** `sys/dev/sound/pci/aureal.c` · **Severity:** Low · **Bucket:** memcorrupt · **Confidence:** certain
**Family:** DF-4156 / DF-4193 / DF-4299 / DF-4334 / DF-4344 / DF-4421 / DF-4457 / DF-4468 / DF-4504 / DF-4537 / DF-4550 / DF-4610 / DF-4651 (13 filed prior; this is the next instance of the same pattern in a driver the family sweep had not yet reached)

## Root cause (path:line)

`au_pci_attach()` publishes the mixer **before** the last fallible steps and has no cleanup
for it on failure:

- `sys/dev/sound/pci/aureal.c:634` — `mixer_init(dev, ac97_getmixerclass(), codec)` succeeds →
  `mixer.c:make_dev(&mixer_ops, ..., UID_ROOT, GID_WHEEL, 0666, "mixer%d", unit)` creates a
  **world-writable /dev/mixerN** whose mixer object keeps `codec` (→ `au`) as its devinfo.
- Two later steps can still fail and `goto bad`:
  - `sys/dev/sound/pci/aureal.c:636-645` — `bus_dma_tag_create(...) != 0`
  - `sys/dev/sound/pci/aureal.c:651` — `pcm_register(dev, au, 1, 1)`
- `bad:` (`sys/dev/sound/pci/aureal.c:658-664`) does `free(au, M_DEVBUF)` and releases bus
  resources — it never calls `mixer_uninit(dev)`/`ac97_destroy(codec)`.

DragonFly newbus does **not** run `device_detach()` when attach returns an error
(`sys/kern/subr_bus.c:2095-2117`, `device_doattach()` — on error it only prints
"attach returned %d", clears the driver, and marks the device NOTPRESENT), so nothing
anywhere destroys the devfs node or the mixer object.

## Impact

After such a failed attach, `/dev/mixerN` (mode 0666) stays registered forever. Any
unprivileged local user opening it and issuing a mixer ioctl dispatches through
`au_rdcd()`/`au_wrcd()` (`aureal.c:126-169`) with the **freed** `au` as arg:
`au_wr/au_rd` dereference `au->st[mapno]`/`au->sh[mapno]` (`aureal.c:93-122`) — freed,
heap-groomable kernel memory driving `bus_space_{read,write}` — a UAF read/write
primitive (plus the codec object itself is leaked dangling). Ceiling: kernel memory
corruption; floor: panic.

Preconditions (why Low, per family convention): an Aureal Vortex 8820 PCI card
(PCI ID 0x12eb:0x0001) must be present, the driver must be compiled in — note
`aureal.c` is **not wired into any build file** (`sys/conf/files` has no entry;
`sys/dev/sound/driver/Makefile` SUBDIR lacks it; no snd_aureal.ko ships in the
default build) — and one of the post-mixer_init allocations must fail
(kmem pressure). Not user-triggerable on demand.

## Verification (what ran on the QEMU guest, 2026-09-23)

The full UAF cannot run in QEMU (no Aureal PCI device emulation). The **load-bearing
premise** was verified live on DragonFly 6.5-DEVELOPMENT:

1. Built a minimal KLD (`premtest.c`) whose attach() does `make_dev(..., 0666, ...)`
   and then returns ENXIO — the exact shape of `mixer_init()`-success followed by
   `goto bad`.
2. `kldload` → dmesg: `PREMTEST: attach() ... FAIL ENXIO` / `device_probe_and_attach:
   premtest0 attach returned 6` — attach failed.
3. `/dev/premtest0` **persisted**, `crw-rw-rw- root wheel`.
4. As unprivileged uid=1001: `exec 3<>/dev/premtest0` → OPEN_RC=0, and the module's
   d_open handler executed (`PREMTEST: open() reached module code`) — i.e. an
   unprivileged user reaches module code that, in the real driver, dereferences the
   freed softc.
5. Unloaded; guest left clean.

Newbus premise additionally proven from source: `sys/kern/subr_bus.c:2095-2117`.

## Recommended fix

On every failure path after `mixer_init()` succeeds, run `mixer_uninit(dev)` (which
destroys the cdev *and* the codec via `ac97mix_uninit`→`ac97_destroy`) before freeing
`au`. See `fix.diff`. (First wire the driver into the build or retire it — see notes.)

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