# VERDICT — DF-4968

**Status: untested** (no radeon hardware on this guest). Arithmetic certain and validated
by `gart_math.c` (11/11 PASS, `run.log`). Filed as **Info/hardening**: the current code
fails closed, but only by accident of the power-of-two validator, and the missing
table-size consistency check is the exact gap DF-2012 exposed in amdgpu.

## Chain

1. `sys/dev/drm/radeon/radeon_device.c:1117-1134` — power-of-two + ≥32 MB validation, no
   upper bound; line 1137 `gtt_size = (uint64_t)radeon_gart_size << 20`.
2. `sys/dev/drm/radeon/radeon_gart.c:345-346` — `num_cpu_pages`/`num_gpu_pages` are
   `unsigned` (u32) fields assigned from the u64 with no overflow check
   (`radeon.h:659-660`); they truncate for gtt ≥ 16 TiB.
3. Per-asic table sizing (32-bit unsigned multiply, no overflow check):
   - ×8: `r600.c:1115`, `rs600.c:546` → wraps to 0 for gtt ≥ 2 TiB
   - ×4: `r100.c:647`, `r300.c:136` (rv370), `rs400.c:101` → wraps to 0 for gtt ≥ 4 TiB
   (rs400 additionally *is* bounded 32..2048 MB by its own switch at `rs400.c:86-93`;
   r100/rv370/rs600/r600 are not).
4. `sys/dev/drm/radeon/radeon_gart.c:68-87` (`radeon_gart_table_ram_alloc`) and
   `:127-140` (`radeon_gart_table_vram_alloc`) use `table_size` directly with **no check
   that `table_size >= num_gpu_pages * sizeof(entry)`**.
5. Write sinks if a wrapped/short table ever mapped successfully:
   `radeon_gart_bind` → `radeon_gart_set_page` (`radeon_gart.c:305-313`) and the
   `radeon_gart_table_vram_pin` restore loop (`radeon_gart.c:178-179`) iterate to
   `num_gpu_pages-1`.

## Why fail-closed today

The power-of-two constraint makes every accepted `radeon_gart_size` ≥ 2 TiB produce
`table_size == 0` exactly (2^k × 2^11 ≡ 0 mod 2^32 for k ≥ 21). A 0-size table cannot be
usefully mapped: `radeon_bo_create(..., 0, ...)` / `pci_alloc_consistent(..., 0, ...)` give
a zero-page BO or NULL, `radeon_bo_kmap` of 0 pages returns an error or NULL mapping
(`ttm_bo_util.c:599-627`, `ttm_bo_ioremap` returns -ENOMEM when `ioremap` yields NULL), and
gart enable fails → device init fails. No kernel OOB write is constructible from the
tunable alone in this tree; hence Info.

## Fix

`fix.diff` adds the missing invariant check at both allocation sites in
`sys/dev/drm/radeon/radeon_gart.c` (64-bit multiply): reject when the computed
`table_size` cannot hold `num_gpu_pages` entries. This converts any future relaxation of
the validator (e.g. someone "fixing" the power-of-two requirement the way amdgpu's
validator works) from a silent OOB into an -EINVAL at init.

## Fix validation

Not testable on this guest (no radeon hardware; the trigger is additionally a root boot
tunable). Baseline and patched kernels cannot be exercised.

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