# DF-4848 — feeder_volume.c FXDIV frame-overcount + count underflow (evidence pack)

## What this proves

The REAL, UNMODIFIED `sys/dev/sound/pcm/feeder_volume.c` divides its source
feeder's RETURN VALUE with the inexact generated `SND_FXDIV`
(`feeder_volume.c:277`). The return value is user-paced (it is the amount of
data actually flowing — `feed_root` returns `min(count, sndbuf_getready)`,
and `ready` is exactly what the unprivileged user `write()`s). For bad-
residue returns inside the claimed [1,65536] domain (first bad: 32768 for
align 6, 16384 for align 10, 8195 for 12, 5473 for 14), `FXDIV` returns
floor+1 frames, so:

- **T1** `apply()` reads AND writes a frame past the fed data — past the
  destination window when the return fills the window (ret == count).
- **T2** `j*align > count` ⇒ `count -= j` at :286 **underflows to ~4GiB** ⇒
  the loop re-arms and asks the source for a wild window at `dst+overrun`;
  with more data ready (user wrote more), the source writes up to
  bufsoft-ready bytes PAST the window end — a directed heap overflow with
  user-controlled audio bytes.

feeder_volume is inserted by default for every vchan child
(feeder_chain.c:713-716, SD_F_VPC with snd_maxautovchans=16 default).

## Build / run (guest)

```
cd /root/fx && sh build.sh && ./ffvol    # baseline: FAIL (2810/21604)
cp snd_fxdiv_gen_fixed.h snd_fxdiv_gen.h && cc -O1 -g -o ffvol_fixed ffvol.c fxsrc.c
./ffvol_fixed                            # ALL PASS
```

## Expected output

`vol.log`: `ffvol: checks=21604 failures=2810 -> FAIL`, decisive lines:
`FAIL[T1 write] ch=3 align=6 count=32771 ret=32772 REAR guard (write past
window) maxoff=32772` — the 3-channel (align 6) case at the first bad
residue region.

## Fix

`fix.diff` (shared generator fix). A/B: baseline 2810 failures → fixed 0.
