Merged revisions 168593 via svnmerge from
authorTerry Wilson <twilson@digium.com>
Wed, 14 Jan 2009 02:00:40 +0000 (02:00 +0000)
committerTerry Wilson <twilson@digium.com>
Wed, 14 Jan 2009 02:00:40 +0000 (02:00 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r168593 | twilson | 2009-01-13 19:27:18 -0600 (Tue, 13 Jan 2009) | 20 lines

  Don't overflow when paging more than 128 extensions

  The number of available slots for calls in app_page was hardcoded to 128.
  Proper bounds checking was not in place to enforce this limit, so if more than
  128 extensions were passed to the Page() app, Asterisk would crash.  This patch
  instead dynamically allocates memory for the ast_dial structures and removes
  the (non-functional) arbitrary limit.

  This issue would have special importance to anyone who is dynamically creating
  the argument passed to the Page application and allowing more than 128
  extensions to be added by an outside user via some external interface.

  The patch posted by a_villacis was slightly modified for some coding guidelines
  and other cleanups.  Thanks, a_villacis!
  (closes issue #14217)
  Reported by: a_villacis
  Patches:
        20080912-asterisk-app_page-fix-buffer-overflow.patch uploaded by a (license 660)
  Tested by: otherwiseguy
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@168594 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_page.c

index 1884f43..0681e72 100644 (file)
@@ -117,7 +117,6 @@ AST_APP_OPTIONS(page_opts, {
        AST_APP_OPTION('i', PAGE_IGNORE_FORWARDS),
 });
 
-#define MAX_DIALS 128
 
 static int page_exec(struct ast_channel *chan, void *data)
 {
@@ -127,7 +126,8 @@ static int page_exec(struct ast_channel *chan, void *data)
        unsigned int confid = ast_random();
        struct ast_app *app;
        int res = 0, pos = 0, i = 0;
-       struct ast_dial *dials[MAX_DIALS];
+       struct ast_dial **dial_list;
+       unsigned int num_dials;
        int timeout = 0;
        char *parse;
 
@@ -167,6 +167,18 @@ static int page_exec(struct ast_channel *chan, void *data)
        snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
                (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
 
+       /* Count number of extensions in list by number of ampersands + 1 */
+       num_dials = 1;
+       tmp = args.devices;
+       while (*tmp && *tmp++ == '&') {
+               num_dials++;
+       }
+
+       if (!(dial_list = ast_calloc(num_dials, sizeof(void *)))) {
+               ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (sizeof(void *) * num_dials));
+               return -1;
+       }
+
        /* Go through parsing/calling each device */
        while ((tech = strsep(&args.devices, "&"))) {
                int state = 0;
@@ -222,7 +234,7 @@ static int page_exec(struct ast_channel *chan, void *data)
                ast_dial_run(dial, chan, 1);
 
                /* Put in our dialing array */
-               dials[pos++] = dial;
+               dial_list[pos++] = dial;
        }
 
        if (!ast_test_flag(&flags, PAGE_QUIET)) {
@@ -239,7 +251,7 @@ static int page_exec(struct ast_channel *chan, void *data)
 
        /* Go through each dial attempt cancelling, joining, and destroying */
        for (i = 0; i < pos; i++) {
-               struct ast_dial *dial = dials[i];
+               struct ast_dial *dial = dial_list[i];
 
                /* We have to wait for the async thread to exit as it's possible Meetme won't throw them out immediately */
                ast_dial_join(dial);