# DF-1254 — vega20 OD8 capability/settings arrays: heap OOB read (LATENT)

## Verdict
**NOT REPRODUCED on the audit guest (LATENT / HW-gated).** The bug is
**confirmed real by source-level trace**; it cannot fire on this guest
because there is no AMD GPU, so the `dev/drm/amd` powerplay/VBIOS-parse
path is dead code at runtime.

## Mechanism (confirmed in source)
- `vega20_processpptables.c:824-846` computes
  `od_feature_count = min(VBIOS.ODFeatureCount, ATOM_VEGA20_ODFEATURE_COUNT)`
  (10) and `od_setting_count = min(VBIOS.ODSettingCount, ATOM_VEGA20_ODSETTING_COUNT)`
  (14).
- `copy_overdrive_feature_capabilities_array` (`vega20_processpptables.c:694`)
  allocates **exactly** `od_feature_count` bytes (`kzalloc(count)`), and
  `phm_copy_overdrive_settings_limits_array` (`smu_helper.c:73`) allocates
  **exactly** `od_setting_count` u32s. So a VBIOS reporting `ODFeatureCount<10`
  or `ODSettingCount<14` yields an **undersized** destination buffer.
- The consumer `vega20_od8_set_feature_capabilities`
  (`vega20_hwmgr.c:906-975`) indexes `od_feature_capabilities[ATOM_VEGA20_ODFEATURE_*]`
  with the **hardcoded** constants 0..9, and `vega20_od8_initialize_default_settings`
  (`vega20_hwmgr.c:1216-1221`) indexes `od_settings_min/max[i]` for
  `i in 0..OD8_SETTING_COUNT`. These constant indices exceed the undersized
  allocation → **heap OOB read** (`kmalloc-16/32` bucket).
- `check_powerplay_tables` (`vega20_processpptables.c:636`) validates **neither**
  count. OOB values surface via `pp_od_clk_voltage` sysfs → heap info leak.
- VBIOS source arrays `ODFeatureCapabilities[32]`, `ODSettingsMax[32]`,
  `ODSettingsMin[32]` (`vega20_pptable.h:80-83`) are declared 32-wide, so the
  *copy* itself never over-reads; only the *destination* is too small.

## Why it does not reproduce here
`pciconf -lv` shows no display/VGA device; the guest has `display none`.
`amdgpu.ko`/`drm.ko` ship in `/boot/kernel/` but are not loaded (no AMD GPU to
probe), and even loaded they would not attach. The vulnerable code runs only
during GPU powerplay init while parsing a real (or crafted) VBIOS. Reaching it
needs a Vega20-class AMD GPU + a crafted powerplay table — neither available.
This is a **valid hard blocker**: the code path is unreachable at runtime on
this guest and no userspace syscall exercises it.

## Exploit chain
N/A — read-only OOB (info leak), and HW-gated (latent). No escalation chain is
developable on this guest. Realistic threat: a malicious/crafted VBIOS on real
AMD hardware (reflashed card or hostile PCIe device) leaking heap bytes.

## PoC changes
`trigger.c` is a documentation stub (the bug path is not a syscall); the real
deliverables are this trace and `fix.diff`.

## Fix (`fix.diff`)
Always allocate the full ATOM_VEGA20 maximum so the consumer's hardcoded
indices cannot run off the end; copy only the VBIOS-declared valid entries
(the rest stay zeroed from `kzalloc`). Concretely:
- `copy_overdrive_feature_capabilities_array`: allocate
  `ATOM_VEGA20_ODFEATURE_MAX_COUNT` (32) instead of `od_feature_count`.
- new `vega20_copy_overdrive_settings_limits_array` (vega20-local) allocates
  `ATOM_VEGA20_ODSETTING_MAX_COUNT` (32) and copies `od_setting_count` entries;
  the two vega20 call sites use it instead of the shared
  `phm_copy_overdrive_settings_limits_array` (which vega12 still uses with its
  own full constant count, unaffected). Applies cleanly (`patch -p1` rc=0).
Supersedes the finding markdown proposal (which had no markdown; this is the
authoritative verified fix).

## Fix validation
`not_testable` — the code path is not reachable on the audit guest, so no PoC
runs before/after. Validated: diff applies cleanly to the read-only `sys/` tree
and is syntactically reviewed; building the amdgpu/powerplay stack is not
warranted for a non-reproducible latent OOB read.
