# DF-1257 — amdgpu_vm_bo_map offset+size integer overflow -> OOB

## Verdict (one line)
**CONFIRMED REAL (source trace + harness primitive), NOT reproduced on audit guest (no AMD GPU / no amdgpu).**

## Finding
`sys/dev/drm/amd/amdgpu/amdgpu_vm.c:amdgpu_vm_bo_map()` (and
`amdgpu_vm_bo_replace_map()`) validate the BO mapping with
`offset + size > amdgpu_bo_size(bo)` in `uint64`. The addition wraps, so a
huge page-aligned `offset` near `UINT64_MAX` plus a small `size` passes the
check and a wrapped `mapping->offset` is stored. The later page-table walk
computes `pfn = mapping->offset >> PAGE_SHIFT` ≈ 2^52 and indexes
`pages_addr[pfn]` — a massive out-of-bounds read.

## Mechanism (path:line)
1. `amdgpu_vm.c:2504-2506` — alignment/size gates pass for
   `offset=0xFFFFFFFFFFFFF000, size=0x2000` (both page-aligned, size≠0).
2. `amdgpu_vm.c:2511` — `if (... || (bo && offset + size > amdgpu_bo_size(bo)))`
   `0xFFFFFFFFFFFFF000 + 0x2000` wraps to `0x1000` ≤ a 0x2000 BO ⇒ **passes**.
3. `amdgpu_vm.c:2532` — `mapping->offset = offset;` stores the huge value.
4. `amdgpu_vm.c:2576` — `amdgpu_vm_bo_replace_map` has the identical bug.
5. `amdgpu_vm.c:1988` — `pfn = mapping->offset >> PAGE_SHIFT;` ⇒ `0x000FFFFFFFFFFFFF`.
6. `amdgpu_vm.c:2028` — `addr = pages_addr[pfn];` ⇒ OOB read ~2^52 elements.
   (also `amdgpu_vm.c:2019` `pages_addr[idx]`.)

## Why not reproduced on the audit guest
`amdgpu` is a loadable DRM module, **not in GENERIC**, and the QEMU/KVM
guest has **no AMD GPU** (no `/dev/dri/renderD128`). The mapping ioctl is
reached only after an amdgpu device attaches. The realistic trigger is an
unprivileged local user on a machine with an AMD GPU issuing the AMDGPU_VM
ioctl with the wrapped offset — a legitimate local kernel-OOB threat on
such hardware, not exercisable here.

## Primitive proof (harness)
`harness.c` replicates the bounds check and the pfn computation exactly:
```
alignment gate (amdgpu_vm.c:2504): PASS
offset + size (uint64) = 0x0000000000001000   (wrapped!)
bounds check (amdgpu_vm.c:2511) result: ACCEPT (bug)
pfn = mapping->offset >> 12 = 0x000fffffffffffff
pages_addr[pfn] would read at index 0x000fffffffffffff -> MASSIVE OOB read
PRIMITIVE CONFIRMED: wrapped offset+size passes the bounds check; stored offset
yields pfn ~ 2^52 -> OOB read in pages_addr[]. Bug is REAL.
```

## Fix
`fix.diff` rewrites both checks (`amdgpu_vm.c:2511` and `:2576`) to avoid
the overflowing addition: with `__bo_sz = amdgpu_bo_size(bo)`, reject if
`size > __bo_sz || offset > __bo_sz - size`. **Validated: builds cleanly
into `amdgpu.ko` with `-Werror`.**

## Reproduce
```
ssh dfbsd-maxx; cd poc/DF-1257 && cc -O2 -Wall -o harness harness.c && ./harness
```
