CENTRAL FIX: Vega10 PowerPlay parser has no bounds-validation layer β all 22 firmware USHORT offsets, every UCHAR count and every revision dispatch consumed unvalidated against soft_pp_table_size (vega10 side of DF-4388)
Summary
The Vega10 parser consumes everything with zero range validation: subtable pointers computed as base + raw u16 offset and dereferenced (one entry-count helper with NO validation at all); every u8 count sizes both the kzalloc and the source-read loop (7 MM/clk families incl. the 12-byte GFXCLK V2 walk); rev dispatches over-read larger structs from possibly-shorter subtables; and init_dpm_2 clobbers 'result' per lookup so a failing VDDC lookup is masked - parse 'succeeds' with NULL tables that consumers deref (the DF-3702 crash list). DF-4388's V1 helper is NOT reusable verbatim (different struct family) - the layer is re-authored. CENTRAL FIX (564 lines, git-apply OK, kernel-toolchain syntax-validated, 22/22 clamp tests PASS incl. the DF-1586/1588/4395 neutralization cases). NEUTRALIZATION: kills knowns DF-1586/1587/1588/1589 and starves the vega10_hwmgr consumers (DF-1179..1183/3701..3707) of wild counts; per-file fixes stand as defense in depth.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4396 Β· 20 files| File | Type | Description | Size | |
|---|---|---|---|---|
| rig/gen_rig.sh | β | 4.1 KB | view raw | |
| rig/check_verbatim.sh | β | 3.4 KB | view raw | |
| rig/rig_shims.h | β | 6.2 KB | view raw | |
| rig/vega10_rig.c | β | 43.9 KB | view raw | |
| rig/Makefile | β | 494 B | β download | |
| rig/build.sh | β | 501 B | view raw | |
| rig/run.sh | β | 1.0 KB | view raw | |
| fix.diff | β | 20.1 KB | view raw | |
| build.sh | β | 134 B | view raw | |
| run.sh | β | 133 B | view raw | |
| build.log | β | 2.9 KB | view raw | |
| run.log | β | 25.8 KB | view raw | |
| run.2.log | β | 25.8 KB | view raw | |
| run.3.log | β | 25.8 KB | view raw | |
| leak_sample.txt | β | 1.8 KB | view raw | |
| env.txt | β | 1.0 KB | view raw | |
| README.md | β | 6.8 KB | β raw | |
| VERDICT.md | β | 8.5 KB | β raw | |
| manifest.json | β | 3.0 KB | view raw | |
| verdict.json | β | 7.5 KB | view raw |
DF-4396 β CENTRAL FIX: Vega10 PowerPlay parser has no bounds-validation layer
Severity: High | Bucket: kernleak | Verified: REPRODUCED (verbatim-rig evidence class, same as DF-4165/DF-4247) + fix A/B-validated (fixed) on the identical inputs.
Status
Every defect family cited by the finding was demonstrated in byte-identical
production parser code (vega10_processpptables.c:34-1326, machine-extracted
and checker-verified on the DragonFly guest against /usr/src/sys β the tree
its running kernel was compiled from), compiled into a harness and driven with
crafted ATOM_Vega10_* PowerPlay tables β 16 SIGSEGV-confirmed unclamped
accesses (12 source OOB reads incl. two +65,281-byte deep-offset reads, one
NULL deref, two heap OOB writes past kzalloc'd objects), two byte-exact
kernel-heap leak proofs (73 OOB records), two attacker-controlled
heap-overflow canaries (247/247 and 1232 bytes byte-exact), and the
result-clobbering masked failure (DF-3702 feeder). In-kernel execution remains
AMD-ASIC-gated on this guest (no 0x1002 device, no /dev/dri, no amdgpu module
β env.txt). The pack's fix.diff was A/B-validated in the same rig: every
crafted mode clean, valid tables parse identically (no regression).
Rig layout (rig/)
gen_rig.shsed-extracts the entire parser body (lines 34-1326) plus 22 verbatim struct/type header slices (the whole packedATOM_Vega10_*family invega10_pptable.h:26-419, thephm_ppt_v1_*kernel-side types, hwmgr/hardwaremanager/power_state slices) β bracketed with VERBATIM markers.check_verbatim.shre-proved all 23 blocks byte-identical on the guest against/usr/src/sys(build.log:ALL VERBATIM CHECKS PASSED), and thatpp_slice_fixed.incis exactly pristine+fix.diff (forward apply fuzz=0, slice equal, reverse apply restores pristine byte-exactly).rig_shims.htouches no defect path: identityle*_to_cpu, three-modekzalloc(plain / page-guarded destination / 0xAA-canary tail), minimizedstruct pp_hwmgr/amdgpu_device/pci_devwith production names/types for every field the parser and the fix consult, verbatimPP_ASSERT_WITH_CODE.- Crafted images mimic the ATOM Vega10 PowerPlay table a crafted/corrupt VBIOS
(or a root-written
pp_tablesysfs blob β amd_powerplay.c:671-706) feeds the driver on a Vega10 board; images end at a 22-page PROT_NONE tail (deep u16-offset reads fault deterministically) or at a patterned victim region (leak provenance).
Observed (run.log / run.2.log / run.3.log β fault-offset fingerprints identical across 3 runs)
| mode (crafted input) | baseline (verbatim) | fixed (+fix.diff) |
|---|---|---|
| clean-valid (full table) | rc=0, 23/23 checks OK | identical (no regression) |
statearray-offset-oob (usStateArrayOffset=0xFF00, 128B image) |
SIGSEGV image+65281 (:82) |
rc=-1 "out of range" |
numentries-offset-oob (direct :1249 call) |
SIGSEGV image+65281 | rc=-1 |
thermal-offset-oob (:134) |
SIGSEGV image+65281 | rc=-EINVAL |
| fan-v2-tail (rev 11 header, 1 byte in image) | SIGSEGV image_end+31 (:214) |
rc=-EINVAL |
od-acg-count-255 (rev1, entries[254].ucACGEnable) |
SIGSEGV image_end+3298 (:273, DF-1589) |
rc=0, clamped |
gfxclk-v1-count-255 (:620 walk) |
SIGSEGV image_end+4 | rc=0, count clamped to 1 |
| socclk / mclk / pixclk / mm count-255 | SIGSEGV image_end+0..4 | rc=0, counts clamped to image |
| powertune-v3-short (rev7, 38B table, V3 fields) | SIGSEGV image_end+0 (:488) |
rc=-EINVAL |
hardlimit-tail (entries[0], no record) |
SIGSEGV image_end+0 (:814) |
rc=-1 |
| pcie-null-sclk (gfxclk offset 0) | SIGSEGV addr 0x0 (:781, DF-1587) |
rc=-EINVAL (NULL guard) |
| dcefclk-pioneer-write (dev 0x6863, count 255) | SIGSEGV obj+232, alloc 228 (:740-748) |
rc=0, loop=8, no fault |
| dcefclk-pioneer-canary | 1232 changed bytes in [+0,+6892] past the 228B object | canary intact |
| vddc-lookup-write (count 255, max_levels 8) | SIGSEGV obj+86, alloc 84 (:1036, DF-1586) |
rc=0, loop=8 |
| vddc-lookup-canary | 494 bytes changed [+2,+2463]; 247/247 us_vdd writes byte-exact with the image | canary intact, count=8 |
| gfxclk-v2-leak (rev1 count 40, 2 records) | count=40; 38 OOB records byte-exact with victim bytes; od engineClock decided by the OOB ACG byte (LEAK) | count=2; 0 OOB; decision bit in-image |
| socclk-leak-canary (count 40, 5 records) | count=40; 35/35 OOB records byte-exact | count=5, 0 OOB |
| result-clobber (vddc count 0, vddmem/vddci ok) | rc=0 with NULL vddc_lookup_table (masked, DF-3702 feeder) | rc=1 propagated |
entry-offbyone (entry_index==ucNumEntries) |
SIGSEGV image_end+12 (:1308 <=, DF-1588) |
rc=-1 (< + range check) |
Primitive and impact
The firmware image (VBIOS ROM copy or root-written sysfs blob) fully controls every offset (u16) and count (u8):
- Heap OOB write, attacker-controlled:
get_vddc_lookup_table(:1026-1038) writes up to 247Γ2 bytes in a +2/+12/+22β¦ stride 2463 bytes past an 84-bytekmalloc-128object β 247/247 writes byte-exact with the crafted image;get_dcefclk_voltage_dependency_tablepioneer path (:721-750) copies 255 records into a 228-bytekmalloc-256object β overwrite reaches +6892 (~6.6 KB into adjacent slab objects). - Kernel-heap info leak: count-driven copy loops clone bytes from past
the table image into
hwmgr->dyn_state/pptable_infotables that userland reads back via powerplay sysfs (pp_dpm_*); even the overdrive-limit decision bit is taken from an OOB byte (gfxclk-v2-leak A/B). - Deep OOB reads / NULL deref (u16 offsets to +65,281; missing-subtable
NULL at
:781) β kernel panic paths. - Masked parse failure (:1103-1128) β NULL-table consumer crashes (DF-3702 class).
Gating: an AMD Vega10 ASIC whose VBIOS carries a crafted/corrupt PowerPlay
table (flashed ROM, vfio romfile, malicious device), or root re-parsing via
/sys/class/drm/card0/device/pp_table. No unprivileged trigger on stock
hardware (same threat model as DF-4165/DF-4247).
Build / run (on the audit guest, or any DF box with the kernel tree)
scp -r rig fix.diff root@guest:/root/df4396/ cd /root/df4396 && ../df4396/build.sh /usr/src # verbatim checks + 2 binaries ./run.sh # baseline vs fixed, 23 modes
(The pre-verification pack carried a syntax-check + clamp-unit-test approach
(vega10_clamp_test.c, vega10_processpptables_fixed.c) β superseded by this
full verbatim-rig verification; files removed.)
Fix validation
fix.diff (564 lines) applied to the same verbatim slice (checker-proven
equality with pristine+fix.diff): all crafted modes clean, all counts clamped
to image/destination, NULL guarded, off-by-one fixed, failure propagated,
clean-valid parses identically to baseline (no regression). The pack's
fix.diff is the validated artifact, unchanged from the pre-verification
version.
DF-4396 VERDICT β central Vega10 PowerPlay validation layer
Status: REPRODUCED (verbatim-rig evidence class, DF-4165/DF-4247) | fix A/B-validated: FIXED | confidence: certain
Verification method
The entire production parser β vega10_processpptables.c:34-1326, every
offset/count/index site β plus 22 struct/type header slices were
machine-extracted from the kernel tree (rig/gen_rig.sh) and compiled into a
harness on the DragonFly guest. rig/check_verbatim.sh re-proved all 23
VERBATIM blocks byte-identical against /usr/src/sys on the guest β the tree
its running kernel (Jul 2 2026 build) was compiled from (build.log: ALL
VERBATIM CHECKS PASSED; host/guest parser SHA256 equal in env.txt). The
fixed build is the same slice with this pack's fix.diff applied via
patch --fuzz=0 (bidirectionally proven: forward-apply + slice equality +
reverse-apply restores the pristine file byte-exactly).
The rig's only non-production code (rig_shims.h) touches no defect path:
identity endian helpers, a 3-mode kzalloc (plain / page-guarded destination /
0xAA canary), minimized pp_hwmgr/amdgpu_device/pci_dev with production
names and types for every field the parser and the fix consult, and the
verbatim PP_ASSERT_WITH_CODE. Crafted images end either at a 22-page
PROT_NONE tail (deep-offset reads fault deterministically β a small guard let
the +0xFF00 modes land in adjacent heap mappings in the first rig iteration,
which is why the guard region is 22 pages) or at a deterministic victim
pattern (leak provenance).
Every cited defect family proven (baseline = verbatim production code)
All numbers from run.log (fault-offset fingerprints identical across
run.2.log/run.3.log β 3 runs, 16 SIGSEGVs each):
A. USHORT offsets dereferenced unvalidated (deep OOB reads + NULL deref)
- check_powerplay_tables:72-82 β usStateArrayOffset=0xFF00 on a 128-byte
image: state_arrays->ucNumEntries read at image+65281 β SIGSEGV
(+65153 past image end).
- vega10_get_number_of_powerplay_table_entries:1246-1249 β the same offset,
zero validation of any kind: SIGSEGV at image+65281.
- init_thermal_controller:127-134 β usThermalControllerOffset=0xFF00:
ucType read at image+65281 β SIGSEGV.
- get_pcie_table:781 β PCIE table present + usGfxclkDependencyTableOffset
== 0 β table_info->vdd_dep_on_sclk->count on NULL β SIGSEGV at 0x0
(DF-1587).
B. u8 counts size alloc AND copy loop (source OOB reads β kernel-heap leak)
- socclk/mclk/pixclk (shared getter)/mm and the GFXCLK V1 walk: ucNumEntries
=255 with 1-2 records in image β SIGSEGV at image_end+0..4 in the copy
loop. Leak legs (victim-pattern images): vdd_dep_on_socclk 35/35 OOB
records and the GFXCLK V2 13-byte-stride walk 38/38 OOB records
byte-exact with the bytes past the image β the cloned values surface to
userland via powerplay sysfs (pp_dpm_*), exactly the DF-4247 leak class.
- init_over_drive_limits:269-273 β rev-1 GFXCLK table, ucNumEntries=255,
1 record: patom_record_v2[254].ucACGEnable read 3298 bytes past image end
β SIGSEGV (the DF-1589 unclamped [count-1]). Leak leg: with the OOB byte
readable, overdriveLimit.engineClock (sysfs-visible) is decided by that
OOB byte while the last in-image record carries the opposite bit β
byte-exact 1-bit leak provenance, A/B-decisive against the fixed build.
C. Rev dispatch over-reads larger structs from shorter subtables
- fan table: header ucRevId=11 (V2) with only the header byte in image β V2
field read at image_end+31 β SIGSEGV (:210-254).
- PowerTune: rev 7 (βV3) with a V2-sized 38-byte table β usBoostStartTemperature
read at image_end+0 β SIGSEGV (:472-513).
- hard limits: header claims 1 entry, no record bytes β entries[0] read at
image_end+0 β SIGSEGV (:810-819).
D. Heap OOB WRITES past kzalloc'd destinations (attacker-controlled)
- get_vddc_lookup_table:1026-1038 (DF-1586): alloc 4+8*10=84
(kmalloc-128 class), loop copies 255 β dest-guard SIGSEGV at obj+86;
canary run: 494 bytes changed in [+2,+2463], 247/247 OOB us_vdd writes
byte-exact equal to the crafted image bytes (strided 2-byte writes, +2
every 10 bytes β fully attacker-controlled linear overflow of the adjacent
slab object).
- get_dcefclk_voltage_dependency_table:721-750 (pioneer, dev 0x6863 rev 0):
alloc 4+8*28=228 (kmalloc-256), loop runs 255 β dest-guard SIGSEGV at
obj+232; canary run: 1232 bytes changed reaching +6892 past the
object (~6.6 KB into adjacent slab objects; values = crafted-image clocks).
E. Masked parse failure (the DF-3702 NULL-table feeder)
- init_dpm_2_parameters:1103-1128 β failing VDDC lookup (returns 1, leaves
vddc_lookup_table==NULL) overwritten by succeeding VDDMEM/VDDCI lookups:
parse returns rc=0 with a NULL table β reproduced exactly; consumers
NULL-deref (vega10_hwmgr.c:293-313).
F. Off-by-one state entry (DF-1588)
- vega10_get_powerplay_table_entry:1308 entry_index <= ucNumEntries lets
entry_index==ucNumEntries pass β states[N].usClassification read at
image_end+12 β SIGSEGV.
G. No regression: clean-valid β a complete, well-formed table parses
identically in baseline and fixed builds (23/23 structural checks OK,
including the state-entry callback path).
Fix A/B (same rig, same inputs, fix.diff applied to the same slice)
| family | baseline | fixed |
|---|---|---|
| deep offsets (state/thermal/number) | SIGSEGV +65281 | rc=-1/-22, range-checked |
| fan V2 / PowerTune V3 / hard-limit tail | SIGSEGV | rc=-EINVAL/-1, full-struct range checks |
| count-255 copy loops | SIGSEGV / byte-exact leak | counts clamped to image (1/2/5), 0 leaked |
od ACG [count-1] |
SIGSEGV +3298 / OOB decision bit | clamped, decision bit in-image |
| pcie NULL sclk | SIGSEGV addr 0 | rc=-EINVAL (NULL guard) |
| vddc lookup write | SIGSEGV obj+86 / 247 strided writes | canary intact, count=8 |
| dcefclk pioneer write | SIGSEGV obj+232 / +6892 overwrite | canary intact, loop=8 |
| result clobber | rc=0, NULL vddc table | rc=1 propagated |
| entry off-by-one | SIGSEGV image_end+12 | rc=-1 (< + per-entry range check) |
| clean-valid | OK | identical |
fix_status: fixed (baseline reproduced on the verbatim slice; patched slice clean on every mode; valid tables parse identically).
Hardware gating (unchanged from the pre-verification assessment)
In-kernel execution requires an AMD Vega10 ASIC: the parse runs at driver
attach (ROM-provided table) or on root-written pp_table sysfs re-parse
(amd_powerplay.c:671-706 β kmemdup + soft_pp_table swap + reset). This
guest has no 0x1002 PCI device, no /dev/dri, no amdgpu module (env.txt), so
the guest kernel never executes the path; reproduction is in the verbatim rig
per the established evidence class for crafted-firmware parsers. There is no
unprivileged userland trigger on stock hardware; the realistic vectors are a
crafted/corrupt VBIOS (flashed ROM, vfio romfile, malicious device) or the
root-gated sysfs blob.
Impact ceiling
Strongest proven primitive: attacker-controlled heap OOB write up to
~6.6 KB past a kmalloc-256 object (dcefclk pioneer) and a 2463-byte strided
overwrite past a kmalloc-128 object (vddc lookup), both with byte-exact
content control from the firmware image; plus a byte-exact kernel-heap info
leak into sysfs-visible tables and several panic paths. Recorded impact
"dos" follows the DF-4165 precedent for the identical evidence class and
gating (heap OOB write proven in verbatim code, in-kernel execution
ASIC-gated, no unprivileged trigger).
Corrections to the pre-verification pack (this run)
- The verbatim rig supersedes the syntax-check + clamp-unit-test approach
(
vega10_clamp_test.c,vega10_processpptables_fixed.cremoved). - The finding text calls the GFXCLK V2 record "12-byte"; the packed struct is
13 bytes (
ulClk 4 + ucVddInd 1 + usCKSVOffsetandDisable 2 + usAVFSOffset 2 + ucACGEnable 1 + ucReserved[3] 3, vega10_pptable.h:147-154) β the rig measures and uses sizeof() throughout; no impact on any defect or fix. - fix.diff required NO corrections this run (applies fuzz=0, compiles clean, all modes fixed; contrast DF-4247 where the pre-verification fix had two compile bugs).
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.
Fix verification
fixedFIXED in the verbatim rig (same slice + fix.diff, identical inputs): all 16 baseline fault modes clean (offsets range-checked to soft_pp_table_size, counts clamped to image and destination, fan/PowerTune full-struct checks, pcie NULL guard, off-by-one '<' + per-entry range check, lookup failures propagated), both heap OOB writes gone (canaries intact, loops clamped to 8), all leaks gone (0 OOB records), and the fully valid table parses IDENTICALLY to baseline (23/23 structural checks) - no regression. In-kernel validation remains ASIC-gated on this guest (same as baseline).
run.log FIXED half (every mode vs baseline); build.log (fix.diff fuzz=0 forward-apply + byte-exact reverse-restore proof); rig/pp_slice_fixed.inc generation in rig/gen_rig.sh
Confirmed kernel references
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:82
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:134
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:214
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:273
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:488
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:620
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:740
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:781
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:814
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1036
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1103
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1249
- sys/dev/drm/amd/powerplay/hwmgr/vega10_processpptables.c:1308
- sys/dev/drm/amd/powerplay/hwmgr/vega10_pptable.h:73
- sys/dev/drm/amd/powerplay/amd_powerplay.c:671
Detail
Exploit chain
crafted VBIOS PowerPlay table (ROM flash / vfio romfile / malicious device) or root pp_table sysfs blob -> vega10_pp_tables_initialize on Vega10 -> (a) u8-count heap OOB WRITE: vddc_lookup ucNumEntries=255 vs max_levels=8 overwrites 2463 bytes past a kmalloc-128 slab object with fully attacker-chosen u16 values (adjacent-object corruption); dcefclk pioneer count=255 overwrites ~6.6KB past a kmalloc-256 object -> memory corruption / code-exec potential on the ASIC; (b) count-driven OOB reads clone adjacent kernel heap into sysfs-visible DPM tables -> kernel-heap info leak; (c) u16 offsets -> deep OOB reads/NULL deref -> panic; (d) masked lookup failure -> NULL-table consumer crash. No unprivileged trigger on stock hardware.
Evidence (decisive lines)
run.log/run.2.log/run.3.log (3 stable runs, 16 FAULTs each, baseline vs fixed A/B); build.log (23/23 VERBATIM blocks identical on guest /usr/src/sys + fix.diff forward/reverse proof + cc build); leak_sample.txt (decisive leak/overwrite lines); env.txt (guest uname, no-AMD-GPU gate, host/guest parser sha256 equality); rig/ (full reproducible rig); fix.diff (validated artifact)
PoC changes
Replaced the pre-verification syntax-check + clamp-unit-test approach (vega10_clamp_test.c / vega10_processpptables_fixed.c, removed) with the full verbatim rig per the proven DF-4165/DF-4247 evidence class: machine-extracted parser slice + 22 header slices, guest-side verbatim checker, 23 crafted-table modes with guard/victim images and guard/canary destinations. Rig fixes during bring-up: unbuffered stdout so fault reports survive _exit; 22-page guard tail (a 1-page guard let the +0xFF00 reads land in adjacent heap mappings); pr_info / u8-u16 typedef / GetIndexIntoMasterDataTable shims; offsetof()-driven GFXCLK V2 ucACGEnable (+9, not +8) in the leak-expectation math.
Verified recommended fix
central vega10_pp_table_range_ok/vega10_pp_clamp_count/VEGA10_SUBTABLE_OK layer with destination-constant clamps (VDDC 8, VDDMEM/VDDCI 4, DCEFCLK NUM_DSPCLK_LEVELS), full-struct range checks for fan/PowerTune rev dispatch, pcie NULL guard, entry_index '<' fix, and result propagation in init_dpm_2_parameters (fix.diff, A/B-validated in the rig)
Verdict
REPRODUCED via the DF-4165/DF-4247 verbatim-rig evidence class: the ENTIRE production parser (vega10_processpptables.c:34-1326, checker-proven byte-identical ON THE GUEST against /usr/src/sys, the tree its running kernel was built from; 23/23 VERBATIM blocks, fix.diff forward/reverse proven) compiled into a harness and driven with crafted ATOM_Vega10 PowerPlay tables. Baseline: 16 SIGSEGVs at exactly the predicted sites across 3 runs (identical fault-offset fingerprints) - u16 subtable offsets dereferenced at image+65281 (check_powerplay_tables:82, get_number_of_entries:1249, init_thermal_controller:134), tail overreads at image_end+0..31 (count-255 copy loops for socclk/mclk/pixclk/mm/gfxclk V1, fan rev>10 V2 walk:214, PowerTune rev7 V3 overread:488, hard-limit entries[0]:814, od entries[254].ucACGEnable +3298:273), the get_pcie_table:781 NULL vdd_dep_on_sclk deref at addr 0x0 (DF-1587), and TWO HEAP OOB WRITES past kzalloc'd objects: get_vddc_lookup_table:1036 SIGSEGV at obj+86 of an 84-byte kmalloc-128 object with 247/247 OOB us_vdd writes byte-exact equal to the crafted image bytes (strided 2-byte overwrite to +2463, DF-1586), and the dcefclk pioneer path :740-748 SIGSEGV at obj+232 of a 228-byte kmalloc-256 object with a 1232-byte attacker-controlled overwrite reaching +6892. Leak legs byte-exact: 35/35 socclk and 38/38 GFXCLK V2-walk OOB records equal the bytes past the image (kernel-heap values surface to userland via powerplay sysfs), and the overdrive-limit engineClock decision bit provably comes from an OOB byte 490 bytes past the image. init_dpm_2_parameters:1103-1128 result-clobbering proven: parse returns rc=0 with NULL vddc_lookup_table (DF-3702 feeder). entry off-by-one :1308 ('<=') SIGSEGVs at image_end+12 (DF-1588). FIX A/B-VALIDATED in the same rig: fix.diff applied to the same slice - every crafted mode clean (range-checked offsets, clamped counts, NULL guard, '<' fix, propagated failures) and clean-valid parses IDENTICALLY (no regression). In-kernel execution AMD-ASIC-gated on this guest (no 0x1002 device, no /dev/dri, no amdgpu module - env.txt); threat model = crafted/corrupt VBIOS at driver attach or root-written pp_table sysfs re-parse; no unprivileged trigger on stock hardware. Impact 'dos' follows the DF-4165 precedent for the identical evidence class and gating (attacker-controlled heap OOB write proven in verbatim code, ASIC-gated in kernel).
No comments yet.