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; }