# DF-4504 — VERDICT

**NOT DEMONSTRATED LIVE (hardware-blocked) — code-certain UAF, established
9-member family (DF-4156 maestro, DF-4193 es137x, DF-4299/4334/4344/4421/
4457/4468). fix.diff applies clean; runtime fix validation impossible on
this guest.**

## Root cause (path:line)

- t4dwave.c:880-882 — `AC97_CREATE()` then `mixer_init(dev,
  ac97_getmixerclass(), codec)`; mixer.c:730-733 does
  `make_dev(&mixer_ops, ..., 0666, "mixer%d")` + `si_drv1 = m` with
  `m->devinfo = codec` (mixer.c:635 via mixer_obj_create).
- Still-failing paths after that point:
  t4dwave.c:887 (IRQ alloc / snd_setup_intr), t4dwave.c:920-922
  (bus_dma_tag_create), t4dwave.c:928-929 (pcm_register).
- t4dwave.c:937-945 `bad:` — `ac97_destroy(codec)` (938: kobj_delete of the
  method table + snd_mtxfree + kfree, ac97.c:852-861) and `kfree(tr)` (944),
  but the mixer cdev is never destroyed: `mixer_uninit()` is called only
  from `pcm_unregister()` (sound.c:1205), unreachable on failed attach.
- Post-failure, any user opening the surviving world-writable `/dev/mixerN`
  and issuing a mixer ioctl runs the kobj method dispatch
  (`ac97mix_set/recsrc` -> `tr_wrcd`/`tr_rdcd`) on freed codec + freed
  `tr_info` (whose `tr->lock` was also `snd_mtxfree`d at 943): UAF read/
  write and indirect-dispatch control-flow potential.

## Why not reproduced

The audit guest's QEMU emulates no Trident 4DWave DX/NX (1023:2000/2001),
SiS 7018 (1039:7018) or ALi M5451 (1102:5451) audio controller;
`snd_t4dwave.ko` exists in /boot/kernel but `tr_pci_probe()` returns ENXIO
for every emulated PCI id, so no `/dev/mixerN` from this driver exists
(run.log). Additionally the trigger itself requires a *partially failing*
attach (IRQ/dma-tag/pcm_register failure after a successful mixer_init) —
a boot-time resource anomaly an unprivileged user cannot create on demand.
Both limitations are shared with the filed family (DF-4156/DF-4193 were
verified "untested" for the same reasons). A logic-level harness cannot
honestly demonstrate a hardware-lifetime UAF, so no harness was faked.

## Fix

`fix.diff`: track `mixinit`; on `bad:`, if the mixer was created call
`mixer_uninit(dev)` — which destroys the cdev, the snd_mixer, and the codec
itself (ac97mix_uninit -> ac97_destroy, ac97.c:1027-1039, mirroring the
pcm_unregister order at sound.c:1205) — otherwise `ac97_destroy(codec)` as
today. `git apply --check` clean against sys/. Note the subtlety this fixes
correctly: calling *both* mixer_uninit and ac97_destroy would double-free
the codec (mixer_uninit already destroys it).

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