⬢ DragonFlyBSD Kernel Audit
DF-4371 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/r600_dpm.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/dev/drm/radeon/r600_dpm.c	2026-09-19 18:44:01.666218647 +0000
@@ -937,6 +937,7 @@
 							       dep_table);
 			if (ret) {
 				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+				rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries = NULL;
 				return ret;
 			}
 		}
@@ -948,7 +949,9 @@
 							       dep_table);
 			if (ret) {
 				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+				rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries = NULL;
 				kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
+				rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries = NULL;
 				return ret;
 			}
 		}
@@ -960,8 +963,11 @@
 							       dep_table);
 			if (ret) {
 				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
+				rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries = NULL;
 				kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
+				rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries = NULL;
 				kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries);
+				rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries = NULL;
 				return ret;
 			}
 		}
@@ -1300,18 +1306,25 @@
 {
 	struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state;
 
-	kfree(dyn_state->vddc_dependency_on_sclk.entries);
-	kfree(dyn_state->vddci_dependency_on_mclk.entries);
-	kfree(dyn_state->vddc_dependency_on_mclk.entries);
-	kfree(dyn_state->mvdd_dependency_on_mclk.entries);
-	kfree(dyn_state->cac_leakage_table.entries);
-	kfree(dyn_state->phase_shedding_limits_table.entries);
-	kfree(dyn_state->ppm_table);
-	kfree(dyn_state->cac_tdp_table);
-	kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
-	kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
-	kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
-	kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
+	/*
+	 * NULL every pointer after kfree(): this function is reachable a
+	 * second time (parse error paths above plus *_dpm_fini() at driver
+	 * unload/reboot); a stale non-NULL pointer here is a double free.
+	 */
+#define RADEON_KFREE_NULL(p) do { kfree(p); (p) = NULL; } while (0)
+	RADEON_KFREE_NULL(dyn_state->vddc_dependency_on_sclk.entries);
+	RADEON_KFREE_NULL(dyn_state->vddci_dependency_on_mclk.entries);
+	RADEON_KFREE_NULL(dyn_state->vddc_dependency_on_mclk.entries);
+	RADEON_KFREE_NULL(dyn_state->mvdd_dependency_on_mclk.entries);
+	RADEON_KFREE_NULL(dyn_state->cac_leakage_table.entries);
+	RADEON_KFREE_NULL(dyn_state->phase_shedding_limits_table.entries);
+	RADEON_KFREE_NULL(dyn_state->ppm_table);
+	RADEON_KFREE_NULL(dyn_state->cac_tdp_table);
+	RADEON_KFREE_NULL(dyn_state->vce_clock_voltage_dependency_table.entries);
+	RADEON_KFREE_NULL(dyn_state->uvd_clock_voltage_dependency_table.entries);
+	RADEON_KFREE_NULL(dyn_state->samu_clock_voltage_dependency_table.entries);
+	RADEON_KFREE_NULL(dyn_state->acp_clock_voltage_dependency_table.entries);
+#undef RADEON_KFREE_NULL
 }
 
 enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev,