# DF-4576 — amdgpu GEM_VA alloc_pts-before-validate: page-table memory exhaustion

## What it is
`amdgpu_gem_va_ioctl()` (MAP and REPLACE) allocates VM page tables for the
whole attacker-supplied `[va_address, va_address+map_size)` range via
`amdgpu_vm_alloc_pts()` **before** `amdgpu_vm_bo_map()` validates
`offset_in_bo`/`map_size` against the BO. When the validation rejects the
mapping (which the attacker deliberately provokes), the freshly-allocated
page-table BOs are never freed — they stay owned by the per-fd VM until the
DRM fd is closed. One 4 KiB BO + one failed ioctl pins ~(span >> 18) bytes of
GTT/VRAM (128 TiB span → ~512 MiB). Repeat with fresh render-node fds →
GTT/kernel-memory exhaustion → GPU unusable for every process (local,
cross-process DoS by an unprivileged render-node client).

## Files
- `gem_va_pt_exhaust.c` — self-contained PoC (raw ioctls, no libdrm needed)
- `build.sh` / `run.sh` — exact commands
- `build.log` / `run.log` / `env.txt` — guest evidence
- `VERDICT.md` — full analysis narrative + line-level trace
- `fix.diff` — validation-before-allocation patch (NOT applied to sys/)
- `manifest.json` / `verdict.json`

## Build
```
cc -O2 -Wall -o gem_va_pt_exhaust gem_va_pt_exhaust.c
```
(verified to build clean on the DragonFly 6.5-DEVELOPMENT audit guest)

## Run
```
./gem_va_pt_exhaust [iterations] [span_bytes_hex]     # defaults: 64, 0x800000000000 (128 TiB)
```

## Expected output
On real AMD hardware (amdgpu render node present):
- every iteration prints `MAP rejected (Invalid argument) — page tables for
  128.0 TiB of VA now pinned by fd N` — the EINVAL is the *rejection of the
  mapping*; the leak is the already-committed page tables;
- GTT usage grows ~512 MiB per iteration
  (`cat /sys/kernel/debug/dri/<n>/amdgpu_mm_info`);
- after enough iterations: amdgpu allocation failures in dmesg, GPU clients
  fail for all users.

On a machine without an AMD GPU (this audit's QEMU guest: virtio VGA only,
`/dev/dri` absent, amdgpu not even in the guest kernel build):
```
iter 0: cannot open any DRM node (No such file or directory)
  -> no AMD GPU on this machine; PoC needs real amdgpu hardware.
```
exit code 2 — which is what `run.log` records.
