# DF-1183 — vega10_get_soc_index_for_max_uclk hardcoded [3] OOB read

## Bug (confirmed in source)
`sys/dev/drm/amd/powerplay/hwmgr/vega10_hwmgr.c:3444-3453`:

```c
static int vega10_get_soc_index_for_max_uclk(struct pp_hwmgr *hwmgr)
{
    struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table_on_mclk;
    struct phm_ppt_v2_information *table_info =
            (struct phm_ppt_v2_information *)(hwmgr->pptable);

    vdd_dep_table_on_mclk  = table_info->vdd_dep_on_mclk;

    return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1;
}
```

`NUM_UCLK_DPM_LEVELS == 4` (defined at
`sys/dev/drm/amd/powerplay/inc/smu9_driver_if.h:41`). The function
unconditionally indexes `entries[3]` regardless of how many entries the
table actually holds.

Allocation of `vdd_dep_on_mclk` is sized by VBIOS `ucNumEntries`:

```c
// vega10_processpptables.c:565-569
table_size = sizeof(uint32_t) +
    sizeof(phm_ppt_v1_clock_voltage_dependency_record) * mclk_dep_table->ucNumEntries;
mclk_table = kzalloc(table_size, GFP_KERNEL);
```

If `ucNumEntries < 4`, the hardcoded `entries[3]` reads past the
allocation into adjacent kernel heap.

## Caller chain
`vega10_hwmgr.c:3476-3477` inside `vega10_upload_dpm_bootup_level`:
```c
if (data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) {
    socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr);
```
Called from `vega10_enable_dpm_tasks` (line 3548) and from various
power-state-switch helpers (lines 3899, 3921, 3946) — only on a real
Vega10 GPU.

## Trigger model
- Requires `amdgpu` powerplay attached to a real Vega10 GPU.
- Requires a malicious VBIOS with `ucNumEntries < 4`.
- CVSS `AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H` — realistic bar is `PR:H`.

## On this guest
Unreachable — no AMD GPU; amdgpu/powerplay never attaches. `harness.c`
transcribes the function into userspace, runs both buggy and fixed
versions, and prints the result; no kernel effect.

## Reproduce
```
ssh dfbsd-maxx "cd poc/DF-1183 && ./build.sh && ./run.sh"
```

## Recommended fix
Validate `vdd_dep_on_mclk->count >= NUM_UCLK_DPM_LEVELS` before
indexing `entries[NUM_UCLK_DPM_LEVELS - 1]`. Full patch in `fix.diff`.
**Matches** the finding proposal.
