From eb0d0eb4d1b16be7bd71defd341f55fc3af74809 Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Wed, 2 Jan 2013 21:48:57 +0000 Subject: [PATCH] Prevent crashes from occurring when reading from data sources with large values When reading configuration data from an Asterisk .conf file or when pulling data from an Asterisk RealTime backend, Asterisk was copying the data on the stack for manipulation. Unfortunately, it is possible to read configuration data or realtime data from some data source that provides a large blob of characters. This could potentially cause a crash via a stack overflow. This patch prevents large sets of data from being read from an ARA backend or from an Asterisk conf file. (issue ASTERISK-20658) Reported by: wdoekes Tested by: wdoekes, mmichelson patches: * issueA20658_dont_process_overlong_config_lines.patch uploaded by wdoekes (license 5674) * issueA20658_func_realtime_limit.patch uploaded by wdoekes (license 5674) git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@378375 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- funcs/func_realtime.c | 17 +++++++++++++++++ main/config.c | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/funcs/func_realtime.c b/funcs/func_realtime.c index a1b6d200ee..6d7338c739 100644 --- a/funcs/func_realtime.c +++ b/funcs/func_realtime.c @@ -219,6 +219,13 @@ static int function_realtime_read(struct ast_channel *chan, const char *cmd, cha /* add space for delimiters and final '\0' */ resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1; + if (resultslen > len) { + ast_log(LOG_WARNING, "Failed to fetch. Realtime data is too large: need %zu, have %zu.\n", resultslen, len); + return -1; + } + + /* len is going to be sensible, so we don't need to check for stack + * overflows here. */ out = ast_str_alloca(resultslen); for (var = head; var; var = var->next) ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); @@ -439,6 +446,16 @@ static int function_realtime_readdestroy(struct ast_channel *chan, const char *c /* add space for delimiters and final '\0' */ resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1; + if (resultslen > len) { + /* Unfortunately this does mean that we cannot destroy the row + * anymore. But OTOH, we're not destroying someones data without + * giving him the chance to look at it. */ + ast_log(LOG_WARNING, "Failed to fetch/destroy. Realtime data is too large: need %zu, have %zu.\n", resultslen, len); + return -1; + } + + /* len is going to be sensible, so we don't need to check for stack + * overflows here. */ out = ast_str_alloca(resultslen); for (var = head; var; var = var->next) { ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); diff --git a/main/config.c b/main/config.c index 4a71c1f75c..f90cfc1638 100644 --- a/main/config.c +++ b/main/config.c @@ -1524,6 +1524,17 @@ static struct ast_config *config_text_file_load(const char *database, const char while (!feof(f)) { lineno++; if (fgets(buf, sizeof(buf), f)) { + /* Skip lines that are too long */ + if (strlen(buf) == sizeof(buf) - 1 && buf[sizeof(buf) - 1] != '\n') { + ast_log(LOG_WARNING, "Line %d too long, skipping. It begins with: %.32s...\n", lineno, buf); + while (fgets(buf, sizeof(buf), f)) { + if (strlen(buf) != sizeof(buf) - 1 || buf[sizeof(buf) - 1] == '\n') { + break; + } + } + continue; + } + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && ast_str_strlen(lline_buffer)) { CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ ast_str_reset(lline_buffer); /* erase the lline buffer */ -- 2.47.3