DragonFlyBSD Kernel Audit
DF-1534 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/radeon/atom.c b/sys/dev/drm/radeon/atom.c
--- a/sys/dev/drm/radeon/atom.c
+++ b/sys/dev/drm/radeon/atom.c
@@ -60,10 +60,12 @@
 	unsigned last_jump;
 	unsigned long last_jump_jiffies;
 	bool abort;
+	int recursion_depth;
 } atom_exec_context;
 
 int atom_debug = 0;
-static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
+static int atom_execute_table_locked(struct atom_context *ctx, int index,
+					    uint32_t * params, int recursion_depth);
 
 static uint32_t atom_arg_mask[8] = {
 	0xFFFFFFFF, 0x0000FFFF, 0x00FFFF00, 0xFFFF0000,
@@ -631,7 +633,8 @@
 	else
 		ATOM_SDEBUG_PRINT("   table: %d\n", idx);
 	if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
-		r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
+		r = atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift,
+					    ctx->recursion_depth + 1);
 	if (r) {
 		ctx->abort = true;
 	}
@@ -1160,7 +1163,8 @@
 	atom_op_shr, ATOM_ARG_MC}, {
 atom_op_debug, 0},};
 
-static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
+static int atom_execute_table_locked(struct atom_context *ctx, int index,
+					    uint32_t * params, int recursion_depth)
 {
 	int base = CU16(ctx->cmd_table + 4 + 2 * index);
 	int len, ws, ps, ptr;
@@ -1168,6 +1172,9 @@
 	atom_exec_context ectx;
 	int ret = 0;
 
+	if (recursion_depth > 20)
+		return -EINVAL;
+
 	if (!base)
 		return -EINVAL;
 
@@ -1237,7 +1244,7 @@
 	/* reset divmul */
 	ctx->divmul[0] = 0;
 	ctx->divmul[1] = 0;
-	r = atom_execute_table_locked(ctx, index, params);
+	r = atom_execute_table_locked(ctx, index, params, 0);
 	lockmgr(&ctx->mutex, LK_RELEASE);
 	return r;
 }