vid_mapping_table num_entries==0 -> entries[0xFFFFFFFF] wild read (~16 GiB) in kv_convert_vid2_to_vid7 / kv_convert_vid7_to_vid2
Summary
sumo_construct_vid_mapping_table can leave num_entries==0 (empty sAvail_SCLK or missing IntegratedSystemInfo); with vddc_dependency_on_sclk.count==0 (KB/ML boards) the else-branch evaluates entries[num_entries-1] with u32 num_entries: index 0xFFFFFFFF x 4 = +0x3FFFFFFFC (~16 GiB) past the kv_power_info heap object -> boot panic. VERIFIED: harness prints displacement 0x3fffffffc (16.00 GiB); verbatim expression faults SIGSEGV. amdgpu twin DF-3890.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3956 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.3 KB | β raw | |
| VERDICT.md | β | 3.2 KB | β raw | |
| trigger_df3956.c | β | 5.8 KB | view raw | |
| build.sh | β | 92 B | view raw | |
| run.sh | β | 116 B | view raw | |
| build.log | β | 89 B | view raw | |
| run.log | β | 1.2 KB | view raw | |
| env.txt | β | 725 B | view raw | |
| fix.diff | β | 1.1 KB | view raw | |
| manifest.json | β | 1.8 KB | view raw | |
| verdict.json | β | 3.6 KB | view raw |
DF-3956 β radeon kv_dpm vid_mapping_table num_entries==0 β entries[0xFFFFFFFF] wild read (~16 GiB)
File: sys/dev/drm/radeon/kv_dpm.c (pass 2, GLM 5.3)
Severity: Low Β· CWE: CWE-191/CWE-125 (integer underflow β OOB read)
Confidence: certain (source) Β· Status: inconclusive on guest (no AMD GPU);
arithmetic-simulation harness verified.
What
sumo_construct_vid_mapping_table() (sumo_dpm.c:1616-1645) ends with
vid_mapping_table->num_entries = i; where i == 0 when no entry obtained a
nonzero vid_7bit β i.e. the VBIOS IntegratedSystemInfo table's
sAvail_SCLK[] list has all-zero ulSupportedSCLK values, or the
IntegratedSystemInfo table is missing entirely, in which case
kv_parse_sys_info_table() (kv_dpm.c:2495-2546) skips the whole body and still
return 0 (success), leaving the kzalloc'd table all-zero.
Consumers in this file take the else-branch whenever
vddc_dependency_on_sclk.count == 0 (Kabini/Mullins boards lacking the sclk
dependency table):
kv_convert_vid2_to_vid7() kv_dpm.c:562-566 /* loop 0 iterations */
return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit;
kv_convert_vid7_to_vid2() kv_dpm.c:585-590 /* same expression */
num_entries is u32 (sumo_dpm.h:65), sizeof(entry) = 4 β index
0xFFFFFFFF β +0x3FFFFFFFC (~16 GiB) past the kv_power_info heap object β
kernel page fault β panic.
Boot-time reachability: kv_dpm_enable β kv_init_graphics_levels
(:2344, else-branch) β kv_set_vid (:2382β:618) / high-voltage check
(:2378) β kv_convert_2bit_index_to_voltage (:604) β :566; also
kv_parse_sys_info_table β kv_construct_max_power_limits_table
(:2543β:1973) and kv_get_high_voltage_limit (:2122).
Scope note
The usVoltageIndex OOB write inside sumo_construct_vid_mapping_table
itself is DF-1437 (sumo_dpm.c, already filed) β not re-reported here. This
finding is the kv_dpm.c consumer-side underflow. amdgpu twin: DF-3890 (Low).
Reproduce
cd findings/poc/DF-3956 ./build.sh # cc -O2 -Wall -o trigger_df3956 trigger_df3956.c ./run.sh
Expected (crash mode): entries[0xffffffff] -> +0x3fffffffc (16.00 GiB),
child SIGSEGV sig=11, RESULT: WILD READ FAULTS AS PREDICTED.
Fix
Guard num_entries == 0 in both converters (fix.diff, in-file).
DF-3956 VERDICT
Verdict: INCONCLUSIVE at kernel level (no AMD GPU) β source-certain u32 underflow wild read at +0x3FFFFFFFC (~16 GiB); the verbatim consumer expression faults in the userland simulation exactly as predicted.
Trace
-
Producer can legitimately produce num_entries == 0. sumo_construct_vid_mapping_table (sumo_dpm.c:1616-1645): entries are only written for
table[i].ulSupportedSCLK != 0; the compaction loop then breaks withi == 0whenentries[0].vid_7bit == 0(empty table). Also, kv_parse_sys_info_table (kv_dpm.c:2495-2546) treats a missing IntegratedSystemInfo table as success (return 0outside theatom_parse_data_headerguard), leaving the whole kzalloc'dpi->sys_info.vid_mapping_tablezeroed β num_entries == 0 without any crafted sAvail_SCLK at all. -
Consumer underflow (this file). kv_convert_vid2_to_vid7 (kv_dpm.c:548-568) and kv_convert_vid7_to_vid2 (:570-592) only touch vid_mapping_table when
vddc_sclk_table->count == 0(the else-branch) β true on KB/ML boards whose VBIOS lacks the sclk voltage-dependency table. With num_entries == 0 the match loop runs zero iterations and falls through toentries[num_entries - 1]: num_entries isu32(sumo_dpm.h:64-67) β 0xFFFFFFFF, entry size 4 β displacement 0xFFFFFFFF Γ 4 = 0x3FFFFFFFC β 16 GiB past the kv_power_info object. -
Boot-time call-in. kv_dpm_enable β kv_init_graphics_levels else-branch (kv_dpm.c:2370-2386): kv_set_vid (:2382 β :612-621 β kv_convert_2bit_index_to_voltage :604 β :566) and the high-voltage break check (:2378). Earlier still: kv_dpm_init β kv_parse_sys_info_table β kv_construct_max_power_limits_table (:2543 β :1973) and kv_get_high_voltage_limit (:2122). All boot-time on the target APU with the crafted/empty VBIOS.
Harness
Replicates the producer's num_entries computation (0 on the all-zero
sAvail_SCLK list), the consumer's verbatim entries[num_entries - 1].vid_7bit
expression, and the struct layout (_Static_assert(entry==4)). Crash mode
places the table against a guard page: child SIGSEGV sig=11; analysis prints
entries[0xffffffff] -> +0x3fffffffc (16.00 GiB).
Why Low
Wild load (a 16-bit vid value) feeding voltage math; no write, no leak channel; trigger needs KV-family APU + VBIOS with both the sclk dependency table absent and the vid mapping empty/missing. Precedent: amdgpu twin DF-3890 (Low). (The sibling DF-1437 in sumo_dpm.c covers the OOB write inside the producer β different file, different primitive, already filed.)
Fix validation
fix.diff adds num_entries == 0 guards returning 0 in both converters
(in-file fix; a producer-side clamp in sumo_dpm.c would also work but is that
file's scope). Not built on the guest (no AMD GPU): fix_status:
not_testable. Guards are trivially sufficient by inspection.
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
not_testablefix.diff authored against the read-only sys/ tree; not built - no AMD hardware on the guest. Guards remove both sinks by construction.
findings/poc/DF-3956/fix.diff
Confirmed kernel references
Detail
Exploit chain
KV/KB/ML APU with VBIOS lacking the sclk dependency table AND an empty/missing IntegratedSystemInfo vid mapping -> boot-time kv_init_graphics_levels -> kv_convert_vid2_to_vid7 -> wild read ~16 GiB out -> page fault -> panic (DoS). Load-only 16-bit value feeding voltage math; no write, no leak channel.
Evidence (decisive lines)
run.log: 'producer: sumo_construct_vid_mapping_table -> num_entries = 0', 'consumer: kv_convert_vid2_to_vid7 :566 -> entries[0xffffffff] -> +0x3fffffffc (16.00 GiB)', 'child: SIGNALLED sig=11', 'RESULT: WILD READ FAULTS AS PREDICTED'; VERDICT.md; fix.diff
PoC changes
No seed (pass-2 self-authored). Two fix cycles: missing
Verified recommended fix
num_entries==0 early-outs returning 0 in kv_convert_vid2_to_vid7 and kv_convert_vid7_to_vid2 (fix.diff); ideally also treat a missing IntegratedSystemInfo table as an error in kv_parse_sys_info_table.
Verdict
Source-certain u32-underflow wild read, amdgpu twin DF-3890 (Low). sumo_construct_vid_mapping_table (sumo_dpm.c:1616-1645, producer - its usVoltageIndex OOB write is already DF-1437, NOT re-reported) leaves vid_mapping_table.num_entries==0 when sAvail_SCLK has no nonzero ulSupportedSCLK, and kv_parse_sys_info_table (kv_dpm.c:2495-2546) also 'succeeds' with an all-zero table when IntegratedSystemInfo is missing entirely. With vddc_dependency_on_sclk.count==0 (KB/ML) the else-branch of kv_convert_vid2_to_vid7 (:566) / kv_convert_vid7_to_vid2 (:590) evaluates entries[num_entries - 1] with u32 num_entries (sumo_dpm.h:65): index 0xFFFFFFFF * sizeof(entry)=4 = +0x3FFFFFFFC (~16 GiB) past the kv_power_info heap object -> kernel page fault -> panic. Boot path: kv_dpm_enable -> kv_init_graphics_levels else-branch (:2382->kv_set_vid:618 / :2378) and kv_parse_sys_info_table -> kv_construct_max_power_limits_table (:2543->:1973). Harness: producer replay yields num_entries=0; verbatim consumer expression faults SIGSEGV against a guard page; displacement print 0x3fffffffc (16.00 GiB). Runtime-inconclusive: no AMD GPU on guest.
No comments yet.