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

OD8 capability/settings arrays indexed by constants but allocated to VBIOS-supplied length -> heap OOB read

Summary

vega20_od8_set_feature_capabilities/initialize_default_settings at vega20_hwmgr.c:894-1222: read od_feature_capabilities[0..9], od_settings_min/max[0..15] using hardcoded ATOM_VEGA20 constants. Arrays allocated by copy_overdrive_feature_capabilities_array to min(VBIOS.ODFeatureCount,10)/min(ODSettingCount,16) elements. VBIOS with count<10 or <16 -> OOB read from heap. check_powerplay_tables validates neither count. OOB values surface via pp_od_clk_voltage sysfs -> heap info leak. Sibling of DF-1180/DF-1183 OD8 patterns. Fix: always allocate full ATOM_VEGA20 counts, copy only valid entries.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1254 Β· 12 files
FileTypeDescriptionSize
trigger.c trigger-source documentation stub; bug path is VBIOS-parse/GPU-init, not a syscall 1.6 KB view raw
fix.diff suggested-fix git-apply-able fix 2.3 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.8 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 21.5 KB view raw
README.md readme human reproduce doc 573 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-1254 PoC β€” vega20 OD8 OOB read (LATENT)

Status: source-confirmed real; NOT reproducible on audit guest (no AMD GPU). Impact: heap OOB read (info leak) via crafted VBIOS powerplay table. Driver: sys/dev/drm/amd/powerplay/hwmgr/vega20_hwmgr.c + vega20_processpptables.c (amdgpu, not in GENERIC, no HW).

Reproduce

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

The bug fires only at Vega20 GPU powerplay init with a crafted VBIOS. See VERDICT.md for the full source-level trace and fix.diff for the fix.

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

DF-1254 β€” vega20 OD8 capability/settings arrays: heap OOB read (LATENT)

Verdict

NOT REPRODUCED on the audit guest (LATENT / HW-gated). The bug is confirmed real by source-level trace; it cannot fire on this guest because there is no AMD GPU, so the dev/drm/amd powerplay/VBIOS-parse path is dead code at runtime.

Mechanism (confirmed in source)

  • vega20_processpptables.c:824-846 computes od_feature_count = min(VBIOS.ODFeatureCount, ATOM_VEGA20_ODFEATURE_COUNT) (10) and od_setting_count = min(VBIOS.ODSettingCount, ATOM_VEGA20_ODSETTING_COUNT) (14).
  • copy_overdrive_feature_capabilities_array (vega20_processpptables.c:694) allocates exactly od_feature_count bytes (kzalloc(count)), and phm_copy_overdrive_settings_limits_array (smu_helper.c:73) allocates exactly od_setting_count u32s. So a VBIOS reporting ODFeatureCount<10 or ODSettingCount<14 yields an undersized destination buffer.
  • The consumer vega20_od8_set_feature_capabilities (vega20_hwmgr.c:906-975) indexes od_feature_capabilities[ATOM_VEGA20_ODFEATURE_*] with the hardcoded constants 0..9, and vega20_od8_initialize_default_settings (vega20_hwmgr.c:1216-1221) indexes od_settings_min/max[i] for i in 0..OD8_SETTING_COUNT. These constant indices exceed the undersized allocation β†’ heap OOB read (kmalloc-16/32 bucket).
  • check_powerplay_tables (vega20_processpptables.c:636) validates neither count. OOB values surface via pp_od_clk_voltage sysfs β†’ heap info leak.
  • VBIOS source arrays ODFeatureCapabilities[32], ODSettingsMax[32], ODSettingsMin[32] (vega20_pptable.h:80-83) are declared 32-wide, so the copy itself never over-reads; only the destination is too small.

Why it does not reproduce here

pciconf -lv shows no display/VGA device; the guest has display none. amdgpu.ko/drm.ko ship in /boot/kernel/ but are not loaded (no AMD GPU to probe), and even loaded they would not attach. The vulnerable code runs only during GPU powerplay init while parsing a real (or crafted) VBIOS. Reaching it needs a Vega20-class AMD GPU + a crafted powerplay table β€” neither available. This is a valid hard blocker: the code path is unreachable at runtime on this guest and no userspace syscall exercises it.

Exploit chain

N/A β€” read-only OOB (info leak), and HW-gated (latent). No escalation chain is developable on this guest. Realistic threat: a malicious/crafted VBIOS on real AMD hardware (reflashed card or hostile PCIe device) leaking heap bytes.

PoC changes

trigger.c is a documentation stub (the bug path is not a syscall); the real deliverables are this trace and fix.diff.

Fix (fix.diff)

Always allocate the full ATOM_VEGA20 maximum so the consumer's hardcoded indices cannot run off the end; copy only the VBIOS-declared valid entries (the rest stay zeroed from kzalloc). Concretely: - copy_overdrive_feature_capabilities_array: allocate ATOM_VEGA20_ODFEATURE_MAX_COUNT (32) instead of od_feature_count. - new vega20_copy_overdrive_settings_limits_array (vega20-local) allocates ATOM_VEGA20_ODSETTING_MAX_COUNT (32) and copies od_setting_count entries; the two vega20 call sites use it instead of the shared phm_copy_overdrive_settings_limits_array (which vega12 still uses with its own full constant count, unaffected). Applies cleanly (patch -p1 rc=0). Supersedes the finding markdown proposal (which had no markdown; this is the authoritative verified fix).

Fix validation

not_testable β€” the code path is not reachable on the audit guest, so no PoC runs before/after. Validated: diff applies cleanly to the read-only sys/ tree and is syntactically reviewed; building the amdgpu/powerplay stack is not warranted for a non-reproducible latent OOB read.

Fix verification

not_testable

compile validated

kernel/module build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. Vega20 OD8 arrays kzalloc(count) vs hardcoded indices 0..9/0..13 -> OOB read. amdgpu not in GENERIC.