DragonFlyBSD Kernel Audit
DF-1127 / fix.diff
← back to finding ↓ download raw
# DF-1127 fix: validates nonClockInfoIndex against ucNumEntries.
# NOTE: the finding cited sys/dev/drm/amd/amdgpu/si_dpm.c which is
# NOT compiled (absent from amdgpu Makefile SRCS). The live copy is
# sys/dev/drm/radeon/si_dpm.c (compiled into radeon.ko). Both fixed.

diff --git a/sys/dev/drm/amd/amdgpu/si_dpm.c b/sys/dev/drm/amd/amdgpu/si_dpm.c
--- a/sys/dev/drm/amd/amdgpu/si_dpm.c
+++ b/sys/dev/drm/amd/amdgpu/si_dpm.c
@@ -7251,6 +7251,17 @@
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
+		/*
+		 * nonClockInfoIndex is read from the (untrusted) VBIOS.
+		 * Validate against ucNumEntries exactly like the sibling
+		 * clock loop below does for clockInfoIndex -- otherwise a
+		 * malformed BIOS yields an OOB read from the BIOS mapping.
+		 */
+		if (non_clock_array_index >= non_clock_info_array->ucNumEntries) {
+			power_state_offset +=
+			    2 + power_state->v2.ucNumDPMLevels;
+			continue;
+		}
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
 		ps = kzalloc(sizeof(struct  si_ps), GFP_KERNEL);
diff --git a/sys/dev/drm/radeon/si_dpm.c b/sys/dev/drm/radeon/si_dpm.c
--- a/sys/dev/drm/radeon/si_dpm.c
+++ b/sys/dev/drm/radeon/si_dpm.c
@@ -6846,6 +6846,17 @@
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
+		/*
+		 * nonClockInfoIndex is read from the (untrusted) VBIOS.
+		 * Validate against ucNumEntries exactly like the sibling
+		 * clock loop below does for clockInfoIndex -- otherwise a
+		 * malformed BIOS yields an OOB read from the BIOS mapping.
+		 */
+		if (non_clock_array_index >= non_clock_info_array->ucNumEntries) {
+			power_state_offset +=
+			    2 + power_state->v2.ucNumDPMLevels;
+			continue;
+		}
 		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)