⬢ DragonFlyBSD Kernel Audit
DF-4054 / fix.diff
← back to finding ↓ download raw
# DF-4054 — vega12_setup_single_dpm_table SMU-fed num_of_levels unclamped
# smum_get_argument() returns a raw uint32 from the SMU firmware response
# register. vega12_get_number_of_dpm_level() only rejects 0
# (vega12_hwmgr.c:481-483); vega12_setup_single_dpm_table() then stores it
# in dpm_table->count (:518) and the fill loop writes dpm_levels[i]
# for i < num_of_levels (:520-527) past dpm_levels[MAX_REGULAR_DPM_NUMBER=16]
# (vega12_hwmgr.h:107-110) — a firmware-controlled linear heap overflow of
# the kzalloc'd struct vega12_hwmgr backend (12 bytes/entry).
# vega12_find_highest_dpm_level (:989) already asserts the count<=16
# invariant; enforce it where the value enters the kernel.
--- a/sys/dev/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
@@ -479,6 +479,10 @@ static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
 			"[GetNumOfDpmLevel] number of clk levels is invalid!",
 			return -EINVAL);
 
+	PP_ASSERT_WITH_CODE(*num_of_levels <= MAX_REGULAR_DPM_NUMBER,
+			"[GetNumOfDpmLevel] number of clk levels exceeds dpm_levels[]!",
+			return -EINVAL);
+
 	return ret;
 }