# HG changeset patch # User Maxim Dounin # Date 1498154946 -10800 # Node ID bd2f97a3aecc14f8a971fd8fd710979736131c23 # Parent 6169dbad37d85fa8642b9d0a51f0f0f6c19dd3d1 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. diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- 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); }