Merge branch 'nginx' (nginx-1.13.3).
Change-Id: Id47104dc65ce8e6479304589c892961011edb753
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags
index 849abee..62a304a 100644
--- a/.hgtags
+++ b/.hgtags
@@ -415,3 +415,4 @@
3671096a45bce570a2afa20b9faf42c7fb0f7e66 release-1.13.0
539f7893ecb96bee60965528c8958d7eb2f1ce6b release-1.13.1
5be2b25bdc65775a85f18f68a4be4f58c7384415 release-1.13.2
+8457ce87640f9bfe6221c4ac4466ced20e03bebe release-1.13.3
diff --git a/BUILD b/BUILD
index 0a3141c..7330d05 100644
--- a/BUILD
+++ b/BUILD
@@ -1468,5 +1468,5 @@
preinst = "@nginx_pkgoss//:debian_preinst",
prerm = "@nginx_pkgoss//:debian_prerm",
section = "httpd",
- version = "1.13.2",
+ version = "1.13.3",
)
diff --git a/build.bzl b/build.bzl
index b5a8c99..09469c1 100644
--- a/build.bzl
+++ b/build.bzl
@@ -663,7 +663,7 @@
name = "nginx_pkgoss",
build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) +
_PKGOSS_BUILD_FILE_TAIL,
- commit = "0be78ae1bf9b0fbb97b94e2569581bb77ff4cb60", # nginx-1.13.2
+ commit = "0f32bf04f8e7599eca0083d0670b53baeab5b98c", # nginx-1.13.3
remote = "https://nginx.googlesource.com/nginx-pkgoss",
)
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 535704c..e2da1e4 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,26 @@
<change_log title="nginx">
+<changes ver="1.13.3" date="2017-07-11">
+
+<change type="security">
+<para lang="ru">
+специально созданный запрос мог вызвать целочисленное переполнение
+в range-фильтре и последующую некорректную обработку запрошенных диапазонов,
+что потенциально могло привести к утечке конфиденциальной информации
+(CVE-2017-7529).
+</para>
+<para lang="en">
+a specially crafted request might result in an integer overflow
+and incorrect processing of ranges in the range filter,
+potentially resulting in sensitive information leak
+(CVE-2017-7529).
+</para>
+</change>
+
+</changes>
+
+
<changes ver="1.13.2" date="2017-06-27">
<change type="change">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 9718bd2..a43efd5 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -13,8 +13,8 @@
#define NGINX_NAME "nginx"
#endif
-#define nginx_version 1013002
-#define NGINX_VERSION "1.13.2"
+#define nginx_version 1013003
+#define NGINX_VERSION "1.13.3"
#define NGINX_VER NGINX_NAME "/" NGINX_VERSION
#ifdef NGX_BUILD
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 91f8a5e..cd55520 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -105,6 +105,8 @@
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,
u_char *buf, u_char *src, u_char *last);
+static ngx_int_t ngx_resolver_set_timeout(ngx_resolver_t *r,
+ ngx_resolver_ctx_t *ctx);
static void ngx_resolver_timeout_handler(ngx_event_t *ev);
static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn);
static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
@@ -189,6 +191,7 @@
r->event->handler = ngx_resolver_resend_handler;
r->event->data = r;
r->event->log = &cf->cycle->new_log;
+ r->event->cancelable = 1;
r->ident = -1;
r->resend_timeout = 5;
@@ -728,19 +731,8 @@
}
if (rn->waiting) {
-
- if (ctx->event == NULL && ctx->timeout) {
- ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
- if (ctx->event == NULL) {
- return NGX_ERROR;
- }
-
- ctx->event->handler = ngx_resolver_timeout_handler;
- ctx->event->data = ctx;
- ctx->event->log = r->log;
- ctx->ident = -1;
-
- ngx_add_timer(ctx->event, ctx->timeout);
+ if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
+ return NGX_ERROR;
}
last->next = rn->waiting;
@@ -864,18 +856,8 @@
goto failed;
}
- if (ctx->event == NULL && ctx->timeout) {
- ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
- if (ctx->event == NULL) {
- goto failed;
- }
-
- ctx->event->handler = ngx_resolver_timeout_handler;
- ctx->event->data = ctx;
- ctx->event->log = r->log;
- ctx->ident = -1;
-
- ngx_add_timer(ctx->event, ctx->timeout);
+ if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
+ goto failed;
}
if (ngx_resolver_resend_empty(r)) {
@@ -1007,19 +989,8 @@
}
if (rn->waiting) {
-
- if (ctx->event == NULL && ctx->timeout) {
- ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
- if (ctx->event == NULL) {
- return NGX_ERROR;
- }
-
- ctx->event->handler = ngx_resolver_timeout_handler;
- ctx->event->data = ctx;
- ctx->event->log = r->log;
- ctx->ident = -1;
-
- ngx_add_timer(ctx->event, ctx->timeout);
+ if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
+ return NGX_ERROR;
}
ctx->next = rn->waiting;
@@ -1089,18 +1060,8 @@
goto failed;
}
- if (ctx->event == NULL && ctx->timeout) {
- ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
- if (ctx->event == NULL) {
- goto failed;
- }
-
- ctx->event->handler = ngx_resolver_timeout_handler;
- ctx->event->data = ctx;
- ctx->event->log = r->log;
- ctx->ident = -1;
-
- ngx_add_timer(ctx->event, ctx->timeout);
+ if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
+ goto failed;
}
if (ngx_resolver_resend_empty(r)) {
@@ -3034,25 +2995,15 @@
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 +3020,8 @@
srv->naddrs = cctx->naddrs;
}
+done:
+
ngx_resolve_name_done(cctx);
if (ctx->count == 0) {
@@ -4041,6 +3994,30 @@
}
+static ngx_int_t
+ngx_resolver_set_timeout(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
+{
+ if (ctx->event || ctx->timeout == 0) {
+ return NGX_OK;
+ }
+
+ ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
+ if (ctx->event == NULL) {
+ return NGX_ERROR;
+ }
+
+ ctx->event->handler = ngx_resolver_timeout_handler;
+ ctx->event->data = ctx;
+ ctx->event->log = r->log;
+ ctx->event->cancelable = ctx->cancelable;
+ ctx->ident = -1;
+
+ ngx_add_timer(ctx->event, ctx->timeout);
+
+ return NGX_OK;
+}
+
+
static void
ngx_resolver_timeout_handler(ngx_event_t *ev)
{
@@ -4254,10 +4231,21 @@
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 +4265,6 @@
return;
}
- srvs = ctx->srvs;
- nsrvs = ctx->nsrvs;
-
i = 0;
n = 0;
diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
index 6f099b7..0bd3921 100644
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -220,6 +220,7 @@
unsigned quick:1;
unsigned async:1;
+ unsigned cancelable:1;
ngx_uint_t recursion;
ngx_event_t *event;
};
diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
index 1d4ce2b..9e7796d 100644
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -181,8 +181,8 @@
ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size)
{
size_t s;
- uintptr_t p, n, m, mask, *bitmap;
- ngx_uint_t i, slot, shift, map;
+ uintptr_t p, m, mask, *bitmap;
+ ngx_uint_t i, n, slot, shift, map;
ngx_slab_page_t *page, *prev, *slots;
if (size > ngx_slab_max_size) {
@@ -226,7 +226,7 @@
bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page);
- map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8);
+ map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t));
for (n = 0; n < map; n++) {
@@ -239,7 +239,7 @@
bitmap[n] |= m;
- i = (n * sizeof(uintptr_t) * 8 + i) << shift;
+ i = (n * 8 * sizeof(uintptr_t) + i) << shift;
p = (uintptr_t) bitmap + i;
@@ -339,11 +339,17 @@
}
/* "n" elements for bitmap, plus one requested */
- bitmap[0] = ((uintptr_t) 2 << n) - 1;
- map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8);
+ for (i = 0; i < (n + 1) / (8 * sizeof(uintptr_t)); i++) {
+ bitmap[i] = NGX_SLAB_BUSY;
+ }
- for (i = 1; i < map; i++) {
+ m = ((uintptr_t) 1 << ((n + 1) % (8 * sizeof(uintptr_t)))) - 1;
+ bitmap[i] = m;
+
+ map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t));
+
+ for (i = i + 1; i < map; i++) {
bitmap[i] = 0;
}
@@ -369,7 +375,7 @@
slots[slot].next = page;
- pool->stats[slot].total += sizeof(uintptr_t) * 8;
+ pool->stats[slot].total += 8 * sizeof(uintptr_t);
p = ngx_slab_page_addr(pool, page);
@@ -480,8 +486,8 @@
}
n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift;
- m = (uintptr_t) 1 << (n % (sizeof(uintptr_t) * 8));
- n /= sizeof(uintptr_t) * 8;
+ m = (uintptr_t) 1 << (n % (8 * sizeof(uintptr_t)));
+ n /= 8 * sizeof(uintptr_t);
bitmap = (uintptr_t *)
((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1));
@@ -506,13 +512,16 @@
n = 1;
}
- if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) {
+ i = n / (8 * sizeof(uintptr_t));
+ m = ((uintptr_t) 1 << (n % (8 * sizeof(uintptr_t)))) - 1;
+
+ if (bitmap[i] & ~m) {
goto done;
}
- map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8);
+ map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t));
- for (i = 1; i < map; i++) {
+ for (i = i + 1; i < map; i++) {
if (bitmap[i]) {
goto done;
}
@@ -558,7 +567,7 @@
ngx_slab_free_pages(pool, page, 1);
- pool->stats[slot].total -= sizeof(uintptr_t) * 8;
+ pool->stats[slot].total -= 8 * sizeof(uintptr_t);
goto done;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index bc8d2a7..fae90e7 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1150,8 +1150,8 @@
static ngx_int_t
ngx_http_proxy_create_request(ngx_http_request_t *r)
{
- size_t len, uri_len, loc_len, body_len;
- size_t key_len, val_len;
+ size_t len, uri_len, loc_len, body_len,
+ key_len, val_len;
uintptr_t escape;
ngx_buf_t *b;
ngx_str_t method;
@@ -1266,18 +1266,20 @@
le.flushed = 1;
while (*(uintptr_t *) le.ip) {
+
lcode = *(ngx_http_script_len_code_pt *) le.ip;
key_len = lcode(&le);
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
}
+ le.ip += sizeof(uintptr_t);
- if (val_len) {
- len += key_len + sizeof(": ") - 1 + val_len + sizeof(CRLF) - 1;
+ if (val_len == 0) {
+ continue;
}
- le.ip += sizeof(uintptr_t);
+ len += key_len + sizeof(": ") - 1 + val_len + sizeof(CRLF) - 1;
}
@@ -1377,34 +1379,41 @@
le.ip = headers->lengths->elts;
while (*(uintptr_t *) le.ip) {
+
lcode = *(ngx_http_script_len_code_pt *) le.ip;
(void) lcode(&le);
for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
lcode = *(ngx_http_script_len_code_pt *) le.ip;
}
-
le.ip += sizeof(uintptr_t);
- e.skip = (val_len == 0) ? 1 : 0;
+ if (val_len == 0) {
+ e.skip = 1;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+ e.ip += sizeof(uintptr_t);
+
+ e.skip = 0;
+
+ continue;
+ }
code = *(ngx_http_script_code_pt *) e.ip;
code((ngx_http_script_engine_t *) &e);
- if (!e.skip) {
- *e.pos++ = ':'; *e.pos++ = ' ';
- }
+ *e.pos++ = ':'; *e.pos++ = ' ';
while (*(uintptr_t *) e.ip) {
code = *(ngx_http_script_code_pt *) e.ip;
code((ngx_http_script_engine_t *) &e);
}
-
- if (!e.skip) {
- *e.pos++ = CR; *e.pos++ = LF;
- }
-
e.ip += sizeof(uintptr_t);
+
+ *e.pos++ = CR; *e.pos++ = LF;
}
b->last = e.pos;
@@ -3552,7 +3561,7 @@
size = (sizeof(ngx_http_script_copy_code_t)
+ src[i].key.len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
+ & ~(sizeof(uintptr_t) - 1);
copy = ngx_array_push_n(headers->values, size);
if (copy == NULL) {
@@ -3565,44 +3574,16 @@
p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
ngx_memcpy(p, src[i].key.data, src[i].key.len);
- if (ngx_http_script_variables_count(&src[i].value) == 0) {
- copy = ngx_array_push_n(headers->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
- copy->code = (ngx_http_script_code_pt)
- ngx_http_script_copy_len_code;
- copy->len = src[i].value.len;
+ sc.cf = cf;
+ sc.source = &src[i].value;
+ sc.flushes = &headers->flushes;
+ sc.lengths = &headers->lengths;
+ sc.values = &headers->values;
- size = (sizeof(ngx_http_script_copy_code_t)
- + src[i].value.len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- copy = ngx_array_push_n(headers->values, size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = ngx_http_script_copy_code;
- copy->len = src[i].value.len;
-
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- ngx_memcpy(p, src[i].value.data, src[i].value.len);
-
- } else {
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &src[i].value;
- sc.flushes = &headers->flushes;
- sc.lengths = &headers->lengths;
- sc.values = &headers->values;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_ERROR;
}
code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 7ad9db9..292a2b8 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -355,7 +355,7 @@
}
if (suffix) {
- start = content_length - end;
+ start = (end < content_length) ? content_length - end : 0;
end = content_length - 1;
}
@@ -377,6 +377,10 @@
range->start = start;
range->end = end;
+ if (size > NGX_MAX_OFF_T_VALUE - (end - start)) {
+ return NGX_HTTP_RANGE_NOT_SATISFIABLE;
+ }
+
size += end - start;
if (ranges-- == 0) {
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 4be6550..031bae4 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -1463,17 +1463,15 @@
ngx_http_variable_is_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
if (r->args.len == 0) {
- v->len = 0;
- v->data = NULL;
+ *v = ngx_http_variable_null_value;
return NGX_OK;
}
v->len = 1;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
v->data = (u_char *) "?";
return NGX_OK;
@@ -1990,11 +1988,7 @@
return NGX_OK;
}
- v->len = 0;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = (u_char *) "";
+ *v = ngx_http_variable_null_value;
return NGX_OK;
}