⬢ DragonFlyBSD Kernel Audit
DF-4117 / fix.diff
← back to finding ↓ download raw
Fix for DF-4117 (cypress-side halves): free eg_pi on cypress_dpm_init early failures instead of leaking it, and make cypress_dpm_fini idempotent (NULL ps/priv after kfree so a fini after a failed init cannot double-free).  MUST be combined with the shared rv7xx_parse_power_table error-path fix (free ps_priv[0..i-1], NULL rdev->pm.dpm.ps at rv770_dpm.c:2306-2310) — identical to the DF-4023/DF-3973 family fix, reproduced at the bottom of this file.

--- a/sys/dev/drm/radeon/cypress_dpm.c
+++ b/sys/dev/drm/radeon/cypress_dpm.c
@@ -2044,12 +2044,18 @@
 	pi->max_vddc_in_table = 0;
 
 	ret = r600_get_platform_caps(rdev);
-	if (ret)
+	if (ret) {
+		kfree(eg_pi);
+		rdev->pm.dpm.priv = NULL;
 		return ret;
+	}
 
 	ret = rv7xx_parse_power_table(rdev);
-	if (ret)
+	if (ret) {
+		kfree(eg_pi);
+		rdev->pm.dpm.priv = NULL;
 		return ret;
+	}
 
 	if (rdev->pm.dpm.voltage_response_time == 0)
 		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
@@ -2151,7 +2157,9 @@
 		kfree(rdev->pm.dpm.ps[i].ps_priv);
 	}
 	kfree(rdev->pm.dpm.ps);
+	rdev->pm.dpm.ps = NULL;
 	kfree(rdev->pm.dpm.priv);
+	rdev->pm.dpm.priv = NULL;
 }
 
 bool cypress_dpm_vblank_too_short(struct radeon_device *rdev)

Shared-site half of the DF-4117 fix (rv7xx_parse_power_table error path, serves rv770/btc/cypress dispatches):

--- a/sys/dev/drm/radeon/rv770_dpm.c
+++ b/sys/dev/drm/radeon/rv770_dpm.c
@@ -2305,7 +2305,10 @@
 			u8 *idx;
 			ps = kzalloc(sizeof(struct rv7xx_ps), GFP_KERNEL);
 			if (ps == NULL) {
+				while (i > 0)
+					kfree(rdev->pm.dpm.ps[--i].ps_priv);
 				kfree(rdev->pm.dpm.ps);
+				rdev->pm.dpm.ps = NULL;
 				return -ENOMEM;
 			}
 			rdev->pm.dpm.ps[i].ps_priv = ps;