# DF-4181 — Verification Verdict

**Status:** inconclusive (hardware-gated: no radeon GPU in the QEMU guest)
**Impact:** none on this guest (display-engine OOB read past a GEM object on affected hardware — info disclosure of adjacent VRAM to the physical display)
**Confidence:** certain (absence of any size validation provable from source)

## Mechanism (source trace)

1. `DRM_IOCTL_MODE_ADDFB2` → `drm_mode_addfb2` →
   `drm_internal_framebuffer_create` (drm_framebuffer.c:277).
   `framebuffer_check()` (drm_framebuffer.c:165-275) validates:
   format known (via `__drm_format_info`), width/height within
   mode_config min/max, `width*cpp <= UINT_MAX`,
   `height*pitches[i] + offsets[i] <= UINT_MAX` (:208),
   `pitches[i] >= width*cpp` (:211).  **It never looks at the buffer
   object at all** (it doesn't have it — handles are resolved by the
   driver's fb_create).
2. `radeon_user_framebuffer_create()` (radeon_display.c:1311-1348):
   `drm_gem_object_lookup()` on handles[0] (:1320), rejects imported
   dma-bufs (:1328), allocates the fb (:1334) and calls
   `radeon_framebuffer_init()` (:1340).  **No comparison of required
   image size vs BO size.**
3. `radeon_framebuffer_init()` (radeon_display.c:1294-1309):
   `drm_helper_mode_fill_fb_struct()` fills pitches/format; then straight
   to `drm_framebuffer_init()` — again no size check.
4. Scanout path: set_config/page_flip pin the BO
   (`radeon_bo_pin(..., RADEON_GEM_DOMAIN_VRAM, ...)` — pinning does not
   check fb dimensions either) and program the display base address +
   pitch; the display engine then fetches `pitch * crtc_vdisplay` bytes
   starting at the BO — reading far past its end when the fb is larger
   than the BO.  The flip path repeats this
   (radeon_display.c:524-539, radeon_crtc_page_flip_target pins new_rbo
   and computes `pitch_pixels = fb->pitches[0] / fb->format->cpp[0]`).
5. Same gap exists in amdgpu_display_user_framebuffer_create
   (amd/amdgpu/amdgpu_display.c:523) — this DRM vintage predates the
   drm_gem_fb size checks; upstream later moved radeon/amdgpu to
   drm_gem_fb_create which checks per-plane min-size vs BO size.

Impact: an unprivileged user with DRM master/modeset rights (any desktop
session via logind) creates a small VRAM BO, registers an oversized fb on
it, and modesets: the panel then displays the contents of VRAM
immediately following the BO — other applications' buffers.  The leak is
to the physical display (photo/screen-capture by a second GPU path is not
available), so the ceiling is visual disclosure; no kernel memory is
involved and no write primitive exists.  Rating: Medium (info leak,
default desktop configs, needs radeon KMS).

## Why it cannot be reproduced on this guest

QEMU guest has no ATI/AMD GPU: no /dev/dri, radeon.ko not loaded.
`rfb_oob` builds and runs; `open("/dev/dri/card0")` fails ENOENT
(run.log).

## Fix validation

`fix.diff` adds the per-plane
`offsets[i] + pitches[i] * DIV_ROUND_UP(height, vsub) <= radeon_bo_size()`
check in `radeon_framebuffer_init()`.  Applies cleanly; radeon.ko module
built with the patch (fix_build.log — module build, since radeon is not
part of X86_64_GENERIC).  Expected behavioral change on hardware: the PoC
ADDFB2 returns -EINVAL.

## 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.
