NULL-pointer dereference of rdev->pm.dpm.boot_ps when the VBIOS power table has no ATOM_PPLIB_CLASSIFICATION_BOOT state
Summary
boot_ps is assigned only when a parsed state carries the BOOT classification; a crafted VBIOS without one leaves it NULL, and ci_init_smc_table -> ci_populate_smc_initial_state -> ci_get_ps (rps->ps_priv) derefs NULL; ci_dpm_enable and radeon_pm.c:1449 likewise. Boot-time panic (twin of DF-3586/DF-3610/DF-3623).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3646 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | doc | 613 B | β raw | |
| VERDICT.md | doc | 2.7 KB | β raw | |
| fix.diff | doc | 702 B | view raw | |
| env.txt | doc | 799 B | view raw | |
| verdict.json | doc | 3.0 KB | view raw | |
| manifest.json | doc | 1.0 KB | view raw |
DF-3646 β NULL-pointer dereference of rdev->pm.dpm.boot_ps when the VBIOS power table has no ATOM_PPLIB_CLASSIFICATION_BOOT state
File: sys/dev/drm/radeon/ci_dpm.c (pass 2, GLM 5.3 re-audit)
Severity: Medium | CWE-476 NULL Pointer Dereference | confidence: certain
Reproduce
No harness: the defect is a NULL/UAF control-flow property (source-level certainty); the kernel path needs CI-class hardware absent from the guest β see env.txt.
(source review only; see VERDICT.md)
Full narrative: VERDICT.md. Proposed fix: fix.diff (authored against the read-only sys/ tree; never applied there).
DF-3646 β verdict narrative
Finding
NULL-pointer dereference of rdev->pm.dpm.boot_ps when the VBIOS power table has no ATOM_PPLIB_CLASSIFICATION_BOOT state
Kernel references
sys/dev/drm/radeon/ci_dpm.c:5500sys/dev/drm/radeon/ci_dpm.c:3593sys/dev/drm/radeon/ci_dpm.c:3675sys/dev/drm/radeon/ci_dpm.c:2623sys/dev/drm/radeon/ci_dpm.c:2629sys/dev/drm/radeon/ci_dpm.c:5200sys/dev/drm/radeon/ci_dpm.c:5317sys/dev/drm/radeon/radeon_pm.c:1449
Was it reproduced?
No β not on the kernel path. The audit guest is virtio-only (0 AMD PCI devices, /dev/dri absent, no radeon/drm kld; env.txt), so sys/dev/drm/radeon/ci_dpm.c can never execute there. Per the pass-2 instruction for this hardware-gated file, the verdict is inconclusive (source-level certainty certain) rather than reproduced.
Root cause and reasoning
Source-certain NULL deref, radeon/ci twin of DF-3586 (amdgpu kv/ci), DF-3610 (radeon si), DF-3623 (amdgpu ci). rdev->pm.dpm.boot_ps is assigned in exactly one place: ci_parse_pplib_non_clock_info (ci_dpm.c:5500-5501), only when some parsed power state has ATOM_PPLIB_CLASSIFICATION_BOOT set in its VBIOS classification flags. A crafted VBIOS whose state array omits that flag leaves boot_ps NULL; nothing else initializes it (grep across sys/dev/drm/radeon: only the per-asic parse functions set it). radeon_pm_init_dpm then stores NULL into current_ps/requested_ps (radeon_pm.c:1449) and ci_dpm_enable -> ci_init_smc_table takes radeon_boot_state = rdev->pm.dpm.boot_ps (ci_dpm.c:3593) and passes it to ci_populate_smc_initial_state (3675), whose first act is ci_get_ps(rps): return rps->ps_priv (ci_dpm.c:197) - a read at NULL+offsetof(ps_priv) - followed by boot_state->performance_levels[0].sclk (2629). ci_dpm_enable's own ci_update_current_ps(rdev, boot_ps) at 5317 would copy *rps from NULL as well. Boot-time kernel panic (NULL-page fault). Upstream Linux master is identical (verified against torvalds/linux ci_dpm.c). Not runtime-reproducible on this virtio-only guest.
Exploitability
Crafted VBIOS on a CI-class card without any BOOT-classified power state -> NULL-page kernel read at driver load -> panic. Pure DoS; no control over the dereference contents. (Hardware-gated; no kernel PoC possible on this guest.)
Recommended fix
Reject a NULL boot_ps early: return -EINVAL from ci_init_smc_table and ci_dpm_enable when rdev->pm.dpm.boot_ps is unset. See fix.diff.
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 validation would require a CI-class GPU with a crafted VBIOS (baseline panic/corruption) and a single-fix kernel build; the audit guest is virtio-only, so the fix is source-reviewed only (fix.diff).
fix.diff in this pack; not applied to sys/ (read-only audit target).
Confirmed kernel references
Detail
Exploit chain
Crafted VBIOS on a CI-class card without any BOOT-classified power state -> NULL-page kernel read at driver load -> panic. Pure DoS; no control over the dereference contents. (Hardware-gated; no kernel PoC possible on this guest.)
Evidence (decisive lines)
VERDICT.md (full source trace); env.txt (guest has no AMD GPU: pciconf 0x1002 count=0, /dev/dri absent, no drm kld); fix.diff
PoC changes
n/a β no seeded PoC; source-trace only
Verified recommended fix
Reject a NULL boot_ps early: return -EINVAL from ci_init_smc_table and ci_dpm_enable when rdev->pm.dpm.boot_ps is unset.
Verdict
Source-certain NULL deref, radeon/ci twin of DF-3586 (amdgpu kv/ci), DF-3610 (radeon si), DF-3623 (amdgpu ci). rdev->pm.dpm.boot_ps is assigned in exactly one place: ci_parse_pplib_non_clock_info (ci_dpm.c:5500-5501), only when some parsed power state has ATOM_PPLIB_CLASSIFICATION_BOOT set in its VBIOS classification flags. A crafted VBIOS whose state array omits that flag leaves boot_ps NULL; nothing else initializes it (grep across sys/dev/drm/radeon: only the per-asic parse functions set it). radeon_pm_init_dpm then stores NULL into current_ps/requested_ps (radeon_pm.c:1449) and ci_dpm_enable -> ci_init_smc_table takes radeon_boot_state = rdev->pm.dpm.boot_ps (ci_dpm.c:3593) and passes it to ci_populate_smc_initial_state (3675), whose first act is ci_get_ps(rps): return rps->ps_priv (ci_dpm.c:197) - a read at NULL+offsetof(ps_priv) - followed by boot_state->performance_levels[0].sclk (2629). ci_dpm_enable's own ci_update_current_ps(rdev, boot_ps) at 5317 would copy *rps from NULL as well. Boot-time kernel panic (NULL-page fault). Upstream Linux master is identical (verified against torvalds/linux ci_dpm.c). Not runtime-reproducible on this virtio-only guest.
No comments yet.