# DF-4552 VERDICT — not_reproduced on this guest (hardware absent); source-level: certain

## Narrative

`sv_attach()` ordering (sys/dev/sound/pci/vibes.c):

| step | line | effect |
|------|------|--------|
| alloc sc | 730 | `kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO)` — driver-private, freed only in `sv_detach` |
| irq setup | 763-770 | `snd_setup_intr(dev, sc->irq, 0, sv_intr, sc, &sc->ih)` |
| **mixer_init** | **789** | publishes **0666** `/dev/mixerN`, `m->devinfo = sc` (mixer.c:730-733) |
| dmaa hack | 823-848 | midi/games port-gap hack; `goto fail` on assumption violation (815-821) or alloc failure (837-840) |
| dmac hack | 850-867 | `goto fail` on alloc failure (856-859) |
| pcm_register | 872-875 | `goto fail` on failure |
| `fail:` | 888-901 | destroys dmat, tears down irq, releases enh/dmaa/dmac resources — **no mixer_uninit, no kfree(sc)** |

`mixer_uninit()` (mixer.c:767) is only ever called from `pcm_unregister()`
(sound.c:1205). A failed attach means `device_is_attached()` is false, so
detach is never invoked, and even if it were, `pcm_unregister` returns 0
early because `PCM_ALIVE(d)` is false for the never-registered device —
so **nothing ever destroys the mixer cdev**. Same asymmetry as the 11
accepted family instances (DF-4156 … DF-4550); in the other instances the
fail path additionally `kfree`s the softc making it a heap UAF — here the
softc leaks, so the live mixer drives `bus_space_*` on **released** I/O
port resources instead (rman may have re-assigned them).

Post-failure reachability for an unprivileged user: `/dev/mixerN` is
0666 root:wheel (mixer.c:730-731). `MIXER_WRITE` → `mixer_ioctl` →
`sv_mix_set` (vibes.c:541) → `sv_gain` → `sv_channel_gain` (vibes.c:483) →
`sv_indirect_get/set` (vibes.c:139/151) using `sc->enh_st/enh_sh`, which
were cached at vibes.c:750-751 from a resource released at vibes.c:896.

Also noted (folded into this finding): the early `return ENXIO` at
vibes.c:746-749 leaks `sc` outright (no resource cleanup needed there, but
no `kfree`), and every `fail:` path leaks `sc`.

## Guest run (audit guest, 2026-09-21, uname in env.txt)

* `pciconf -l | grep 5333` → **no SonicVibes device present** (QEMU/i440fx
  machine: only Intel PIIX + virtio + Red Hat VGA).
* `kldload snd_vibes` succeeds (module loads, probe finds nothing):
  `/dev/sndstat` → `Installed devices:` (empty); no `/dev/mixer0` is ever
  created (mixer_init never runs).
* `./mixer_probe /dev/mixer0` (root and unprivileged):
  `open: No such file or directory`.
* `./mixer_probe /dev/mixer` (the sound-core default clone node,
  sound.c:1426): `open: Bad file descriptor` — with zero registered pcm
  devices `mixer_clone()` (mixer.c:1340-1360) finds no
  `PCM_REGISTERED` unit and returns ENODEV; harmless here.
* Module unloaded again; guest left clean.

Incidental: the *second* unload cycle (without any `cat /dev/sndstat` in
between) panicked the guest in `sndstat_sysuninit()` — that is the
**already-known DF-4116** (sndstat.c never-initialized sbuf deleted on
sound.ko unload), reproduced live and consistent with its existing
`reproduced/panic` verdict. Not a vibes.c defect; not re-filed here.

## Bottom line

* Source-level defect: **certain** — identical, already-accepted family
  pattern; all four post-mixer_init failure paths enumerated.
* On this guest: **not_reproduced** — the PCI device does not exist, so
  the trigger window cannot be entered at all.
* Realistic impact ceiling on real hardware: unprivileged mixer ioctls
  poking I/O ports the driver no longer owns (worst case: another PCI
  device's registers), plus a permanent softc/mixer leak per failed
  attach. No kernel heap memory corruption (softc is leaked, not freed).

## Fix validation

Not testable on this guest (no hardware). `fix.diff` is source-reviewed
only: mirror the family fix — unwind the mixer before releasing resources
on every failure path taken after `mixer_init()`, and free `sc`.

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