DF-4054 / fix.diff
# 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; } |