DF-3953 / verdict.json
{ "finding_id": "DF-3953", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-certain NULL-pointer dereference (radeon-kv boot_ps family; amdgpu twin is DF-3889). kv_parse_pplib_non_clock_info (kv_dpm.c:2598-2601) only assigns rdev->pm.dpm.boot_ps for an ATOM_PPLIB_CLASSIFICATION_BOOT state; nothing validates one exists, and radeon_pm.c:1448 DISCARDS kv_dpm_init()s return value so DPM is enabled regardless. kv_dpm_enable (:1277) and kv_dpm_disable (:1326, suspend radeon_pm.c:1260 / fini radeon_pm.c:1694 / resume radeon_pm.c:1321-1322) call kv_update_current_ps(rdev, NULL) -> kv_get_ps(NULL) (:239-244) reads rps->ps_priv at NULL+64 -> page fault -> panic. Additional sink: kv_dpm_get_sclk (:2881) dereferences pi->requested_rps.ps_priv which stays NULL when radeon_dpm_pick_power_state returned NULL (radeon_pm.c:1051) and compute_clocks bailed (:1075-1078); next dce8_bandwidth_update (cik.c:9287/9327) faults. Harness executes the verbatim NULL+64 deref in children -> SIGSEGV sig=11 both sinks (kernel equivalent: panic). Runtime-inconclusive on this guest: virtio VGA only, no radeon hardware.", "exploit_chain": "crafted-VBIOS power table without BOOT classification -> DPM enabled with boot_ps==NULL -> boot/suspend/resume/detach -> kv_update_current_ps(NULL) -> NULL+64 page fault -> panic (DoS). No uid0 path: NULL-page read only, value never used as write target.", "evidence": "run.log: offsetof(struct radeon_ps, ps_priv) = 64, child1 ... SIGNALLED sig=11, child2 (kv_dpm_get_sclk :2881): SIGNALLED sig=11, RESULT: BOTH SINKS FAULT AS PREDICTED (rc=0); VERDICT.md traces every hop; fix.diff", "kernel_refs": [ "sys/dev/drm/radeon/kv_dpm.c:1277", "sys/dev/drm/radeon/kv_dpm.c:1326", "sys/dev/drm/radeon/kv_dpm.c:239", "sys/dev/drm/radeon/kv_dpm.c:2881", "sys/dev/drm/radeon/kv_dpm.c:2598", "sys/dev/drm/radeon/radeon_pm.c:1448", "sys/dev/drm/radeon/radeon_pm.c:1051", "sys/dev/drm/radeon/cik.c:9287" ], "poc_changes": "No seed (pass-2 self-authored). Two fix cycles: nested comment broke the first build; first crash run had child1s fault optimized away (dead store) - made the loaded pointer volatile so the faulting load is observable.", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 150, "guest_dirty": 0, "build_cmd": "cd /tmp/df395x && cc -O2 -Wall -o trigger_df3953 trigger_df3953.c", "run_cmd": "cd /tmp/df395x && ./trigger_df3953 && ./trigger_df3953 crash", "code_hash": "537ebc2dae1065d5cd007d3acdf6796deb56f3d1b9eaf39b7f19743e4199aeab", "notes": "Guest virtio-only (no AMD GPU); verdict per DF-3889/3890/3891 precedent (inconclusive + certain source). Family: DF-3586 (si_dpm), DF-3623 (ci_dpm), DF-3754 (ni_dpm), DF-3889 (amdgpu kv_dpm). Distinct from pass-1 DF-1305/1306/1307 (different indices/sinks). radeon_pm.c:1448 error-swallow is the enabler and also feeds DF-3955.", "recommended_fix": "Guard boot_ps in kv_dpm_enable/kv_dpm_disable and NULL-check requested_state in kv_dpm_get_sclk (fix.diff); additionally honor kv_dpm_init()s return value at radeon_pm.c:1448.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored against the read-only sys/ tree after source+harness verification; not built - no AMD hardware on the guest.", "fix_evidence": "findings/poc/DF-3953/fix.diff" } |