DF-1332 / trigger.c
/* DF-1332 amdgpu_fill_buffer uint32 truncation skips VRAM clear */ #include <stdio.h> #include <stdint.h> #define PAGE_SHIFT 12 #define DIV_ROUND_UP(n,d) (((n)+(d)-1)/(d)) static int num_loops_vuln(uint64_t mm_node_size, uint32_t max_bytes){ uint32_t byte_count = mm_node_size << PAGE_SHIFT; /* TRUNCATES if >= 4GiB */ return DIV_ROUND_UP(byte_count, max_bytes); } static int num_loops_fixed(uint64_t mm_node_size, uint32_t max_bytes){ uint64_t byte_count = mm_node_size << PAGE_SHIFT; if (byte_count == 0) return 0; /* emulate integer ceil-divide across the full u64 range */ uint64_t loops = (byte_count + max_bytes - 1) / max_bytes; if (loops > 1000000) return 1000000; /* saturate for test */ return (int)loops; } int main(void){ /* mm_node->size of 0x100000 = 4 GiB worth of pages */ uint64_t huge = 0x100000ULL; /* 2^20 pages = 4 GiB */ uint32_t max_bytes = 0x400000; /* typical SDMA fill chunk */ printf("== BEFORE-FIX (vulnerable) ==\n"); int n = num_loops_vuln(huge, max_bytes); printf("BUG: byte_count = mm_node->size<<PAGE_SHIFT truncates to 0x%08x, num_loops=%d -> VRAM clear SKIPPED\n", (uint32_t)(huge << PAGE_SHIFT), n); printf(" Freshly allocated VRAM contains previous BO contents -> cross-user leak of GPU memory\n"); printf("== AFTER-FIX ==\n"); int n2 = num_loops_fixed(huge, max_bytes); printf("FIX: byte_count is uint64_t, num_loops=%d -> SDMA fill runs correctly\n", n2); return 0; } |