# DF-2268 — Heap overflow in cdcheckmedia via uncapped num_entries

## Verdict: NOT REPRODUCED (hardware-gated) — source bug CONFIRMED real; fix.diff compiles.

**Classification:** `not_reproduced` / HW-gated / impact=none (on this guest, for an
unprivileged user). The cited memory-corruption bug is **real in source** and the
defense-in-depth `fix.diff` **compiles cleanly** in a full `nativekernel` build
(`rc=0`, `-Werror`, `-DINVARIANTS`).

### Why not reproduced (the gate)

`cdcheckmedia()` runs in the **cd(4) CAM peripheral**, which only attaches to a
CAM-registered SCSI/ATAPI CD target. The audit QEMU guest has exactly **one** CAM
target — the QEMU DVD-ROM reached through the Intel PIIX3 IDE controller via
`ata-cam`, exposing `/dev/cd0` (mode `0640 root:operator`). The trigger further
requires a **malicious SCSI target** that returns a crafted READ TOC whose
`ending_track`/`starting_track` produce `num_entries > 100`. The trusted QEMU
DVD-ROM with no medium (`NOT READY, Medium not present`) cannot be coerced into
emitting such a TOC. The unprivileged actor `maxx` (uid 1001, in **no** privileged
group — not `operator`, not `wheel`) additionally cannot even `open("/dev/cd0")`.

Gate proof (this guest):
```
$ camcontrol devlist
<QEMU QEMU DVD-ROM 2.5+>  at scbus1 target 0 lun 0  (sg0,pass0,cd0)
$ ls -la /dev/cd0
crw-r-----  root operator  /dev/cd0      # maxx not in operator -> EACCES
$ id maxx
uid=1001(maxx) gid=1001(maxx) groups=1001(maxx)
```
(No `/dev/ch*`, no `/dev/da*`, no SCSI HBA — see `env.txt`.)

### The source bug (real, cited `path:line`)

`sys/bus/cam/scsi/scsi_cd.c`:
- `struct cd_tocdata` cache holds **100** entries + leadout (`scsi_cd.c:136-139`,
  `softc->toc` at `:172`).
- `cdcheckmedia()` computes `num_entries = (toch->ending_track - toch->starting_track) + 2`
  (`scsi_cd.c:2947`) directly from the **device-supplied** TOC header, then guards
  only `num_entries <= 0` (`:2949`). With `ending_track=255, starting_track=0`,
  `num_entries = 257`.
- `toclen = num_entries * sizeof(struct cd_toc_entry)` (`:2952`) and
  `cdreadtoc(periph, CD_MSF_FORMAT, ..., &softc->toc, toclen + sizeof(*toch), ...)`
  (`:2954-2956`) DMA up to `257*8 + 4 = 2060` bytes into the 804-byte `softc->toc`
  cache → **~1256-byte heap overflow** with attacker-controlled content.
- The same uncapped `num_entries` drives OOB writes in the leadout fixup
  (`softc->toc.entries[cdindex - toch->starting_track]` at `:2983`, `cdindex` up to
  `starting_track + 256`) and the BCD-conversion / search loops at `:2987`, `:2997`
  (iterate `num_entries - 1 = 256` times into `entries[100]`).

Attacker model (per the finding): control of the SCSI/USB CD device (USB mass-storage
gadget, iSCSI LUN, scsi_target LUN). Victim: a `SYSCAP_RESTRICTEDROOT`-ok opener
(`cdopen` gate). `cdcheckmedia` runs on `open()` / first read.

### Exploit chain

Not developed — the primitive requires a malicious device that is absent on this
guest, and the device node is not reachable by the unprivileged actor. This is the
**valid hard blocker "device-controlled primitive, no malicious device present"**:
the write content is fully attacker-controlled but only a malicious SCSI target can
supply it, and there is no such target here. No userspace-only path can shape the
TOC the trusted QEMU DVD-ROM returns.

### Fix (defense-in-depth, validated to compile)

`fix.diff` caps `num_entries` at `nitems(softc->toc.entries)` (=100) before the READ
TOC and the fixup/conversion loops, turning an uncapped device-driven overflow into a
clean early-out. Validated: applies cleanly and the patched `scsi_da.c`/`scsi_cd.c`
tree builds `nativekernel` `rc=0` with `-Werror -DINVARIANTS` (`fix_build.log`).

### Reproduce

No runnable PoC on this guest (no malicious CD target, `/dev/cd0` not openable by
`maxx`). `build.sh`/`run.sh` are placeholders that document the gate; the
authoritative artifacts are `env.txt` (gate proof), `fix.diff`, and `fix_build.log`.
