mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 08:02:27 +02:00
drm/amd/display: Fix bounds checking in dml2_0 clock table array
[Why] Multiple locations in dml2_0 used num_clk_values-1 as array index without checking if num_clk_values > 0. When num_clk_values is 0, this results in accessing array index -1, which wraps to 255 for unsigned types, causing out-of-bounds memory access and potential crashes. [How] Add proper bounds checking using ternary operators to guard all num_clk_values-1 array accesses. When num_clk_values is 0, return 0 as fallback value instead of accessing invalid memory. This prevents buffer overflows while maintaining backward compatibility and provides sensible default behavior for empty clock tables. Reviewed-by: Dillon Varone <dillon.varone@amd.com> Signed-off-by: Gabe Teeger <gabe.teeger@amd.com> Signed-off-by: Chuanyu Tseng <chuanyu.tseng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
ee212b0208
commit
1f991ceb2c
|
|
@ -279,6 +279,26 @@ static bool round_up_and_copy_to_next_dpm(unsigned long min_value, unsigned long
|
|||
bool result = false;
|
||||
int index = 0;
|
||||
|
||||
/* Guard against empty clock tables (e.g. DTBCLK on DCN42B where the
|
||||
* clock is tied off and num_clk_values == 0). Without this check the
|
||||
* else-if branch below would evaluate
|
||||
* clk_values_khz[num_clk_values - 1] with num_clk_values == 0, which
|
||||
* wraps the unsigned char index to 255 — a 235-element out-of-bounds
|
||||
* read on an array of DML_MAX_CLK_TABLE_SIZE (20) entries.
|
||||
*
|
||||
* Semantic: if the clock doesn't exist on this ASIC but no frequency
|
||||
* is required (min_value == 0), the request is trivially satisfied.
|
||||
* If a non-zero frequency is required but the clock is absent, the
|
||||
* configuration is unsupportable.
|
||||
*/
|
||||
if (clock_table->num_clk_values == 0) {
|
||||
if (min_value == 0) {
|
||||
*rounded_value = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (clock_table->num_clk_values > 2) {
|
||||
while (index < clock_table->num_clk_values && clock_table->clk_values_khz[index] < min_value)
|
||||
index++;
|
||||
|
|
|
|||
|
|
@ -178,9 +178,12 @@ static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_
|
|||
|
||||
min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ?
|
||||
soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0;
|
||||
min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ?
|
||||
soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0;
|
||||
min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ?
|
||||
soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0;
|
||||
|
||||
min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
|
|
|
|||
|
|
@ -54,9 +54,12 @@ static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_
|
|||
|
||||
min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
|
||||
min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ?
|
||||
soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0;
|
||||
min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ?
|
||||
soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0;
|
||||
min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ?
|
||||
soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0;
|
||||
|
||||
min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user