# DF-4887 — cik_ih: unvalidated device-DMA'd IH wptr (DF-4843 twin, 16-byte grid) + phase-preserving RB_OVERFLOW recovery parking rptr within 12 bytes of ring end → up to 12-byte OOB read past the 64 KiB GTT ring BO

File: `sys/dev/drm/amd/amdgpu/cik_ih.c:186-206` (with the shared walk at
`amdgpu_ih.c:140-165`).

## Answers to the batch's specific cik questions

- **wptr source**: cik DOES use the writeback buffer, same as tonga —
  `wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs])`
  (cik_ih.c:190); `cik_ih_sw_init` passes `use_bus_addr=false`
  (cik_ih.c:321) so the `ring[]`-embedded shadow path never runs. NOT a
  different shape: this is the DF-4843 shape on a 16-byte IV grid.
- **doorbell**: none — CIK predates IH doorbells. The funcs table
  (cik_ih.c:462-467) has only get_wptr/prescreen_iv/decode_iv/set_rptr,
  and `set_rptr` uses the `mmIH_RB_RPTR` register (cik_ih.c:297-300).
- **RB_OVERFLOW path**: present and same-phase as tonga:
  `adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask`
  (cik_ih.c:200) — the DF-4854 aggravator exists here too (12-byte
  variant, worse in one respect: the GTT BO allocation has NO +8 slack).

## The defect

`cik_ih_get_wptr` consumes the GPU-writeback u32 with nothing but
`& ptr_mask` (cik_ih.c:205). The consumer walk (`amdgpu_ih_process`,
amdgpu_ih.c:154-157) terminates on `rptr == wptr` while `rptr` advances
strictly in 16-byte steps (`+= 16` at cik_ih.c:255 prescreen-drop and
cik_ih.c:287 decode). Two consequences for a wptr that is not a multiple
of 16 (hostile/faulting firmware DMA, corrupted writeback after a PCIe
fault):

1. **Permanent interrupt-thread spin (the DF-4843 core).** With the
   overflow bit clear, `rptr` (phase 0) can never equal a phase-p wptr:
   the ithread laps the 64 KiB ring forever — 4096 IVs re-dispatched per
   lap — with `ih->lock` held (amdgpu_ih.c:144) and `restart_ih`
   re-reading the same bad wptr (amdgpu_ih.c:163-165). One CPU pegged in
   interrupt context, all GPU interrupt delivery dead.
2. **OOB read aggravator (the DF-4854 shape, 12-byte variant).** With the
   overflow bit SET and wptr' (overflow-cleared) in `[0xFFE4..0xFFEF]`
   (sub-16 phase 4..15 near ring end), the recovery
   `rptr = (wptr' + 16) & 0xFFFF` lands in `[0xFFF4..0xFFFF]` — within
   12 bytes of the ring end. The first `prescreen_iv`/`decode_iv` then
   reads `ring[ring_index .. ring_index + 3]` with `ring_index = rptr>>2`
   up to `0x3FFF` (cik_ih.c:243-246, 274-277) → dwords `0x4000..0x4002`
   = up to **12 bytes past the 64 KiB ring buffer**. The ring here is a
   `amdgpu_bo_create_kernel` GTT BO of exactly `ring_size`
   (amdgpu_ih.c:80-88) — unlike vega10's `ring_size+8`
   `dma_alloc_coherent`, there is **zero slack**: the read touches the
   next mapped page (adjacent kernel memory interpreted as an IV and
   handed to `amdgpu_amdkfd_interrupt` at amdgpu_irq.c:170) or faults
   outright. The garbage IV is then decoded and dispatched to IP-block
   handlers (dispatch indices themselves are bounds-checked in
   amdgpu_irq.c, so the blast radius is the 12-byte OOB read + bogus
   dispatch).

Prescreen/PASID (cik_ih.c:238-257): same fault-credit logic as tonga —
`amdgpu_vm_pasid_fault_credit` (amdgpu_vm.c:3370-3397) is idr_find under
`pasid_lock`; the drop path advances rptr by 16 consistently with the
walk. No cik-unique defect there.

## Threat model / severity

Hostile or faulting GPU device (the wptr source is device DMA into host
writeback memory). No unprivileged-software trigger; hardware-gated DoS +
bounded OOB read. Same Low grading as DF-4843/DF-4854.

## Reproduce

Not runnable on the audit guest: guest PCI tree has no AMD GPU (env.txt),
and the trigger requires device-side DMA of a misaligned wptr. Code-certain
by inspection (arithmetic above). See trigger_sketch.c for the hostile
write pattern that would be needed.

## Fix

In `cik_ih_get_wptr`, after clearing the overflow bit, normalize a
misaligned wptr down to the 16-byte entry boundary (`wptr &= ~0xF;` after
masking, with a `dev_warn`), and compute the overflow-recovery rptr from
the *aligned* value — plus a per-invocation entry cap in
`amdgpu_ih_process` so a storm or bad wptr can never hard-spin the ithread.
