DF-4396 / verdict.json
{ "finding_id": "DF-4396", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "REPRODUCED via the DF-4165/DF-4247 verbatim-rig evidence class: the ENTIRE production parser (vega10_processpptables.c:34-1326, checker-proven byte-identical ON THE GUEST against /usr/src/sys, the tree its running kernel was built from; 23/23 VERBATIM blocks, fix.diff forward/reverse proven) compiled into a harness and driven with crafted ATOM_Vega10 PowerPlay tables. Baseline: 16 SIGSEGVs at exactly the predicted sites across 3 runs (identical fault-offset fingerprints) - u16 subtable offsets dereferenced at image+65281 (check_powerplay_tables:82, get_number_of_entries:1249, init_thermal_controller:134), tail overreads at image_end+0..31 (count-255 copy loops for socclk/mclk/pixclk/mm/gfxclk V1, fan rev>10 V2 walk:214, PowerTune rev7 V3 overread:488, hard-limit entries[0]:814, od entries[254].ucACGEnable +3298:273), the get_pcie_table:781 NULL vdd_dep_on_sclk deref at addr 0x0 (DF-1587), and TWO HEAP OOB WRITES past kzallocd objects: get_vddc_lookup_table:1036 SIGSEGV at obj+86 of an 84-byte kmalloc-128 object with 247/247 OOB us_vdd writes byte-exact equal to the crafted image bytes (strided 2-byte overwrite to +2463, DF-1586), and the dcefclk pioneer path :740-748 SIGSEGV at obj+232 of a 228-byte kmalloc-256 object with a 1232-byte attacker-controlled overwrite reaching +6892. Leak legs byte-exact: 35/35 socclk and 38/38 GFXCLK V2-walk OOB records equal the bytes past the image (kernel-heap values surface to userland via powerplay sysfs), and the overdrive-limit engineClock decision bit provably comes from an OOB byte 490 bytes past the image. init_dpm_2_parameters:1103-1128 result-clobbering proven: parse returns rc=0 with NULL vddc_lookup_table (DF-3702 feeder). entry off-by-one :1308 (<=) SIGSEGVs at image_end+12 (DF-1588). FIX A/B-VALIDATED in the same rig: fix.diff applied to the same slice - every crafted mode clean (range-checked offsets, clamped counts, NULL guard, < fix, propagated failures) and clean-valid parses IDENTICALLY (no regression). In-kernel execution AMD-ASIC-gated on this guest (no 0x1002 device, no /dev/dri, no amdgpu module - env.txt); threat model = crafted/corrupt VBIOS at driver attach or root-written pp_table sysfs re-parse; no unprivileged trigger on stock hardware. Impact dos follows the DF-4165 precedent for the identical evidence class and gating (attacker-controlled heap OOB write proven in verbatim code, ASIC-gated in kernel).", "exploit_chain": "crafted VBIOS PowerPlay table (ROM flash / vfio romfile / malicious device) or root pp_table sysfs blob -> vega10_pp_tables_initialize on Vega10 -> (a) u8-count heap OOB WRITE: vddc_lookup ucNumEntries=255 vs max_levels=8 overwrites 2463 bytes past a kmalloc-128 slab object with fully attacker-chosen u16 values (adjacent-object corruption); dcefclk pioneer count=255 overwrites ~6.6KB past a kmalloc-256 object -> memory corruption / code-exec potential on the ASIC; (b) count-driven OOB reads clone adjacent kernel heap into sysfs-visible DPM tables -> kernel-heap info leak; (c) u16 offsets -> deep OOB reads/NULL deref -> panic; (d) masked lookup failure -> NULL-table consumer crash. No unprivileged trigger on stock hardware.", "evidence": "run.log/run.2.log/run.3.log (3 stable runs, 16 FAULTs each, baseline vs fixed A/B); build.log (23/23 VERBATIM blocks identical on guest /usr/src/sys + fix.diff forward/reverse proof + cc build); leak_sample.txt (decisive leak/overwrite lines); env.txt (guest uname, no-AMD-GPU gate, host/guest parser sha256 equality); rig/ (full reproducible rig); fix.diff (validated artifact)", "kernel_refs": [ "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:82", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:134", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:214", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:273", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:488", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:620", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:740", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:781", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:814", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1036", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1103", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1249", "sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1308", "sys/dev/drm/amd/powerplay/hwmgr/vega10_pptable.h:73", "sys/dev/drm/amd/powerplay/amd_powerplay.c:671" ], "poc_changes": "Replaced the pre-verification syntax-check + clamp-unit-test approach (vega10_clamp_test.c / vega10_processpptables_fixed.c, removed) with the full verbatim rig per the proven DF-4165/DF-4247 evidence class: machine-extracted parser slice + 22 header slices, guest-side verbatim checker, 23 crafted-table modes with guard/victim images and guard/canary destinations. Rig fixes during bring-up: unbuffered stdout so fault reports survive _exit; 22-page guard tail (a 1-page guard let the +0xFF00 reads land in adjacent heap mappings); pr_info / u8-u16 typedef / GetIndexIntoMasterDataTable shims; offsetof()-driven GFXCLK V2 ucACGEnable (+9, not +8) in the leak-expectation math.", "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": 1500, "guest_dirty": 0, "build_cmd": "./build.sh /usr/src (guest: gen_rig + check_verbatim 23/23 + make rig_base rig_fixed, cc 8.3 DragonFly)", "run_cmd": "./run.sh (23 modes x baseline/fixed; 3 consecutive runs logged)", "code_hash": "3411c1a3f5267d0847acb6529b1de4267fcec9bdb0d8de654c721f5468be96a8", "notes": "Guest /usr/src untouched (rig ran from /root/df4396; syntax/runtime only). GFXCLK V2 record is 13 packed bytes (vega10_pptable.h:147-154), not the 12 the finding text says - no impact on defects or fix. fix.diff needed NO corrections this run (contrast DF-4247). Neutralization confirmed in the A/B for this files knowns DF-1586 (vddc write), DF-1587 (pcie NULL), DF-1588 (off-by-one), DF-1589 (od entries[-1]/[255]) and the DF-3702 result-clobber feeder. Guest left up and clean.", "recommended_fix": "central vega10_pp_table_range_ok/vega10_pp_clamp_count/VEGA10_SUBTABLE_OK layer with destination-constant clamps (VDDC 8, VDDMEM/VDDCI 4, DCEFCLK NUM_DSPCLK_LEVELS), full-struct range checks for fan/PowerTune rev dispatch, pcie NULL guard, entry_index < fix, and result propagation in init_dpm_2_parameters (fix.diff, A/B-validated in the rig)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "FIXED in the verbatim rig (same slice + fix.diff, identical inputs): all 16 baseline fault modes clean (offsets range-checked to soft_pp_table_size, counts clamped to image and destination, fan/PowerTune full-struct checks, pcie NULL guard, off-by-one < + per-entry range check, lookup failures propagated), both heap OOB writes gone (canaries intact, loops clamped to 8), all leaks gone (0 OOB records), and the fully valid table parses IDENTICALLY to baseline (23/23 structural checks) - no regression. In-kernel validation remains ASIC-gated on this guest (same as baseline).", "fix_evidence": "run.log FIXED half (every mode vs baseline); build.log (fix.diff fuzz=0 forward-apply + byte-exact reverse-restore proof); rig/pp_slice_fixed.inc generation in rig/gen_rig.sh" } |