# DF-1894 — Verification Verdict

## Verdict: REPRODUCED (source-confirmed + arithmetic-harness)

The `fw_size * 4` integer overflow is confirmed at
`sys/dev/drm/i915/intel_csr.c:404`. The harness reproduces the
wraparound and shows the resulting ~10⁹-dword OOB read in
`intel_csr_load_program`.

## Mechanism

```c
// intel_csr.c:404
nbytes = dmc_header->fw_size * 4;    // uint32 mult — wraps mod 2^32
// :413
if (nbytes > max_fw_size) return NULL;   // tests WRAPPED value
// :417
csr->dmc_fw_size = dmc_header->fw_size;  // stores ORIGINAL (huge)
// :419
dmc_payload = kmalloc(nbytes, ...);      // tiny alloc
// :425
return memcpy(dmc_payload, &fw->data[readcount], nbytes);  // tiny copy — ok
```

With `fw_size = 0x40000001`: `nbytes` wraps to `4`, `kmalloc(4)`
succeeds, the 4-byte memcpy is fine. But `csr->dmc_fw_size` stores the
ORIGINAL `0x40000001`. Then `intel_csr_load_program` (intel_csr.c:259-265):

```c
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
```

reads ~10⁹ dwords past `payload` (which is only 4 bytes) into kernel
heap, writing each to MMIO `CSR_PROGRAM(i) = 0x80000 + i*4` under
`preempt_disable` (:262) — corrupting display/GPU HW state and wedging
the CPU.

Same anti-pattern as DF-1838/1854/1875 PSP firmware, but i915 DMC.

## Harness evidence

```
DF-1894: parse_csr_fw (intel_csr.c:404-425) + intel_csr_load_program (:259)
  dmc_header->fw_size = 0x40000001
  nbytes = fw_size * 4 = 0x00000004 (WRAPS — should be 0x100000004)
  nbytes > max_fw_size (0x100000)? NO (check bypassed)
  -> kmalloc(4) succeeds; memcpy 4 bytes is fine
  -> csr->dmc_fw_size = 0x40000001 (ORIGINAL, not wrapped)
  -> intel_csr_load_program loops i=0..0x40000001 calling I915_WRITE_FW (CSR_PROGRAM(i), payload[i])
     payload has 4 bytes allocated; reads ~1073741824 dwords past it into kernel heap -> OOB read + MMIO corruption -> GPU/CPU wedge
```

## Why no live trigger on this guest

The DMC firmware path runs on Intel graphics (i915). The audit guest has
no Intel GPU; `i915.ko` is present but not loaded. The trigger requires
a crafted DMC firmware, reachable via root-controlled
`dmc_firmware_path` module param (mode 0400) or a compromised firmware
update / NFS-root / embedded kiosk. Valid Phase-6 hard blocker.

## Exploit chain

Not applicable (Intel-GPU-gated + root-controlled firmware path). No
`uid=0` claim. Live ceiling: ~10⁹-dword OOB read + MMIO corruption →
hard CPU/GPU wedge / DoS; the OOB read could also leak kernel heap.

## PoC changes

- Added `harness.c`: reproduces the `fw_size * 4` wrap arithmetic.
- Added `fix.diff`: validate `fw_size > max_fw_size/4` BEFORE the
  multiplication.

## Fix

`fix.diff` moves the `max_fw_size` computation before the `nbytes`
multiplication and adds `if (dmc_header->fw_size > max_fw_size / 4)
return NULL` — rejecting the oversized fw_size before it can wrap or be
stored in `csr->dmc_fw_size`.

- BEFORE: harness shows nbytes wraps to 4, check bypassed.
- AFTER: fw_size > max_fw_size/4 is rejected before the multiply.
