# DF-1296 — Unchecked VBIOS UVD/VCE/ACP level counts → heap OOB write past fixed SMC arrays

**File:** `sys/dev/drm/amd/powerplay/smumgr/ci_smumgr.c:1525` (UVD), `:1566` (VCE), `:1598` (ACP)
**Class:** CWE-787 Out-of-bounds Write (heap)
**Severity:** High

## The bug (source-confirmed)

`ci_populate_smc_uvd_level` (`ci_smumgr.c:1516`) populates the SMC DPM table from
the VBIOS UVD clock/voltage table:

```c
table->UvdLevelCount = (uint8_t)(uvd_table->count);          /* :1525 */
for (count = 0; count < table->UvdLevelCount; count++) {     /* :1527 */
    table->UvdLevel[count].VclkFrequency = ...;              /* :1528+ */
    ...
}
```

`UvdLevel` is `SMU7_Discrete_UvdLevel UvdLevel[SMU7_MAX_LEVELS_UVD]` =
`UvdLevel[8]` (`smu7_discrete.h:328`, `SMU7_MAX_LEVELS_UVD = 8`, `smu7.h:45`).
`uvd_table->count` comes straight from the VBIOS power table's `numEntries`
(`processpptables.c:1097` copies it verbatim — a `u8` 0–255 with **no** cap against
`SMU7_MAX_LEVELS_UVD`). `count > 8` therefore writes past `UvdLevel[8]` into the
adjacent DpmTable fields (`VceLevel`, `AcpLevel`, `SamuLevel`, `Ulv`, `Smio[]`, …).

Identical twins: `ci_populate_smc_vce_level` (`:1566`/`VceLevel[8]`) and
`ci_populate_smc_acp_level` (`:1598`/`AcpLevel[8]`). Sibling of DF-1136/1141/1166/
1179/1271/1272 (same unchecked-VBIOS-count class).

## Reachability / threat model

The ci (CIK / Bonaire/Hawaii/Kaveri) powerplay code runs only on AMD Sea Islands
GPUs. The audit QEMU guest has a **QEMU std-vga** (`pciconf vgapci0 chip=0x11111234`),
**not** an AMD GPU, so the path is not runtime-reachable here. On real AMD CIK
hardware, the parse runs during DRM/powerplay init from the on-card VBIOS; a
malicious/corrupt VBIOS (or a crafted VBIOS image on a passed-through GPU) with
`numEntries > 8` triggers the overflow. See `VERDICT.md`.

## Reproduce (harness)

```sh
./build.sh && ./run.sh
```

Decisive output:
```
[DF-1296] attacker VBIOS UVD numEntries=40 (max array=8)
[DF-1296] BUG CONFIRMED: loop wrote UvdLevel[0..39] -> 32 entries (512 bytes) overflow past UvdLevel into VceLevel/AcpLevel/...
[DF-1296] adjacent VceLevel[0] corrupted: YES
```

## Fix

`fix.diff` clamps `UvdLevelCount`/`VceLevelCount`/`AcpLevelCount` to the respective
`SMU7_MAX_LEVELS_*` before the loop. Validated: applies cleanly; `ci_smumgr.c`
compiles under `-Werror` and the full `amdgpu.ko` links in-tree.
