# VERDICT — DF-5782

**Status: untested** (no Intel GPU on the audit rig; verified by line-level
static analysis + upstream differential). **Impact ceiling: OOB GPU scanout
read from wrong/adjacent GGTT mappings — info-leak-class to the display
and/or hardware upset.** Upstream author's own impact statement for this bug
family (commit 4e05047d3e00, the *other* half of the same check, which IS
present): "in the worst case we might anger the hw by attempting scanout past
the end of the ggtt, or we might scan out some data that we're not supposed
to see from other parts of the ggtt." The display engine cannot write; this
is a read-side primitive disclosed through the visible screen content.

## Proven chain (all line refs into sys/dev/drm/i915/intel_display.c unless noted)

1. **Entry, unprivileged:** `DRM_IOCTL_MODE_ADDFB2` is registered
   `DRM_UNLOCKED` with *no* `DRM_AUTH`/`DRM_MASTER` in
   `sys/dev/drm/drm_ioctl.c:671` → any local user holding an open
   `/dev/dri/card0` fd reaches `intel_user_framebuffer_create()`
   (intel_display.c:14770) → `intel_framebuffer_init()` (14544) →
   `intel_fill_fb_info()` (2487) → `intel_fb_offset_to_xy()` (2398).

2. **Core check passes:** `sys/dev/drm/drm_framebuffer.c:205-209` rejects
   `(u64)height * pitch + offset > UINT_MAX` using the **raw** plane height.

3. **Driver re-heights and overflows:** the driver aligns the plane height up
   to the tile height (`intel_fb_align_height` 1989-1996;
   `intel_fill_fb_info` 2587 `DIV_ROUND_UP(y + height, tile_height)`), and
   computes with u32 arithmetic:
   * `intel_compute_aligned_offset` :2360 `offset = (tile_rows * pitch_tiles + tiles) * tile_size;`
   * `intel_fill_fb_info` :2635 `size = DIV_ROUND_UP((y + height) * fb->pitches[i] + x * cpp, tile_size);`
   With `offsets[1]` ∈ [0, 0xffffffff] (only plane 1: `offsets[0]` is forced
   to 0 at :14706) and an 8192-wide tiled NV12/CCS geometry, the tile-aligned
   product crosses 2^32 and wraps after the core check already passed.

4. **Final sanity check fooled:** the wrapped `size` is small, so
   `mul_u32_u32(max_size, tile_size) > obj->base.size` (:2643) passes while
   the real plane extent exceeds the object → scanout runs past the object's
   GGTT mapping.

5. **The guard that should exist here** (from upstream v5.0
   `70bbe53c6eac`, absent in this tree — differential hunk stored in
   `differential/upstream_4.20_to_v5.1.fb_overflow_hunk.txt`):
   ```c
   height = drm_framebuffer_plane_height(fb->height, fb, color_plane);
   height = ALIGN(height, intel_tile_height(fb, color_plane));
   /* Catch potential overflows early */
   if (add_overflows_t(u32, mul_u32_u32(height, fb->pitches[color_plane]),
                       fb->offsets[color_plane]))
           return -ERANGE;
   ```

## Hardware gating (honest bound)
* NV12 path only on gen9 KBL/CFL/GLK/CNL (`intel_framebuffer_init`
  :14690-14698 rejects NV12 on <gen9, SKL, BXT, ≥gen11).
* CCS path needs `I915_FORMAT_MOD_{Y,Yf}_TILED_CCS` (gen9+ with CCS planes).
* Creating the malicious fb needs **no master**; *displaying* it (to realize
  the leak) needs a plane update (DRM master) — or a cooperating compositor
  importing attacker-specified geometry (DRI3/pixmap-from-fd with crafted
  stride/offset is the realistic vector on a multi-user desktop).

## Why not executed here
Guest is QEMU with Bochs VGA (`pciconf -lv`: chip=0x11111234); the i915
driver never attaches and `/dev/dri/card*` is absent — the trigger's own
first step reports this (see env.txt). No panic/leak can be produced on this
rig. Classification: `untested` with static+differential proof, per task
instructions ("verification is code-reading + differential where arithmetic
classes appear (no hardware)").

## Fix validation
`fix.diff` is the faithful backport of 70bbe53c6eac written with explicit
64-bit math (the DFly tree has `add_overflows` but not `add_overflows_t`, so
the diff avoids the helper). Not kernel-built here — no i915 hardware to
boot; fix_status=not_tested.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
