# DF-4125 verdict — Dangling rdev->pm.dpm.ps after kzalloc-failure kfree in rv6xx_parse_power_table + swallowed rv6xx_dpm_init error -> double free in rv6xx_dpm_fini; ps_priv[0..i-1] leaked

## Reproduced? — inconclusive (none)
Source-certain, hardware-gated (no RV6xx GPU in the guest; OOM-injection at probe not reachable without the hardware — family rows DF-4117/DF-4023/DF-3973 carry the same status). The defect chain is fully traced in VERDICT.md: kfree-without-NULL at :1910, num_ps never assigned at :1928, error propagated to a caller that ignores it (radeon_pm.c:1448), and unconditional kfree of the same pointer in rv6xx_dpm_fini at :2106.

## Root cause (path:line)
rv6xx_parse_power_table() (rv6xx_dpm.c:1908-1912) on inner kzalloc
failure does `kfree(rdev->pm.dpm.ps); return -ENOMEM;` WITHOUT NULLing the
pointer (and leaks the already-allocated ps_priv states 0..i-1;
rdev->pm.dpm.num_ps is never set, so a later fini cannot free them either).
rv6xx_dpm_init propagates the error (:1948-1950) but
radeon_pm_init_dpm() swallows every dpm.init return (radeon_pm.c:1448 bare
statement), so the driver keeps going with rdev->pm.dpm.ps dangling. At
unload/reboot radeon_pm_fini_dpm() calls radeon_dpm_fini()
(radeon_pm.c:1705) -> rv6xx_dpm_fini() -> kfree(rdev->pm.dpm.ps)
(rv6xx_dpm.c:2106) — kfree on the dangling pointer: double free / UAF of the
radeon_ps array. Reachable on the warm path when rv6xx_dpm_enable bails early
(r600_dynamicpm_enabled) or after the DF-4124 NULL-boot_ps panic is otherwise
avoided. rv6xx dispatch instance of the DF-4023/DF-3973/DF-4117 family (last
member).

## Chain
kzalloc failure mid-parse -> kfree(rdev->pm.dpm.ps) not NULLed + ps_priv[0..i-1] leak -> rv6xx_dpm_init returns -ENOMEM -> radeon_pm.c:1448 swallows it -> unload/reboot -> rv6xx_dpm_fini:2106 kfree(dangling) -> double free / UAF

## Kernel refs
- sys/dev/drm/radeon/rv6xx_dpm.c:1908
- sys/dev/drm/radeon/rv6xx_dpm.c:1910
- sys/dev/drm/radeon/rv6xx_dpm.c:1928
- sys/dev/drm/radeon/rv6xx_dpm.c:2106
- sys/dev/drm/radeon/radeon_pm.c:1448
- sys/dev/drm/radeon/radeon_pm.c:1705

## Fix
Two-part fix, family standard: unwind fully on parse failure (free ps_priv states, NULL the array), and stop swallowing dpm.init's return (dpm_failed_unlock must mutex_unlock first — see diff note in VERDICT.md).

fix.diff applies cleanly against the read-only sys/ tree (2-file for DF-4125; note the
radeon_pm.c hunk also needs `dpm_failed_unlock: mutex_unlock(&rdev->pm.mutex);` added to
the existing dpm_failed label path — spelled out here since the label does not exist in
the unfixed tree). Kernel-level fix validation is not possible on this guest (no
i915/RV6xx devices; the drivers never attach in QEMU).

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