DF-1894 / harness.c
/* * DF-1894 source-confirmation harness (i915 DMC firmware fw_size*4 overflow). * * sys/dev/drm/i915/intel_csr.c:404-425 parse_csr_fw: * nbytes = dmc_header->fw_size * 4; // uint32 mult โ wraps * if (nbytes > max_fw_size) return NULL; // tests wrapped value * csr->dmc_fw_size = dmc_header->fw_size; // stores ORIGINAL (huge) * dmc_payload = kmalloc(nbytes, ...); // tiny alloc * return memcpy(dmc_payload, &fw->data[off], nbytes); // tiny copy โ ok * * Then intel_csr_load_program (intel_csr.c:259-265): * fw_size = csr->dmc_fw_size; // 0x40000001 * for (i = 0; i < fw_size; i++) * I915_WRITE_FW(CSR_PROGRAM(i), payload[i]); // payload[i] OOB read * * With fw_size = 0x40000001: nbytes wraps to 4, kmalloc(4) succeeds, * 4-byte memcpy is fine, but the load_program loop reads ~10^9 dwords * past payload[] into kernel heap, writing each to MMIO. * * Needs root-controlled firmware path (module param dmc_firmware_path, * mode 0400) โ not unpriv-reachable on this guest. The harness shows * the wrap arithmetic. * * Build: cc -O2 -o harness harness.c * Run: ./harness */ #include <stdio.h> #include <stdint.h> int main(void) { uint32_t fw_size = 0x40000001u; uint32_t nbytes = fw_size * 4; /* intel_csr.c:404 โ wraps mod 2^32 */ uint32_t max_fw = 0x100000; /* BXT_CSR_MAX_FW_SIZE ~1MB */ printf("DF-1894: parse_csr_fw (intel_csr.c:404-425) + intel_csr_load_program (:259)\n"); printf(" dmc_header->fw_size = 0x%08x\n", fw_size); printf(" nbytes = fw_size * 4 = 0x%08x (WRAPS โ should be 0x%llx)\n", nbytes, (unsigned long long)fw_size * 4); printf(" nbytes > max_fw_size (0x%x)? %s\n", max_fw, nbytes > max_fw ? "YES (reject)" : "NO (check bypassed)"); printf(" -> kmalloc(%u) succeeds; memcpy %u bytes is fine\n", nbytes, nbytes); printf(" -> csr->dmc_fw_size = 0x%08x (ORIGINAL, not wrapped)\n", fw_size); printf(" -> intel_csr_load_program loops i=0..0x%08x calling I915_WRITE_FW " "(CSR_PROGRAM(i), payload[i])\n", fw_size); printf(" payload has %u bytes allocated; reads ~%u dwords past it into " "kernel heap -> OOB read + MMIO corruption -> GPU/CPU wedge\n", nbytes, fw_size - (nbytes/4)); return 0; } |