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

VBIOS-controlled mm_dep_table->count drives heap overflow in UVD/VCE/ACP SMC level population

Summary

tonga_populate_smc_uvd_level/vce_level/acp_level at tonga_smumgr.c:1320/1380/1425: table->U/V/AcpLevelCount=(uint8_t)mm_table->count, loop for(count=0;count<Count) writes UvdLevel[SMU72_MAX_LEVELS_UVD=8]/VceLevel[8]/AcpLevel[8]. mm_dep_table->count from VBIOS ucNumEntries (u8 1-255, only !=0 check). count>8 -> overflow past smc_state_table into tonga_smumgr.power_tune_defaults pointer -> dereferenced by populate_svi_load_line. Sibling of DF-1136/DF-1141 dpm_levels pattern. Fix: clamp loop to SMU72_MAX_LEVELS_*.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1271 Β· 11 files
FileTypeDescriptionSize
tonga_mm_dep_overflow.c trigger-source trigger / documentation PoC 1.8 KB view raw
fix.diff suggested-fix git-apply-able patch closing the cited path 1.3 KB view raw
VERDICT.md verdict full source trace + reachability + fix analysis 3.2 KB ↓ raw
README.md readme build/run/expected 1.4 KB ↓ raw
build.sh build-script cc -O2 -Wall -o tonga_mm_dep_overflow tonga_mm_dep_overflow.c 135 B view raw
run.sh run-script ./tonga_mm_dep_overflow 55 B view raw
run.log run-log decisive run, full output 319 B view raw
fix_build.log build-log nativekernel compile-validation excerpt, rc=0 32.5 KB view raw
env.txt environment uname, cc version, device/module state 583 B view 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 build/run/expected
↓ download raw

DF-1271 PoC β€” tonga mm_dep_table->count UvdLevel/VceLevel/AcpLevel overflow

Status

INCONCLUSIVE on the audit guest: bug confirmed real by source trace at sys/dev/drm/amd/powerplay/smumgr/tonga_smumgr.c:1307, but hardware-gated and not triggerable here. fix.diff authored and validated to apply + compile (nativekernel rc=0, -Werror). See VERDICT.md for the full trace and fix.diff for the patch.

Build

./build.sh

(equivalent: cc -O2 -Wall -o tonga_mm_dep_overflow tonga_mm_dep_overflow.c)

Run (as unprivileged user)

./run.sh

Expected on the audit guest

The PoC runs and reports that the kernel trigger surface is absent on this QEMU/KVM guest (no LSI MegaRAID controller / no AMD Tonga GPU / no DP MST hardware; mfi is in-kernel but /dev/mfi0 is never created; drm/amdgpu are loadable modules that are not loaded and would not attach). It exits 0 without exercising the sink. The bug is therefore a latent, hardware-dependent defect, not a false positive.

Files

  • tonga_mm_dep_overflow.c β€” trigger / documentation PoC
  • fix.diff β€” standalone git apply -p1 patch closing the cited path
  • VERDICT.md β€” full source-level mechanism + reachability + fix analysis
  • build.log / run.log β€” captured build/run output
  • fix_build.log β€” nativekernel compile-validation excerpt (rc=0)
  • env.txt β€” guest environment
  • manifest.json β€” machine-readable artifact catalog
VERDICT.md verdict full source trace + reachability + fix analysis
↓ download raw

DF-1271 β€” tonga VBIOS mm_dep_table->count drives heap overflow

Verdict

INCONCLUSIVE (hardware-gated latent bug, not triggerable on this guest). The overflow is confirmed real by source tracing; not reachable on the audit QEMU guest because the sink lives in the loadable amdgpu.ko module and runs only on AMD Tonga hardware driven by a (crafted/buggy) VBIOS PowerPlay table (absent). fix.diff authored and validated to apply + compile (nativekernel rc=0, -Werror).

Mechanism (source trace)

Three sibling functions in sys/dev/drm/amd/powerplay/smumgr/tonga_smumgr.c: - tonga_populate_smc_uvd_level (:1307): table->UvdLevelCount = (uint8_t)mm_table->count; then for (count=0; count<UvdLevelCount; count++) table->UvdLevel[count] = ...; (:1323) - tonga_populate_smc_vce_level (:1367): table->VceLevelCount = ...; VceLevel[count]=... (:1383) - tonga_populate_smc_acp_level (:1413): table->AcpLevelCount = ...; AcpLevel[count]=... (:1428)

Array bounds / caps: - SMU72_MAX_LEVELS_UVD = SMU72_MAX_LEVELS_VCE = SMU72_MAX_LEVELS_ACP = 8 (smu72.h:113-115). - SMU72_Discrete_DpmTable: UvdLevel[8], VceLevel[8], AcpLevel[8] (smu72_discrete.h:270-272).

Count source: - mm_table->count = the VBIOS PowerPlay ucNumEntries (a u8, 1–255), assigned in processpptables.c:391 (dep_table->count = (unsigned long)table->ucNumEntries;) with only a != 0 validity check during parse. So count can be up to 255.

With mm_table->count > 8, the loop writes UvdLevel/VceLevel/AcpLevel[8..], overflowing the level arrays into the adjacent SMU72_Discrete_DpmTable fields and, far enough, into the tonga_smumgr power_tune_defaults pointer (subsequently dereferenced) β†’ heap corruption / controlled-pointer deref. The written values (frequencies, voltage indices) are partly VBIOS-derived.

Reachability on the audit guest

  • tonga_smumgr.c is module-only: in amdgpu.ko (nm /boot/kernel/amdgpu.ko β‡’ tonga_populate_all_graphic_levels etc.), NOT in the base kernel. amdgpu.ko is not loaded on the guest.
  • The functions run during PowerPlay SMC table population on an AMD Tonga GPU, fed by the card's VBIOS. The guest has no AMD GPU (vgapci0 is virtio-class). Not triggerable here.

Exploit chain

None β€” not exercisable on this guest (module-only + no AMD Tonga HW). The primitive is an OOB write of VBIOS-derived values past UvdLevel/VceLevel/ AcpLevel[8] in an SMU table; reachable only on Tonga hardware with a malformed VBIOS (a malicious discrete-GPU VBIOS is a strong local-attacker primitive on such systems).

PoC changes

Authored tonga_mm_dep_overflow.c β€” documentation stub recording the module-only / VBIOS-driven reachability finding.

Fix validation

  • fix.diff applies cleanly: git apply --check -p1 β‡’ OK (3 hunks).
  • Compiles: make nativekernel rebuilt amdgpu.ko β‡’ NK_DONE rc=0, tonga_smumgr.c built with -Werror (fix_build.log).
  • Functional test: not_testable (no AMD Tonga HW).

Clamp each level count to its array cap with min(): table->UvdLevelCount = (uint8_t)min(mm_table->count, (uint32_t)SMU72_MAX_LEVELS_UVD); (and likewise VCE/ACP). See fix.diff.

Fix verification

not_testable

compile validated -Werror

module/kernel build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. tonga mm_dep_table->count vs UvdLevel/VceLevel/AcpLevel[8] overflow. amdgpu not in GENERIC.