changeset 7042:bd2f97a3aecc

Upstream: introduced ngx_http_upstream_ssl_handshake_handler(). This change reworks 13a5f4765887 to only run posted requests once, with nothing on stack. Running posted requests with other request functions on stack may result in use-after-free in case of errors, similar to the one reported in #788. To only run posted request once, a separate function was introduced to be used as ssl handshake handler in c->ssl->handler, ngx_http_upstream_ssl_handshake_handler(). The ngx_http_run_posted_requests() is only called in this function, and not in ngx_http_upstream_ssl_handshake() which may be called directly on stack. Additionaly, ngx_http_upstream_ssl_handshake_handler() now does appropriate debug logging of the current subrequest, similar to what is done in other event handlers.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 22 Jun 2017 21:09:06 +0300
parents 6169dbad37d8
children aeaac3ccee4f
files src/http/ngx_http_upstream.c
diffstat 1 files changed, 24 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -182,7 +182,9 @@ static char *ngx_http_upstream_init_main
 #if (NGX_HTTP_SSL)
 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
     ngx_http_upstream_t *u, ngx_connection_t *c);
-static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
+static void ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c);
+static void ngx_http_upstream_ssl_handshake(ngx_http_request_t *,
+    ngx_http_upstream_t *u, ngx_connection_t *c);
 static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
     ngx_http_upstream_t *u, ngx_connection_t *c);
 #endif
@@ -1667,26 +1669,43 @@ ngx_http_upstream_ssl_init_connection(ng
             ngx_add_timer(c->write, u->conf->connect_timeout);
         }
 
-        c->ssl->handler = ngx_http_upstream_ssl_handshake;
+        c->ssl->handler = ngx_http_upstream_ssl_handshake_handler;
         return;
     }
 
-    ngx_http_upstream_ssl_handshake(c);
+    ngx_http_upstream_ssl_handshake(r, u, c);
 }
 
 
 static void
-ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
+ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c)
 {
-    long                  rc;
     ngx_http_request_t   *r;
     ngx_http_upstream_t  *u;
 
     r = c->data;
+
     u = r->upstream;
+    c = r->connection;
 
     ngx_http_set_log_request(c->log, r);
 
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http upstream ssl handshake: \"%V?%V\"",
+                   &r->uri, &r->args);
+
+    ngx_http_upstream_ssl_handshake(r, u, u->peer.connection);
+
+    ngx_http_run_posted_requests(c);
+}
+
+
+static void
+ngx_http_upstream_ssl_handshake(ngx_http_request_t *r, ngx_http_upstream_t *u,
+    ngx_connection_t *c)
+{
+    long  rc;
+
     if (c->ssl->handshaked) {
 
         if (u->conf->ssl_verify) {
@@ -1714,28 +1733,19 @@ ngx_http_upstream_ssl_handshake(ngx_conn
         c->write->handler = ngx_http_upstream_handler;
         c->read->handler = ngx_http_upstream_handler;
 
-        c = r->connection;
-
         ngx_http_upstream_send_request(r, u, 1);
 
-        ngx_http_run_posted_requests(c);
         return;
     }
 
     if (c->write->timedout) {
-        c = r->connection;
         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
-        ngx_http_run_posted_requests(c);
         return;
     }
 
 failed:
 
-    c = r->connection;
-
     ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
-
-    ngx_http_run_posted_requests(c);
 }