# DF-5272 VERDICT — CDIOCREADSUBCHANNEL heap leak: REPRODUCED

## Bottom line
**Reproduced.** With the evil device completing READ SUBCHANNEL as a
4-byte short transfer while its header claims `data_len = 0x0014`, the
driver copyouts 24 bytes of a **non-zeroed** 24-byte kmalloc buffer:
64/64 ioctls per round, three rounds, leaked the same stable kernel-heap
remnant (`ffffffff 00000000 00000000 01000000`), and the in-process
marker phase leaked the kernel's own sysctl OID name string fragment
`"…ilcd\0spray_leak\0"` (`bytes[0..23] = 00110014|ffffffff|696c6364…`),
proving uninitialized kernel heap crosses the copyout boundary.  The
0xEE userland canary confirms the leaked bytes are kernel-supplied, and
the device only ever wrote the first 4.

## Mechanism (path:line)
- scsi_cd.c:2141 `kmalloc(sizeof(struct cd_sub_channel_info), M_SCSICD,
  M_WAITOK)` — no M_ZERO.
- scsi_cd.c:2148-2158: user length bounds-checked to
  [sizeof(header)=4, sizeof(info)=24] — fine.
- scsi_cd.c:2163-2164 `cdreadsubchannel(..., len)` — the CDB allocation
  length is `len`; nothing requires the device to fill it.
- cam_periph.c:962-963: `CAM_REQ_CMP` with `resid != 0` is success; no
  caller checks resid on this path.
- scsi_cd.c:2174-2176: `len = min(len, data_len[0]<<8 + data_len[1] + 4)`
  — the clamp uses the **device-supplied** length field, so the device
  keeps len at the full user value while having transferred 4 bytes.
- scsi_cd.c:2178 `copyout(data, args->data, len)` — 20 uninitialized
  heap bytes disclosed.

## Fix validation
`fix.diff` adds `M_ZERO` to the allocation.  Validated in the same
single-fix kernel build as DF-5271 (`fix_build.log`, `fix_run.log`,
`run.patched.log`): after the patch the identical PoC returns
`bytes[0..23] = 00110014 0000...000` — the 20 tail bytes are zeroes on
every run (64/64), no heap remnants, no markers, guest stays up.

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