DF-4388 / verdict.json
{ "finding_id": "DF-4388", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "REPRODUCED via the DF-4165/4247/4396 verbatim-rig evidence class: the ENTIRE production V1 parser (process_pptables_v1_0.c:34-1337, checker-proven byte-identical on the guest against /usr/src/sys, the tree its running kernel was built from) compiled into a harness and driven with crafted Tonga-format PowerPlay tables. 16 defect modes demonstrated at exactly the predicted verbatim sites, stable across 3 identical runs: (1) heap OOB WRITE in get_vddc_lookup_table (:176-190) - firmware ucNumEntries=255 bounds the copy loop into a fixed kzalloc(4+10*16=164) destination, fault at the first byte past the allocation, up to ~2390B of firmware-chosen content (both usVddcLookupTableOffset and usVddgfxLookupTableOffset paths); (2) six unvalidated USHORT-offset dereferences (state/thermal/fan/sclk-dep/ppm/vce) faulting at image+0xFF00; (3) count-bounded source OOB read loops (sclk 255 vs 3 records); (4) byte-exact kernel-heap leak: MM dep count=40 vs 5 records -> 175/175 parsed field values byte-exact with victim bytes past the image, parse completing into userland-readable DPM tables; (5) VCE ucSCLKIndex=0xFF -> entries[0xFF] read at sclk_table+2+2805; (6) entries[-1] NEGATIVE-INDEX underflow read before the image when ucNumEntries=0 (:1263-1267); (7) entry_index<=ucNumEntries off-by-one (:1310); (8) NULL derefs of vdd_dep_on_sclk in get_pcie_table/get_gpio_table (:522/:745); (9) the never-NULL GPIO gate parsing the PowerPlay header when usGPIOTableOffset==0; (10) num_vce_state_tables stored unclamped (200 vs vce_states[6], :1328). Fix A/B-validated in the same rig: fix.diff (git-apply proven bidirectionally, byte-equal to the packed reference) applied to the same slice -> 0 SIGSEGVs on identical input, counts clamped to image AND destination constants (255->16 lookup, 255->3 sclk, 40->5 mm, 200->6 vce), offsets rejected (rc=-1/-22), indices clamped, entries[-1] gone, NULL guards added, GPIO gate moved to the offset, and clean-valid parses byte-identically in both builds. In-kernel execution is AMD-ASIC-gated on this guest (no 1002: device, hw_probe.log); impact recorded as dos = the realistic in-kernel floor of the demonstrated heap-corruption primitive (panic), with content-controlled overwrite potential; threat model is VBIOS-crafted (flashed ROM / vfio romfile / malicious device) or root-written pp_table, same class as the DF-4247 V0 twin - no unprivileged userland trigger on stock hardware.", "exploit_chain": "crafted/corrupted GPU VBIOS PowerPlay table (Tonga format, PP_TABLE_V1: Tonga/Fiji/Polaris10/11/12/VegaM) at driver attach -> pptable_v1_0_initialize -> get_vddc_lookup_table heap OOB write (255 firmware entries into a 16-record kmalloc(164), ~2390B content-controlled overwrite) and/or OOB reads with byte-exact leak into userland-readable DPM tables and/or vdd_dep_on_sclk NULL-deref panic; alternatively root-written /sys/class/drm/card0/device/pp_table -> pp_dpm_set_pp_table -> amd_powerplay_reset -> same parse. No unprivileged userland route on stock hardware.", "evidence": "run.log (baseline 13 classified SIGSEGVs at exact predicted offsets + 175/175 byte-exact leak + 2 behavioral proofs; FIXED half: 0 faults, all clamps visible; byte-identical across run.2.log/run.3.log); build.log (ALL VERBATIM CHECKS PASSED vs guest /usr/src, 24 blocks + bidirectional fix proof); VERDICT.md (full path:line trace); rig/ (pp_rig.c 18 modes, gen_rig.sh, check_verbatim.sh); env.txt (guest md5s = host tree)", "kernel_refs": [ "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:176", "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:1042", "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:522", "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:745", "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:1263", "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:1310", "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:1328", "sys/dev/drm/amd/powerplay/hwmgr/hwmgr.c:86", "sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:5144" ], "poc_changes": "fresh rig this run (no prior PoC existed - prior verification was compile-validation + clamp unit test only): guard-backed end-anchored kzalloc shim to make the destination heap OOB write fault decisively; 18-mode driver (16 defect modes + layout + clean-valid regression control); verbatim slice of the whole parser body + 24 header slices with guest-side byte-identity proof", "attempts": 3, "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": 1500, "guest_dirty": 0, "build_cmd": "./build.sh /usr/src (guest-side: check_verbatim vs /usr/src + make rig_base rig_fixed, cc 8.3)", "run_cmd": "./run.sh (baseline vs fixed A/B over 18 modes; 3 identical runs)", "code_hash": "bfc04eb6312476d813145c0af98750fcff4b71ec24fb31412ce2ab9f4e6a35ae", "notes": "Verbatim-rig evidence class (DF-4165/4247/4396): production parser machine-extracted, checker-proven byte-identical on the guest against the tree its running kernel was built from, compiled and driven with crafted tables; all 13 fault modes fault at the exact cited path:line offsets; leak leg 175/175 byte-exact across 3 runs. Guest /usr/src verified pristine (md5) after the run. Baseline faults are exit=88 (handler-classified); the FIXED build shows 0 SIGSEGV and clean-valid parses byte-identically. Historical pre-verification artifacts retained: syntax_check_guest.txt, unit_test_guest.log (11/11), v1_clamp_test.c, process_pptables_v1_0_fixed.c.", "recommended_fix": "central pp_v1_table_range_ok/pp_v1_clamp_count layer with destination-constant clamps at every offset/count/index consumer (fix.diff, A/B-validated in the rig)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "A/B-validated in the verbatim rig (DF-4165/4247/4396 protocol): rig_fixed = same byte-identical slice + fix.diff (patch --fuzz=0, reverse-apply restores pristine byte-exactly; byte-equal to the packed process_pptables_v1_0_fixed.c). On the identical crafted inputs that fault the baseline 13 times, the fixed build faults ZERO times: vddc lookup count clamped 255->16 (write gone), oversized USHORT offsets rejected (rc=-1/-22), dep counts clamped to image and destination constants (255->3 sclk, 40->5 mm), VCE indices clamped, entries[-1] underflow eliminated, entry_index guard corrected to <, vdd_dep_on_sclk NULL guards added (rc=-22), GPIO gate moved to the offset, num_vce_state_tables clamped 200->6; clean-valid table parses byte-identically to the baseline build. A rebuilt-kernel A/B was not performed: the fix sites execute in-kernel only on AMD ASICs absent from this guest.", "fix_evidence": "run.log FIXED half (0 SIGSEGV / 11 graceful rejections + clamped counts); build.log (verbatim checks + bidirectional fix proof); fix.diff" } |