DF-4171 / verdict.json
{ "finding_id": "DF-4171", "status": "reproduced", "reproduced": true, "verdict": "The count==0 out-of-bounds read was demonstrated in byte-identical production smu8_hwmgr.c code on the DragonFly guest (verbatim-rig evidence class; in-kernel execution is AMD-ASIC-gated, no AMD GPU in the guest), on both cited sites and under both cited triggers -- but with a MECHANISM CORRECTION that changes the impact ceiling. ptable->count is uint8_t (hwmgr.h:137-141 uvd / :183-186 vce), so ptable->entries[ptable->count - 1] with count==0 promotes to int -1: the access is entries[-1] at exactly table-8 (entries at offset 4, record 12B), NOT index 0xFFFFFFFF at ~16GB. The rig prints the predicted address before the call and the fault lands on it exactly (SIGSEGV READ 8 bytes BEFORE the start of the 8B table object: NEGATIVE-INDEX UNDERFLOW READ), for smu8_dpm_update_vce_dpm under the StablePState cap (:1260-1261) and for smu8_dpm_update_uvd_dpm under en_umd_pstate with no cap (:1856-1857) -- the user-reachable route (power_dpm_force_performance_level profile_* sysfs -> pp_dpm_en_umd_pstate, amd_powerplay.c:310-335, confirmed in-tree). count==0 passing the only load-time guard (count <= SMU8_MAX_HARDWARE_POWERLEVELS, :471-474) is shown arithmetically. Consequences of the correction: in-kernel the read lands in the preceding slab page, so it does NOT fault/panic (the findings availability impact is overstated); the realistic manifestation is a silent 8-byte kernel-heap under-read whose value becomes vce_dpm/uvd_dpm.hard_min_clk and is programmed into the SMU as a hard-min clock (wrong-clock integrity defect). No userland readback of the raw value was found, so no confidentiality leak is demonstrated either -- the CWE-125 OOB-read class itself is confirmed verbatim. The packs fix.diff was A/B-validated in the same rig: both modes return -EINVAL with no fault, clean-valid byte-identical, and the DF-4169 modes keep faulting under it (orthogonality). Three runs byte-identical.", "impact": "leak", "confidence": "certain", "exploit_chain": "crafted/corrupted VBIOS (or root-written pp_table blob) on a Carrizo/Bristol Ridge SMU8 APU ships a VCE or UVD clock/voltage limit table with numEntries==0 -> processpptables get_vce/uvd_clock_voltage_limit_table allocates the table with count=0 (the :471-474 load-time guard accepts 0) -> user writes profile_standard/profile_peak/... to power_dpm_force_performance_level -> pp_dpm_en_umd_pstate sets en_umd_pstate -> first VCE/UVD DPM update after ungate computes entries[count-1] = entries[-1] -> 8-byte kernel-heap read before the table object -> garbage hard_min_clk programmed to the SMU. Bounded negative-index OOB read; no demonstrated userland exfiltration, no in-kernel fault (mechanism corrected from the filed 0xFFFFFFFF/panic claim).", "evidence": "findings/poc/DF-4171/run.log: [BASELINE] MODE 4171-vce-count0 -> :1261 reads entries[count-1].ecclk = entries[-1] at 0x800475ff8 (table-8 ...) -> !! SIGSEGV (addr=0x800475ff8, READ) => fault 8 bytes BEFORE the start of the 8B table object: NEGATIVE-INDEX UNDERFLOW READ; same for 4171-uvd-count0-en-umd at :1857; layout mode prints the promotion arithmetic (uint8_t -> int -1 ... table - 8) and the guard passthrough (count=0 <= 8 -> PASSES); FIXED sections show rc=-22/no fault for both modes; build.log: 26 verbatim blocks ALL PASSED on the guest against /usr/src; run.2/run.3.log md5-identical", "kernel_refs": [ "sys/dev/drm/amd/powerplay/hwmgr/smu8_hwmgr.c:471", "sys/dev/drm/amd/powerplay/hwmgr/smu8_hwmgr.c:473", "sys/dev/drm/amd/powerplay/hwmgr/smu8_hwmgr.c:1260", "sys/dev/drm/amd/powerplay/hwmgr/smu8_hwmgr.c:1261", "sys/dev/drm/amd/powerplay/hwmgr/smu8_hwmgr.c:1856", "sys/dev/drm/amd/powerplay/hwmgr/smu8_hwmgr.c:1857", "sys/dev/drm/amd/powerplay/inc/hwmgr.h:137", "sys/dev/drm/amd/powerplay/inc/hwmgr.h:183", "sys/dev/drm/amd/powerplay/hwmgr/processpptables.c:1119", "sys/dev/drm/amd/powerplay/amd_powerplay.c:310" ], "poc_changes": "Seed pack had no runnable PoC. Built the verbatim rig per the DF-4388 pattern (same rig as DF-4169, run in the same guest session): gen_rig.sh/check_verbatim.sh extract and guest-verify 26 byte-identical blocks; tables are allocated with the production formula and page-aligned after a PROT_NONE leading-guard page so the underflow faults at the exact predicted address; modes added for both update paths and both triggers (StablePState cap; en_umd_pstate). Fixed build applies this packs fix.diff (header-normalized, hunk bodies cmp-identical, bidirectional patch proof).", "attempts": 4, "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": 1, "guest_dirty": 0, "build_cmd": "cd rig && sh build.sh /usr/src (guest: /root/pack4171/rig)", "run_cmd": "cd rig && sh run.sh (guest: /root/pack4171/rig)", "code_hash": "aa27837d55a922b1b0cfc10810471ce2bbb6158d7fce9bcb9ba0d2a75f5a61b5", "notes": "MECHANISM CORRECTION vs the filed summary: uint32_t count => 0xFFFFFFFF index is wrong for smu8 -- both phm_vce/uvd_clock_voltage_dependency_table.count are uint8_t, count-1 promotes to int -1, the OOB read is entries[-1] at table-8 (rig: predicted == faulting address, both modes). In-kernel this neither faults nor panics (read lands in the preceding slab page); impact is a bounded 8-byte kernel-heap under-read feeding SMU hard-min-clock programming, class CWE-125 (kernleak bucket), with no demonstrated userland readback -- the filed CVSS availability component is overstated. The :454 hunk of the packs fix.diff (upload-path NULL-table guard, DF-4170 residual) is outside the sliced functions and not exercised by this rig. Guest /usr/src verified pristine (md5 a0cb59b723434a78e88bf0580d5a5508) before and after; guest left up and clean.", "recommended_fix": "Zero-count guard before both entries[count-1] reads: apply fix.diff (if (!ptable || ptable->count == 0) return -EINVAL; in smu8_dpm_update_vce_dpm :1258-1259 and smu8_dpm_update_uvd_dpm :1854-1855; the !ptable half also covers DF-4170s runtime residual).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "A/B validated in the same rig: rig_fixed = same verbatim slice + this packs fix.diff (forward apply --fuzz=0 no rejects, reverse apply restores pristine byte-exactly, hunk bodies cmp-identical). On identical inputs both 4171 modes return rc=-EINVAL with no fault/no underflow read; clean-valid output byte-identical to baseline (hard_min_clk entries[1].ecclk=300000/vclk=133300, SMU msgs [0x20,0x1]/[0x1c,0x1]); the DF-4169 modes still fault under this fix, proving orthogonality. Rebuilt-kernel validation not performed: AMD-ASIC-gated on this guest (verbatim-rig protocol).", "fix_evidence": "run.log FIXED sections: 4171-vce-count0 rc=-22 / returned WITHOUT faulting (guard active in fixed build) and same for 4171-uvd-count0-en-umd; clean-valid lines identical to baseline; build.log: ALL VERBATIM CHECKS PASSED incl. fixed-slice == pristine+fix.diff and reverse-apply restore proof" } |