Mercurial > hg > nginx
comparison src/core/ngx_resolver.c @ 7048:80224192163c
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.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Tue, 04 Jul 2017 18:07:29 +0300 |
parents | d49b74a683b1 |
children | 137c5be7df09 |
comparison
equal
deleted
inserted
replaced
7047:3fef8c5caa75 | 7048:80224192163c |
---|---|
3032 | 3032 |
3033 ctx->valid = ngx_min(ctx->valid, cctx->valid); | 3033 ctx->valid = ngx_min(ctx->valid, cctx->valid); |
3034 | 3034 |
3035 addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t)); | 3035 addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t)); |
3036 if (addrs == NULL) { | 3036 if (addrs == NULL) { |
3037 ngx_resolve_name_done(cctx); | 3037 srv->state = NGX_ERROR; |
3038 | 3038 goto done; |
3039 ctx->state = NGX_ERROR; | |
3040 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); | |
3041 | |
3042 ctx->handler(ctx); | |
3043 return; | |
3044 } | 3039 } |
3045 | 3040 |
3046 sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t)); | 3041 sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t)); |
3047 if (sockaddr == NULL) { | 3042 if (sockaddr == NULL) { |
3048 ngx_resolver_free(r, addrs); | 3043 ngx_resolver_free(r, addrs); |
3049 ngx_resolve_name_done(cctx); | 3044 srv->state = NGX_ERROR; |
3050 | 3045 goto done; |
3051 ctx->state = NGX_ERROR; | |
3052 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); | |
3053 | |
3054 ctx->handler(ctx); | |
3055 return; | |
3056 } | 3046 } |
3057 | 3047 |
3058 for (i = 0; i < cctx->naddrs; i++) { | 3048 for (i = 0; i < cctx->naddrs; i++) { |
3059 addrs[i].sockaddr = &sockaddr[i].sockaddr; | 3049 addrs[i].sockaddr = &sockaddr[i].sockaddr; |
3060 addrs[i].socklen = cctx->addrs[i].socklen; | 3050 addrs[i].socklen = cctx->addrs[i].socklen; |
3066 } | 3056 } |
3067 | 3057 |
3068 srv->addrs = addrs; | 3058 srv->addrs = addrs; |
3069 srv->naddrs = cctx->naddrs; | 3059 srv->naddrs = cctx->naddrs; |
3070 } | 3060 } |
3061 | |
3062 done: | |
3071 | 3063 |
3072 ngx_resolve_name_done(cctx); | 3064 ngx_resolve_name_done(cctx); |
3073 | 3065 |
3074 if (ctx->count == 0) { | 3066 if (ctx->count == 0) { |
3075 ngx_resolver_report_srv(r, ctx); | 3067 ngx_resolver_report_srv(r, ctx); |
4252 { | 4244 { |
4253 ngx_uint_t naddrs, nsrvs, nw, i, j, k, l, m, n, w; | 4245 ngx_uint_t naddrs, nsrvs, nw, i, j, k, l, m, n, w; |
4254 ngx_resolver_addr_t *addrs; | 4246 ngx_resolver_addr_t *addrs; |
4255 ngx_resolver_srv_name_t *srvs; | 4247 ngx_resolver_srv_name_t *srvs; |
4256 | 4248 |
4249 srvs = ctx->srvs; | |
4250 nsrvs = ctx->nsrvs; | |
4251 | |
4257 naddrs = 0; | 4252 naddrs = 0; |
4258 | 4253 |
4259 for (i = 0; i < ctx->nsrvs; i++) { | 4254 for (i = 0; i < nsrvs; i++) { |
4260 naddrs += ctx->srvs[i].naddrs; | 4255 if (srvs[i].state == NGX_ERROR) { |
4256 ctx->state = NGX_ERROR; | |
4257 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); | |
4258 | |
4259 ctx->handler(ctx); | |
4260 return; | |
4261 } | |
4262 | |
4263 naddrs += srvs[i].naddrs; | |
4261 } | 4264 } |
4262 | 4265 |
4263 if (naddrs == 0) { | 4266 if (naddrs == 0) { |
4264 ctx->state = NGX_RESOLVE_NXDOMAIN; | 4267 ctx->state = NGX_RESOLVE_NXDOMAIN; |
4265 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); | 4268 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); |
4274 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); | 4277 ctx->valid = ngx_time() + (r->valid ? r->valid : 10); |
4275 | 4278 |
4276 ctx->handler(ctx); | 4279 ctx->handler(ctx); |
4277 return; | 4280 return; |
4278 } | 4281 } |
4279 | |
4280 srvs = ctx->srvs; | |
4281 nsrvs = ctx->nsrvs; | |
4282 | 4282 |
4283 i = 0; | 4283 i = 0; |
4284 n = 0; | 4284 n = 0; |
4285 | 4285 |
4286 do { | 4286 do { |