httpd: defend against attempts to OOM us. Closes 9611
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 26 Jan 2017 18:35:40 +0000 (19:35 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 26 Jan 2017 18:35:40 +0000 (19:35 +0100)
We were strdup'ing "Cookie: foo" every time we saw it.

function                                             old     new   delta
handle_incoming_and_exit                            2733    2821     +88

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/httpd.c

index 39aad90a8eca29cfe8de72300696fdaa303baadc..8703fbd3d20686f41b417f5a5230b71dd1a69085 100644 (file)
@@ -460,11 +460,6 @@ struct globals {
 #define ip_a_d            (G.ip_a_d           )
 #define g_realm           (G.g_realm          )
 #define remoteuser        (G.remoteuser       )
-#define referer           (G.referer          )
-#define user_agent        (G.user_agent       )
-#define host              (G.host             )
-#define http_accept       (G.http_accept      )
-#define http_accept_language (G.http_accept_language)
 #define file_size         (G.file_size        )
 #if ENABLE_FEATURE_HTTPD_RANGES
 #define range_start       (G.range_start      )
@@ -1529,11 +1524,11 @@ static void send_cgi_and_exit(
 #endif
                }
        }
-       setenv1("HTTP_USER_AGENT", user_agent);
-       if (http_accept)
-               setenv1("HTTP_ACCEPT", http_accept);
-       if (http_accept_language)
-               setenv1("HTTP_ACCEPT_LANGUAGE", http_accept_language);
+       setenv1("HTTP_USER_AGENT", G.user_agent);
+       if (G.http_accept)
+               setenv1("HTTP_ACCEPT", G.http_accept);
+       if (G.http_accept_language)
+               setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language);
        if (post_len)
                putenv(xasprintf("CONTENT_LENGTH=%d", post_len));
        if (cookie)
@@ -1546,9 +1541,9 @@ static void send_cgi_and_exit(
                putenv((char*)"AUTH_TYPE=Basic");
        }
 #endif
-       if (referer)
-               setenv1("HTTP_REFERER", referer);
-       setenv1("HTTP_HOST", host); /* set to "" if NULL */
+       if (G.referer)
+               setenv1("HTTP_REFERER", G.referer);
+       setenv1("HTTP_HOST", G.host); /* set to "" if NULL */
        /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this,
         * just run "env SERVER_NAME=xyz httpd ..." instead */
 
@@ -2269,10 +2264,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
 #if ENABLE_FEATURE_HTTPD_PROXY
                        /* We need 2 more bytes for yet another "\r\n" -
                         * see near fdprintf(proxy_fd...) further below */
-                       if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 2) {
-                               int len = strlen(iobuf);
-                               if (len > IOBUF_SIZE - (header_ptr - header_buf) - 4)
-                                       len = IOBUF_SIZE - (header_ptr - header_buf) - 4;
+                       if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 4) {
+                               int len = strnlen(iobuf, IOBUF_SIZE - (header_ptr - header_buf) - 4);
                                memcpy(header_ptr, iobuf, len);
                                header_ptr += len;
                                header_ptr[0] = '\r';
@@ -2303,19 +2296,26 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
 #endif
 #if ENABLE_FEATURE_HTTPD_CGI
                        else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
-                               cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
+                               if (!cookie) /* in case they send millions of these, do not OOM */
+                                       cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
                        } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
-                               content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
+                               if (!content_type)
+                                       content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
                        } else if (STRNCASECMP(iobuf, "Referer:") == 0) {
-                               referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
+                               if (!G.referer)
+                                       G.referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
                        } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
-                               user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
+                               if (!G.user_agent)
+                                       G.user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
                        } else if (STRNCASECMP(iobuf, "Host:") == 0) {
-                               host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1));
+                               if (!G.host)
+                                       G.host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1));
                        } else if (STRNCASECMP(iobuf, "Accept:") == 0) {
-                               http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1));
+                               if (!G.http_accept)
+                                       G.http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1));
                        } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) {
-                               http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1));
+                               if (!G.http_accept_language)
+                                       G.http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1));
                        }
 #endif
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH