# DF-1178 — gfx_v9_1_parse_ind_reg_list stack overflow + OOB read + BUG_ON panic

## Bug (confirmed in source)
`sys/dev/drm/amd/amdgpu/gfx_v9_0.c:2084-2118`, reached only via
`gfx_v9_0_init_pg()` → `gfx_v9_1_init_rlc_save_restore_list()` (lines 2405,
2142) when `adev->gfx.rlc.is_rlc_v2_1 == true`.

Three distinct defects in `gfx_v9_1_parse_ind_reg_list()`:

1. **Stack buffer overflow (CWE-121)** at `gfx_v9_0.c:2096-2098`:
   `WARN_ON(*indirect_start_offsets_count >= max_start_offsets_count);` is
   *non-fatal* in DragonFly (`sys/dev/drm/include/asm/bug.h:43-49` — it
   `kprintf`s a warning and returns the condition). Execution continues
   unconditionally into
   `indirect_start_offsets[*indirect_start_offsets_count] = indirect_offset;`
   With `max_start_offsets_count == 10` (the stack array declared at line
   2126 has exactly 10 ints), a crafted RLC v2.1 firmware with >10 indirect
   blocks smashes past `indirect_start_offsets[10]` into saved RBP / the
   return address.

2. **Heap OOB read (CWE-125)** at `gfx_v9_0.c:2100-2101`: the inner
   `while (register_list_format[indirect_offset] != 0xFFFFFFFF)` loop does
   `indirect_offset += 2;` with **no check that `indirect_offset < list_size`**.
   The `register_list_format` array is a `kmalloc()` (line 2134) of
   `reg_list_format_size_bytes >> 2` ints; a firmware that omits the
   `0xFFFFFFFF` terminator causes the parser to walk off the end of the heap
   allocation.

3. **BUG_ON panic** at `gfx_v9_0.c:2111`: `BUG_ON(idx >= unique_indirect_reg_count)`
   expands to `panic()` in DragonFly (`sys/dev/drm/include/asm/bug.h:33-37`).
   A firmware with >8 distinct indirect register IDs is an unconditional
   kernel panic / local DoS — the per-call `unique_indirect_regs[8]` (line
   2123) cannot hold a ninth entry.

Class: NEW class not present in gfx_v7/v8 — added with gfx_v9.

## Trigger model
- Requires the `amdgpu` driver attached to a real AMD Vega-class GPU
  (`vgapci0` here is QEMU stdvga vendor 0x1234 — not AMD, no attachment).
- Triggered during GPU init by a crafted RLC v2.1 firmware.
- CVSS `AV:L/AC:L/PR:H/UI:N/S:U:C:H/I:H/A:H` — high integrity/availability
  impact but high privilege required (malicious firmware must be flashed
  by an attacker with root or physical access).

## On this guest
The path is unreachable on this guest (no AMD GPU; the amdgpu module is
present in `/boot/kernel/amdgpu.ko` but never attaches). This is a
**latent** bug — confirmed real in source, not triggerable on the audit
guest. The harness `harness.c` is a faithful userspace transcription of the
parser that demonstrates the overflow logic without any kernel dependency.

## Reproduce
```
ssh dfbsd-maxx "cd poc/DF-1178 && ./build.sh && ./run.sh"
```
Expected: the harness prints `WARN_ON fires` and
`Stack-buffer overflows past indirect_start_offsets[10]: N slot(s)`, proving
the parser logic permits the overflow.  No kernel effect on this guest.

## Recommended fix
Convert `WARN_ON` to a hard `break`, add an `indirect_offset < list_size`
bounds check on the inner `while`, and convert the `BUG_ON` to a `break`.
Full git-apply-able patch in `fix.diff`.  This **matches** the finding
proposal (convert WARN_ON to break, add indirect_offset bounds check).
