⬢ DragonFlyBSD Kernel Audit
DF-4190 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/sumo_dpm.c
+++ b/sys/dev/drm/radeon/sumo_dpm.c
@@ -1493,6 +1493,17 @@
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
+		/* DF-4190: both indices are u8 values from the VBIOS image and
+		 * were never bounds-checked; a crafted table reads past the
+		 * NonClockInfoArray / ClockInfoArray in the kmalloc'd BIOS
+		 * image. */
+		if (non_clock_array_index >= non_clock_info_array->ucNumEntries) {
+			DRM_ERROR("invalid nonClockInfoIndex %d\n",
+			    non_clock_array_index);
+			kfree(rdev->pm.dpm.ps);
+			rdev->pm.dpm.ps = NULL;
+			return -EINVAL;
+		}
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
 		if (!rdev->pm.power_state[i].clock_info)
@@ -1509,6 +1520,15 @@
 			clock_array_index = idx[j];
 			if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
 				break;
+			if (clock_array_index >= clock_info_array->ucNumEntries) {
+				DRM_ERROR("invalid clockInfoIndex %d\n",
+				    clock_array_index);
+				for (; i >= 0; i--)
+					kfree(rdev->pm.dpm.ps[i].ps_priv);
+				kfree(rdev->pm.dpm.ps);
+				rdev->pm.dpm.ps = NULL;
+				return -EINVAL;
+			}
 
 			clock_info = (union pplib_clock_info *)
 				((u8 *)&clock_info_array->clockInfo[0] +