--- 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] +