# DF-1146 — i915_gem_fault missing offset bounds + partial-VMA GMADR offset (i915_gem.c)

**Status:** REPRODUCED at code level — **latent at runtime on this guest** (no Intel GPU).
**Severity (finding):** High · CWE-787 OOB Write + CWE-125 OOB Read

## What the bug is (two DragonFly-port defects)
1. **Missing bounds check:** `i915_gem_fault` (`sys/dev/drm/i915/i915_gem.c:2229`)
   computes `page_offset = offset >> PAGE_SHIFT` (`:2263`) with **no check** that
   `offset < obj->base.size`. `drm_gem_mmap_single` (`drm_gem.c:1099`) passes the
   user mmap length straight to `cdev_pager_allocate` without clamping to the GEM
   object size, so a process can mmap a tiny object with a huge length and fault
   past it. Upstream Linux has the guard; the DFly port dropped it.
2. **Partial-VMA GMADR miscompute:** for an `I915_GGTT_VIEW_PARTIAL` VMA the GMADR
   address at `:2391-2392` (`ggtt->gmadr.start + vma->node.start + offset`) does
   not subtract `vma->ggtt_view.partial.offset * PAGE_SIZE`, returning pages from
   neighbouring GTT slots. (The correct idiom exists at `i915_vma.c:905`.)

## Why it does not trigger here
Only QEMU std VGA (`0x1234:0x1111`) on the guest — not an Intel i915; `i915` is
not in `X86_64_GENERIC` (only in LINT64 as a test config). Latent on
Intel-graphics hardware.

## What was validated
1. **Source trace** confirmed (see VERDICT.md `kernel_refs`).
2. **Baseline** `i915.ko` (incl. `i915_gem.o`) builds clean under `-Werror`.
3. **Fix** `fix.diff` applies (2 hunks) and patched `i915_gem.o` rebuilds clean
   under `-Werror` (`i915_gem.o`: 117984 -> 118080 bytes).

## Reproduce (compile-validation only)
```
scp this-folder/fix.diff root@guest:/root/df1146.diff
cd /usr/src && patch -p1 --forward < /root/df1146.diff
cd sys/dev/drm/i915 && rm -f i915_gem.o && make i915_gem.o   # -Werror clean
```

## Fix
`fix.diff` adds `if (offset >= obj->base.size) return VM_PAGER_ERROR;` after
`page_offset` is computed, and subtracts `partial.offset << PAGE_SHIFT` from the
GMADR address for PARTIAL views.
