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

Unbounded VBIOS dependency-table counts overflow fixed SMU7 level arrays (heap OOB write)

Summary

kv_init_graphics_levels (:2426), kv_populate_uvd/vce/samu/acp_table (:915/986/1049/1115): for(i=0;i<table->count;i++) write pi->graphics_level[i]/uvd_level[i]/etc[SMU7_MAX_LEVELS=8]. count from VBIOS atom ucNumEntries (amdgpu_dpm.c:302/617/650), u8 0-255, uncapped. Dead guard if(pi->high_voltage_t&&...) break: high_voltage_t kzalloc-zeroed, never assigned -> always false. Sibling of DF-1136/DF-1141/DF-1166 dpm_levels overflow. Crafted VBIOS count>8 -> heap OOB write past kv_power_info. Fix: cap i<SMU7_MAX_LEVELS_*.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1268 Β· 12 files
FileTypeDescriptionSize
trigger.c trigger-source documentation stub; bug path is VBIOS-parse/GPU-init, not a syscall 1.3 KB view raw
fix.diff suggested-fix git-apply-able fix 1.9 KB view raw
build.sh repro-script build the stub 470 B view raw
run.sh repro-script run the stub 244 B view raw
build.log build-log trigger build output 71 B view raw
run.log run-log trigger run output (no effect; latent) 65 B view raw
VERDICT.md verdict full source-level trace + fix rationale 3.1 KB ↓ raw
env.txt environment guest uname, modules, PCI (no GPU) 1.7 KB view raw
fix_build.log build-log compile-validation: kernel+module build with fix applied, rc=0, no errors 26.4 KB view raw
README.md readme human reproduce doc 516 B ↓ 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 reproduce doc
↓ download raw

DF-1268 PoC β€” kv_dpm unbounded VBIOS counts: heap OOB WRITE (LATENT)

Status: source-confirmed real (certain); NOT reproducible on audit guest (no AMD GPU). Impact: heap OOB write past kv_power_info.*_level[] via crafted VBIOS count>8. Driver: sys/dev/drm/amd/amdgpu/kv_dpm.c (amdgpu kv path, not in GENERIC, no HW). The high_voltage_t guard is dead (never assigned).

Reproduce

./build.sh && ./run.sh   # stub; bug path is VBIOS-parse at GPU dpm init

See VERDICT.md + fix.diff.

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

DF-1268 β€” kv_dpm unbounded VBIOS dependency-table counts: heap OOB WRITE (LATENT)

Verdict

NOT REPRODUCED on the audit guest (LATENT / HW-gated). The bug is confirmed real by source-level trace (and marked confidence=certain in the DB finding); it cannot fire here because there is no AMD APU/GPU, so the dev/drm/amd/amdgpu/kv_dpm.c code path is dead at runtime.

Mechanism (confirmed in source)

  • Five loops iterate for (i = 0; i < table->count; i++) writing fixed-size destination arrays:
  • kv_populate_uvd_table (kv_dpm.c:915) β†’ pi->uvd_level[i] (SMU7_MAX_LEVELS_UVD=8, kv_dpm.h:159)
  • kv_populate_vce_table (kv_dpm.c:986) β†’ pi->vce_level[i] (SMU7_MAX_LEVELS_VCE=8, :160)
  • kv_populate_samu_table (kv_dpm.c:1049) β†’ pi->samu_level[i] (SMU7_MAX_LEVELS_SAMU=8,:162)
  • kv_populate_acp_table (kv_dpm.c:1115) β†’ pi->acp_level[i] (SMU7_MAX_LEVELS_ACP=8, :161)
  • kv_init_graphics_levels(kv_dpm.c:2426 and else-branch :2446) β†’ pi->graphics_level[i] (SMU__NUM_SCLK_DPM_STATE=8, :157)
  • table->count is the VBIOS atom ucNumEntries β€” a u8, 0..255, uncapped at all these sites.
  • The apparent guard if (pi->high_voltage_t && ...) break; is DEAD: pi is kzalloc-zeroed (kv_dpm.c allocates kv_power_info with kzalloc) and high_voltage_t is never assigned anywhere in kv_dpm.c (grep 'high_voltage_t =' β†’ no hits), so the condition is always false and the break never fires.
  • A crafted VBIOS with count > 8 therefore writes past the embedded arrays in struct kv_power_info β†’ heap OOB write at dpm init. Sibling of DF-1136/DF-1141/DF-1166 (dpm_levels overflow).

Why it does not reproduce here

pciconf -lv shows no AMD display device; amdgpu.ko is present in /boot/kernel/ but not loaded (nothing to probe). kv_dpm attaches only to Kabini/Kaveri-class AMD APUs. Reaching the bug needs that hardware + a crafted VBIOS. Valid hard blocker: path unreachable at runtime on this guest.

Exploit chain

N/A for this guest β€” the write primitive is HW-gated (latent). On real AMD hardware with a crafted VBIOS it is a kernel-heap OOB write (more severe than DF-1254's read): controllable-ish content (VBIOS table entries) written past kv_power_info into adjacent slab objects. No chain developed here because the path is dead on the audit guest; characterization would require the matching GPU.

PoC changes

trigger.c is a documentation stub (bug path is VBIOS parse, not a syscall).

Fix (fix.diff)

Cap each loop at its SMU7_MAX_LEVELS_* constant so a VBIOS count > 8 cannot overflow:

for (i = 0; i < table->count && i < SMU7_MAX_LEVELS_<X>; i++)

applied to all six loops (uvd/vce/samu/acp + the two graphics-level branches). Applies cleanly (patch -p1 rc=0). Matches the finding proposal ("cap i<SMU7_MAX_LEVELS_*").

Fix validation

not_testable β€” code path unreachable on audit guest; diff validated to apply cleanly and is syntactically reviewed. Building the amdgpu stack is not warranted for a non-reproducible latent OOB write.

Fix verification

not_testable

compile validated

kernel/module build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. kv_dpm 5 loops uncapped vs [8] + dead high_voltage_t guard -> heap OOB WRITE. amdgpu not in GENERIC.