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 | 1.1 KB | β raw |
| build.sh | build-script | N/A (source-only) | 65 B | view raw |
| run.sh | run-script | N/A (source-only) | 89 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 status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
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.