DragonFlyBSD Kernel Audit
DF-1544 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/amdgpu/atom.c b/sys/dev/drm/amd/amdgpu/atom.c
--- a/sys/dev/drm/amd/amdgpu/atom.c
+++ b/sys/dev/drm/amd/amdgpu/atom.c
@@ -60,6 +60,7 @@
 	unsigned last_jump;
 	unsigned long last_jump_jiffies;
 	bool abort;
+	int ps_size; /* declared param size, bytes */
 } atom_exec_context;
 
 int amdgpu_atom_debug = 0;
@@ -213,6 +214,12 @@
 	case ATOM_ARG_PS:
 		idx = U8(*ptr);
 		(*ptr)++;
+		if (idx + 4 > ctx->ps_size) {
+			DRM_ERROR("ATOM: ps read beyond params: %d vs. %d\n",
+				  idx, ctx->ps_size);
+			val = 0;
+			break;
+		}
 		/* get_unaligned_le32 avoids unaligned accesses from atombios
 		 * tables, noticed on a DEC Alpha. */
 		val = get_unaligned_le32((u32 *)&ctx->ps[idx]);
@@ -488,6 +495,11 @@
 		idx = U8(*ptr);
 		(*ptr)++;
 		DEBUG("PS[0x%02X]", idx);
+		if (idx + 4 > ctx->ps_size) {
+			DRM_ERROR("ATOM: ps write beyond params: %d vs. %d\n",
+				  idx, ctx->ps_size);
+			break;
+		}
 		ctx->ps[idx] = cpu_to_le32(val);
 		break;
 	case ATOM_ARG_WS:
@@ -1215,6 +1227,7 @@
 
 	ectx.ctx = ctx;
 	ectx.ps_shift = ps / 4;
+	ectx.ps_size = ps;
 	ectx.start = base;
 	ectx.ps = params;
 	ectx.abort = false;