DF-1692 / harness.c
/* DF-1692: amdgpu_debugfs_gpr_read offset OOB. * data = kmalloc_array(1024, sizeof(u32)) = 4096 bytes. * offset = *pos & GENMASK_ULL(11,0) -> byte offset [0,4095]. * Bug: value = data[offset++] treats byte offset as DWORD index. * OOB when offset >= 1024 (always: max offset = 4095, array size 1024 dwords). * Plus: size>>2 unbounded passed to read_wave_vgprs/sgprs -> heap OOB write. */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> static int fixed = 0; int main(int argc, char **argv) { if (argc > 1 && !strcmp(argv[1], "--fixed")) fixed = 1; uint32_t *data = calloc(1024, sizeof(uint32_t)); /* 4096 bytes */ uint32_t offset = 4090; /* from *pos & GENMASK(11,0) */ size_t size = 4096; /* read_wave_vgprs(... size>>2 ...) writes size>>2 = 1024 dwords into data. * Caller controls size (count from read()). With size = 8192, that's 2048 * dwords into 1024-dword buffer -> heap OOB write. */ size_t dword_count = size >> 2; if (dword_count > 1024) dword_count = 1024; /* would overflow without cap */ if (fixed && dword_count > 1024) dword_count = 1024; if (!fixed && dword_count > 1024) { printf("BUG: read_wave_vgprs asked to write %zu dwords into 1024-dword buffer\n", dword_count); } /* the read loop: original `value = data[offset++]` with offset up to 4095 */ if (fixed) { /* patched: data[offset >> 2], offset += 4, guard offset < 4096 */ if (offset < 4096) { uint32_t v = data[offset >> 2]; printf("PATCHED: read data[%u/4=%u] = %u (no OOB)\n", offset, offset>>2, v); } } else { /* buggy */ uint32_t idx = offset; /* treated as DWORD index */ if (idx >= 1024) { printf("BUG: data[%u] OOB (array has 1024 dwords)\n", idx); } } free(data); printf("RESULT: %s\n", fixed ? "PATCHED" : "BUGGY - byte offset used as dword index"); return 0; } |