# DF-5332 evidence pack — `chgetelemstatus()` READ ELEMENT STATUS buffers are kmalloc'd without M_ZERO; a short-but-GOOD transfer leaves stale kernel heap that is walked and copyout()ed via CHIOGSTATUS

## Finding (one line)
`chgetelemstatus()` (sys/bus/cam/scsi/scsi_ch.c:1089 and :1129) allocates
both READ ELEMENT STATUS transfer buffers with `kmalloc(..., M_INTWAIT)`
**without `M_ZERO`** and never checks `csio.resid`; a medium changer that
completes the command GOOD but transfers fewer bytes than the allocation
length (perfectly legal SCSI — the allocation length is a *maximum*)
leaves the un-written tail of the buffer as **stale kernel heap**, which
`copy_element_status()` (scsi_ch.c:984-1051) then reads (page-header
flags, descriptor fields, and — if the stale page-header flags say so —
32+6-byte volume tags) and `copyout()`s to the caller (scsi_ch.c:1186).
Same class as DF-5272 (scsi_cd CDIOCREADSUBCHANNEL), which the pass-1
findings for this driver (DF-1028 desclen/avail/flags OOB, DF-2271
avail-walk-past-buffer) do not cover: those read *past* the allocation;
this discloses *uninitialized memory inside* the allocation.

## Reproduce (guest, root; EVIL kernel = GENERIC + `device ch`)
```
cd /root/df5332
./build.sh && ./run.sh
```
- `evilcd3.ko` (derived from the DF-5327 evilcd2 rig) emulates a
  T_CHANGER at target 1 (`/dev/ch0`), mode pages 0x1d (1 picker, 8 slots
  at address 256) / 0x1f.
- `debug.evilcd.resmode=1`: the sizing RES (count==1) answers normally
  with edl=16; every real RES (count>1) transfers **only the 8-byte
  status header** (with `avail = count` inside it) and completes
  CAM_REQ_CMP with resid>0 — byte-for-byte what an evil real changer
  does on the wire.
- `debug.evilcd.markres=N` stamps 96 chunks of exactly `8+8+16*N` bytes
  (the size the driver will allocate) and frees them, so the driver's
  kmalloc re-uses marked heap.
- `poc_chres 3 1 4`: 3 runs, marked, CHIOGSTATUS(chet=CHET_ST, base=0,
  count=4); then 2 unmarked runs.

## Expected (vulnerable kernel)
`[EVILCH] RES evil short: ... SENT=8B only` on the console, and the
returned `struct changer_element_status` array full of non-zero bytes
(marker pattern `A`/`B`/... in marked runs; natural stale heap — old
allocation contents — in unmarked runs) in `ces_int_addr`, `ces_flags`,
`ces_sensecode/qual`, `ces_source_addr/type`, `ces_scsi_id/lun` and the
volume tags, even though the device sent nothing but the 8-byte header.
With a patched kernel (fix.diff: `M_ZERO` on both allocations) the same
run returns all-zero structs.

## Rig knobs
- `debug.evilcd.resmode` 0/1
- `debug.evilcd.markres` N
- `debug.evilcd.rescan` 1
- `debug.evilcd.resshorts/ressize/ressent` (readback)
