# DF-1134 — cz_init_cp_jump_table jt_offset/jt_size OOB read/write

## Verdict
**CONFIRMED (source-trace + harness) — INCONCLUSIVE on-guest (HW-gated).** Real bug;
not triggerable on the QEMU guest (no AMD Carrizo/Stoney APU; amdgpu not in GENERIC).

## Bug (one line)
`cz_init_cp_jump_table()` reads `jt_offset`/`jt_size` from each CE/PFP/ME/MEC/MEC2
firmware header with no bounds check, then `dst_ptr[bo_offset+i] = fw_data[table_offset+i]`
for `i in [0, jt_size)` — a large `jt_size` writes past the 67584-byte `cp_table` VRAM
BO and a large `jt_offset` reads past the firmware blob.

## Mechanism (path:line)
- `gfx_v8_0.c:1321-1322` (and 1329/1337/1345/1353) — `table_offset = le32(hdr->jt_offset)`,
  `table_size = le32(hdr->jt_size)`, both **unvalidated**.
- `gfx_v8_0.c:1318-1320` — `fw_data = fw->data + ucode_array_offset_bytes` (offset unchecked).
- `gfx_v8_0.c:1357-1359` — `dst_ptr[bo_offset+i] = le32(fw_data[table_offset+i])`.
- `gfx_v8_0.c:1362` — `bo_offset += table_size` accumulates across 4..5 ME blobs.
- `gfx_v8_0.c:1407` — `cp_table_size = ALIGN(96*5*4, 2048) + 64*1024 = 67584` =>
  capacity `67584/4 = 16896` dwords. `dst_ptr` is the VRAM BO mapping.
- OOB write: `bo_offset + i >= 16896`. OOB read: `table_offset + i >= fw->datasize/4`.
- `amdgpu_ucode.c:251-260` — `amdgpu_ucode_validate()` only checks `datasize==size_bytes`.

## Trigger / threat model
Crafted CE/PFP/ME/MEC firmware headers on a Carrizo/Stoney APU (reflash / KVM
passthrough / emulated). OOB write corrupts adjacent VRAM BOs; OOB read pulls adjacent
kernel heap into VRAM. CVSS PR:H (privileged loader).

## Reproduction on the audit guest
Not possible — no AMD APU; amdgpu not in GENERIC. `harness.c` models the per-ME loop
with attacker-chosen jt_offset/jt_size and shows 4300 OOB-write + 18072 OOB-read
iterations, then the fix (reject invalid jt bounds) yields 0 OOB.

## Build / run
```
./build.sh && ./run.sh
```
Expected: `DF-1134: CONFIRMED OOB write past cp_table VRAM BO AND/OR OOB read past firmware blob`
then `DF-1134 FIX: VALIDATED - bounds validation rejects all OOB jt_offset/jt_size`.

## Fix
`fix.diff` captures `fw_dwords` per ME branch and, before the copy loop, rejects
`jt_size`/`jt_offset` that would read past the firmware blob or write past the
cp_table BO (`continue` on violation). Applies cleanly; compiles in the amdgpu
module build (`gfx_v8_0.o`, rc=0).
