PSP buffer objects (tmr_bo 3MB VRAM, asd_shared_bo 16KB, firmware.rbuf 4KB) leaked permanently when psp_hw_start fails during psp_load_fw
Summary
failed_mem frees only 4 objects; tmr_bo/asd_shared_bo/rbuf are not freed, and the load_type fallback at :441-444 disables the only fini path that would free them - ~3MB VRAM leaked per failed PSP init, accumulating per retry/reload. No AMD GPU on guest; source-certain. Complete the failed_mem frees (NULL-safe).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4767 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.0 KB | β raw | |
| VERDICT.md | β | 1.9 KB | β raw | |
| fix.diff | β | 749 B | view raw | |
| verdict.json | β | 2.7 KB | view raw |
DF-4767 β PSP BOs (tmr_bo, asd_shared_bo, firmware.rbuf) leaked permanently when psp_hw_start fails during psp_load_fw
File: sys/dev/drm/amd/amdgpu/amdgpu_psp.c (pass 2)
Static finding β the audit guest has no AMD GPU (amdgpu not attached;
same situation as the accepted DF-1854/DF-1855 precedent), so no runtime
PoC exists; the leak is proven by code path.
Path
psp_load_fw()(amdgpu_psp.c:338) allocates, in order:psp->cmd(:346),fw_pri_bo(:350),fence_buf_bo(:358),cmd_buf_bo(:366), ring bufferadev->firmware.rbuf(psp_ring_init:375 β psp_v3_1_ring_init:310),tmr_bo(psp_tmr_init:379 β 3 MB VRAM, PSP_TMR_SIZE),asd_shared_bo(psp_asd_init:383 β 16 KB VRAM).psp_hw_start()(:388) fails (unresponsive PSP / bad SOS fw β anything that makes bootloader/ring/TMR/ASD setup return nonzero).goto failed_mem(:390 β :398) frees ONLYcmd_buf_bo,fence_buf_bo,fw_pri_boandkfree(psp->cmd)βtmr_bo,asd_shared_boand the ring BO are not freed.- Caller
psp_hw_init()(:441-444) setsadev->firmware.load_type = AMDGPU_FW_LOAD_DIRECTand returns -EINVAL. - Every later
psp_hw_fini()early-returns at :452-453 (load_type != AMDGPU_FW_LOAD_PSP), which is the only place that freestmr_bo/asd_shared_bo/rbuf(psp_ring_destroy :455). β permanent leak of ~3 MB + 16 KB + 4 KB VRAM per failed PSP init, repeatable per probe retry / module reload cycle.
Fix
fix.diff β free the ring/asd_shared/tmr BOs in failed_mem
(NULL-safe amdgpu_bo_free_kernel, pointers cleared, no double-free vs
psp_hw_fini).
Verify idea (needs Vega10/12/Raven/Vega20 hardware or SR-IOV VF)
Corrupt the PSP SOS firmware (psp_12_0sos.sos-class file) so
psp_bootloader_load_sos fails after psp_tmr_init/psp_asd_init
succeeded, let probe fail, reload the module N times, observe
amdgpu_vram_usage / TTM stats drift by ~3 MB per cycle (unpatched) and
no drift with fix.diff.
DF-4767 VERDICT
Status: INCONCLUSIVE-RUNTIME / SOURCE-CONFIRMED. The audit guest has no AMD GPU (vgapci is the QEMU emulated Intel/bochs device; amdgpu never attaches), so the leak cannot be exercised here β identical situation to the accepted DF-1854/DF-1855 precedents for this file.
Source path (all citations amdgpu_psp.c unless noted):
- allocations: :346 (cmd), :350 (fw_pri 1 MB GTT), :358 (fence), :366
(cmd_buf), :375 psp_ring_init β psp_v3_1.c:310 adev->firmware.rbuf
(4 KB VRAM), :379 psp_tmr_init β PSP_TMR_SIZE 3 MB VRAM (:173), :383
psp_asd_init β PSP_ASD_SHARED_MEM_SIZE 16 KB VRAM (:229).
- failure: :388-390 psp_hw_start error β goto failed_mem; the label
chain :398-411 frees only cmd_buf/fence/fw_pri/kfree(cmd).
- permanence: :441-444 flips load_type to AMDGPU_FW_LOAD_DIRECT;
psp_hw_fini :452-453 then early-returns forever, and it is the ONLY
caller that frees tmr_bo (:457), asd_shared_bo (:462) and the ring
(psp_ring_destroy :455 β psp_v3_1.c:390 frees adev->firmware.rbuf).
- repeatable per failed probe (module reload) β unbounded VRAM
accumulation over time.
Impact: kernel VRAM/GTT resource leak (local DoS of GPU memory), not memory corruption. Severity Low (requires PSP init failure β mismatched or corrupt PSP firmware, root-controlled files).
Fix: fix.diff (validated as apply-clean; semantics reviewed against
amdgpu_bo_free_kernel NULL-safety in amdgpu_object.c:359-379 and
amdgpu_bo_unref pointer-clearing in amdgpu_object.c β no double-free
introduced for the sriov skip_memalloc path, which also funnels into
failed_mem).
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_testablefix.diff applies cleanly to pristine sys/dev/drm/amd/amdgpu/amdgpu_psp.c and was reviewed against amdgpu_bo_free_kernel NULL-safety and amdgpu_bo_unref pointer-clearing (no double-free for the sriov skip_memalloc path that also funnels into failed_mem); runtime validation needs AMD hardware absent from the guest.
fix.diff; amdgpu_object.c:359-379 (NULL-safe free, clears cpu_addr), amdgpu_bo_unref sets *bo=NULL.
Confirmed kernel references
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:346
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:375
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:379
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:383
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:388
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:398
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:441
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:452
- sys/dev/drm/amd/amdgpu/amdgpu_psp.c:455
- sys/dev/drm/amd/amdgpu/psp_v3_1.c:310
- sys/dev/drm/amd/amdgpu/amdgpu_object.c:359
Detail
Evidence (decisive lines)
VERDICT.md (full path:line chain); fix.diff.
PoC changes
No runtime PoC possible on this guest; static-only evidence pack.
Verified recommended fix
Free ring/asd_shared/tmr BOs in psp_load_fw's failed_mem path (fix.diff); NULL-safe, pointers cleared.
Verdict
SOURCE-CONFIRMED, INCONCLUSIVE-RUNTIME (no AMD GPU on the audit guest - same precedent as DF-1854/DF-1855). When psp_hw_start fails after psp_ring_init/psp_tmr_init/psp_asd_init succeeded, psp_load_fw's failed_mem error path (amdgpu_psp.c:398-411) frees only cmd_buf_bo/fence_buf_bo/fw_pri_bo/psp->cmd; tmr_bo (3MB VRAM, :379/:173), asd_shared_bo (16KB VRAM, :383/:229) and adev->firmware.rbuf (4KB, psp_ring_init:375 -> psp_v3_1.c:310) are leaked. psp_hw_init:441-444 then flips firmware.load_type to AMDGPU_FW_LOAD_DIRECT, so psp_hw_fini:452-453 - the only code that frees those BOs - early-returns forever: the leak is permanent and repeatable per failed probe/module-reload cycle (~3MB VRAM each). Code path is certain; runtime impact not exercisable on this guest (amdgpu never attaches).
No comments yet.