vega10_get_sclk_od/get_mclk_od divide by zero when the golden top clock is 0 (crafted VBIOS) β world-readable sysfs trigger
Summary
vega10_setup_default_single_dpm_table appends the first dep entry unconditionally, so a GFXCLK/MCLK dependency table whose entries are all ulClk==0 yields golden_dpm_table top value 0; vega10_get_sclk_od/get_mclk_od then compute DIV_ROUND_UP(value*100, golden_value) -> integer #DE -> kernel panic. The pp_sclk_od sysfs attr is S_IRUGO, so with such a VBIOS ANY local user can trigger it via 'cat'. Crafted/blank-field VBIOS precondition keeps it Low.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3707 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.6 KB | β raw | |
| VERDICT.md | β | 1.7 KB | β raw | |
| trigger_notes.c | β | 998 B | view raw | |
| build.sh | β | 86 B | view raw | |
| run.sh | β | 166 B | view raw | |
| run.log | β | 437 B | view raw | |
| env.txt | β | 848 B | view raw | |
| fix.diff | β | 892 B | view raw | |
| manifest.json | β | 925 B | view raw | |
| verdict.json | β | 2.2 KB | view raw |
DF-3707 β vega10_get_sclk_od / vega10_get_mclk_od divide by zero when the top golden clock is 0 (crafted VBIOS)
File: sys/dev/drm/amd/powerplay/hwmgr/vega10_hwmgr.c (pass 2).
Bug (:4529-4543, :4580-4594)
int value = sclk_table->dpm_levels[sclk_table->count - 1].value; // :4535
int golden_value = golden_sclk_table->dpm_levels
[golden_sclk_table->count - 1].value; // :4536-4537
value -= golden_value;
value = DIV_ROUND_UP(value * 100, golden_value); // :4540 <- /0
golden_sclk_table is the saved default dpm table; vega10_setup_default_single_dpm_table
(:1200-1217) appends entry 0 unconditionally (i == 0 ||), so a GFXCLK dependency table whose
entries are all ulClk == 0 (e.g. ucNumEntries == 1 with ulClk == 0) produces
dpm_levels[0].value == 0, count == 1 β golden_value == 0 β integer division by zero β
kernel trap (#DE) β panic. Identical shape for MCLK at :4586-4591.
Reachability (wider than the other vega10 findings)
The sysfs node is WORLD-READABLE: amdgpu_pm.c:1019-1020
static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR, amdgpu_get_pp_sclk_od, ...) β
cat /sys/class/drm/card0/device/pp_sclk_od by ANY local user calls get_sclk_od β
DIV_ROUND_UP β #DE. Precondition is still the crafted-VBIOS (golden 0 clock), so overall
severity Low.
Trigger (requires AMD Vega10 hardware)
VBIOS with a single GFXCLK dependency entry ulClk=0 (and matching MCLK for the mclk twin),
then any local unprivileged cat .../pp_sclk_od.
PoC status
Guest virtio-only β inconclusive, source-certain.
DF-3707 VERDICT β get_sclk_od/get_mclk_od divide-by-zero
status: inconclusive (hardware-gated) β source-certain. reproduced=0 on audit guest.
Proof chain (lines verified in guest /usr/src, see run.log)
- vega10_setup_default_single_dpm_table (:1208-1215) appends the first dep entry
unconditionally (
i == 0 || ...), so a GFXCLK dep table with a single ulClk==0 entry yields dpm_levels[0].value==0, count==1 β no lower-bound clamp exists anywhere. - golden_dpm_table is a memcpy of that table (:1417-1419).
- vega10_get_sclk_od :4535-4540: golden_value = dpm_levels[count-1].value == 0 β DIV_ROUND_UP(value100, 0) β (value100 + 0 - 1)/0 β integer #DE β kernel panic. vega10_get_mclk_od :4586-4591 identical.
- Trigger surface: amdgpu_pm.c:1019-1020 DEVICE_ATTR(pp_sclk_od, S_IRUGO|S_IWUSR, ...) β world-readable, so with the crafted VBIOS present ANY local user can panic the kernel (local DoS). vega10_dpm_get_sclk/get_mclk (:3659/:3681) also index [count-1] but count>=1 holds (asserted at :756/:761), so only the division is the fault.
Severity Low: requires the crafted/malformed VBIOS precondition; after that, unprivileged DoS.
Guest result
0 AMD PCI devices; amdgpu.ko never binds; pp_sclk_od absent. Lines confirmed in guest /usr/src (run.log). Verdict: inconclusive, source-certain.
Fix
fix.diff returns 0 when golden_value == 0 in both getters.
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 read-only sys/ tree; no AMD hw on guest so no patched-kernel validation possible
fix.diff; run.log hardware gate
Confirmed kernel references
Detail
Exploit chain
crafted VBIOS (single 0MHz GFXCLK/MCLK dep entry) -> unprivileged 'cat pp_sclk_od' -> DIV_ROUND_UP(x,0) #DE -> panic (DoS)
Evidence (decisive lines)
VERDICT.md; run.log (guest-src excerpt :4535-4540); trigger_notes.c (arithmetic demo); fix.diff
PoC changes
no runnable PoC possible (hardware-gated); documented chain + arithmetic
Verified recommended fix
Guard golden_value==0 and return 0 in both getters (fix.diff)
Verdict
Source-certain divide-by-zero: vega10_get_sclk_od (:4540) and vega10_get_mclk_od (:4591) divide by golden_dpm_table's top clock value, which is 0 when the crafted VBIOS dep table's first/max entry has ulClk==0 (setup_default_single_dpm_table :1209 appends entry 0 unconditionally); the pp_sclk_od sysfs attr is world-readable (amdgpu_pm.c:1019 S_IRUGO), so once such a VBIOS is present any local user can trigger the kernel #DE panic. Confidence 'likely' only because the full chain (0-clock golden table accepted through earlier stages) is argued from source, not executed. Not reproducible on the virtio-only audit guest (0 AMD PCI devices).
No comments yet.