]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
cel_pgsql.c: Fix buffer overflow calling libpq
authorJosh Roberson <josh@asteriasgi.com>
Mon, 27 Mar 2017 16:49:08 +0000 (11:49 -0500)
committertwisted <josh@asteriasgi.com>
Wed, 29 Mar 2017 13:53:43 +0000 (07:53 -0600)
PQEscapeStringConn() expects the buffer passed in to be an
adequitely sized buffer to write out the escaped SQL value string
into.  It is possible, for large values (such as large values to
Dial with a lot of devices) to have more than our 512+1 byte
allocation and thus cause libpq to create a buffer overrun.

glibc will nicely ABRT asterisk for you, citing a stack smash.

Let's only allocate it to be as large as needed:
If we have a value, then (strlen(value) * 2) + 1 (as recommended
by libpq), and if we have none, just one byte to hold our null
will do.

ASTERISK-26896 #close

Change-Id: If611c734292618ed68dde17816d09dd16667dea2

cel/cel_pgsql.c

index e4e280e41c7a9375c442acc836dcbcfa21277a26..7ce76d2980da9b7374e4c1f719dc09f0882f4698 100644 (file)
@@ -181,11 +181,14 @@ static void pgsql_log(struct ast_event *event)
        if (connected) {
                struct columns *cur;
                struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
-               char buf[257], escapebuf[513];
+               char buf[257];
+               char *escapebuf = NULL;
                const char *value;
                int first = 1;
+               size_t bufsize = 513;
 
-               if (!sql || !sql2) {
+               escapebuf = ast_malloc(bufsize);
+               if (!escapebuf || !sql || !sql2) {
                        goto ast_log_cleanup;
                }
 
@@ -309,6 +312,22 @@ static void pgsql_log(struct ast_event *event)
                                        /* XXX Might want to handle dates, times, and other misc fields here XXX */
                                } else {
                                        if (value) {
+                                               size_t required_size = strlen(value) * 2 + 1;
+
+                                               /* If our argument size exceeds our buffer, grow it,
+                                                * as PQescapeStringConn() expects the buffer to be
+                                                * adequitely sized and does *NOT* do size checking.
+                                                */
+                                               if (required_size > bufsize) {
+                                                       char *tmpbuf = ast_realloc(escapebuf, required_size);
+
+                                                       if (!tmpbuf) {
+                                                               goto ast_log_cleanup;
+                                                       }
+
+                                                       escapebuf = tmpbuf;
+                                                       bufsize = required_size;
+                                               }
                                                PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
                                        } else {
                                                escapebuf[0] = '\0';
@@ -379,6 +398,7 @@ static void pgsql_log(struct ast_event *event)
 ast_log_cleanup:
                ast_free(sql);
                ast_free(sql2);
+               ast_free(escapebuf);
        }
 
        ast_mutex_unlock(&pgsql_lock);