Merge branch 'nginx' (nginx-1.17.4). Change-Id: Ieb1e8b9a7e6d883c7a15fbe2868093a07691f17a Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags index ec85611..19ec901 100644 --- a/.hgtags +++ b/.hgtags
@@ -442,3 +442,4 @@ 7816bd7dabf6ee86c53c073b90a7143161546e06 release-1.17.1 2fc9f853a6b7cd29dc84e0af2ed3cf78e0da6ca8 release-1.17.2 ed4303aa1b31a9aad5440640c0840d9d0af45fed release-1.17.3 +ce2ced3856909f36f8130c99eaa4dbdbae636ddc release-1.17.4
diff --git a/BUILD b/BUILD index 10b0b42..bfe49ee 100644 --- a/BUILD +++ b/BUILD
@@ -1520,5 +1520,5 @@ preinst = "@nginx_pkgoss//:debian_preinst", prerm = "@nginx_pkgoss//:debian_prerm", section = "httpd", - version = "1.17.3", + version = "1.17.4", )
diff --git a/build.bzl b/build.bzl index 76b5029..662cfa4 100644 --- a/build.bzl +++ b/build.bzl
@@ -673,9 +673,9 @@ name = "nginx_pkgoss", build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) + _PKGOSS_BUILD_FILE_TAIL, - commit = "f1d1a9fbc78c37a28de92df4e4cbed9268aa7304", # nginx-1.17.3 + commit = "b111e7858767a7f112093e752eba1a27a69bf778", # nginx-1.17.4 remote = "https://nginx.googlesource.com/nginx-pkgoss", - shallow_since = "1565719153 +0300", + shallow_since = "1569336583 +0300", ) def nginx_repositories_zlib(bind):
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index 492b469..fd7e308 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,95 @@ <change_log title="nginx"> +<changes ver="1.17.4" date="2019-09-24"> + +<change type="change"> +<para lang="ru"> +улучшено детектирование некорректного поведения клиентов в HTTP/2. +</para> +<para lang="en"> +better detection of incorrect client behavior in HTTP/2. +</para> +</change> + +<change type="change"> +<para lang="ru"> +в обработке непрочитанного тела запроса +при возврате ошибок в HTTP/2. +</para> +<para lang="en"> +in handling of not fully read client request body +when returning errors in HTTP/2. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +директива worker_shutdown_timeout могла не работать +при использовании HTTP/2. +</para> +<para lang="en"> +the "worker_shutdown_timeout" directive might not work +when using HTTP/2. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +при использовании HTTP/2 и директивы proxy_request_buffering +в рабочем процессе мог произойти segmentation fault. +</para> +<para lang="en"> +a segmentation fault might occur in a worker process +when using HTTP/2 and the "proxy_request_buffering" directive. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +на Windows при использовании SSL +уровень записи в лог ошибки ECONNABORTED был "crit" вместо "error". +</para> +<para lang="en"> +the ECONNABORTED error log level was "crit" instead of "error" +on Windows when using SSL. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +nginx игнорировал лишние данные при использовании chunked transfer encoding. +</para> +<para lang="en"> +nginx ignored extra data when using chunked transfer encoding. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +если использовалась директива return и +при чтении тела запроса возникала ошибка, +nginx всегда возвращал ошибку 500. +</para> +<para lang="en"> +nginx always returned the 500 error +if the "return" directive was used +and an error occurred during reading client request body. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в обработке ошибок выделения памяти. +</para> +<para lang="en"> +in memory allocation error handling. +</para> +</change> + +</changes> + + <changes ver="1.17.3" date="2019-08-13"> <change type="security">
diff --git a/misc/GNUmakefile b/misc/GNUmakefile index 2a34ae5..6938fe9 100644 --- a/misc/GNUmakefile +++ b/misc/GNUmakefile
@@ -6,7 +6,7 @@ CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.1.1c +OPENSSL = openssl-1.1.1d ZLIB = zlib-1.2.11 PCRE = pcre-8.43
diff --git a/src/core/nginx.h b/src/core/nginx.h index 3b0b837..053201d 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h
@@ -13,8 +13,8 @@ #define NGINX_NAME "nginx" #endif -#define nginx_version 1017003 -#define NGINX_VERSION "1.17.3" +#define nginx_version 1017004 +#define NGINX_VERSION "1.17.4" #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 593645d..e51712c 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c
@@ -972,7 +972,8 @@ name = ngx_resolver_dup(r, rn->name, rn->nlen); if (name == NULL) { - goto failed; + ngx_resolver_free(r, ctx); + return NGX_ERROR; } ctx->name.len = rn->nlen;
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 5abd167..b8d7b08 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c
@@ -2837,6 +2837,9 @@ if (sslerr == SSL_ERROR_SYSCALL) { if (err == NGX_ECONNRESET +#if (NGX_WIN32) + || err == NGX_ECONNABORTED +#endif || err == NGX_EPIPE || err == NGX_ENOTCONN || err == NGX_ETIMEDOUT
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 9adce1b..74741f5 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c
@@ -790,7 +790,7 @@ if (conf->client_certificate.len == 0 && conf->verify != 3) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no ssl_client_certificate for ssl_client_verify"); + "no ssl_client_certificate for ssl_verify_client"); return NGX_CONF_ERROR; }
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 110cb8a..1afdb19 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c
@@ -1660,8 +1660,10 @@ ngx_buf_t *b; ngx_chain_t out; - if (ngx_http_discard_request_body(r) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + rc = ngx_http_discard_request_body(r); + + if (rc != NGX_OK) { + return rc; } r->headers_out.status = status;
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index d9a1dbe..8e1b118 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c
@@ -2268,6 +2268,9 @@ break; case LF: state = sw_chunk_start; + break; + default: + goto invalid; } break;
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 8d0d54f..345d1fc 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c
@@ -355,6 +355,11 @@ if (c->close) { c->close = 0; + if (c->error) { + ngx_http_v2_finalize_connection(h2c, 0); + return; + } + if (!h2c->goaway) { h2c->goaway = 1; @@ -420,6 +425,14 @@ } while (p != end); + h2c->total_bytes += n; + + if (h2c->total_bytes / 8 > h2c->payload_bytes + 1048576) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, "http2 flood detected"); + ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); + return; + } + } while (rev->ready); if (ngx_handle_read_event(rev, 0) != NGX_OK) { @@ -506,13 +519,12 @@ ngx_http_core_loc_conf_t *clcf; c = h2c->connection; + wev = c->write; if (c->error) { - return NGX_ERROR; + goto error; } - wev = c->write; - if (!wev->ready) { return NGX_AGAIN; } @@ -948,6 +960,15 @@ return ngx_http_v2_state_skip_padded(h2c, pos, end); } + r = stream->request; + + if (r->reading_body && !r->request_body_no_buffering) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "skipping http2 DATA frame"); + + return ngx_http_v2_state_skip_padded(h2c, pos, end); + } + size = end - pos; if (size >= h2c->state.length) { @@ -955,7 +976,7 @@ stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; } - r = stream->request; + h2c->payload_bytes += size; if (r->request_body) { rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); @@ -1101,20 +1122,19 @@ return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); } - h2c->last_sid = h2c->state.sid; - - h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); - if (h2c->state.pool == NULL) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); - } - if (depend == h2c->state.sid) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent HEADERS frame for stream %ui " "with incorrect dependency", h2c->state.sid); - status = NGX_HTTP_V2_PROTOCOL_ERROR; - goto rst_stream; + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); + } + + h2c->last_sid = h2c->state.sid; + + h2c->state.pool = ngx_create_pool(1024, h2c->connection->log); + if (h2c->state.pool == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -1843,28 +1863,7 @@ "client sent PRIORITY frame for stream %ui " "with incorrect dependency", h2c->state.sid); - node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); - - if (node && node->stream) { - if (ngx_http_v2_terminate_stream(h2c, node->stream, - NGX_HTTP_V2_PROTOCOL_ERROR) - == NGX_ERROR) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } - - } else { - if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, - NGX_HTTP_V2_PROTOCOL_ERROR) - == NGX_ERROR) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } - } - - return ngx_http_v2_state_complete(h2c, pos, end); + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); } node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 1); @@ -2276,41 +2275,11 @@ h2c->state.sid, window); if (window == 0) { - if (h2c->state.sid == 0) { - ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, - "client sent WINDOW_UPDATE frame " - "with incorrect window increment 0"); - - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_PROTOCOL_ERROR); - } - ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, - "client sent WINDOW_UPDATE frame for stream %ui " - "with incorrect window increment 0", h2c->state.sid); + "client sent WINDOW_UPDATE frame " + "with incorrect window increment 0"); - node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); - - if (node && node->stream) { - if (ngx_http_v2_terminate_stream(h2c, node->stream, - NGX_HTTP_V2_PROTOCOL_ERROR) - == NGX_ERROR) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } - - } else { - if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, - NGX_HTTP_V2_PROTOCOL_ERROR) - == NGX_ERROR) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } - } - - return ngx_http_v2_state_complete(h2c, pos, end); + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); } if (h2c->state.sid) { @@ -2997,9 +2966,9 @@ "requested control frame is too large: %uz", length); return NULL; } +#endif frame->length = length; -#endif buf->last = ngx_http_v2_write_len_and_type(buf->pos, length, type); @@ -3026,6 +2995,8 @@ frame->next = h2c->free_frames; h2c->free_frames = frame; + h2c->total_bytes += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; + return NGX_OK; } @@ -3811,7 +3782,8 @@ static void ngx_http_v2_run_request(ngx_http_request_t *r) { - ngx_connection_t *fc; + ngx_connection_t *fc; + ngx_http_v2_connection_t *h2c; fc = r->connection; @@ -3843,6 +3815,10 @@ r->headers_in.chunked = 1; } + h2c = r->stream->connection; + + h2c->payload_bytes += r->request_length; + ngx_http_process_request(r); failed: @@ -4378,33 +4354,11 @@ } } else if (!stream->in_closed) { -#if 0 if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR) != NGX_OK) { h2c->connection->error = 1; } -#else - /* - * At the time of writing at least the latest versions of Chrome - * do not properly handle RST_STREAM with NO_ERROR status. - * - * See: https://bugs.chromium.org/p/chromium/issues/detail?id=603182 - * - * As a workaround, the stream window is maximized before closing - * the stream. This allows a client to send up to 2 GB of data - * before getting blocked on flow control. - */ - - if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW - && ngx_http_v2_send_window_update(h2c, node->id, - NGX_HTTP_V2_MAX_WINDOW - - stream->recv_window) - != NGX_OK) - { - h2c->connection->error = 1; - } -#endif } }
diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 69d55d1..59ddf54 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h
@@ -119,6 +119,9 @@ ngx_connection_t *connection; ngx_http_connection_t *http_connection; + off_t total_bytes; + off_t payload_bytes; + ngx_uint_t processing; ngx_uint_t frames; ngx_uint_t idle;
diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index f1618ae..5a38737 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c
@@ -1886,6 +1886,8 @@ stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; + h2c->payload_bytes += frame->length; + ngx_http_v2_handle_frame(stream, frame); ngx_http_v2_handle_stream(h2c, stream); @@ -1940,6 +1942,8 @@ stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; + h2c->payload_bytes += frame->length; + ngx_http_v2_handle_frame(stream, frame); ngx_http_v2_handle_stream(h2c, stream); @@ -2033,6 +2037,8 @@ stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE; + h2c->payload_bytes += frame->length; + ngx_http_v2_handle_frame(stream, frame); ngx_http_v2_handle_stream(h2c, stream); @@ -2045,12 +2051,17 @@ ngx_http_v2_handle_frame(ngx_http_v2_stream_t *stream, ngx_http_v2_out_frame_t *frame) { - ngx_http_request_t *r; + ngx_http_request_t *r; + ngx_http_v2_connection_t *h2c; r = stream->request; r->connection->sent += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; + h2c = stream->connection; + + h2c->total_bytes += NGX_HTTP_V2_FRAME_HEADER_SIZE + frame->length; + if (frame->fin) { stream->out_closed = 1; }
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index 5544f75..e193b29 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c
@@ -388,7 +388,7 @@ if (conf->client_certificate.len == 0 && conf->verify != 3) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no ssl_client_certificate for ssl_client_verify"); + "no ssl_client_certificate for ssl_verify_client"); return NGX_CONF_ERROR; }
diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index ec9524e..79f30a8 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c
@@ -745,7 +745,7 @@ if (conf->client_certificate.len == 0 && conf->verify != 3) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no ssl_client_certificate for ssl_client_verify"); + "no ssl_client_certificate for ssl_verify_client"); return NGX_CONF_ERROR; }