DF-4854 / trigger_sketch.c
/* * DF-4854 trigger sketch — vega10_ih unvalidated IH wptr * (twin of DF-4843 / tonga_ih; 32-byte IV entries, 256 KiB ring) * * NOT A RUNNABLE POC. The wptr is written by the GPU into the writeback * shadow word at rb_dma_addr + ring_size ( programmed as the IH_RB_WPTR_ADDR * in vega10_ih_irq_init, vega10_ih.c:127-132 ). Forging it requires a * hostile/faulting Vega10 GPU (or PCI DMA master) — the audit guest has no * AMD GPU. * * Primitive 1 (permanent spin / GPU IRQ DoS): * hostile GPU writes wptr_shadow = 0x00010004 (misaligned mod 32) * -> vega10_ih_get_wptr returns 0x10004 & 0x3FFFF = 0x10004 * -> amdgpu_ih_process: rptr (0-phase, steps 32) can never equal 0x10004 * -> ithread laps the ring forever, ih->lock held, all amdgpu IRQs dead * * Primitive 2 (20-byte OOB read past the ring allocation): * hostile GPU writes wptr_shadow = 0x0003FFDD (OFFSET=0x3FFDC, RB_OVERFLOW=1) * -> get_wptr: bit0 cleared -> 0x3FFDC; rptr := (0x3FFDC + 32) & 0x3FFFF = 0x3FFFC * -> decode_iv: ring_index = 0xFFFF, reads ring[0xFFFF .. 0x10006] * (words 0x10002..0x10006 are past dma_alloc_coherent(0x40008)) * -> OOB dwords become entry->src_data/timestamp/pasid and are dispatched * (amdgpu_irq.c:170/173-175); also passed to amdgpu_amdkfd_interrupt. * * If a Vega10 system is available, primitive 1 can be exercised without * hostile DMA by poking the shadow from a kld / ddb: * *(volatile uint32_t *)((uint8_t *)adev->irq.ih.ring + adev->irq.ih.ring_size) = 0x10004; * then send any GPU interrupt (e.g. X session / vulkaninfo) and observe the * amdgpu ithread peg a CPU with interrupts dead until reboot. */ int main(void) { return 0; } |