Hello community, here is the log from the commit of package nginx for openSUSE:Factory checked in at 2018-12-19 13:50:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nginx (Old) and /work/SRC/openSUSE:Factory/.nginx.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nginx" Wed Dec 19 13:50:53 2018 rev:32 rq:659039 version:1.15.7 Changes: -------- --- /work/SRC/openSUSE:Factory/nginx/nginx.changes 2018-11-12 09:44:13.888936754 +0100 +++ /work/SRC/openSUSE:Factory/.nginx.new.28833/nginx.changes 2018-12-19 13:51:07.399142812 +0100 @@ -1,0 +2,15 @@ +Fri Dec 7 14:53:14 UTC 2018 - ch...@computersalat.de + +- update to 1.15.7 + * Feature: the "proxy_requests" directive in the stream module. + * Feature: the "delay" parameter of the "limit_req" directive. + Thanks to Vladislav Shabanov and Peter Shchuchkin. + * Bugfix: memory leak on errors during reconfiguration. + * Bugfix: in the $upstream_response_time, $upstream_connect_time, and + $upstream_header_time variables. + * Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_mp4_module was used on 32-bit platforms. +- fix changes file for submit to Backports + * see https://build.opensuse.org/request/show/653792 + +------------------------------------------------------------------- @@ -5 +20,2 @@ - - Security: when using HTTP/2 a client might cause excessive memory + * fix for boo#1115022, boo#1115025 + Security: when using HTTP/2 a client might cause excessive memory @@ -7 +23,2 @@ - - Security: processing of a specially crafted mp4 file with the + * fix for boo#1115015 + Security: processing of a specially crafted mp4 file with the Old: ---- nginx-1.15.6.tar.gz nginx-1.15.6.tar.gz.asc New: ---- nginx-1.15.7.tar.gz nginx-1.15.7.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nginx.spec ++++++ --- /var/tmp/diff_new_pack.8vUldx/_old 2018-12-19 13:51:08.079141870 +0100 +++ /var/tmp/diff_new_pack.8vUldx/_new 2018-12-19 13:51:08.083141865 +0100 @@ -70,7 +70,7 @@ %define ngx_doc_dir %{_datadir}/doc/packages/%{name} # Name: nginx -Version: 1.15.6 +Version: 1.15.7 Release: 0 %define ngx_fancyindex_version 0.4.2 %define ngx_fancyindex_module_path ngx-fancyindex-%{ngx_fancyindex_version} ++++++ nginx-1.15.6.tar.gz -> nginx-1.15.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/CHANGES new/nginx-1.15.7/CHANGES --- old/nginx-1.15.6/CHANGES 2018-11-06 14:32:17.000000000 +0100 +++ new/nginx-1.15.7/CHANGES 2018-11-27 15:40:40.000000000 +0100 @@ -1,4 +1,20 @@ +Changes with nginx 1.15.7 27 Nov 2018 + + *) Feature: the "proxy_requests" directive in the stream module. + + *) Feature: the "delay" parameter of the "limit_req" directive. + Thanks to Vladislav Shabanov and Peter Shchuchkin. + + *) Bugfix: memory leak on errors during reconfiguration. + + *) Bugfix: in the $upstream_response_time, $upstream_connect_time, and + $upstream_header_time variables. + + *) Bugfix: a segmentation fault might occur in a worker process if the + ngx_http_mp4_module was used on 32-bit platforms. + + Changes with nginx 1.15.6 06 Nov 2018 *) Security: when using HTTP/2 a client might cause excessive memory diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/CHANGES.ru new/nginx-1.15.7/CHANGES.ru --- old/nginx-1.15.6/CHANGES.ru 2018-11-06 14:32:14.000000000 +0100 +++ new/nginx-1.15.7/CHANGES.ru 2018-11-27 15:40:35.000000000 +0100 @@ -1,4 +1,21 @@ +Изменения в nginx 1.15.7 27.11.2018 + + *) Добавление: директива proxy_requests в модуле stream. + + *) Добавление: параметр "delay" директивы "limit_req". + Спасибо Владиславу Шабанову и Петру Щучкину. + + *) Исправление: утечки памяти в случае ошибок при переконфигурации. + + *) Исправление: в переменных $upstream_response_time, + $upstream_connect_time и $upstream_header_time. + + *) Исправление: в рабочем процессе мог произойти segmentation fault, + если использовался модуль ngx_http_mp4_module на 32-битных + платформах. + + Изменения в nginx 1.15.6 06.11.2018 *) Безопасность: при использовании HTTP/2 клиент мог вызвать чрезмерное diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/core/nginx.h new/nginx-1.15.7/src/core/nginx.h --- old/nginx-1.15.6/src/core/nginx.h 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/core/nginx.h 2018-11-27 15:40:21.000000000 +0100 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1015006 -#define NGINX_VERSION "1.15.6" +#define nginx_version 1015007 +#define NGINX_VERSION "1.15.7" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/core/ngx_cycle.c new/nginx-1.15.7/src/core/ngx_cycle.c --- old/nginx-1.15.6/src/core/ngx_cycle.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/core/ngx_cycle.c 2018-11-27 15:40:21.000000000 +0100 @@ -843,6 +843,69 @@ } } + /* free the newly created shared memory */ + + part = &cycle->shared_memory.part; + shm_zone = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + part = part->next; + shm_zone = part->elts; + i = 0; + } + + if (shm_zone[i].shm.addr == NULL) { + continue; + } + + opart = &old_cycle->shared_memory.part; + oshm_zone = opart->elts; + + for (n = 0; /* void */ ; n++) { + + if (n >= opart->nelts) { + if (opart->next == NULL) { + break; + } + opart = opart->next; + oshm_zone = opart->elts; + n = 0; + } + + if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { + continue; + } + + if (ngx_strncmp(shm_zone[i].shm.name.data, + oshm_zone[n].shm.name.data, + shm_zone[i].shm.name.len) + != 0) + { + continue; + } + + if (shm_zone[i].tag == oshm_zone[n].tag + && shm_zone[i].shm.size == oshm_zone[n].shm.size + && !shm_zone[i].noreuse) + { + goto old_shm_zone_found; + } + + break; + } + + ngx_shm_free(&shm_zone[i].shm); + + old_shm_zone_found: + + continue; + } + if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; @@ -1274,6 +1337,7 @@ shm_zone->data = NULL; shm_zone->shm.log = cf->cycle->log; + shm_zone->shm.addr = NULL; shm_zone->shm.size = size; shm_zone->shm.name = *name; shm_zone->shm.exists = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/core/ngx_output_chain.c new/nginx-1.15.7/src/core/ngx_output_chain.c --- old/nginx-1.15.6/src/core/ngx_output_chain.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/core/ngx_output_chain.c 2018-11-27 15:40:21.000000000 +0100 @@ -126,6 +126,26 @@ continue; } + if (bsize < 0) { + + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, + "negative size buf in output " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + ctx->in->buf->temporary, + ctx->in->buf->recycled, + ctx->in->buf->in_file, + ctx->in->buf->start, + ctx->in->buf->pos, + ctx->in->buf->last, + ctx->in->buf->file, + ctx->in->buf->file_pos, + ctx->in->buf->file_last); + + ngx_debug_point(); + + return NGX_ERROR; + } + if (ngx_output_chain_as_is(ctx, ctx->in->buf)) { /* move the chain link to the output chain */ @@ -665,7 +685,6 @@ for (size = 0; in; in = in->next) { -#if 1 if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) { ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, @@ -685,7 +704,26 @@ continue; } -#endif + + if (ngx_buf_size(in->buf) < 0) { + + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, + "negative size buf in chain writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + in->buf->temporary, + in->buf->recycled, + in->buf->in_file, + in->buf->start, + in->buf->pos, + in->buf->last, + in->buf->file, + in->buf->file_pos, + in->buf->file_last); + + ngx_debug_point(); + + return NGX_ERROR; + } size += ngx_buf_size(in->buf); @@ -709,7 +747,6 @@ for (cl = ctx->out; cl; cl = cl->next) { -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, @@ -729,7 +766,26 @@ continue; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, + "negative size buf in chain writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/core/ngx_string.c new/nginx-1.15.7/src/core/ngx_string.c --- old/nginx-1.15.6/src/core/ngx_string.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/core/ngx_string.c 2018-11-27 15:40:21.000000000 +0100 @@ -2013,6 +2013,14 @@ } +void +ngx_explicit_memzero(void *buf, size_t n) +{ + ngx_memzero(buf, n); + ngx_memory_barrier(); +} + + #if (NGX_MEMCPY_LIMIT) void * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/core/ngx_string.h new/nginx-1.15.7/src/core/ngx_string.h --- old/nginx-1.15.6/src/core/ngx_string.h 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/core/ngx_string.h 2018-11-27 15:40:21.000000000 +0100 @@ -88,6 +88,8 @@ #define ngx_memzero(buf, n) (void) memset(buf, 0, n) #define ngx_memset(buf, c, n) (void) memset(buf, c, n) +void ngx_explicit_memzero(void *buf, size_t n); + #if (NGX_MEMCPY_LIMIT) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/event/ngx_event.h new/nginx-1.15.7/src/event/ngx_event.h --- old/nginx-1.15.6/src/event/ngx_event.h 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/event/ngx_event.h 2018-11-27 15:40:21.000000000 +0100 @@ -509,6 +509,7 @@ void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); #endif +void ngx_delete_udp_connection(void *data); ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle); ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/event/ngx_event_openssl.c new/nginx-1.15.7/src/event/ngx_event_openssl.c --- old/nginx-1.15.6/src/event/ngx_event_openssl.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/event/ngx_event_openssl.c 2018-11-27 15:40:21.000000000 +0100 @@ -1051,7 +1051,7 @@ ngx_close_file_n " \"%s\" failed", file->data); } - ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE); + ngx_explicit_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE); return passwords; } @@ -1068,7 +1068,7 @@ pwd = passwords->elts; for (i = 0; i < passwords->nelts; i++) { - ngx_memzero(pwd[i].data, pwd[i].len); + ngx_explicit_memzero(pwd[i].data, pwd[i].len); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/event/ngx_event_udp.c new/nginx-1.15.7/src/event/ngx_event_udp.c --- old/nginx-1.15.6/src/event/ngx_event_udp.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/event/ngx_event_udp.c 2018-11-27 15:40:21.000000000 +0100 @@ -23,7 +23,6 @@ static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, size_t size); static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c); -static void ngx_delete_udp_connection(void *data); static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, socklen_t socklen, struct sockaddr *local_sockaddr, socklen_t local_socklen); @@ -261,7 +260,10 @@ rev->handler(rev); - c->udp->buffer = NULL; + if (c->udp) { + c->udp->buffer = NULL; + } + rev->ready = 0; goto next; @@ -555,12 +557,18 @@ } -static void +void ngx_delete_udp_connection(void *data) { ngx_connection_t *c = data; + if (c->udp == NULL) { + return; + } + ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node); + + c->udp = NULL; } @@ -638,4 +646,12 @@ return NULL; } +#else + +void +ngx_delete_udp_connection(void *data) +{ + return; +} + #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/http/modules/ngx_http_limit_req_module.c new/nginx-1.15.7/src/http/modules/ngx_http_limit_req_module.c --- old/nginx-1.15.6/src/http/modules/ngx_http_limit_req_module.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/http/modules/ngx_http_limit_req_module.c 2018-11-27 15:40:21.000000000 +0100 @@ -44,7 +44,7 @@ ngx_shm_zone_t *shm_zone; /* integer value, 1 corresponds to 0.001 r/s */ ngx_uint_t burst; - ngx_uint_t nodelay; /* unsigned nodelay:1 */ + ngx_uint_t delay; } ngx_http_limit_req_limit_t; @@ -499,12 +499,12 @@ excess = *ep; - if (excess == 0 || (*limit)->nodelay) { + if ((ngx_uint_t) excess <= (*limit)->delay) { max_delay = 0; } else { ctx = (*limit)->shm_zone->data; - max_delay = excess * 1000 / ctx->rate; + max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate; } while (n--) { @@ -544,11 +544,11 @@ ctx->node = NULL; - if (limits[n].nodelay) { + if ((ngx_uint_t) excess <= limits[n].delay) { continue; } - delay = excess * 1000 / ctx->rate; + delay = (excess - limits[n].delay) * 1000 / ctx->rate; if (delay > max_delay) { max_delay = delay; @@ -875,9 +875,9 @@ { ngx_http_limit_req_conf_t *lrcf = conf; - ngx_int_t burst; + ngx_int_t burst, delay; ngx_str_t *value, s; - ngx_uint_t i, nodelay; + ngx_uint_t i; ngx_shm_zone_t *shm_zone; ngx_http_limit_req_limit_t *limit, *limits; @@ -885,7 +885,7 @@ shm_zone = NULL; burst = 0; - nodelay = 0; + delay = 0; for (i = 1; i < cf->args->nelts; i++) { @@ -908,7 +908,19 @@ burst = ngx_atoi(value[i].data + 6, value[i].len - 6); if (burst <= 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid burst rate \"%V\"", &value[i]); + "invalid burst value \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { + + delay = ngx_atoi(value[i].data + 6, value[i].len - 6); + if (delay <= 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid delay value \"%V\"", &value[i]); return NGX_CONF_ERROR; } @@ -916,7 +928,7 @@ } if (ngx_strcmp(value[i].data, "nodelay") == 0) { - nodelay = 1; + delay = NGX_MAX_INT_T_VALUE / 1000; continue; } @@ -956,7 +968,7 @@ limit->shm_zone = shm_zone; limit->burst = burst * 1000; - limit->nodelay = nodelay; + limit->delay = delay * 1000; return NGX_CONF_OK; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/http/modules/ngx_http_mp4_module.c new/nginx-1.15.7/src/http/modules/ngx_http_mp4_module.c --- old/nginx-1.15.6/src/http/modules/ngx_http_mp4_module.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/http/modules/ngx_http_mp4_module.c 2018-11-27 15:40:21.000000000 +0100 @@ -169,7 +169,14 @@ #define ngx_mp4_atom_next(mp4, n) \ - mp4->buffer_pos += (size_t) n; \ + \ + if (n > (size_t) (mp4->buffer_end - mp4->buffer_pos)) { \ + mp4->buffer_pos = mp4->buffer_end; \ + \ + } else { \ + mp4->buffer_pos += (size_t) n; \ + } \ + \ mp4->offset += n diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/http/ngx_http_upstream.c new/nginx-1.15.7/src/http/ngx_http_upstream.c --- old/nginx-1.15.6/src/http/ngx_http_upstream.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/http/ngx_http_upstream.c 2018-11-27 15:40:21.000000000 +0100 @@ -1505,8 +1505,8 @@ r->connection->log->action = "connecting to upstream"; - if (u->state && u->state->response_time) { - u->state->response_time = ngx_current_msec - u->state->response_time; + if (u->state && u->state->response_time == (ngx_msec_t) -1) { + u->state->response_time = ngx_current_msec - u->start_time; } u->state = ngx_array_push(r->upstream_states); @@ -1518,7 +1518,9 @@ ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); - u->state->response_time = ngx_current_msec; + u->start_time = ngx_current_msec; + + u->state->response_time = (ngx_msec_t) -1; u->state->connect_time = (ngx_msec_t) -1; u->state->header_time = (ngx_msec_t) -1; @@ -2002,7 +2004,7 @@ "http upstream send request"); if (u->state->connect_time == (ngx_msec_t) -1) { - u->state->connect_time = ngx_current_msec - u->state->response_time; + u->state->connect_time = ngx_current_msec - u->start_time; } if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) { @@ -2413,7 +2415,7 @@ /* rc == NGX_OK */ - u->state->header_time = ngx_current_msec - u->state->response_time; + u->state->header_time = ngx_current_msec - u->start_time; if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) { @@ -4309,8 +4311,8 @@ u->resolved->ctx = NULL; } - if (u->state && u->state->response_time) { - u->state->response_time = ngx_current_msec - u->state->response_time; + if (u->state && u->state->response_time == (ngx_msec_t) -1) { + u->state->response_time = ngx_current_msec - u->start_time; if (u->pipe && u->pipe->read_length) { u->state->bytes_received += u->pipe->read_length @@ -5419,18 +5421,18 @@ state = r->upstream_states->elts; for ( ;; ) { - if (state[i].status) { - if (data == 1 && state[i].header_time != (ngx_msec_t) -1) { - ms = state[i].header_time; + if (data == 1) { + ms = state[i].header_time; - } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) { - ms = state[i].connect_time; + } else if (data == 2) { + ms = state[i].connect_time; - } else { - ms = state[i].response_time; - } + } else { + ms = state[i].response_time; + } + if (ms != -1) { ms = ngx_max(ms, 0); p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/http/ngx_http_upstream.h new/nginx-1.15.7/src/http/ngx_http_upstream.h --- old/nginx-1.15.6/src/http/ngx_http_upstream.h 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/http/ngx_http_upstream.h 2018-11-27 15:40:21.000000000 +0100 @@ -365,7 +365,7 @@ ngx_int_t (*rewrite_cookie)(ngx_http_request_t *r, ngx_table_elt_t *h); - ngx_msec_t timeout; + ngx_msec_t start_time; ngx_http_upstream_state_t *state; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/http/ngx_http_write_filter_module.c new/nginx-1.15.7/src/http/ngx_http_write_filter_module.c --- old/nginx-1.15.6/src/http/ngx_http_write_filter_module.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/http/ngx_http_write_filter_module.c 2018-11-27 15:40:21.000000000 +0100 @@ -80,7 +80,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -98,7 +97,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); @@ -136,7 +152,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -154,7 +169,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/stream/ngx_stream_proxy_module.c new/nginx-1.15.7/src/stream/ngx_stream_proxy_module.c --- old/nginx-1.15.6/src/stream/ngx_stream_proxy_module.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/stream/ngx_stream_proxy_module.c 2018-11-27 15:40:21.000000000 +0100 @@ -26,6 +26,7 @@ size_t buffer_size; size_t upload_rate; size_t download_rate; + ngx_uint_t requests; ngx_uint_t responses; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; @@ -73,6 +74,8 @@ static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c); static void ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write); +static ngx_int_t ngx_stream_proxy_test_finalize(ngx_stream_session_t *s, + ngx_uint_t from_upstream); static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s); static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc); static u_char *ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf, @@ -193,6 +196,13 @@ offsetof(ngx_stream_proxy_srv_conf_t, download_rate), NULL }, + { ngx_string("proxy_requests"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, requests), + NULL }, + { ngx_string("proxy_responses"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -680,7 +690,7 @@ u->proxy_protocol = pscf->proxy_protocol; if (u->state) { - u->state->response_time = ngx_current_msec - u->state->response_time; + u->state->response_time = ngx_current_msec - u->start_time; } u->state = ngx_array_push(s->upstream_states); @@ -691,9 +701,11 @@ ngx_memzero(u->state, sizeof(ngx_stream_upstream_state_t)); + u->start_time = ngx_current_msec; + u->state->connect_time = (ngx_msec_t) -1; u->state->first_byte_time = (ngx_msec_t) -1; - u->state->response_time = ngx_current_msec; + u->state->response_time = (ngx_msec_t) -1; rc = ngx_event_connect_peer(&u->peer); @@ -807,7 +819,7 @@ } } - u->state->connect_time = ngx_current_msec - u->state->response_time; + u->state->connect_time = ngx_current_msec - u->start_time; if (u->peer.notify) { u->peer.notify(&u->peer, u->peer.data, @@ -1339,11 +1351,14 @@ } else { if (s->connection->type == SOCK_DGRAM) { - if (pscf->responses == NGX_MAX_INT32_VALUE) { + + if (pscf->responses == NGX_MAX_INT32_VALUE + || (u->responses >= pscf->responses * u->requests)) + { /* * successfully terminate timed out UDP session - * with unspecified number of responses + * if expected number of responses was received */ handler = c->log->handler; @@ -1609,7 +1624,7 @@ if (from_upstream) { if (u->state->first_byte_time == (ngx_msec_t) -1) { u->state->first_byte_time = ngx_current_msec - - u->state->response_time; + - u->start_time; } } @@ -1646,44 +1661,7 @@ c->log->action = "proxying connection"; - if (c->type == SOCK_DGRAM - && pscf->responses != NGX_MAX_INT32_VALUE - && u->responses >= pscf->responses * u->requests - && !src->buffered && dst && !dst->buffered) - { - handler = c->log->handler; - c->log->handler = NULL; - - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "udp done" - ", packets from/to client:%ui/%ui" - ", bytes from/to client:%O/%O" - ", bytes from/to upstream:%O/%O", - u->requests, u->responses, - s->received, c->sent, u->received, pc ? pc->sent : 0); - - c->log->handler = handler; - - ngx_stream_proxy_finalize(s, NGX_STREAM_OK); - return; - } - - if (c->type == SOCK_STREAM - && src->read->eof && dst && (dst->read->eof || !dst->buffered)) - { - handler = c->log->handler; - c->log->handler = NULL; - - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "%s disconnected" - ", bytes from/to client:%O/%O" - ", bytes from/to upstream:%O/%O", - from_upstream ? "upstream" : "client", - s->received, c->sent, u->received, pc ? pc->sent : 0); - - c->log->handler = handler; - - ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + if (ngx_stream_proxy_test_finalize(s, from_upstream) == NGX_OK) { return; } @@ -1710,6 +1688,87 @@ } +static ngx_int_t +ngx_stream_proxy_test_finalize(ngx_stream_session_t *s, + ngx_uint_t from_upstream) +{ + ngx_connection_t *c, *pc; + ngx_log_handler_pt handler; + ngx_stream_upstream_t *u; + ngx_stream_proxy_srv_conf_t *pscf; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + c = s->connection; + u = s->upstream; + pc = u->connected ? u->peer.connection : NULL; + + if (c->type == SOCK_DGRAM) { + + if (pscf->requests && u->requests < pscf->requests) { + return NGX_DECLINED; + } + + if (pscf->requests) { + ngx_delete_udp_connection(c); + } + + if (pscf->responses == NGX_MAX_INT32_VALUE + || u->responses < pscf->responses * u->requests) + { + return NGX_DECLINED; + } + + if (pc == NULL || c->buffered || pc->buffered) { + return NGX_DECLINED; + } + + handler = c->log->handler; + c->log->handler = NULL; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "udp done" + ", packets from/to client:%ui/%ui" + ", bytes from/to client:%O/%O" + ", bytes from/to upstream:%O/%O", + u->requests, u->responses, + s->received, c->sent, u->received, pc ? pc->sent : 0); + + c->log->handler = handler; + + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + + return NGX_OK; + } + + /* c->type == SOCK_STREAM */ + + if (pc == NULL + || (!c->read->eof && !pc->read->eof) + || (!c->read->eof && c->buffered) + || (!pc->read->eof && pc->buffered)) + { + return NGX_DECLINED; + } + + handler = c->log->handler; + c->log->handler = NULL; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "%s disconnected" + ", bytes from/to client:%O/%O" + ", bytes from/to upstream:%O/%O", + from_upstream ? "upstream" : "client", + s->received, c->sent, u->received, pc ? pc->sent : 0); + + c->log->handler = handler; + + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + + return NGX_OK; +} + + static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s) { @@ -1800,7 +1859,9 @@ pc = u->peer.connection; if (u->state) { - u->state->response_time = ngx_current_msec - u->state->response_time; + if (u->state->response_time == (ngx_msec_t) -1) { + u->state->response_time = ngx_current_msec - u->start_time; + } if (pc) { u->state->bytes_received = u->received; @@ -1905,6 +1966,7 @@ conf->buffer_size = NGX_CONF_UNSET_SIZE; conf->upload_rate = NGX_CONF_UNSET_SIZE; conf->download_rate = NGX_CONF_UNSET_SIZE; + conf->requests = NGX_CONF_UNSET_UINT; conf->responses = NGX_CONF_UNSET_UINT; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; @@ -1949,6 +2011,9 @@ ngx_conf_merge_size_value(conf->download_rate, prev->download_rate, 0); + ngx_conf_merge_uint_value(conf->requests, + prev->requests, 0); + ngx_conf_merge_uint_value(conf->responses, prev->responses, NGX_MAX_INT32_VALUE); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/stream/ngx_stream_upstream.c new/nginx-1.15.7/src/stream/ngx_stream_upstream.c --- old/nginx-1.15.6/src/stream/ngx_stream_upstream.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/stream/ngx_stream_upstream.c 2018-11-27 15:40:21.000000000 +0100 @@ -267,24 +267,22 @@ for ( ;; ) { if (data == 1) { - if (state[i].first_byte_time == (ngx_msec_t) -1) { - *p++ = '-'; - goto next; - } - ms = state[i].first_byte_time; - } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) { + } else if (data == 2) { ms = state[i].connect_time; } else { ms = state[i].response_time; } - ms = ngx_max(ms, 0); - p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); + if (ms != -1) { + ms = ngx_max(ms, 0); + p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); - next: + } else { + *p++ = '-'; + } if (++i == s->upstream_states->nelts) { break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/stream/ngx_stream_upstream.h new/nginx-1.15.7/src/stream/ngx_stream_upstream.h --- old/nginx-1.15.6/src/stream/ngx_stream_upstream.h 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/stream/ngx_stream_upstream.h 2018-11-27 15:40:21.000000000 +0100 @@ -130,6 +130,7 @@ time_t start_sec; ngx_uint_t requests; ngx_uint_t responses; + ngx_msec_t start_time; ngx_str_t ssl_name; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nginx-1.15.6/src/stream/ngx_stream_write_filter_module.c new/nginx-1.15.7/src/stream/ngx_stream_write_filter_module.c --- old/nginx-1.15.6/src/stream/ngx_stream_write_filter_module.c 2018-11-06 14:32:09.000000000 +0100 +++ new/nginx-1.15.7/src/stream/ngx_stream_write_filter_module.c 2018-11-27 15:40:21.000000000 +0100 @@ -104,7 +104,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -122,7 +121,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); @@ -160,7 +176,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -178,7 +193,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf);