DF-4843 / trigger_sketch.c
/* DF-4843 sketch — unvalidated-wptr livelock in the Tonga/VI IH ring walk. * * The GPU (hostile or faulting device model) writes the IH wptr into the * writeback slot ring[wptr_offs]. tonga_ih_get_wptr() only masks it with * ptr_mask (tonga_ih.c:196-219); amdgpu_ih_process() then walks * * while (ih->rptr != wptr) { amdgpu_ih.c:154 * callback(adev, ih); (prescreen/decode/dispatch) * ih->rptr &= ih->ptr_mask; amdgpu_ih.c:156 * } * ... * wptr = amdgpu_ih_get_wptr(adev); amdgpu_ih.c:163 * if (wptr != ih->rptr) goto restart_ih; amdgpu_ih.c:165 * * rptr only ever advances by 16 bytes per entry (tonga_ih.c:245,277), so a * wptr that is not 16-byte aligned (any garbage the device DMA'd into the * writeback slot, e.g. after a firmware compromise or a falling-off-the- * bus event that corrupts the slot) can NEVER equal rptr: the loop wraps * the whole 64 KiB ring forever, re-dispatching 4096 stale/garbage entries * per lap, and restart_ih re-reads the same misaligned wptr -> permanent * hard-spin of the amdgpu interrupt thread (one CPU pegged at 100% in * ithread context, ih->lock held at 1, all further GPU interrupts dead). * * No entry-count bound and no wptr alignment validation exist anywhere on * the path. This file documents the trigger; runtime verification needs a * Tonga/Vega10 GPU (or an adev fake whose set_rptr MMIO is stubbed) and * was not run on the audit guest (no GPU present). */ static void df4843_sketch(void) { /* * amdgpu_irq.ih.ring[amdgpu_irq.ih.wptr_offs] = 0x15; (device DMA) * -> amdgpu_ih_get_wptr() returns 0x15 * -> rptr takes 0,16,32,...,0xfff0,0,... != 0x15 forever * -> ithread spins dispatching forever (restart_ih never exits) */ } |