psm_fini_power_state_table() leaves hwmgr->boot_ps and hwmgr->uvd_ps dangling into the freed hwmgr->ps allocation (incomplete cleanup; no in-tree reader today)
Summary
fini NULLs request/ps/current but forgets the two interior pointers assigned from the ps array - no in-tree reader exists so latent UAF-shape only. NULL-them-too fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5069 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 999 B | β raw | |
| VERDICT.md | β | 2.6 KB | β raw | |
| fix.diff | β | 370 B | view raw | |
| verdict.json | β | 2.6 KB | view raw | |
| env.txt | β | 1.7 KB | view raw |
DF-5069 β psm_fini_power_state_table() leaves hwmgr->boot_ps / hwmgr->uvd_ps dangling after kfree(hwmgr->ps)
Build
Not buildable/runnable on the audit guest (requires AMD GPU / amdgpu attach β see env.txt; guest has only QEMU std VGA, /dev/dri absent).
Run
N/A β see env.txt.
Expected behavior
psm_fini_power_state_table() (pp_psm.c:94-109) frees hwmgr->ps (:104) and NULLs
request_ps/ps/current_ps (:105-107) but leaves hwmgr->boot_ps and
hwmgr->uvd_ps β assigned at pp_psm.c:79/:87 as pointers into the freed ps
array β dangling. No in-tree reader of hwmgr->boot_ps/hwmgr->uvd_ps exists
today (verified by grep across sys/dev/drm/amd: only the two assignments in
pp_psm.c; the adev->pm.dpm.boot_ps family used by si/ci/kv_dpm.c is a different
struct), so this is a defense-in-depth fix: the first future consumer of these
published pointers would be a use-after-free read.
Fix
Apply fix.diff (NULL both pointers in psm_fini alongside the others).
VERDICT β DF-5069 (pass 2, df-bsd-reviewer)
Status: untested (hardware-gated β requires amdgpu attach; guest has no AMD GPU, see env.txt). Defect existence: certain (dangling assignment is objective). Impact today: none β latent hardening; no in-tree reader of the dangling pointers exists.
Where the defect is (path:line)
sys/dev/drm/amd/powerplay/hwmgr/pp_psm.c:
79: hwmgr->boot_ps = state; /* state walks the hwmgr->ps array */
87: hwmgr->uvd_ps = state;
...
102: kfree(hwmgr->current_ps);
103: kfree(hwmgr->request_ps);
104: kfree(hwmgr->ps); <- the array boot_ps/uvd_ps point into
105: hwmgr->request_ps = NULL;
106: hwmgr->ps = NULL;
107: hwmgr->current_ps = NULL;
boot_ps and uvd_ps are set as interior pointers of the kcalloc(table_entries,
size) allocation made at :53; after psm_fini they reference freed memory while
ps/request_ps/current_ps are properly NULLed. Fields are declared at
inc/hwmgr.h:754-755.
Reachability analysis (why this is Info, not UAF)
grep over sys/dev/drm/amd for boot_ps/uvd_ps:
- only writers: pp_psm.c:79 and pp_psm.c:87 (into struct pp_hwmgr);
- the many other matches (si_dpm.c, ci_dpm.c, kv_dpm.c, amdgpu_pm.c,
amdgpu_dpm.c/h) operate on adev->pm.dpm.boot_ps β a different field of the
legacy dpm manager, never hwmgr->boot_ps.
So no current code dereferences the dangling pointers; the hazard materializes only for future consumers of the (published, header-declared) fields. Classic incomplete-cleanup / CWE-459 shape; fixing costs two lines. (Note: upstream Linux cross-check was attempted but web fetch of the upstream file was unavailable during this run β firecrawl backend refused, git.kernel.org/elixir under an anti-bot gate, raw.githubusercontent 429 β so the finding is argued purely on in-tree evidence.)
Why untested on the guest
pp_psm functions run only after amdgpu attach; guest has no AMD display device (pciconf chip=0x11111234 QEMU std VGA; /dev/dri absent; no drm attach in dmesg β env.txt). No runtime trigger exists; a fix-validation kernel rebuild without the hardware cannot demonstrate anything.
Fix (fix.diff)
hwmgr->request_ps = NULL;
hwmgr->ps = NULL;
hwmgr->current_ps = NULL;
+ hwmgr->boot_ps = NULL;
+ hwmgr->uvd_ps = NULL;
return 0;
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_testableTwo-line NULLing fix, trivially correct by inspection; cannot be boot-validated on the audit guest (path requires an AMD GPU - env.txt).
findings/poc/DF-5069/fix.diff; VERDICT.md fix section.
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (assignments :79/:87 vs fini :102-107, reader-grep proving latency); env.txt (hardware-absence documentation); fix.diff (NULL both pointers in fini).
PoC changes
No PoC exists (latent hardening finding on a hardware-gated path). Evidence pack is analysis-only with hardware-absence documentation.
Verified recommended fix
NULL hwmgr->boot_ps and hwmgr->uvd_ps in psm_fini_power_state_table() alongside request_ps/ps/current_ps (pp_psm.c:105).
Verdict
psm_fini_power_state_table() (sys/dev/drm/amd/powerplay/hwmgr/pp_psm.c:94-109) frees hwmgr->ps at :104 and NULLs request_ps/ps/current_ps (:105-107) but leaves hwmgr->boot_ps and hwmgr->uvd_ps - assigned as interior pointers of that array at pp_psm.c:79/:87, declared at inc/hwmgr.h:754-755 - dangling into freed memory. Grep across sys/dev/drm/amd shows no in-tree reader of hwmgr->boot_ps/hwmgr->uvd_ps (the si/ci/kv/amdgpu_pm boot_ps uses are the separate adev->pm.dpm.boot_ps field), so this is latent incomplete cleanup (CWE-459 shape), not a live UAF. Hardware-gated path (amdgpu attach) absent from the audit guest (QEMU std VGA, /dev/dri absent - env.txt), so no runtime verification is possible. Upstream-Linux cross-reference was attempted but web retrieval was unavailable during this run (firecrawl backend refused; kernel.org/elixir anti-bot gate; raw.github 429); finding argued on in-tree evidence only.
No comments yet.