# DF-3597 — VERDICT

**status: inconclusive (kernel run) / algorithm proven (replica)**
**reproduced: 0 (no AMD hardware/module on the audit guest)**
**source-level confidence: certain**

## What was verified and how

1. **Source trace (certain).** `gfx_v8_0_parse_ind_reg_list`
   (gfx_v8_0.c:3974-4022) is handed a *private* heap copy of the RLC
   firmware's register-list-format array (`kmalloc` :4033, `memcpy` :4037,
   `list_size = reg_list_format_size_bytes >> 2` :4042). The loop consumes
   3-dword entries: at :4001 it executes `ind_offset += 2` and then reads
   `register_list_format[ind_offset]` at :4008/:4013 and writes it at :4020
   — with no `ind_offset < list_size` re-check. When the last list word is
   not the 0xFFFFFFFF terminator, `ind_offset` becomes `list_size` (+1 word
   OOB) or `list_size+1` (+2 words OOB):

   * OOB **read** of the kmalloc buffer at gfx_v8_0.c:4008 and :4013 — the
     value read lands in `unique_indices[]` and is later programmed into
     `mmRLC_SRM_INDEX_CNTL_{ADDR,DATA}_n` (:4079-4080); no direct user-visible
     leak, but attacker-controlled garbage in RLC SRM index registers.
   * OOB **write** at gfx_v8_0.c:4020 — `register_list_format[ind_offset] =
     indices` writes an int in [0,7] four or eight bytes past the end of a
     firmware-sized heap object.
   * `BUG_ON(*offset_count >= max_offset)` :3993 and
     `BUG_ON(*indices_count >= max_indices)` :4017 fire *after* the array
     writes they guard; a list with a 10th entry or an 8th unique indirect
     index panics the kernel (firmware-controlled DoS).

   This is independent of pass-1 DF-1133 (init_microcode size arithmetic and
   array offsets) — the parser walks past the end of an exactly-sized local
   copy even with DF-1133 fixed.

2. **Logic replica (deterministic).** `poc_dfr3597.c` is the kernel parser
   verbatim (BUG_ON redefined to report). Built and executed **on the audit
   guest** (DragonFly 6.5-DEVELOPMENT x86_64, cc 8.3):
   * mode `oob`: 18-element list ending in a truncated entry → write of `0x1`
     at element 19 (**+4 bytes past the 72-byte allocation**) — canary
     clobbered. See `run.log`.
   * mode `bugon`: 8 unique indirect indices → BUG_ON fires (kernel panic
     equivalent).

3. **Why not a kernel run.** The guest is virtio-only: `pciconf -l` lists no
   AMD vendor (0x1002) device, `kldstat -v | grep -c drm` = 0, and
   `/boot/modules` does not exist — the amdgpu driver is neither loadable nor
   present. The in-kernel trigger requires a Carrizo/Stoney/Polaris11/12/VegaM
   machine plus a crafted `amdgpufw_*_rlc` firmware module. Hence the honest
   classification `inconclusive` for the kernel path; the algorithm and reachability
   are proven from source and the replica.

## Exploit chain (would-be, for the maintainer's threat model)

replace `amdgpufw_<asic>_rlc` module → RLC header v2.0 fields
(`reg_list_format_size_bytes` = allocation size ⇒ slab-class selection;
list content = truncation point ⇒ +4/+8 byte write offset) → at driver load,
`kmalloc`'d copy parsed → small-int (0..7) heap overwrite of the adjacent
object's first 4-8 bytes → groom an adjacent victim whose type/flags/length
field is corrupted → classic slab-exploitation path to code execution in
kernel context. The BUG_ON variant is a straight load-time DoS.

## Fix validation

`fix.diff` adds (a) `if (ind_offset + 2 >= list_size) { DRM_ERROR(...);
return; }` before the +=2 dereference, and (b) converts both post-write
`BUG_ON`s into pre-write `WARN_ON` guards. Not build-testable on this guest
(no kernel toolchain for the DRM module, module absent from the tree build);
`fix_status: not_testable` with the diff line-matched against
gfx_v8_0.c:3986-4021 in the current tree.

## kernel_refs

- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:3974-4022 (parser, OOB R/W)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:4024-4048 (kmalloc/memcpy/parse caller)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:4127-4144 (init_pg ASIC gating)
- sys/dev/drm/amd/amdgpu/gfx_v8_0.c:4176-4183, 4864-4878 (resume/hw_init)

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