β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-1166

Heap overflow: unvalidated VBIOS dependency-table count overflows fixed dpm_levels[8] array

Summary

smu7_setup_dpm_tables_v1 (:784-810) and v0 (:691-713) copy VBIOS dep_table->count (u8 up to 255) entries into dpm_levels[MAX_REGULAR_DPM_NUMBER=8] with NO bound check. count set from PP table ucNumEntries with only !=0 check by process_pptables. Crafted PP table with >8 distinct entries overflows sclk_table into mclk_table/vddc/vddci/mvdd then golden_dpm_table/odn_dpm_table in heap-allocated smu7_hwmgr. Same class as DF-1141/1149/1150. Attacker: malicious VBIOS/VFIO/root sysfs pp_table write. Fix: cap each loop at MAX_REGULAR_DPM_NUMBER.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1166 Β· 11 files
FileTypeDescriptionSize
harness.c trigger-source userspace replica of smu7_setup_dpm_tables_v0/v1 loops; counts OOB writes for crafted count=255 4.4 KB view raw
fix.diff suggested-fix git-apply-able: clamp all 7 loops to MAX_REGULAR_DPM_NUMBER + clamp 3 .count assignments 4.3 KB view raw
build.sh build-script cc -O2 -Wall -o harness harness.c 411 B view raw
run.sh run-script ./harness 217 B view raw
build.log build-log incremental amdgpu.ko build with fix applied (smu7_hwmgr.o, -Werror, rc=0) 1.1 KB view raw
run.log run-log decisive harness run: v0=1235, v1=494, total=1729 OOB writes, fix -> 0 864 B view raw
env.txt environment guest uname/cc, no AMD GPU, amdgpu not in GENERIC 1.3 KB view raw
VERDICT.md verdict full narrative: mechanism, harness, threat model, uid0 assessment, fix validation 4.0 KB ↓ raw
README.md readme how to reproduce + status 1.1 KB ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme how to reproduce + status
↓ download raw

DF-1166 β€” PoC evidence pack

Heap overflow: unvalidated VBIOS dependency-table count overflows dpm_levels[8] (amdgpu powerplay sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c:691-800).

smu7_setup_dpm_tables_v0 (5 loops) and _v1 (2 loops) copy the PP/VBIOS dependency-table count (u8 up to 255) entries into dpm_levels[MAX_REGULAR_DPM_NUMBER=8] with no upper bound. A crafted PP table (count>8) overflows each table into the next and past smu7_dpm_table into the heap-allocated smu7_hwmgr. Same class as DF-1141/DF-1150.

Status

Source-confirmed + harness. Latent at runtime on this guest: amdgpu is NOT in X86_64_GENERIC, and the guest has no AMD GPU.

Reproduce

./build.sh          # cc -O2 -Wall -o harness harness.c   (unprivileged maxx)
./run.sh            # prints v0/v1 OOB write counts + fix check

Expected (harness): v0 OOB writes = 1235 ; v1 OOB writes = 494 ; total = 1729; fix β†’ 0.

Fix

fix.diff clamps all 7 loops to MAX_REGULAR_DPM_NUMBER (and clamps the 3 v0 .count assignments). Validated: applies + compiles clean (incremental amdgpu.ko build, smu7_hwmgr.o, -Werror). See VERDICT.md.

VERDICT.md verdict full narrative: mechanism, harness, threat model, uid0 assessment, fix validation
↓ download raw

DF-1166 β€” Heap overflow: unvalidated VBIOS dependency-table count in smu7_setup_dpm_tables_v0/v1 (amdgpu smu7_hwmgr.c)

Verdict

REPRODUCED (code-level / harness), latent at runtime on this guest. The bug is a genuine unbounded-copy-into-fixed-array heap OOB write, confirmed by source trace and a userspace harness. It is the same class as DF-1141/DF-1150 (VBIOS dep-table count overflow) but in amdgpu powerplay (SMU7 hardware manager). amdgpu is NOT in X86_64_GENERIC and the guest has no AMD GPU, so the path is runtime-unreachable (valid hard blocker). No exploit.c: not a userspace-reachable primitive.

Mechanism (trigger β†’ primitive β†’ effect)

  • Source array: struct smu7_single_dpm_table { u32 count; struct smu7_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; }, MAX_REGULAR_DPM_NUMBER = 8 (sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.h:95,99-100). smu7_dpm_table holds sclk/mclk/pcie/vddc/vddci/mvdd tables (smu7_hwmgr.h:103-109).
  • Attacker-controlled count: the dep-table counts (allowed_vdd_sclk_table->count, allowed_vdd_mclk_table->count in v0; dep_sclk_table->count, dep_mclk_table->count in v1) come from the VBIOS PowerPlay PP table ucNumEntries (u8 up to 255) with only a !=0 / >=1 lower-bound check in process_pptables.
  • Unbounded loops:
  • smu7_setup_dpm_tables_v0 (smu7_hwmgr.c:666): sclk dedup :691, mclk dedup :705, vddc direct-index :716 (also OOB-reads std_voltage_table->entries[i]) + .count :723, vddci :728 + .count :732, mvdd :742 + .count :746.
  • smu7_setup_dpm_tables_v1 (smu7_hwmgr.c:752): sclk dedup :784, mclk dedup :800.
  • Effect: with a crafted PP table (count>8) the writes run off each 8-entry dpm_levels[] into the next smu7_single_dpm_table, past smu7_dpm_table, into the heap-allocated smu7_hwmgr (golden_dpm_table, odn_dpm_table).

Evidence (harness)

harness.c models v0 (5 loops) and v1 (2 loops) with a crafted count of 255. Result: v0 = 1235 OOB writes, v1 = 494 OOB writes, total 1729. With the fix (&& i < MAX_REGULAR_DPM_NUMBER), 0 remain. (Full output in run.log.)

Threat model / reachability

  • Attacker: malicious/reflashed VBIOS / PP table, or a malicious PCIe AMD GPU; on some configs a root sysfs pp_table write. Reached at DPM table setup (smu7_setup_dpm_tables_v0/v1).
  • On this guest: NOT reachable. amdgpu not in GENERIC; only QEMU std VGA. Realistic ceiling on physical AMD HW: kernel heap corruption β†’ panic / DoS.

Exploit chain

None β€” valid hard blocker (HW-gated; amdgpu absent). No unprivileged guest syscall injects a PP table.

PoC changes

Authored from scratch. Deliverables: harness.c, fix.diff, build.sh, run.sh, VERDICT.md, manifest.json, env.txt, build.log, run.log.

fix.diff adds && i < MAX_REGULAR_DPM_NUMBER to all seven loops (v0 :691/:705/:716/:728/:742, v1 :784/:800) and clamps the three v0 .count assignments (:723/:732/:746) to at most MAX_REGULAR_DPM_NUMBER. This matches the finding proposal ("cap each loop at MAX_REGULAR_DPM_NUMBER").

Fix validation (Phase 8)

  • fix.diff applies cleanly (git apply --check OK; 6 hunks, 7 clamps).
  • Incremental amdgpu.ko build (warm obj): cd /usr/src/sys/dev/drm/amd && make β†’ rc=0, smu7_hwmgr.o (71192 B) rebuilt & re-linked, 0 errors under -Werror.
  • fix_status: not_testable for runtime: amdgpu not in GENERIC, no AMD GPU. Validated at apply + compile level.

Kernel references (confirmed)

Fix verification

not_testable

compile+harness validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed+harness. smu7_setup_dpm_tables 7 loops unbounded vs MAX_REGULAR_DPM_NUMBER=8 -> 1729 OOB. amdgpu not in GENERIC.