# DF-4854 VERDICT — vega10_ih unvalidated wptr (DF-4843 twin) + overflow-recovery OOB read

**Status: untested (hardware-bound — no AMD GPU on the audit guest).**
**Confidence: certain (static proof, exact register arithmetic).**

## Why untested

The primitive requires the GPU's IH block to write a malformed wptr into the
DMA'd writeback slot (`ih.ring[ih.wptr_offs]`, `vega10_ih.c:199`). The QEMU
audit guest (`DragonFly dfbsd 6.5-DEVELOPMENT #0 ... X86_64_GENERIC`) has no
AMD GPU; there is no unprivileged-software path that forges the wptr. Same
disposition as the tonga twin DF-4843 (untested / dos / certain).

## Static proof

1. **Ring geometry** — `vega10_ih.c:389`: `amdgpu_ih_ring_init(..., 256*1024, true)`
   → `amdgpu_ih.c:47-50`: `rb_bufsz = order_base_2(0x40000/4) = 16`,
   `ring_size = (1<<16)*4 = 0x40000`, `ptr_mask = 0x3FFFF`;
   `amdgpu_ih.c:61-68`: `dma_alloc_coherent(0x40000 + 8)`, `wptr_offs = 0x10000`,
   `rptr_offs = 0x10001` (the +8 tail).

2. **wptr source is device DMA** — the writeback address programmed into
   `mmIH_RB_WPTR_ADDR_LO/HI` (`vega10_ih.c:127-132`) is
   `rb_dma_addr + wptr_offs*4` = the first shadow word; HW (or a hostile GPU)
   writes it. `vega10_ih.c:198-201` reads it back; `:219` returns
   `wptr & 0x3FFFF` with **no 32-byte alignment validation**.

3. **Spin** — `amdgpu_ih.c:154-157`: rptr is 0-phase (init `amdgpu_ih.c:51`,
   steps +32 at `vega10_ih.c:308`/`:352`). wptr ≡ k (mod 32), k ≠ 0 ⇒ loop
   never terminates; `ih->lock` (`amdgpu_ih.c:144`) never released ⇒ every
   later interrupt returns IRQ_NONE at the `atomic_xchg` ⇒ GPU interrupt
   delivery dead + 1 CPU spinning. (Matches DF-4843 with a 32-byte grid.)

4. **OOB read** — register layout (`osssys_4_0_sh_mask.h:225-231`):
   RB_OVERFLOW = bit 0, OFFSET = bits [17:2] (4-byte granular). Overflow path
   `vega10_ih.c:203-213` clears bit 0 then sets `rptr = (wptr+32) & 0x3FFFF`.
   Device picks wptr = 0x3FFDC | 1 ⇒ rptr = 0x3FFFC ⇒ first
   `vega10_ih_decode_iv` (`vega10_ih.c:324-334`) uses `ring_index = 0xFFFF`
   and reads words `0xFFFF..0x10006` = bytes `0x3FFFC..0x4001B`; words
   `0x10002..0x10006` lie past the `0x40008`-byte allocation ⇒ **20-byte OOB
   read**. `amdgpu_irq_callback` additionally passes `&ring[0xFFFF]` to
   `amdgpu_amdkfd_interrupt` (`amdgpu_irq.c:170`) — same window. Downstream
   dispatch indexes are bounds-checked (`amdgpu_irq.c:409-417`), so impact is
   kernel-consumed OOB data (log fields / IV decode), not a demonstrated
   userspace leak.

## Exploit chain

None (device-gated). Ceiling: hostile-GPU DoS (primitive 1) + hostile-GPU
OOB read of ≤20 bytes of adjacent coherent DMA memory interpreted as an IV
(primitive 2).

## Kill list for the rest of the file (pass-2 negative evidence)

- dispatch client_id/src_id bounds-checked: `amdgpu_irq.c:409-417`
- normal-path decode is exactly in-bounds: max phase-0 rptr = 0x3FFE0 ⇒ words
  `0xFFF8..0xFFFF` — inside the ring; only the overflow path breaks it
- ring-init wb/doorbell math correct (`amdgpu_ih.c:61-68`,
  `vega10_ih.c:127-148`); `AMDGPU_DOORBELL64_IH << 1` is upstream parity
  (`amdgpu.h:457`)
- prescreen `#if 0` kfifo stub (`vega10_ih.c:288-301`): the kprintf half is
  DF-1936 (known); the functional half (all retry faults dropped, per-VM
  fault hash never drained — `amdgpu_vm_add_fault` capped at 128,
  `amdgpu_vm.c:3561`, freed only at `amdgpu_vm_fini:3308`; `fault_credit`
  only ever decremented, `amdgpu_vm.c:3390`) is an upstream-divergence
  robustness issue with no memory-safety consequence — negative note, not a
  finding
- stale wptr shadow across disable/enable (`vega10_ih.c:69-74` clears HW
  registers, not the DMA'd shadow): upstream-parity, subsumed by the
  unvalidated-wptr finding under the hostile-GPU model
- fini ordering correct: `amdgpu_irq_fini` (drm_irq_uninstall/free_irq)
  before `amdgpu_ih_ring_fini` (`vega10_ih.c:405-406`)

## Fix

fix.diff intentionally omitted per policy for untested findings (same as
DF-4843). Recommended shape: in `vega10_ih_get_wptr`, after masking, round a
misaligned wptr down to the 32-byte entry boundary with a dev_warn (and apply
the same alignment mask to the overflow-recovery rptr); cap the per-invocation
entry count in `amdgpu_ih_process` so a bad wptr/storm cannot hard-spin the
interrupt thread.

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

(No fix.diff for this item: documented recommendation only - see Fix above.)
