# DF-4095 VERDICT

**Status: inconclusive on-guest (hardware-gated) / likely at source level.**
**Impact: kernel heap use-after-free (mpu401 softc) during detach — panic
class; exploitation would require heap grooming of a 1-callout-tick window.**

## Was it reproduced?

No. The guest has no emu10k1 hardware (run.log: no 0x1102 PCI device,
`kldload snd_emu10k1` fails), so the MIDI-TX + detach race cannot be
exercised. The missing synchronization is, however, provable by inspection:

1. `emu_intr2()` (sys/dev/sound/pci/emu10k1.c:1196-1203) tests and calls
   `sc->mpu_intr` with `sc->mpu` as argument — no `snd_mtxlock(sc->lock)`.
2. The teardown that invalidates both is: `emu_pci_detach` (emu10k1.c:2161)
   → `emu_uninit` (:2172) → `mpu401_uninit` (:2039) → `midi_uninit` →
   `emu_muninit` (emu10k1.c:1175-1185, clears `sc->mpu_intr` **under
   sc->lock**) → `kfree(m)` (mpu401.c:203).
3. `emu_intr2` is reachable asynchronously via the mpu401 callout:
   `mpu401_intr` rearms `mpu401_timeout` (mpu401.c:162-164) which fires
   `m->si` = `emu_intr2` (mpu401.c:108-109). A CPU can sit between the
   `if (sc->mpu_intr)` test and the indirect call while another CPU clears
   the pointer and kfrees `sc->mpu`.
4. Control flow then enters `mpu401_intr(m)` with freed `m` →
   STATUS()/READ()/WRITE() deref `m` (mpu401.c:113-155) → UAF read + the
   callout-reset write at mpu401.c:163.

The sibling finding DF-3867 (emu10kx, `emu_intr` vs `emu_intr_unregister`)
was the same family shape and was filed Low.

## Why Low and not higher

- Trigger requires physical Creative silicon + MIDI TX + detach timing.
- Window is one callout tick; no userland-controllable heap-spray primitive
  presented itself for the 1-slot `struct mpu401` reuse within the window.
  (The guest, being permissive, would allow grooming, but without the device
  the chain cannot even start.)

## Fix validation

Not performable on-guest (no device). fix.diff adds the mutex around the
check+call, matching the locking discipline already used by the in-IRQ call
site (emu10k1.c:1258-1263) — no new lock order, `mpu401_intr` already runs
under this lock from `emu_intr()`.

## kernel_refs

- sys/dev/sound/pci/emu10k1.c:1196-1203 (lockless check+call)
- sys/dev/sound/pci/emu10k1.c:1175-1185 (locked clear in emu_muninit)
- sys/dev/sound/pci/emu10k1.c:1214 (mpu401_init wiring)
- sys/dev/sound/pci/emu10k1.c:2038-2039,2172 (detach teardown)
- sys/dev/sound/midi/mpu401.c:108-109,162-164,188,203 (callout fire, callback install, kfree)

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