From 264ffaebb1ff864c3efe94e591fcbc7f62a7e959 Mon Sep 17 00:00:00 2001 From: Naveen Albert Date: Thu, 21 Mar 2024 11:25:17 -0400 Subject: [PATCH] pbx_variables.c: Prevent SEGV due to stack overflow. It is possible for dialplan to result in an infinite recursion of variable substitution, which eventually leads to stack overflow. If we detect this, abort substitution and log an error for the user to fix the broken dialplan. Resolves: #480 UpgradeNote: The maximum amount of dialplan recursion using variable substitution (such as by using EVAL_EXTEN) is capped at 15. --- main/pbx_variables.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/main/pbx_variables.c b/main/pbx_variables.c index f589b6bce0..a08114ba4d 100644 --- a/main/pbx_variables.c +++ b/main/pbx_variables.c @@ -662,6 +662,11 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead pbx_substitute_variables_helper_full_location(c, headp, cp1, cp2, count, used, NULL, NULL, 0); } +/*! \brief Thread local keeping track of recursion depth */ +AST_THREADSTORAGE(varsub_recurse_level); + +#define MAX_VARIABLE_SUB_RECURSE_DEPTH 15 + void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, char *context, char *exten, int pri) { /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ @@ -669,8 +674,22 @@ void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct const char *orig_cp2 = cp2; char ltmp[VAR_BUF_SIZE]; char var[VAR_BUF_SIZE]; + int *recurse_depth; *cp2 = 0; /* just in case nothing ends up there */ + + /* It is possible to craft dialplan that will recurse indefinitely and cause a stack overflow. + * This is symptomatic of a dialplan bug, so abort substitution rather than crash. */ + recurse_depth = ast_threadstorage_get(&varsub_recurse_level, sizeof(*recurse_depth)); + if (!recurse_depth) { + return; + } + if ((*recurse_depth)++ >= MAX_VARIABLE_SUB_RECURSE_DEPTH) { + ast_log(LOG_ERROR, "Exceeded maximum variable substitution recursion depth (%d) - possible infinite recursion in dialplan?\n", MAX_VARIABLE_SUB_RECURSE_DEPTH); + (*recurse_depth)--; + return; + } + whereweare = cp1; while (!ast_strlen_zero(whereweare) && count) { char *nextvar = NULL; @@ -881,6 +900,7 @@ void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct if (used) { *used = cp2 - orig_cp2; } + (*recurse_depth)--; } void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count) -- 2.47.2