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.
This commit is contained in:
Maxim Dounin 2017-06-22 21:09:06 +03:00
parent efa61f42c1
commit 6433c841a0

View File

@ -182,7 +182,9 @@ static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
#if (NGX_HTTP_SSL) #if (NGX_HTTP_SSL)
static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
ngx_http_upstream_t *u, ngx_connection_t *c); 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, static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
ngx_http_upstream_t *u, ngx_connection_t *c); ngx_http_upstream_t *u, ngx_connection_t *c);
#endif #endif
@ -1667,26 +1669,43 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
ngx_add_timer(c->write, u->conf->connect_timeout); 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; return;
} }
ngx_http_upstream_ssl_handshake(c); ngx_http_upstream_ssl_handshake(r, u, c);
} }
static void 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_request_t *r;
ngx_http_upstream_t *u; ngx_http_upstream_t *u;
r = c->data; r = c->data;
u = r->upstream; u = r->upstream;
c = r->connection;
ngx_http_set_log_request(c->log, r); 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 (c->ssl->handshaked) {
if (u->conf->ssl_verify) { if (u->conf->ssl_verify) {
@ -1714,28 +1733,19 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
c->write->handler = ngx_http_upstream_handler; c->write->handler = ngx_http_upstream_handler;
c->read->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_upstream_send_request(r, u, 1);
ngx_http_run_posted_requests(c);
return; return;
} }
if (c->write->timedout) { if (c->write->timedout) {
c = r->connection;
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT); ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
ngx_http_run_posted_requests(c);
return; return;
} }
failed: failed:
c = r->connection;
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
ngx_http_run_posted_requests(c);
} }