Heap OOB read in vega10_get_soc_index_for_max_uclk: hardcoded entries[3] without count check
Summary
vega10_get_soc_index_for_max_uclk at :3444-3453: indexes vdd_dep_on_mclk->entries[NUM_UCLK_DPM_LEVELS-1=3] unconditionally. Table allocated for ucNumEntries slots (from VBIOS u8). If ucNumEntries<4: OOB read. Reached when mem_boot_level==3 in vega10_upload_dpm_bootup_level. Fix: validate count>=NUM_UCLK_DPM_LEVELS before indexing.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1183 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | userspace transcription of vega10_get_soc_index_for_max_uclk showing buggy and fixed behavior | 2.8 KB | view raw |
| build.sh | build-script | cc -O2 -o harness harness.c | 101 B | view raw |
| run.sh | run-script | ./harness | 67 B | view raw |
| README.md | readme | human-readable summary + reproduce | 2.2 KB | β raw |
| VERDICT.md | verdict | detailed mechanism, source trace, why-not-reproduced; upgrades confidence from likely to certain | 2.1 KB | β raw |
| fix.diff | suggested-fix | add count >= NUM_UCLK_DPM_LEVELS + NULL check before indexing entries[NUM_UCLK_DPM_LEVELS-1] | 571 B | view raw |
| run.log | run-log | harness stdout showing buggy returns garbage (1), fixed returns 0 | 502 B | view raw |
| fix_build.log | fix-build-log | nativekernel build log showing vega10_hwmgr.c compiles cleanly with fix applied (rc=0, -Werror) | 5.6 MB | β download |
| fix_run.log | fix-run-log | harness on patched kernel (no regression) | 121 B | view raw |
| env.txt | environment | uname, cc version, pciconf | 947 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
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:
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:
// 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:
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
amdgpupowerplay 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 isPR: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.
DF-1183 β VERDICT
Status: NOT REPRODUCED (HW-gated; bug confirmed in source)
Impact: none (cannot trigger on this guest)
Confidence: certain (line-by-line source trace; finding markdown said
likely, I confirm certain β the indexing is unconditional, no guard
upstream)
Class: heap OOB read (CWE-125) β latent
Mechanism (cited)
vega10_hwmgr.c:3444-3453:
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 (smu9_driver_if.h:41). The function
unconditionally dereferences entries[3] regardless of how many entries
the table actually holds. The table is sized from the VBIOS-supplied
ucNumEntries (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. The returned value is then sent to the SMC firmware as a
PPSMC_MSG_SetSoftMinSocclkByIndex parameter at vega10_hwmgr.c:3478,
so corrupted heap bytes also reach the GPU's microcontroller.
Why it cannot be reproduced on this guest
- No AMD GPU on the PCI bus;
amdgpu/powerplaynot in GENERIC. - The MCLK table is parsed from device firmware at attach time, so even
with hardware the trigger requires a malicious VBIOS (
PR:H).
Latent / hardware-gated bug; confirmed real by source trace,
unreachable on the audit guest. harness.c transcribes the function
into userspace, runs both buggy and fixed versions, and prints the
result; no kernel effect.
Fix
fix.diff validates vdd_dep_on_mclk->count >= NUM_UCLK_DPM_LEVELS
(and != NULL) before indexing entries[3]. Validated as applies +
compiles only β fix_status: not_testable.
Fix verification
not_testablecompile+harness validated
kernel build rc=0 + harness
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source+harness. vega10_get_soc_index hardcoded [3] vs ucNumEntries<4 -> heap OOB read. amdgpu not in GENERIC.
No comments yet.