DragonFlyBSD Kernel Audit
DF-1253 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/sys/dev/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
--- a/sys/dev/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -3093,8 +3093,14 @@
 
 	/* Hardmin is dependent on displayconfig */
 	if (disable_mclk_switching) {
+		if (dpm_table->count == 0)
+			goto skip;
 		dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
-		for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
+		/* data->mclk_latency_table.count is uint32_t; guard against the
+		 * 0-1 underflow that would otherwise iterate ~4G times and read
+		 * entries[]/dpm_levels[] OOB past MAX_REGULAR_DPM_NUMBER(16). */
+		for (i = 0; i + 1 < data->mclk_latency_table.count &&
+		     i < MAX_REGULAR_DPM_NUMBER; i++) {
 			if (data->mclk_latency_table.entries[i].latency <= latency) {
 				if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
 					dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
@@ -3103,9 +3109,12 @@
 			}
 		}
 	}
-
-	if (hwmgr->display_config->nb_pstate_switch_disable)
+skip:
+	if (hwmgr->display_config->nb_pstate_switch_disable) {
+		if (dpm_table->count == 0)
+			return 0;
 		dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
+	}
 
 	/* vclk */
 	dpm_table = &(data->dpm_table.vclk_table);