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

Heap OOB write in SMC UVD/VCE/ACP/SAMU level population from unbounded VBIOS count

Summary

ci_populate_smc_uvd_level(:2689)/_vce_level(:2732)/_acp_level(:2765)/_samu_level(:2797) copy VBIOS-supplied count (u8 up to 255) into fixed-size SMU7_Discrete_UvdLevel[8]/VceLevel[8]/AcpLevel[8]/SamuLevel[8] with no upper-bound check. Crafted VBIOS with numEntries>8 overflows arrays into adjacent SMU7_Discrete_DpmTable fields then ci_power_info pointer-bearing voltage tables -> write-what-where. Attacker: malicious PCIe/Thunderbolt GPU or reflashed VBIOS. Reached at DPM init. Same class as DF-1142 (amdgpu ci_dpm.c). Fix: clamp count to SMU7_MAX_LEVELS_*.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1149 Β· 9 files
FileTypeDescriptionSize
fix.diff suggested-fix clamp Uvd/Vce/Acp/Samu LevelCount to SMU7_MAX_LEVELS_* (git-apply-able) 1.6 KB view raw
build.sh build-script apply fix.diff + incremental compile of radeon ci_dpm.o 462 B view raw
run.sh run-script documents runtime-unreachable (no AMD GPU on guest) 489 B view raw
VERDICT.md verdict full source-trace + mechanism + fix rationale 2.8 KB ↓ raw
env.txt environment guest uname, pci, driver build status 2.0 KB view raw
build.log build-log fix compile-validation output (patched ci_dpm.o, -Werror clean) 1.5 KB view raw
README.md readme human repro summary 1.7 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 human repro summary
↓ download raw

DF-1149 β€” Heap OOB write in SMC UVD/VCE/ACP/SAMU level population (radeon ci_dpm.c)

Status: REPRODUCED at code level β€” latent at runtime on this guest (no AMD GPU). Severity (finding): High Β· CWE-787 Out-of-bounds Write

What the bug is

The radeon driver's ci_populate_smc_{uvd,vce,acp,samu}_level (sys/dev/drm/radeon/ci_dpm.c:2689/2732/2765/2797) set each table->*LevelCount directly from the VBIOS-derived *_clock_voltage_dependency_table.count (unbounded u8) and loop writing table->*Level[count] into fixed [SMU7_MAX_LEVELS_*=8] arrays (sys/dev/drm/radeon/smu7_discrete.h:327-330, smu7.h:45-48). No clamp. This is the same bug class as DF-1142; the radeon copy of ci_dpm.c was simply not fixed alongside amdgpu.

Why it does not trigger here

No AMD GPU on the QEMU/KVM guest (0x1234:0x1111 std VGA); radeon is not in X86_64_GENERIC (only in LINT64 as a test config). Latent on physical Sea Islands HW with a malicious/reflashed VBIOS.

What was validated

  1. Source trace confirmed (see VERDICT.md kernel_refs).
  2. Baseline radeon.ko (incl. ci_dpm.o) builds clean under -Werror.
  3. Fix fix.diff applies (4 hunks) and patched ci_dpm.o rebuilds clean under -Werror (ci_dpm.o: 55424 -> 55456 bytes).

Reproduce (compile-validation only)

scp this-folder/fix.diff root@guest:/root/df1149.diff
cd /usr/src && patch -p1 --forward < /root/df1149.diff
cd sys/dev/drm/radeon && rm -f ci_dpm.o && make ci_dpm.o   # -Werror clean

Fix

fix.diff clamps each *LevelCount to its SMU7_MAX_LEVELS_* via min_t(u8, ...) before the loop β€” same shape as the DF-1142 amdgpu fix; matches the finding recommendation.

VERDICT.md verdict full source-trace + mechanism + fix rationale
↓ download raw

DF-1149 β€” Heap OOB write in SMC UVD/VCE/ACP/SAMU level population (radeon ci_dpm.c)

Verdict

REPRODUCED (code-level, latent at runtime). The radeon driver carries the identical unbounded SMC-level-table OOB as amdgpu (DF-1142), confirmed by source trace. Not triggerable at runtime on this guest (no AMD GPU; radeon not in GENERIC) -> runtime not_testable. fix.diff validated to apply + compile under -Werror.

Mechanism (trigger -> primitive -> effect)

  • Sink arrays (in SMU7_Discrete_DpmTable, sys/dev/drm/radeon/smu7_discrete.h:327-330): UvdLevel[SMU7_MAX_LEVELS_UVD], VceLevel[SMU7_MAX_LEVELS_VCE], AcpLevel[SMU7_MAX_LEVELS_ACP], SamuLevel[SMU7_MAX_LEVELS_SAMU], all = 8 (sys/dev/drm/radeon/smu7.h:45-48). Counts UvdLevelCount/VceLevelCount/AcpLevelCount/SamuLevelCount are uint8_t (smu7_discrete.h:314-317).
  • Unbounded count + loop in sys/dev/drm/radeon/ci_dpm.c:
  • ci_populate_smc_uvd_level :2689-2692: table->UvdLevelCount = rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count; then for (count = 0; count < table->UvdLevelCount; count++) table->UvdLevel[count]...
  • ci_populate_smc_vce_level :2732-2735 (writes VceLevel[count]).
  • ci_populate_smc_acp_level :2765-2768 (writes AcpLevel[count]; original already (u8)-casts but never clamps to 8).
  • ci_populate_smc_samu_level :2797-2800 (writes SamuLevel[count]).
  • Count source: each *_clock_voltage_dependency_table.count is parsed from the VBIOS by radeon's atom-bios PowerPlay parser (unbounded u8-class count), exactly mirroring amdgpu.
  • Effect: crafted VBIOS with count > 8 runs each loop off its [8] Level array into the adjacent Level array and downstream SMU state, a write-what-where into radeon SMU control state. Same primitive class as DF-1142; the radeon copy of ci_dpm.c simply was not fixed when the bug class was identified.

Threat model / reachability

  • Attacker: malicious/reflashed VBIOS or malicious PCIe/Thunderbolt AMD GPU (radeon CIK path). Reached at radeon DPM init.
  • On this guest: NOT reachable (QEMU std VGA only; radeon not in GENERIC). Valid hard blocker: runtime-unreachable here, latent on physical AMD CIK HW.

Exploit chain

None developed β€” valid hard blocker (HW-dependent VBIOS-parsing write; no userspace-guest path to supply a VBIOS). Demonstrated work is the source-level confirmation + compiling fix. No exploit.c (not userspace-reachable).

PoC changes

No trigger PoC seeded. This folder adds fix.diff, build.sh, run.sh, VERDICT.md, manifest.json, env.txt, build.log, README.md.

Clamp each *LevelCount to its SMU7_MAX_LEVELS_* (=8) using min_t(u8, ...) before the loop. Implemented in fix.diff for all four functions β€” identical shape to the DF-1142 amdgpu fix. Matches the finding proposal.

Fix verification

not_testable

compile validated -Werror

module build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed+compile. radeon ci_populate_smc_*_level same bug as DF-1142 (sibling driver). radeon not in GENERIC.