# DF-4864 VERDICT — amdgpu_vm_clear_bo() 64-byte IB overrun

**Status: not_reproduced (runtime)** — hardware-gated kernel path; the bug
itself is **code-certain** and its write pattern is demonstrated byte-exactly
by the harness.

## Reproduced?

* **Kernel-side: no — on this guest only because the hardware is absent.**
  The QEMU audit guest has a single Bochs std-VGA (chip 0x11111234, no AMD
  0x1002 device), no /dev/dri or /dev/drm nodes, and no drm/amdgpu modules
  loaded (env.txt). `amdgpu_vm_clear_bo()` is reachable only after amdgpu(4)
  attaches to a real AMD ASIC, and the dual-emit branch needs `CHIP_RAVEN`
  (amdgpu_vm.c:3172: `pte_support_ats = (adev->asic_type == CHIP_RAVEN)`).
* **Source-side: yes, deterministic.** The overrun follows from unambiguous
  constants:
  * allocation: `amdgpu_job_alloc_with_ib(adev, 64, &job)` — amdgpu_vm.c:855
    → `amdgpu_ib_get(..., 64, ...)` (amdgpu_ib.c:61-81) → SA sub-allocation
    of 64 bytes = 16 dwords.
  * emit: two calls through `amdgpu_vm_set_pte_pde` (macro, amdgpu_vm.h:293)
    → `sdma_v4_0_vm_set_pte_pde` emits **10 dwords each**
    (sdma_v4_0.c:1190-1200: header, pe_lo, pe_hi, mask_lo, mask_hi,
    value_lo, value_hi, incr, 0, count-1) — 20 dwords total.
  * pad: `sdma_v4_0_ring_pad_ib` — `(8 - (20 & 7)) % 8` = 4 more dwords
    (sdma_v4_0.c:1214) — **24 dwords total = 96 bytes into 64 bytes**.
  * precondition (both branches): raven rev0/1 root PD = 512 entries with
    ats_entries = 256 / entries = 256 (gmc_v9_0.c:941 → vm 256TB/block 9/3
    levels; amdgpu_vm_num_entries: round_up(2^36,2^27)>>27 = 512;
    AMDGPU_GMC_HOLE_START 2^47 >> (27+12) = 256); raven rev≥2 root PD =
    257 entries with ats 256 / entries 1 (gmc_v9_0.c:945). Verified in-guest
    that host and guest trees agree (amdgpu_vm.c:855 both).
* **Harness-side: yes.** `df4864_trigger` (verbatim emit/pad code against a
  canaried 64-byte buffer) shows 10 → 20 → 24 dwords and 32 destroyed canary
  bytes for both Raven cases, and the exactly-fitting 16-dword result for the
  non-ATS single-packet case (run.log). This is a replica, not the kernel
  executing — hence not_reproduced rather than reproduced.

## Why it is exploitable in the real world (impact ceiling)

1. Unprivileged user opens /dev/drm* on a Raven APU and issues the VM-create
   ioctl family (every GEM VM init → amdgpu_vm_init → amdgpu_vm_clear_bo on
   the root PD, amdgpu_vm.c:3098-3101). No privilege, no races — the overrun
   happens on the very first clear, deterministically.
2. The 64-byte IB is a sub-allocation of the 1MB SA pool
   (AMDGPU_IB_POOL_SIZE(16)*64KB, amdgpu_ib.c:286-289). Overrun bytes corrupt
   the neighbouring SA hole/next IB, or — when the pool is packed to its end,
   groomable by spraying user-sized GFX CS IBs (amdgpu_cs.c:1033-1035) —
   write 32 bytes past the pool's kernel (ttm/vmap) mapping into adjacent
   kernel address space.
3. Written content: second packet's value_hi, incr(0), 0, count-1, four NOP
   headers (0), zeros — partially controllable (VRAM placement of the root PD
   influences value/count fields). Not a free-form write, but a repeatable
   32-byte kernel heap overwrite at attacker-influenced offsets — a genuine
   kernel memory-corruption primitive (GPU command corruption of other
   contexts even in the benign placement case).

Not pushed further (no uid0 chain) because the required hardware is absent:
uid0 escalation would need a Raven APU to groom the SA pool end and shape the
adjacent mapping — out of reach on this QEMU/Bochs guest.

## Fix validation

* `fix.diff` (IB sized 128 bytes = 32 dw ≥ 24 + slack; WARN bound corrected
  from 64-byte/16-dword confusion to 32 dw) applied cleanly to the guest's
  /usr/src (`patch -p1`, hunks at 852/882), and the **full amdgpu.ko module
  rebuilt without warnings under -Werror** (fix_build.log, final
  `cc -r -o amdgpu.ko ... amdgpu_vm.o` link line).
* Runtime baseline/patched comparison impossible on this guest (no AMD GPU),
  so fix_status = not_testable; the fix is compile-validated and the size
  math (128 ≥ 24 dwords used) is provable from the same source constants.
* Guest source tree reverted (`patch -R`, alloc back to 64 at :855) and
  `make clean` run; guest returned via `vm.sh reset with-src`.

## Bottom line

Deterministic 32-byte kernel heap OOB write per GPU-VM create on AMD Raven
APUs (every revision), from an unprivileged DRM client. Fixed by sizing the
clear-IB for two PTE/PDE packets plus padding. Not runtime-reproducible on
this audit guest for absence of AMD hardware; code-certain from source.

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