# VERDICT — DF-4967

**Status: untested** (target hardware absent on this guest; no radeon PCI device, driver
not compiled into the guest kernel). The arithmetic of the defect is **certain** from
source inspection and validated by the guest-built `gart_math.c` (11/11 PASS, `run.log`).
Impact therefore recorded as `none` *on this guest*; the code-level impact on a real
radeon box with an oversized GTT is cross-process GPU memory redirection (Medium).

## The defect, line by line

1. `sys/dev/drm/radeon/radeon_drv.c:175,229,231` — `radeon_gart_size` (MB) is an unbounded
   `int`: `TUNABLE_INT("drm.radeon.gart_size", ...)` / `module_param_named(gartsize, ...)`.
2. `sys/dev/drm/radeon/radeon_device.c:1117-1134` — `radeon_check_arguments()` only
   validates *power of two and ≥ 32*; there is **no upper bound**. Line 1137:
   `rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20;` — e.g. 8192 → 8 GiB.
3. `sys/dev/drm/radeon/radeon_ttm.c:940-943` — the GTT TTM heap is sized with the full
   `gtt_size`: `ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, rdev->mc.gtt_size >> PAGE_SHIFT)`.
   `radeon_ttm_placement_from_domain` uses unbounded `lpfn = 0`, so BOs can be placed at
   any page in the 8 GiB heap.
4. `sys/dev/drm/radeon/radeon_ttm.c:656,659` — `gtt->offset = (unsigned long)(bo_mem->start
   << PAGE_SHIFT);` (`bo_mem->start` is `unsigned long`, 64-bit — `ttm_bo_api.h:97`) then
   `radeon_gart_bind(gtt->rdev, gtt->offset, ...)` — **the callee parameter is
   `unsigned offset`** (`radeon_gart.c:286`), so offsets ≥ 2^32 truncate.
5. `sys/dev/drm/radeon/radeon_gart.c:299` — `t = offset / RADEON_GPU_PAGE_SIZE;` computes
   the GART entry index from the *truncated* offset; `pages[p]`, `pages_entry[t]` and
   `radeon_gart_set_page(rdev, t, ...)` (the actual PTE write into the GART table at
   `radeon_gart.c:309`) all go to the aliased low index.
   Identical truncation in `radeon_gart_unbind` (`radeon_gart.c:241,252`), so bind/unbind
   stay consistent with each other (both wrong).

## Why it matters (and why only Medium)

- With `gart_size ≥ 8192` (8 GiB GTT), two GTT buffer objects at aperture offsets X and
  X + 4 GiB compute the *same* `t`. The later bind overwrites the earlier BO's GART PTE
  and `pages[]`/`pages_entry[]` bookkeeping:
  - user A's GPU access to its BO at offset X is translated to user B's physical page
    (cross-process GPU data disclosure + corruption of B's buffer through A's writes);
  - B's BO at X + 4 GiB has no valid PTEs at its true entries (they hold the dummy/zero
    entry) → GPU reads of dummy page / write loss.
- It is *driver index aliasing*, not a kernel-memory OOB: `p`,`t` stay in bounds of
  `pages[]`/`pages_entry[]` (allocated for the full `num_gpu_pages`), and the set_page
  write goes into the properly sized GART table.
- Precondition is a root-set boot tunable (misconfiguration-assisted), same class as
  DF-2012. After boot, any unprivileged DRM user inherits the aliasing — the security
  boundary violated is user↔user (GPU data), not user→kernel.

## What I ruled out / verified

- `rs400_gart_init` (`rs400.c:86-93`) *does* bound gtt_size (32..2048 MB switch) → RS400
  cannot reach this; r100 (`r100.c:633-652`), rv370 (`r300.c:121-140`), rs600 (`rs600.c:535-548`),
  r600 (`r600.c:1105-1117`) have **no** bound → reachable there.
- `radeon_gtt_location` (`radeon_device.c:597-620`) only clamps gtt_size to the MC address
  space (≫ 8 GiB) — no effective mitigation.
- The AGP path (`radeon_agp.c:245`) takes the aperture size from the northbridge
  (hardware-bounded), unaffected.
- DF-2014 (unbind t/p desync) is a different defect (index *desync between t and p*), not
  re-reported here; this finding is about the *32-bit offset parameter* shared by bind and
  unbind.

## Fix validation

Not performable on this guest (no hardware, and the trigger is a boot-time tunable on real
hardware). `fix.diff` widens the API to `uint64_t offset` (both functions + `radeon.h`
declarations), which removes the truncation for every GTT size the u32 `num_gpu_pages`
model can describe; combined with DF-4968's table-size consistency check the oversized-GTT
misconfiguration space is closed.

## Reproduce the arithmetic

```
cc -O2 -Wall -o gart_math gart_math.c && ./gart_math   # ALL CHECKS PASSED
```

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