# DF-4156 VERDICT

**status: untested (hardware/boot-precondition gated) | impact ceiling: UAF with control-flow potential**

## Reproduced?

No — and it cannot be on this guest: `pciconf -lv` shows no ESS Maestro
multimedia function and there are no /dev/dsp*, /dev/mixer* nodes (run.log);
`snd_maestro` never attaches. Additionally the trigger needs
`pcm_register()` to fail *after* `mixer_init()` succeeded — on this tree
that means `pcm_veto_load` stuck at 1 (root-feeder SYSINIT anomaly) or a
device unit > PCMMAXUNIT(255) (`sound.c:1021-1027`), neither of which an
unprivileged user can create. The evidence is therefore source-level, and
the source is unambiguous:

1. `maestro.c:1894` `mixer_init(dev, ac97_getmixerclass(), codec)`.
2. `mixer.c:730-733` `make_dev(..., UID_ROOT, GID_WHEEL, 0666, "mixer%d")`,
   `pdev->si_drv1 = m`, `m->devinfo = codec` (`mixer.c:635`).
3. `maestro.c:1901-1903` `pcm_register()` may fail → `goto bad`.
4. `maestro.c:1923-1924` `bad:` → `ac97_destroy(codec)` — no `mixer_uninit`.
5. `ac97.c:852-859` frees `codec->methods` (kobj_delete) and `codec`.
6. Post-error, any user opens the surviving 0666 `/dev/mixerN`:
   `mixer_ioctl` (mixer.c:1196) → `mixer_set` → `MIXER_SET` → `ac97_set` →
   `ac97_wrcd(codec)` → `AC97_WRITE(codec->methods, codec->devinfo, ...)`
   — deref of freed heap + indirect dispatch through freed kobj memory.

Contrast the correct unwind: `pcm_unregister()` calls `mixer_uninit(dev)`
before anything else (`sound.c:1205`); `mixer_uninit` does
`destroy_dev(pdev)` and frees the snd_mixer (`mixer.c:767-815`) — it is
safe to call at exactly this point in the failure path because the snddev
softc and mixer cdev both exist once `mixer_init` returned 0.

## Exploit chain (if precondition met)

spray kernel heap to reclaim the freed `ac97_info` + kobj cache lines →
issue SOUND_MIXER_WRITE_VOLUME on /dev/mixerN → `AC97_WRITE` dispatches
through attacker-influenced kobj memory → control flow. Chain untested
(no trigger environment); impact recorded as ceiling, not demonstration.

## Fix validation

Not possible on this guest (no hardware, no trigger). `fix.diff` applies
cleanly (`git apply --check`) and mirrors the pcm_unregister() order.
Bonus: adds the missing `ac97_destroy(ess->codec)` to `agg_detach()`
(codec currently leaks on every detach).

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