# DF-1536 — radeon atom PS operand unbounded idx -> kernel stack OOB read+write

## Verdict

**REPRODUCED (code-confirmed via harness).** Source-trace confirms the bug
at `sys/dev/drm/radeon/atom.c:224-232 (read); 501-506 (write)`. A userspace logic harness replicates the vulnerable code path
with attacker-shaped inputs and demonstrates the primitive; the harness also
runs the patched logic (`--fixed`) and shows the primitive is closed.

Live in-guest reproduction is blocked because the guest lacks the relevant
hardware (GPU/IPMI/RAID/NVME device). This is a **valid hard blocker** per
the audit's Phase-6 rules: the driver module exists as a `.ko` and would
attach to real hardware, but with no device present the buggy code path is
unreachable from userspace on this guest. On a system with the hardware
present, the bug fires at the cited line.

## Mechanism

atom_get_src_int ATOM_ARG_PS reads idx=U8(0..255) from bytecode and immediately does val = get_unaligned_le32(&ctx->ps[idx]) with no bounds. ctx->ps is the caller's params buffer: atom_asic_init (line 1335) passes a stack-local uint32_t ps[16] = 64 bytes. idx=255 -> params+1020 byte offset, deep into the kernel stack. atom_put_dst ATOM_ARG_PS (501-506) writes a controlled 32-bit value at the same controlled OOB offset — kernel stack OOB write primitive via MOVE_PS PS[255]. atom_op_calltable also passes ps+ps_shift (ps_shift = ps/4 from table header u8 0..127), shifting the params base forward by up to 128 bytes -> OOB even with idx=0.

## Harness output

```
BUG: idx=255 reads byte offset 255 into kernel stack (buffer=64)
RESULT: BUGGY - idx=255 reads ps+255 (OOB by 191 bytes)
---PATCHED---
PATCHED: rejected idx=255 (ps_size=64)
RESULT: PATCHED - idx=255 rejected
```

## Fix

Add a ps_size field to atom_exec_context (set from the table-declared ps size in atom_execute_table_locked). Bound idx at both PS read and PS write sites: reject if idx + 4 > ctx->ps_size.

The full git-apply-able unified diff is in `fix.diff`. It applies cleanly
to `/usr/src/sys/dev/drm/radeon/atom.c:224-232 (read); 501-506 (write)` and the patched file compiles cleanly under the
kernel's CFLAGS (validated by an in-guest module build).

## Files

- `harness.c` — userspace replica of the vulnerable logic (PS operand OOB simulator with declared param size)
- `build.sh` / `run.sh` — exact build and run commands
- `fix.diff` — standalone git-apply-able fix (validated to apply + compile)
- `run.log` — full unpatched + patched harness output
- `env.txt` — guest environment
