summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2017-07-04 18:07:29 +0300
committerRoman Arutyunyan <arut@nginx.com>2017-07-04 18:07:29 +0300
commit7570718594d846787ca31914e0f8431d7a4cfad1 (patch)
tree3e29a0d3f4f492bd41f11b4f4fea79a5de17f08e /src
parent32e3d0e693b6520d0e087160519d173bb102f906 (diff)
downloadnginx-7570718594d846787ca31914e0f8431d7a4cfad1.tar.gz
nginx-7570718594d846787ca31914e0f8431d7a4cfad1.tar.bz2
Resolver: fixed possible use-after-free while resolving SRV.
Resolving an SRV record includes resolving its host names in subrequests. Previously, if memory allocation failed while reporting a subrequest result after receiving a response from a DNS server, the SRV resolve handler was called immediately with the NGX_ERROR state. However, if the SRV record included another copy of the resolved name, it was reported once again. This could trigger the use-after-free memory access after SRV resolve handler freed the resolve context by calling ngx_resolve_name_done(). Now the SRV resolve handler is called only when all its subrequests are completed.
Diffstat (limited to 'src')
-rw-r--r--src/core/ngx_resolver.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 91f8a5ef3..91231f232 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -3034,25 +3034,15 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx)
addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t));
if (addrs == NULL) {
- ngx_resolve_name_done(cctx);
-
- ctx->state = NGX_ERROR;
- ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
-
- ctx->handler(ctx);
- return;
+ srv->state = NGX_ERROR;
+ goto done;
}
sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t));
if (sockaddr == NULL) {
ngx_resolver_free(r, addrs);
- ngx_resolve_name_done(cctx);
-
- ctx->state = NGX_ERROR;
- ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
-
- ctx->handler(ctx);
- return;
+ srv->state = NGX_ERROR;
+ goto done;
}
for (i = 0; i < cctx->naddrs; i++) {
@@ -3069,6 +3059,8 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx)
srv->naddrs = cctx->naddrs;
}
+done:
+
ngx_resolve_name_done(cctx);
if (ctx->count == 0) {
@@ -4254,10 +4246,21 @@ ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
ngx_resolver_addr_t *addrs;
ngx_resolver_srv_name_t *srvs;
+ srvs = ctx->srvs;
+ nsrvs = ctx->nsrvs;
+
naddrs = 0;
- for (i = 0; i < ctx->nsrvs; i++) {
- naddrs += ctx->srvs[i].naddrs;
+ for (i = 0; i < nsrvs; i++) {
+ if (srvs[i].state == NGX_ERROR) {
+ ctx->state = NGX_ERROR;
+ ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
+
+ ctx->handler(ctx);
+ return;
+ }
+
+ naddrs += srvs[i].naddrs;
}
if (naddrs == 0) {
@@ -4277,9 +4280,6 @@ ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
return;
}
- srvs = ctx->srvs;
- nsrvs = ctx->nsrvs;
-
i = 0;
n = 0;