# DF-4412 — radeon_vm_get_bos() TOCTOU on vm->max_pde_used → heap OOB write

File: `sys/dev/drm/radeon/radeon_vm.c` (pass 2, GLM 5.3)

## Build

On a DragonFly guest with the kernel source tree:

    cc -O2 -Wall -pthread -o /tmp/trigger_race DF-4412/trigger_race.c
    # radeon_abi.h must sit next to the .c (self-contained UABI definitions)

## Run

    /tmp/trigger_race

**Requires a cayman-or-newer radeon KMS device** (`/dev/dri/card0` with
`vm_manager.enabled`, i.e. Radeon HD 6900 "Cayman" / Trinity / SI / CIK
class). The racy loop retries with a fresh drm fd each round.

## Expected result on capable hardware

Kernel heap corruption: the `list[idx]` writes and the `list_add()` in
`radeon_vm_get_bos()` (radeon_vm.c:149-160) run past the
`kvmalloc_array(vm->max_pde_used + 2, …)` allocation
(radeon_vm.c:135) whenever a concurrent `RADEON_GEM_VA` ioctl on the
same drm fd grows `vm->max_pde_used` between the allocation and the
loop's live re-read of the bound. Expected outcome after enough rounds:
kernel panic / slab corruption, or silent corruption of adjacent heap
objects (each overflow slot writes ~5 kernel pointers and links
`&list[idx].tv.head` into a live list).

## Observed on THIS audit guest

`/dev/dri` does not exist — the QEMU guest has only the std VGA device
(`vgapci0 0x1234:0x1111`), no radeon GPU. The trigger compiles and runs,
and exits at `open("/dev/dri/card0")` with ENOENT. Runtime verification
of the race requires radeon hardware that this guest does not have; the
finding is proven by source trace (see VERDICT.md).
