# DF-3866 VERDICT

**Status: `inconclusive` (runtime-gated: no emu10kx hardware in the QEMU guest)**
**Defect certainty: source-level certain — OOB write geometry proven on the guest kernel ABI.**

## What the bug is

`emu_intr_register()` (sys/dev/sound/pci/emu10kx.c:919-946) returns **-1** when all
32 `ihandler[]` slots are taken. Its callers in emu10kx-pcm.c store that value
**unchecked** into `ch->ihandle` (emu10kx-pcm.c:983, :1137) and later pass it to
`emu_intr_unregister()` (emu10kx-pcm.c:992, :1162). `emu_intr_unregister()`
(emu10kx.c:948-978) indexes `sc->ihandler[hnumber]` with **no bounds check
whatsoever** — first read (emu10kx.c:956), then four writes (emu10kx.c:964-967).

## Why it corrupts memory (proven)

The guest kernel was made to compile a module (`layout_proof.c`) declaring the
verbatim field prefix of `struct emu_sc_info` (emu10kx.c:307-334). Recorded
output (run.log):

```
DF3866: sizeof(struct emu_intr_handler)=24
DF3866: offsetof(reg)=280 irq=288 ih=296 ihandler=304
DF3866: ihandler[-1] spans [280,304)
DF3866: PROVEN: ihandler[-1] overlays {reg, irq, ih}
```

So `ihandler[-1]` = `{ .softc=&sc->reg, .intr_mask=lo32(sc->irq),
.inte_mask=hi32(sc->irq), .irq_func=&sc->ih }`. When `hnumber == -1`:

1. `sc->ihandler[-1].inte_mask` reads the **high dword of the `struct
   resource *irq` pointer** — 0xfffffe… on x86_64, i.e. nonzero — so the
   `inte_mask == 0` early-out (emu10kx.c:956) does NOT save us;
2. `x &= ~ihandler[-1].inte_mask` (emu10kx.c:962) smears pointer bits into the
   EMU_INTE hardware write (clears random interrupt-enable bits);
3. `ihandler[-1].inte_mask = 0; .intr_mask = 0` **NULLs `sc->irq`** (both halves),
   `ihandler[-1].softc = NULL` **NULLs `sc->reg`**, `ihandler[-1].irq_func = NULL`
   **NULLs `sc->ih`** (emu10kx.c:964-967);
4. next detach does `bus_release_resource(dev, SYS_RES_IOPORT, ..., NULL)` /
   `bus_teardown_intr(dev, NULL, NULL)` (emu10kx.c:3524-3527) → NULL-deref panic;
   even before that, the corrupted `sc->irq` poisons every later use.

## How the pool exhausts (precondition)

Concurrent unprivileged use alone cannot exhaust the pool (≤6 card-level + ≤6
rec-channel slots < 32; rec START/STOP is balanced because `chn_abort()`
channel.c:955 refuses to trigger a stopped channel). But the card-level handle
registered at emu10kx-pcm.c:1453 is **never unregistered** — `emu_pcm_uninit()`
(emu10kx-pcm.c:1292-1296) is a no-op. Every `kldunload/kldload snd_emu10kx`
cycle (root, devctl-equivalent) leaks up to 6 slots; after ~6 cycles
`emu_intr_register` starts returning -1 and the OOB fires on the next rec
START→STOP.

## Why it is inconclusive at runtime

The QEMU guest has **no Creative Labs PCI device** (`pciconf -l` shows no
0x1102 vendor). Loading `snd_emu10kx.ko` succeeds but `emu_pci_probe()`
(emu10kx.c:3013-3039) matches nothing → no softc is ever allocated, no
`/dev/emu10kx` and no pcm children exist. The runtime trigger (rec_cycle on
/dev/dsp) therefore stops at `open(): No such file or directory` — recorded in
run.log. Reproduction requires physical SB Live!/Audigy hardware.

## Exploitability ceiling

Both gates (root for the kld cycling, hardware presence) precede the memory
corruption, and the write values are fixed NULLs into a driver-private softc —
an attacker who already has root gains nothing. Realistic impact:
kernel NULL-deref panic / device bricking after privileged module cycling.
Severity: **Low** (memcorrupt bucket for tracking). The primary fix is the
one-line bounds check in `emu_intr_unregister` (see fix.diff, which also
fixes the leak and the unchecked callers).

## Fix validation

Not possible on this guest (no hardware) → fix_status `not_testable`.
`fix.diff` is authored against the read-only sys/ tree and was never applied.

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