OOB stack read in bw_calcs_data_update_from_pplib when powerplay returns zero clock levels (sibling of DF-1549)
- File:
sys/dev/drm/amd/display/dc/dce112/dce112_resource.c - Lines: 1005, 1033, 1041, 1074
- Severity: Low
- CVSS:
CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U:C:N/I:N/A:H - CWE: CWE-129 Improper Validation of Array Index
- Confidence: likely
Summary
bw_calcs_data_update_from_pplib() indexes clocks_in_khz/eng_clks.data/
mem_clks.data at [num_levels-1] without first checking that num_levels > 0.
The powerplay providers (dm_pp_get_clock_levels_by_type at amdgpu_dm_pp_smu.c:296
and dm_pp_get_clock_levels_by_type_with_latency at amdgpu_dm_pp_smu.c:368)
unconditionally return success and leave num_levels==0 when
adev->powerplay.pp_funcs is NULL or its get_clock_by_type[_with_latency] hook
is missing or returns 0 levels.
Because num_levels is uint32_t, 0-1 wraps to 0xFFFFFFFF and the dereference
faults ~16 GB past the stack object β deterministic kernel panic at driver init.
The same bug class was filed as DF-1549 against dce110_resource.c; the sibling
dce120_resource.c was patched upstream with explicit num_levels==0 guards at
lines 789 and 822, but dce112_resource.c was left unfixed.
Root cause
Four unguarded sinks, all reached only from construct() at
dce112_resource.c:1334, which runs once at GPU/driver init via
dce112_create_resource_pool() (line 1353) β dc_create_resource_pool()
(dc_resource.c:135) for DCE_VERSION_11_2 / 11_22 (Polaris10/11/12):
-
dce112_resource.c:1004-1005 β fallback
ENGINE_CLKpath (taken whendm_pp_get_clock_levels_by_type_with_latencyreturned false at line 993).dm_pp_get_clock_levels_by_typealways returns true; whenpp_funcsorpp_funcs->get_clock_by_typeis NULL,num_levels=0, andclks.clocks_in_khz[clks.num_levels-1]=clks.clocks_in_khz[(uint32_t)0-1]is a wild read. -
dce112_resource.c:1032-1034 β fallback
MEMORY_CLKpath. Sameclks.clocks_in_khz[clks.num_levels-1]pattern. -
dce112_resource.c:1040-1041 β primary
ENGINE_CLKpath.eng_clks.data[eng_clks.num_levels-1].clocks_in_khzβ if the SMU returned 0 levels. -
dce112_resource.c:1073-1074 β primary
MEMORY_CLKpath, the most reliable sink: the return value ofdm_pp_get_clock_levels_by_type_with_latencyat line 1058-1061 is IGNORED entirely, so wheneverpp_funcsorget_clock_by_type_with_latencyis NULL (returns false)mem_clksstays zero-initialized withnum_levels==0andmem_clks.data[mem_clks.num_levels-1].clocks_in_khzunconditionally OOBs.
num_levels is uint32_t (dm_services_types.h:90,100).
0-1 wraps to 0xFFFFFFFF.
data[]/clocks_in_khz[] arrays are sized DM_PP_MAX_CLOCK_LEVELS=8
(dm_services_types.h:87).
The dereference lands at &clks + 0xFFFFFFFF*sizeof(uint32_t) β 16 GB, unmapped β
fatal page fault.
Threat
Attacker position: a malicious, malfunctioning, or hot-plugged PCI/Thunderbolt/
USB4 AMD Polaris10/Polaris11/Polaris12 GPU whose powerplay subsystem registers a
NULL pp_funcs, a pp_funcs missing get_clock_by_type or
get_clock_by_type_with_latency, or a powerplay firmware that returns success
with zero clock levels.
No unprivileged-local or unauthenticated-remote path: runs only once at amdgpu driver load or AMD GPU hot-plug.
Impact: deterministic kernel panic (wild read into unmapped address space) β local Denial of Service at GPU init. No info leak and no code execution.
Recommended fix
Mirror the upstream-verified dce120_resource.c:786-835 fix: guard every
*_levels == 0 case with a safe-default fallback before any [num_levels-1]
indexing.
Minimal patch covering the most reliable sink (MEMORY_CLK primary):
--- a/sys/dev/drm/amd/display/dc/dce112/dce112_resource.c
+++ b/sys/dev/drm/amd/display/dc/dce112/dce112_resource.c
@@ -1056,6 +1056,12 @@ static void bw_calcs_data_update_from_pplib(struct dc *dc)
dm_pp_get_clock_levels_by_type_with_latency(
dc->ctx,
DM_PP_CLOCK_TYPE_MEMORY_CLK,
&mem_clks);
+ if (mem_clks.num_levels == 0) {
+ mem_clks.data[0].clocks_in_khz = 250000;
+ mem_clks.data[1].clocks_in_khz = 750000;
+ mem_clks.num_levels = 2;
+ }
/* we don't need to call PPLIB for validation clock since they
Apply the identical if (num_levels == 0) { ... num_levels = 2; } pattern at the
other three sinks (lines 1004-1005, 1032-1034, 1040-1041).
Better still β push the floor into the providers themselves: in
amdgpu_dm_pp_smu.c, after pp_to_dc_clock_levels() (line 316) and
pp_to_dc_clock_levels_with_latency() (line 386), call
get_default_clock_levels(...) when num_levels comes back 0. That single change
closes this bug class across dce110, dce112, and any future caller.
Related findings
- DF-1549 (twin, dce110_resource.c): same defect.
- DF-1486 (twin, dcn_calcs.c):
fclks.data[-1]OOB read.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1568 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix for the cited bug | 554 B | view raw |
| VERDICT.md | verdict | source-confirmation analysis | 733 B | β raw |
| build.sh | build-script | N/A (source-only) | 61 B | view raw |
| run.sh | run-script | N/A (source-only) | 87 B | view raw |
DF-1568 VERDICT
Verdict: REPRODUCED (source-confirmed)
Impact: Low (driver-level NULL deref / OOB / leak / DoS β hardware-gated)
Mechanism: dce112_resource.c:1004-1005 (fallback ENGINE_CLK clks.clocks_in_khz[num_levels-1]), 1032-1034 (fallback MEMORY_CLK), 1040-1041 (primary ENGINE_CLK eng_clks.data[num_levels-1]), 1073-1074 (primary MEMO
Citation: sys/dev/drm/amd/display/dc/dce112/dce112_resource.c:1005-1074
Fix: Applied fix.diff β compiles in batch kernel build (rc=0, -Werror).
Verification method: Source-only line-by-line trace of cited path:line. Low-severity driver bug; PoC trigger requires specific hardware or root context. Confirmed the cited vulnerable pattern exists in source.
Fix verification
fixedfix.diff compiled in batch kernel build rc=0 -Werror
fix.diff compiled in batch kernel build rc=0 -Werror
Confirmed kernel references
β
Detail
Exploit chain
none (Low severity)
Evidence (decisive lines)
Source-confirmed: num_levels-1 underflow OOB when 0 (dce112_resource.c:1004-1074)
Verified recommended fix
Source-confirmed: num_levels-1 underflow OOB when 0 (dce112_resource.c:1004-1074)
Verdict
Source-confirmed: num_levels-1 underflow OOB when 0 (dce112_resource.c:1004-1074)
No comments yet.