⬢ DragonFlyBSD Kernel Audit
DF-3689 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3689",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Source-certain heap OOB read; runtime-inconclusive on this guest (no AMD GPU). smu7_patch_voltage_dependency_tables_with_lookup_table uses each dependency records vddInd/vddcInd - a raw u8 (0..255) from the VBIOS ATOM tables (process_pptables_v1_0.c:398 ucVddcInd etc.) - to index vddc/vddgfx_lookup_table->entries[] with no range check (:1860-1862, :1866-1868, :1873-1875, :1879-1881); smu7_patch_voltage_workaround does the same at :2135. The lookup tables are kmallocd for max_levels=16 records (process_pptables_v1_0.c:286-287/:295-296) while their count field is the VBIOS ucNumEntries, so indices above both 16 and count read adjacent kernel heap. The garbage value read is stored into the dependency records vddc and later programs real voltages (hardware-safety impact) and feeds smu7_calc_voltage_dependency_tables; no direct userspace disclosure was found (sysfs pp_table dumps the raw atom table, not the patched records). DF-1168 covers the ucMemoryClockIndex/ucEngineClockIndex sinks; this is the distinct vddInd sink family. Harness: 239/255 crafted dep entries read past the 16-record allocation, max offset 2550 bytes past entries[0].",
  "exploit_chain": "",
  "evidence": "run.log: dep entries whose vddInd read lands past the 16-record kmalloc: 239 / 255, max index 255 -> byte offset 2550 past entries[0] (allocation holds 160 bytes of entries); VERDICT.md; fix.diff",
  "kernel_refs": [
    "sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:1860",
    "sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:1866",
    "sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:1873",
    "sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:1879",
    "sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:2135",
    "sys/dev/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c:286"
  ],
  "poc_changes": "No seed; wrote an allocation-geometry harness computing which vddInd values read past the 16-record kmalloc block.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 x86_64",
  "runtime_sec": 90,
  "guest_dirty": 0,
  "build_cmd": "cc -Wall -O0 -o t vddind_oob_read.c (DragonFly 6.5 base cc, on guest)",
  "run_cmd": "cd /tmp/DF-3689 && ./t",
  "code_hash": "e1dbd7af847f492f9724e8da4f029b47d008363bb19220b8d1b3c43a8b0984eb",
  "notes": "Guest virtio-only (no AMD GPU: pciconf shows only QEMU 0x1237/0x1111; amdgpu.ko/drm.ko present in /boot/kernel but unloaded). Harness proves the primitive/arithmetic with verbatim kernel code shape and 1:1 struct layouts; the in-kernel trigger needs an SMU7 ASIC + crafted VBIOS / VFIO / root pp_table write. Compiled -O0: -O2 detects the index UB and misoptimizes the accounting.",
  "recommended_fix": "Validate vddInd/vddcInd (and the workarounds index) against the target lookup tables count before indexing, returning -EINVAL on out-of-range.",
  "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 guest).",
  "fix_evidence": "findings/poc/DF-3689/fix.diff"
}