# DF-4338 — atom_index_iio indexes a 10-entry static array with an unvalidated VBIOS byte

**Severity:** Medium **Confidence:** certain **File:** sys/dev/drm/radeon/atom.c:1254-1268

## What

```c
static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };   /* 10 entries */
...
	while (CU8(base) != ATOM_IIO_END)
		base += atom_iio_len[CU8(base)];   /* CU8(base) is 0..255 */
```

The IIO (indirect-I/O) table walker takes its stride from a raw VBIOS byte.
`atom_iio_len` has 10 entries (opcodes `ATOM_IIO_NOP..ATOM_IIO_END`, 0..9);
any opcode byte > 9 reads out of bounds in the kernel `.data` (adjacent
globals), and the garbage stride then walks `base` forward through — and
past — the bios heap allocation with no termination condition other than
stumbling on a byte equal to `ATOM_IIO_END` (9). A crafted IIO table
therefore gives: OOB read of static kernel data + an unbounded OOB walk
(kernel hang at attach while parsing, or page-fault panic).

Reached from `atom_parse()` (atom.c:1309) at driver attach on every ATOM
card; the amdgpu twin has the identical function (`amd/amdgpu/atom.c:1281`).

## Reproduce (logic level; kernel runtime needs ATOM hardware — env.txt)

`atom_harness.c` compiles the verbatim loop with `atom_iio_len` relocated
onto a guard page; the iio case plants opcode 200:

```
cc -O1 -g -o atom_harness atom_harness.c && ./atom_harness iio
# -> Segmentation fault (exit 139)  == atom_iio_len[200] is OOB
```

## Fix

`fix.diff` (git-apply checked): range-check the opcode (`op > ATOM_IIO_END`
→ stop) before indexing. The bios_size bound for the walk itself is part of
DF-4337's central fix.
