vega10_pp_tables_uninitialize leaks 8 subtable allocations (socclk/dcefclk/pixclk/phyclk/dispclk dep tables, pcie_table, valid_socclk_values, valid_dcefclk_values) on every pp_table reload / rebind cycle
Summary
The teardown frees only the 9 original allocations while the parser now kzallocs ~17: 8 subtable allocations are leaked per cycle. Trigger: every pp_table sysfs write (S_IWUSR) and every unbind/rebind - unbounded kernel-heap growth. Nothing else frees them. Add-the-8-kfree-pairs fix (git-apply OK, syntax-validated).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4397 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | β | 1.0 KB | view raw | |
| vega10_processpptables_leakfix.c | β | 46.5 KB | view raw | |
| build_check.sh | β | 717 B | view raw | |
| build.log | β | 382 B | view raw | |
| env.txt | β | 417 B | view raw | |
| README.md | β | 1.8 KB | β raw | |
| VERDICT.md | β | 2.2 KB | β raw | |
| manifest.json | β | 1.1 KB | view raw | |
| verdict.json | β | 2.8 KB | view raw |
DF-4397 β vega10_pp_tables_uninitialize leaks 8 subtable allocations per reload
Severity: Low (root-triggered unbounded kernel-heap growth) | Confidence: certain
What
sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1183-1228:
vega10_pp_tables_uninitialize() frees only 9 of the ~17 allocations
made by vega10_pp_tables_initialize()/init_powerplay_extended_tables()/
init_dpm_2_parameters(). Leaked on every teardown/re-init cycle:
| allocation site | freed? |
|---|---|
| vdd_dep_on_sclk (931-934) | yes |
| vdd_dep_on_mclk (959-962) | yes |
| vdd_dep_on_socclk (926-929) | NO |
| vdd_dep_on_dcefclk (954-957) | NO |
| vdd_dep_on_pixclk (936-940) | NO |
| vdd_dep_on_phyclk (942-946) | NO |
| vdd_dep_on_dispclk (948-952) | NO |
| pcie_table (964-967) | NO |
| valid_socclk_values (986-988) | NO |
| valid_dcefclk_values (1000-1002) | NO |
| valid_sclk_values (993-995) / valid_mclk_values (1007-1009) | yes |
| lookup tables Γ3 (1108-1127) | yes |
| mm_dep_table / tdp_table | yes |
Lifecycle: pp_dpm_set_pp_table (amdgpu_pm.c:676-700, sysfs pp_table,
S_IWUSR) β amd_powerplay_reset β pptable_fini (hwmgr.c:261-281) +
pptable_init β each reload leaks ~8 small allocations (typically a
few hundred bytes to a few KB each, counts are u8-bounded). Rebind/
module reload cycles leak the same. Kernel-heap memory exhaustion over
repeated root-triggered reloads (CWE-401). Upstream later rewrote this
teardown to free everything.
Reproduce / validation
Static source diff (alloc list vs free list) is the proof β see
VERDICT.md. Hardware-gated for runtime (no AMD GPU on the audit guest);
fix.diff adds the 8 missing kfree pairs, git apply --check clean,
and the patched file syntax-validates with 0 errors on the guest
kernel toolchain (build.log).
DF-4397 VERDICT β uninitialize leak
Status: untested (hardware-gated; source-certain) | confidence: certain
Root cause
vega10_pp_tables_uninitialize() (vega10_processpptables.c:1183-1228)
was written against an older version of the parser and never grew with
it. Every table produced by init_powerplay_extended_tables() is
kzalloc'd (vega10_processpptables.c:308, 387, 535, 569, 610, 676, 733,
776, 838) but only the 9 originals are kfree'd:
leaked per cycle: vdd_dep_on_socclk, vdd_dep_on_dcefclk,
vdd_dep_on_pixclk, vdd_dep_on_phyclk, vdd_dep_on_dispclk,
pcie_table, valid_socclk_values, valid_dcefclk_values
(allocated at :926-929, :954-957, :936-940, :942-946, :948-952,
:964-967, :986-988, :1000-1002).
Nothing else frees them: vega10_hwmgr.c's backend teardown frees only
hwmgr->backend and dyn_state.vddc_dep_on_dal_pwrl
(vega10_hwmgr.c:787-790); phm_hwmgr_backend_fini doesn't touch
pptable members.
Trigger cadence
/sys/class/drm/cardN/device/pp_tablewrite (root only, S_IWUSR, amdgpu_pm.c:1007) βpp_dpm_set_pp_table(amdgpu_powerplay.c:676) βamd_powerplay_resetβpptable_fini+pptable_init(hwmgr.c:261-281) β leaks once per write.- GPU unbind/rebind or module reload β leaks once per cycle.
Impact: unbounded kernel heap growth from a privileged trigger; each reload leaks 8 objects (tens of bytes to a few KB each). Low severity (DoS-by-memory-exhaustion needs sustained privileged action), CWE-401.
Verification
Runtime path needs an AMD Vega10 ASIC (absent on the audit guest β no
1002: PCI device, no /dev/dri). Source-certain: the alloc/free set
difference above is mechanical. fix.diff adds the 8 missing
kfree()+NULL pairs, git apply --check clean, and the patched file
compiles with 0 syntax errors on the guest kernel toolchain
(build.log).
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
not_testablenot_testable at runtime (no AMD ASIC on guest); fix.diff compile-validated on the guest kernel toolchain (0 syntax errors).
fix.diff; build.log
Confirmed kernel references
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1183
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:926
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:954
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:964
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:986
- sys/dev/drm/amd/powerplay/hwmgr/vega10_hwmgr.c:787
- sys/dev/drm/amd/powerplay/amd_powerplay.c:676
- sys/dev/drm/amd/amdgpu/amdgpu_pm.c:1007
Detail
Evidence (decisive lines)
VERDICT.md alloc-vs-free table (path:line for all 8 leaked allocations); fix.diff (git apply --check OK); build.log (0 syntax errors, guest kernel toolchain)
PoC changes
authored fresh this run (pass 2); no seed PoC
Verified recommended fix
free the 8 remaining subtable pointers in vega10_pp_tables_uninitialize (fix.diff)
Verdict
Source-certain kernel-heap leak: vega10_pp_tables_uninitialize (vega10_processpptables.c:1183-1228) frees only the original 9 allocations while the parser now creates ~17 β vdd_dep_on_socclk, vdd_dep_on_dcefclk, vdd_dep_on_pixclk, vdd_dep_on_phyclk, vdd_dep_on_dispclk, pcie_table, valid_socclk_values, valid_dcefclk_values (allocated at :926/:954/:936/:942/:948/:964/:986/:1000) are leaked on every teardown/re-init cycle, i.e. once per /sys pp_table write (root, amdgpu_pm.c:1007 -> amd_powerplay.c:676 -> hwmgr.c:261-281) and once per rebind/module-reload. Unbounded kernel-heap growth from a privileged trigger (CWE-401); Low severity. Runtime reproduction hardware-gated (no AMD ASIC on guest); fix.diff adds the 8 missing kfree pairs, git apply --check clean, patched file 0 syntax errors on the guest kernel toolchain.
No comments yet.