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

Extended-header fields read before/without usSize gating (usPPMTableOffset at +16 read before V5 check; overdrive limits read with no size gate)

Summary

init_dpm2_parameters evaluates usPPMTableOffset (+16..17) in the condition BEFORE the usSize>=V5 guard; init_overdrive_limits_V2_1 reads the fields with no usSize gate at all - the only getter among its siblings that skips the gate. Within-image OOB reads compounding with DF-1470. Reorder + gate fix (in the central diff).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4249 Β· 8 files
FileTypeDescriptionSize
README.md β€” 1.5 KB ↓ raw
VERDICT.md β€” 1.8 KB ↓ raw
build.sh β€” 65 B view raw
env.txt β€” 588 B view raw
run.log β€” 425 B view raw
run.sh β€” 89 B view raw
trigger.sh β€” 468 B view raw
verdict.json β€” 1.8 KB view raw

DF-4249 β€” Extended-header fields read before/without usSize gate

Where

sys/dev/drm/amd/powerplay/hwmgr/processpptables.c 1. init_dpm2_parameters :1488 β€” reads extended_header->usPPMTableOffset (byte offset +16..17 of the extended header) before checking usSize >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 (:1489-1490). A VBIOS whose extended header is only V2-sized (12 bytes) still has the field read. 2. init_overdrive_limits_V2_1 :1029-1033 β€” reads header->ulMaxEngineClock / ulMaxMemoryClock (+8..15) with no usSize gate at all, unlike every sibling getter (e.g. get_vce_table_offset gates on usSize >= V2).

What

Both are within-image OOB reads past the firmware-declared end of the extended-header sub-table: the parser honors usSize for gating but reads fields located past it first. Values land in hwmgr->platform_descriptor (overdrive limits) or select a PPM table offset β€” no direct leak to userspace, but the PPM offset then indexes the image and (unpatched) feeds the unvalidated-offset family (DF-1470).

Trigger

Crafted VBIOS / pp_table with usExtendendedHeaderOffset != 0 and a short usSize. Hardware-gated (AMD ASIC required).

Fix

Contained in DF-4247/fix.diff: * PPM: reorder so usSize >= V5 is tested before usPPMTableOffset is read, plus a pp_table_range_ok check on the PPM table itself. * V2_1: gate the header deref on usSize >= V3 footprint via pp_table_range_ok.

Build/run

Hardware-gated; run.sh documents absence of AMD hardware.

VERDICT.md
↓ download raw

DF-4249 VERDICT

status: untested (hardware-gated: no AMD GPU β€” run.log) impact: none demonstrated (bounded within-image OOB read, Low) confidence: certain (code-trace)

Trace

  • processpptables.c:1485-1490: extended_header is computed from an unvalidated offset, then extended_header->usPPMTableOffset (offset 16) is read in the condition while the usSize >= V5 (>= 18 bytes) guard is evaluated only afterwards in the same && chain β€” C evaluates usPPMTableOffset > 0 first. For an extended header whose usSize is 12..15 (V2/V3-sized), bytes 16-17 lie beyond the declared sub-table.
  • processpptables.c:1029-1033: init_overdrive_limits_V2_1 has no usSize gate whatsoever before reading ulMaxEngineClock (offset 4..7) and ulMaxMemoryClock (8..11). The sibling getters (get_vce_table_offset:63, get_uvd_table_offset:164, get_samu:229, get_acp:265, get_cacp_tdp:301, get_sclk_vdd_gfx:352) all gate on usSize first β€” this one is the outlier.

Both reads stay inside the surrounding VBIOS image in practice (the extended header sits mid-image), so the practical impact is mis-parsed limits/offset, not a slab overread β€” rated Low. The PPM offset misuse compounds with DF-1470 until the central layer lands.

Fix

In DF-4247/fix.diff (condition reorder + range checks). fix_status: not_testable (hardware-gated).

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

(No fix.diff for this item: documented recommendation only - see Fix above.)

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not_testable: hardware-gated.

reorder+range-check hunk in DF-4247/fix.diff.
per-fix-DF-4249

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md trace comparing gated siblings (:63,:164,:229,:265,:301,:352); run.log hardware probe.

PoC changes

n/a - pass-2 finding; trigger documentation written fresh (hardware-gated, no seed PoC existed)

Verified recommended fix

gate extended-header field reads on usSize (+range check)

Verdict

Extended-header fields read without/before usSize gating: init_dpm2_parameters:1488 reads usPPMTableOffset (+16) before the usSize>=V5 check in the same condition; init_overdrive_limits_V2_1:1029-1033 reads ulMaxEngineClock/ulMaxMemoryClock with no usSize gate at all (every sibling getter gates). Within-image OOB reads past the declared header; values feed platform limits/PPM offset selection. Low.