β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4767

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4767 Β· 4 files
FileTypeDescriptionSize
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

  1. 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 buffer adev->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).
  2. psp_hw_start() (:388) fails (unresponsive PSP / bad SOS fw β€” anything that makes bootloader/ring/TMR/ASD setup return nonzero).
  3. goto failed_mem (:390 β†’ :398) frees ONLY cmd_buf_bo, fence_buf_bo, fw_pri_bo and kfree(psp->cmd) β€” tmr_bo, asd_shared_bo and the ring BO are not freed.
  4. Caller psp_hw_init() (:441-444) sets adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT and returns -EINVAL.
  5. Every later psp_hw_fini() early-returns at :452-453 (load_type != AMDGPU_FW_LOAD_PSP), which is the only place that frees tmr_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.

VERDICT.md
↓ download raw

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_testable
baseline no→ patch + rebuild →patched clean

fix.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.
↓ fix.diffper-fix-DF-4767

Confirmed kernel references

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).