DF-4162 / verdict.json
{ "finding_id": "DF-4162", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-level certain, runtime hardware-gated (inconclusive per family convention). radeon_pm_init_dpm calls the asic init as a void statement -- radeon_dpm_init(rdev); at radeon_pm.c:1448, macro radeon.h:2793 expands to rdev->asic->dpm.init((rdev)) returning int -- discarding the error upstream honors (ret = radeon_dpm_init(rdev); if (ret) goto dpm_failed;). Verified failure semantics: (a) parse errors return -EINVAL/-ENOMEM (swallowed here); (b) a VBIOS table with no BOOT-classified state returns 0 with boot_ps NULL because boot_ps is only assigned inside the per-state loops (rv770_dpm.c:2172, rv6xx_dpm.c:1811, trinity_dpm.c:1705, si_dpm.c:6727) and NO dispatch init validates it. With the error dropped, :1449 publishes current_ps=requested_ps=boot_ps (NULL/dangling), :1452-1453 run setup_asic+enable whose per-asic bodies deref boot_ps (rv770_dpm.c:1901, rv6xx_dpm.c:1577, btc/trinity/cypress twins = DF-4022/4118/4124/4143/3972 attach panics); the dangling ps survives into radeon_dpm_fini at unload (DF-4117/4125/4144 double frees); suspend/resume/fini-disable re-deref boot_ps (:1262/:1320/:1694) because pm_method stays PM_METHOD_DPM -- the second swallow layer being the asic *_init files calling radeon_pm_init(rdev); as a statement (si.c:6874, ni.c:2432, cik.c:8653, evergreen.c:5235, rv770.c:1962, r600.c:3321). Central fix (fix.diff, one file, covers all six dispatch files): honor the return; explicit if (!rdev->pm.dpm.boot_ps) goto dpm_init_failed gate (closes case (b) which the return alone does not -- rv7xx_parse_power_table returns 0 with boot_ps unset, rv770_dpm.c:2271-2329); scrub ps/boot_ps/current_ps/num_ps on init failure so dpm_fini cannot double-free; gate suspend_dpm/resume_dpm/finis radeon_dpm_disable on boot_ps. Assessment: applying it makes the six family enable-side NULL-boot_ps panics unreachable at boot AND at suspend/resume/unload-disable, and neutralizes the ps double-frees; residual per-asic ext-table double-frees still need the already-filed dispatch fixes. Guest: virtio VGA only, zero 0x1002 devices, hw.drm unknown (env.txt) -> not runtime-testable.", "exploit_chain": "On radeon hardware: crafted/reflash VBIOS PowerPlayInfo without BOOT state (passthrough/hotplug) -> drm attach panics (family signature) or unload double-free. No write primitive controlled by the attacker; primarily reboot-loop DoS plus allocator poisoning window on the double free.", "evidence": "VERDICT.md (two-layer swallow proof + fix-coverage assessment, path:line); env.txt (hardware absence + md5 962543e6e0739668ac24e0b255a44b61 == audited tree); fix.diff (central hub fix, git apply --check clean, 76 lines)", "kernel_refs": [ "sys/dev/drm/radeon/radeon_pm.c:1448", "sys/dev/drm/radeon/radeon_pm.c:1449", "sys/dev/drm/radeon/radeon_pm.c:1453", "sys/dev/drm/radeon/radeon_pm.c:1262", "sys/dev/drm/radeon/radeon_pm.c:1320", "sys/dev/drm/radeon/radeon_pm.c:1694", "sys/dev/drm/radeon/radeon.h:2793", "sys/dev/drm/radeon/si.c:6874", "sys/dev/drm/radeon/rv770_dpm.c:2172", "sys/dev/drm/radeon/rv770_dpm.c:2271", "sys/dev/drm/radeon/rv770_dpm.c:1901" ], "poc_changes": "No seed PoC. Trigger is the DF-4022 family VBIOS trigger; this pack contributes the central fix.diff instead.", "attempts": 1, "guest_uname": "DragonFly dfbsd 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": 15, "guest_dirty": 0, "build_cmd": "n/a (hardware-gated)", "run_cmd": "n/a (hardware-gated; VBIOS trigger per DF-4022)", "code_hash": "", "notes": "The orchestrator-requested systemic consolidation of DF-4022/4117/4118/4124/4125/4143/4144 (+DF-3972). Verified this pass: no dispatch init checks boot_ps (grep clean); rv7xx_parse_power_table returns 0 without BOOT state; asic fini order keeps IRQs live after pm_fini (si.c:6945 vs 6950) which is DF-4163s adjacent-but-separate defect; radeon_pm_print_states name array [5] only indexed by legacy types 0..4 (enum radeon.h:1206-1225).", "recommended_fix": "Honor radeon_dpm_inits return, gate on boot_ps, scrub dangling ps, and guard suspend/resume/fini-disable paths in radeon_pm.c (see fix.diff).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applies clean (git apply --check) against the read-only tree; single-file central fix that makes the six family boot/suspend/resume NULL-boot_ps panics unreachable and neutralizes the ps double-frees; cannot be runtime-validated without radeon hardware.", "fix_evidence": "findings/poc/DF-4162/fix.diff" } |