⬢ DragonFlyBSD Kernel Audit
DF-4665 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/powerplay/hwmgr/smu_helper.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/smu_helper.c
@@ -672,7 +672,8 @@ void *smu_atom_get_data_table(void *dev,
 }
 
 int smu_get_voltage_dependency_table_ppt_v1(
-			const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
-			struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
+			const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
+			struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
+			uint32_t max_entries)
 {
-	uint8_t i = 0;
+	uint32_t i;
 	PP_ASSERT_WITH_CODE((0 != allowed_dep_table->count),
 				"Voltage Lookup Table empty",
 				return -EINVAL);
 
-	dep_table->count = allowed_dep_table->count;
+	/* The destination tables of all callers are fixed-size embedded
+	 * arrays (entries[MAX_REGULAR_DPM_NUMBER]); never copy more than
+	 * the destination can hold.  Also fixes the uint8_t loop counter
+	 * wrap (infinite loop) when count > 255 (DF-1799). */
+	dep_table->count = (allowed_dep_table->count > max_entries)
+				? max_entries : allowed_dep_table->count;
 	for (i=0; i<dep_table->count; i++) {
 		dep_table->entries[i].clk = allowed_dep_table->entries[i].clk;
 		dep_table->entries[i].vddInd = allowed_dep_table->entries[i].vddInd;
--- a/sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -841,12 +841,12 @@ static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
 
-	smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table,
-		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk));
+	smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table,
+		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk),
+		MAX_REGULAR_DPM_NUMBER);
@@ -855,8 +855,8 @@ static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
 
-	smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table,
-		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk));
+	smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table,
+		(struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk),
+		MAX_REGULAR_DPM_NUMBER);
--- a/sys/dev/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -320,8 +320,9 @@ static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
 
 	for (i = 0; i < 3; i++)
-		smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]);
+		smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i],
+				MAX_REGULAR_DPM_NUMBER);
 
-	if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000)
+	if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000)
--- a/sys/dev/drm/amd/powerplay/hwmgr/smu_helper.h
+++ b/sys/dev/drm/amd/powerplay/hwmgr/smu_helper.h
@@ -114,7 +114,8 @@
 
-int smu_get_voltage_dependency_table_ppt_v1(
-			const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
-			struct phm_ppt_v1_clock_voltage_dependency_table *dep_table);
+int smu_get_voltage_dependency_table_ppt_v1(
+			const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
+			struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
+			uint32_t max_entries);