# DF-4849 — feeder_mixer.c FXROUND ring overflow + mcnt-underflow memset bomb

## What this proves

The REAL, UNMODIFIED `sys/dev/sound/pcm/feeder_mixer.c`:

- **M1 (:299)** `count = SND_FXROUND(count, sz)` misrounds PAST the caller's
  free space for bad-residue values inside the claimed domain (first bad
  8195 for sz=12). Children fill `count > free` bytes into `b` and the mixer
  RETURNS rcnt > free — in-kernel `sndbuf_acquire(to, tmpbuf, rcnt)` then
  overflows the ring (buffer.c:615-636, KASSERT-only in production; `rl`
  inflates past `bufsize`, `sndbuf_getfree = bufsize - rl` wraps unsigned).
  **500/500 M1 checks fail.**

- **M2 (:339-364, :362, :368)** when a child feeder returns more than asked
  (proven possible in-tree by DF-4846/DF-4848: feeder_format/feeder_volume
  return count+delta on the same misrounds), `rcnt = SND_FXROUND(ret, sz)`
  exceeds count and `mcnt = count - rcnt` **underflows to ~0xFFFFfffX**,
  then `:368` executes `memset(b + rcnt, zerodata, ~4GiB)` — catastrophic
  heap overwrite. The harness catches the exact call:

  ```
  MEMSET-BOMB: memset(b + 65556, 0x00, 4294967284) [mixer count window was 65544]
  ```

  (exit code 42). This is a vchan-mixing default path:
  `snd_maxautovchans = 16` by default — any two `/dev/dsp` opens mix through
  feed_mixer_feed.

## Build / run (guest)

```
cd /root/fx && sh build.sh && ./ffmix    # exit=42 (memset bomb), M1 500 fails
cp snd_fxdiv_gen_fixed.h snd_fxdiv_gen.h && cc -O1 -g -o ffmix_fixed ffmix.c fxsrc.c
./ffmix_fixed                           # ALL PASS, no bomb
```

## In-kernel churn artifacts

`churn_bad.log` / `churn_dmesg.txt` (ES1370, 6ch+7ch vchan children,
bad-residue-paced writes): no differential anomaly vs the aligned control
(ctlchurn.c) on this no-INVARIANTS production kernel; the observed
"play interrupt timeout, channel dead" occurs equally in the control run
(ES1370-without-audiodev artifact, not attributable to the defect).

## Fix

`fix.diff` (shared generator fix). A/B: baseline M1 500 fails + bomb → fixed
ALL PASS, no bomb. Defensively, :362 should also clamp
(`if (rcnt > count) rcnt = count;`) so no child misbehavior can ever arm the
giant memset.
