NULL-pointer dereference of adev->pm.dpm.boot_ps when the VBIOS power table has no ATOM_PPLIB_CLASSIFICATION_BOOT state
Summary
boot_ps is assigned only when a BOOT-classified state exists; ci_dpm_enable -> ci_init_smc_table -> ci_populate_smc_initial_state -> ci_get_ps(NULL) executes rps->ps_priv on NULL and boot_state->performance_levels[0].sclk; ci_update_current_ps(adev, NULL) and ci_dpm_disable hold the same unguarded pointer. Kernel NULL-page fault at driver bind and every resume. PoC walks the exact chain and SIGSEGVs at NULL+offsetof(ps_priv) on the guest. Twin of amdgpu DF-3586 / radeon DF-3610.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3623 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| ci_bootps_null.c | β | 3.1 KB | view raw | |
| build.sh | β | 92 B | view raw | |
| run.sh | β | 116 B | view raw | |
| build.log | β | 353 B | view raw | |
| run.log | β | 353 B | view raw | |
| env.txt | β | 547 B | view raw | |
| VERDICT.md | β | 2.3 KB | β raw | |
| fix.diff | β | 428 B | view raw |
DF-3623 VERDICT β unvalidated boot_ps NULL dereference
Bottom line
Real bug, source-certain; runtime inconclusive (no AMD GPU on guest).
adev->pm.dpm.boot_ps is only ever assigned in
ci_parse_pplib_non_clock_info() (ci_dpm.c:5573-5574) and only when the
VBIOS power table contains a state classified
ATOM_PPLIB_CLASSIFICATION_BOOT. A crafted (or simply malformed) VBIOS
without such a state leaves boot_ps == NULL; nothing between the parser
and the consumer checks it:
ci_dpm_enable()ci_dpm.c:5297 βboot_ps = adev->pm.dpm.boot_ps;(NULL)ci_init_smc_table()ci_dpm.c:3704 βamdgpu_boot_state = boot_ps;then ci_dpm.c:3786ci_populate_smc_initial_state(adev, amdgpu_boot_state)- first dereference:
ci_get_ps()ci_dpm.c:326-331 executesrps->ps_privon the NULL pointer; the second,boot_state->performance_levels[0].sclkat ci_dpm.c:2731 (and .mclk at :2739) - the tail of a successful enable would additionally deref NULL in
ci_update_current_ps(adev, boot_ps)(ci_dpm.c:5412 β 5245-5248:*rpscopies).ci_dpm_disable()has the same unguardedboot_ps(ci_dpm.c:5420/5450).
NULL-page dereference in the device-init kernel thread β panic at driver
bind (and at each resume, since ci_dpm_resume β ci_dpm_enable).
Verification narrative
- Guest lacks any AMD ASIC β the kernel path cannot execute β inconclusive; module presence verified.
ci_bootps_null.cexecuted on the guest walks the exact call chain with a BOOT-less classification and traps SIGSEGV atNULL+offsetof(ps_priv)(run.log) β the userspace image of the kernel NULL-page fault.- Same defect class and fix as the si_dpm twins DF-3586 / DF-3610 (upstream radeon fixed this class by failing init when boot_ps is NULL).
Fix
fix.diff fails ci_dpm_init() with -EINVAL right after
ci_parse_power_table() when no BOOT state was found, preventing the
later dereferences. Not testable on this guest.
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 aborts dpm init cleanly when no BOOT state exists; not testable without AMD hardware.
fix.diff; no AMD ASIC on guest
Confirmed kernel references
Detail
Exploit chain
crafted VBIOS without a BOOT-classified state -> NULL deref in device-init kernel thread -> panic (DoS). No memory-corruption path.
Evidence (decisive lines)
run.log shows boot_ps=0x0 and the SIGSEGV at NULL+40 with the traced ci_dpm.c line sequence; build.log clean.
PoC changes
authored from scratch
Verified recommended fix
After ci_parse_power_table() in ci_dpm_init(), fail with -EINVAL when adev->pm.dpm.boot_ps is NULL (see fix.diff).
Verdict
Source-certain NULL-pointer dereference: with no ATOM_PPLIB_CLASSIFICATION_BOOT state in the VBIOS power table, adev->pm.dpm.boot_ps stays NULL (only assigned at ci_dpm.c:5573-5574) and is dereferenced by ci_get_ps (rps->ps_priv, ci_dpm.c:328) via ci_populate_smc_initial_state (ci_dpm.c:3786, reached from ci_dpm_enable:5297 -> ci_init_smc_table:3704), then again at boot_state->performance_levels[0].sclk (ci_dpm.c:2731) β kernel NULL-page fault/panic at driver bind and on every resume; ci_update_current_ps (ci_dpm.c:5412) and ci_dpm_disable (ci_dpm.c:5450) hold the same unguarded boot_ps. Runtime inconclusive: guest has no AMD ASIC; the exact chain demonstrated on the guest by ci_bootps_null.c (SIGSEGV at NULL+offsetof(ps_priv)).
No comments yet.