# HG changeset patch # User Igor Sysoev # Date 1331755200 -14400 # Node ID bf8b55a5ac89f05ba954094c22be43336f3e36c4 # Parent a8821023989f7cfba5cb16eb6767a31a71559cc9 nginx 1.1.17 *) Security: content of previously freed memory might be sent to a client if backend returned specially crafted response. Thanks to Matthew Daley. *) Bugfix: in the embedded perl module if used from SSI. Thanks to Matthew Daley. *) Bugfix: in the ngx_http_uwsgi_module. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,11 +1,23 @@ +Changes with nginx 1.1.17 15 Mar 2012 + + *) Security: content of previously freed memory might be sent to a + client if backend returned specially crafted response. + Thanks to Matthew Daley. + + *) Bugfix: in the embedded perl module if used from SSI. + Thanks to Matthew Daley. + + *) Bugfix: in the ngx_http_uwsgi_module. + + Changes with nginx 1.1.16 29 Feb 2012 *) Change: the simultaneous subrequest limit has been raised to 200. *) Feature: the "from" parameter of the "disable_symlinks" directive. - *) Feature: the "return" and "error_page" directives can be used to + *) Feature: the "return" and "error_page" directives can now be used to return 307 redirections. *) Bugfix: a segmentation fault might occur in a worker process if the @@ -45,13 +57,14 @@ Changes with nginx 1.1.15 *) Bugfix: nginx could not be built with the ngx_http_perl_module if the --with-openssl option was used. - *) Bugfix: internal redirects to named locations were not limited. + *) Bugfix: the number of internal redirects to named locations was not + limited. *) Bugfix: calling $r->flush() multiple times might cause errors in the ngx_http_gzip_filter_module. *) Bugfix: temporary files might be not removed if the "proxy_store" - directive were used with SSI includes. + directive was used with SSI includes. *) Bugfix: in some cases non-cacheable variables (such as the $args variable) returned old empty cached value. @@ -72,8 +85,8 @@ Changes with nginx 1.1.14 *) Bugfix: in the OpenSSL library initialization. - *) Bugfix: the "proxy_redirect" directives might not be correctly - inherited. + *) Bugfix: the "proxy_redirect" directives might be inherited + incorrectly. *) Bugfix: memory leak during reconfiguration if the "pcre_jit" directive was used. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,16 @@ +Изменения в nginx 1.1.17 15.03.2012 + + *) Безопасность: содержимое ранее освобождённой памяти могло быть + отправлено клиенту, если бэкенд возвращал специально созданный ответ. + Спасибо Matthew Daley. + + *) Исправление: при использовании встроенного перла из SSI. + Спасибо Matthew Daley. + + *) Исправление: в модуле ngx_http_uwsgi_module. + + Изменения в nginx 1.1.16 29.02.2012 *) Изменение: ограничение на количество одновременных подзапросов diff --git a/man/nginx.8 b/man/nginx.8 --- a/man/nginx.8 +++ b/man/nginx.8 @@ -25,7 +25,7 @@ .\" SUCH DAMAGE. .\" .\" -.Dd August 10, 2011 +.Dd March 6, 2012 .Dt NGINX 8 .Os .Sh NAME @@ -33,25 +33,22 @@ .Nd "HTTP and reverse proxy server, mail proxy server" .Sh SYNOPSIS .Nm -.Op Fl hqtvV? +.Op Fl ?hqtVv .Op Fl c Ar file .Op Fl g Ar directives .Op Fl p Ar prefix .Op Fl s Ar signal .Sh DESCRIPTION -The .Nm -(spelled +(pronounced .Dq engine x ) is an HTTP and reverse proxy server, as well as a mail proxy server. -The -.Nm -is known for its high performance, stability, rich feature set, simple +It is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. .Pp The options are as follows: .Bl -tag -width ".Fl d Ar directives" -.It Fl ?\& | h +.It Fl ?\& , h Print help. .It Fl c Ar file Use an alternative configuration @@ -62,20 +59,20 @@ See .Sx EXAMPLES for details. .It Fl p Ar prefix -Set prefix path. -Default value is +Set the prefix path. +The default value is .Pa %%PREFIX%% . .It Fl q Suppress non-error messages during configuration testing. .It Fl s Ar signal -Send signal to the master process. +Send a signal to the master process. The argument .Ar signal can be one of: .Cm stop , quit , reopen , reload . -The following table shows the corresponding system signals. +The following table shows the corresponding system signals: .Pp -.Bl -tag -width ".It Cm reopen" -compact +.Bl -tag -width ".Cm reopen" -compact .It Cm stop .Dv SIGTERM .It Cm quit @@ -86,49 +83,48 @@ The following table shows the correspond .Dv SIGHUP .El .It Fl t -Don't run, just test the configuration file. -The +Do not run, just test the configuration file. .Nm -checks configuration for correct syntax and then tries to open files -referred in configuration. +checks the configuration file syntax and then tries to open files +referenced in the configuration file. +.It Fl V +Print the +.Nm +version, compiler version, and +.Pa configure +script parameters. .It Fl v -Print +Print the .Nm version. -.It Fl V -Print -.Nm -version, compiler version and -.Pa configure -script parameters. .El .Sh SIGNALS The master process of .Nm -can handle the following signals. +can handle the following signals: .Pp -.Bl -tag -width ".It Dv SIGINT , SIGTERM" -compact +.Bl -tag -width ".Dv SIGINT , SIGTERM" -compact .It Dv SIGINT , SIGTERM Shut down quickly. .It Dv SIGHUP Reload configuration, start the new worker process with a new -configuration, gracefully shut down old worker processes. +configuration, and gracefully shut down old worker processes. .It Dv SIGQUIT Shut down gracefully. .It Dv SIGUSR1 Reopen log files. .It Dv SIGUSR2 -Upgrade +Upgrade the .Nm executable on the fly. .It Dv SIGWINCH -Shut down gracefully worker processes. +Shut down worker processes gracefully. .El .Pp -While there's no need to explicitly control worker processes normally, -they support some signals, too: +While there is no need to explicitly control worker processes normally, +they support some signals too: .Pp -.Bl -tag -width ".It Dv SIGINT , SIGTERM" -compact +.Bl -tag -width ".Dv SIGINT , SIGTERM" -compact .It Dv SIGTERM Shut down quickly. .It Dv SIGQUIT @@ -150,40 +146,44 @@ level of the .Pp .Dl "error_log /path/to/log debug;" .Pp -It is also possible to enable the debugging for some IP address: +It is also possible to enable the debugging for a particular IP address: .Bd -literal -offset indent events { debug_connection 127.0.0.1; } .Ed -.Sh FILES -.Bl -tag -width indent -compact -.It Pa %%PID_PATH%% -Contains the process ID of the +.Sh ENVIRONMENT +The +.Ev NGINX +environment variable is used internally by .Nm -listening for connections. -The content of this file is not sensitive; it can be world-readable. +and should not be set directly by the user. +.Sh FILES +.Bl -tag -width indent +.It Pa %%PID_PATH%% +Contains the process ID of +.Nm . +The contents of this file are not sensitive, so it can be world-readable. .It Pa %%CONF_PATH%% -Main configuration file. +The main configuration file. .It Pa %%ERROR_LOG_PATH%% Error log file. .El .Sh EXIT STATUS Exit status is 0 on success, or 1 if the command fails. .Sh EXAMPLES -.Bd -literal -nginx -t -c ~/mynginx.conf -g "pid /var/run/mynginx.pid; worker_processes 2;" -.Ed Test configuration file .Pa ~/mynginx.conf -with global directives for PID and quantity of worker processes. +with global directives for PID and quantity of worker processes: +.Bd -literal -offset indent +nginx -t -c ~/mynginx.conf \e + -g "pid /var/run/mynginx.pid; worker_processes 2;" +.Ed .Sh SEE ALSO .\"Xr nginx.conf 5 .\"Pp Documentation at -.Pa http://nginx.org/ -and -.Pa http://sysoev.ru/nginx/ . +.Pa http://nginx.org/en/docs/ . .Pp For questions and technical support, please refer to .Pa http://nginx.org/en/support.html . @@ -193,10 +193,10 @@ Development of started in 2002, with the first public release on October 4, 2004. .Sh AUTHORS .An -nosplit -.An Igor Sysoev Aq igor@sysoev.ru +.An Igor Sysoev Aq igor@sysoev.ru . .Pp -This manual page was written by +This manual page was originally written by .An Sergey A. Osokin Aq osa@FreeBSD.org.ru -as a result of compilation of many +as a result of compiling many .Nm -documents all over the world. +documents from all over the world. diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1001016 -#define NGINX_VERSION "1.1.16" +#define nginx_version 1001017 +#define NGINX_VERSION "1.1.17" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -514,7 +514,7 @@ ngx_configure_listening_sockets(ngx_cycl } } -#if (NGX_HAVE_KEEPALIVE_TUNABLE) +#if (NGX_HAVE_KEEPALIVE_TUNABLE) if (ls[i].keepidle) { if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE, diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -478,6 +478,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_ return NGX_OK; } + ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) { @@ -518,6 +519,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s return NGX_OK; } + ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags) { diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -1501,10 +1501,10 @@ ngx_http_fastcgi_process_header(ngx_http h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; - ngx_cpystrn(h->key.data, r->header_name_start, - h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, - h->value.len + 1); + ngx_memcpy(h->key.data, r->header_name_start, h->key.len); + h->key.data[h->key.len] = '\0'; + ngx_memcpy(h->value.data, r->header_start, h->value.len); + h->value.data[h->value.len] = '\0'; } h->hash = r->header_hash; @@ -2432,7 +2432,8 @@ ngx_http_fastcgi_merge_params(ngx_conf_t if (prev->headers_hash.buckets #if (NGX_HTTP_CACHE) - && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) + && ((conf->upstream.cache == NULL) + == (prev->upstream.cache == NULL)) #endif ) { diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1381,8 +1381,10 @@ ngx_http_proxy_process_header(ngx_http_r h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; - ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); + ngx_memcpy(h->key.data, r->header_name_start, h->key.len); + h->key.data[h->key.len] = '\0'; + ngx_memcpy(h->value.data, r->header_start, h->value.len); + h->value.data[h->value.len] = '\0'; if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -941,8 +941,10 @@ ngx_http_scgi_process_header(ngx_http_re h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; - ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); + ngx_memcpy(h->key.data, r->header_name_start, h->key.len); + h->key.data[h->key.len] = '\0'; + ngx_memcpy(h->value.data, r->header_start, h->value.len); + h->value.data[h->value.len] = '\0'; if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); @@ -1384,7 +1386,8 @@ ngx_http_scgi_merge_params(ngx_conf_t *c if (prev->headers_hash.buckets #if (NGX_HTTP_CACHE) - && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) + && ((conf->upstream.cache == NULL) + == (prev->upstream.cache == NULL)) #endif ) { diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -1204,7 +1204,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r if (ctx->value_buf == NULL) { ctx->param->value.data = ngx_pnalloc(r->pool, - ctx->value_len); + ctx->value_len + 1); if (ctx->param->value.data == NULL) { return NGX_ERROR; } @@ -1375,6 +1375,16 @@ ngx_http_ssi_parse(ngx_http_request_t *r case ssi_quoted_symbol_state: state = ctx->saved_state; + if (ctx->param->value.len == ctx->value_len) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "too long \"%V%c...\" value of \"%V\" " + "parameter in \"%V\" SSI command", + &ctx->param->value, ch, &ctx->param->key, + &ctx->command); + state = ssi_error_state; + break; + } + ctx->param->value.data[ctx->param->value.len++] = ch; break; @@ -2886,7 +2896,7 @@ ngx_http_ssi_merge_loc_conf(ngx_conf_t * prev->ignore_recycled_buffers, 0); ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024); - ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256); + ngx_conf_merge_size_value(conf->value_len, prev->value_len, 255); if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, &prev->types_keys, &prev->types, diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -43,7 +43,6 @@ static ngx_int_t ngx_http_uwsgi_create_r static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r); static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r); static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); -static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r); static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r); static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc); @@ -912,10 +911,7 @@ ngx_http_uwsgi_process_status_line(ngx_h } if (rc == NGX_ERROR) { - r->http_version = NGX_HTTP_VERSION_9; - u->process_header = ngx_http_uwsgi_process_header; - return ngx_http_uwsgi_process_header(r); } @@ -985,8 +981,10 @@ ngx_http_uwsgi_process_header(ngx_http_r h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; - ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); - ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); + ngx_memcpy(h->key.data, r->header_name_start, h->key.len); + h->key.data[h->key.len] = '\0'; + ngx_memcpy(h->value.data, r->header_start, h->value.len); + h->value.data[h->value.len] = '\0'; if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); @@ -1015,12 +1013,12 @@ ngx_http_uwsgi_process_header(ngx_http_r ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http uwsgi header done"); - if (r->http_version > NGX_HTTP_VERSION_9) { + u = r->upstream; + + if (u->headers_in.status_n) { return NGX_OK; } - u = r->upstream; - if (u->headers_in.status) { status_line = &u->headers_in.status->value; @@ -1032,20 +1030,15 @@ ngx_http_uwsgi_process_header(ngx_http_r return NGX_HTTP_UPSTREAM_INVALID_HEADER; } - r->http_version = NGX_HTTP_VERSION_10; u->headers_in.status_n = status; u->headers_in.status_line = *status_line; } else if (u->headers_in.location) { - r->http_version = NGX_HTTP_VERSION_10; u->headers_in.status_n = 302; ngx_str_set(&u->headers_in.status_line, "302 Moved Temporarily"); } else { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "upstream sent neither valid HTTP/1.0 header " - "nor \"Status\" header line"); u->headers_in.status_n = 200; ngx_str_set(&u->headers_in.status_line, "200 OK"); } @@ -1441,7 +1434,8 @@ ngx_http_uwsgi_merge_params(ngx_conf_t * if (prev->headers_hash.buckets #if (NGX_HTTP_CACHE) - && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL)) + && ((conf->upstream.cache == NULL) + == (prev->upstream.cache == NULL)) #endif ) { diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -50,7 +50,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '1.1.16'; +our $VERSION = '1.1.17'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c --- a/src/http/ngx_http_busy_lock.c +++ b/src/http/ngx_http_busy_lock.c @@ -300,7 +300,7 @@ char *ngx_http_set_busy_lock_slot(ngx_co if (bl->timeout == 0 && bl->max_waiting) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "busy lock waiting is useless with zero timeout, ignoring"); + "busy lock waiting is useless with zero timeout, ignoring"); } return NGX_CONF_OK; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3970,7 +3970,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx } } - if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0 + if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0 && lsopt.tcp_keepcnt == 0) { goto invalid_so_keepalive; @@ -4629,7 +4629,7 @@ ngx_http_core_open_file_cache(ngx_conf_t if (max == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"open_file_cache\" must have the \"max\" parameter"); + "\"open_file_cache\" must have the \"max\" parameter"); return NGX_CONF_ERROR; } diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -874,6 +874,10 @@ ngx_http_parse_header_line(ngx_http_requ break; } + if (ch == '\0') { + return NGX_HTTP_PARSE_INVALID_HEADER; + } + r->invalid_header = 1; break; @@ -936,6 +940,10 @@ ngx_http_parse_header_line(ngx_http_requ break; } + if (ch == '\0') { + return NGX_HTTP_PARSE_INVALID_HEADER; + } + r->invalid_header = 1; break; @@ -954,6 +962,8 @@ ngx_http_parse_header_line(ngx_http_requ r->header_start = p; r->header_end = p; goto done; + case '\0': + return NGX_HTTP_PARSE_INVALID_HEADER; default: r->header_start = p; state = sw_value; @@ -975,6 +985,8 @@ ngx_http_parse_header_line(ngx_http_requ case LF: r->header_end = p; goto done; + case '\0': + return NGX_HTTP_PARSE_INVALID_HEADER; } break; @@ -988,6 +1000,8 @@ ngx_http_parse_header_line(ngx_http_requ break; case LF: goto done; + case '\0': + return NGX_HTTP_PARSE_INVALID_HEADER; default: state = sw_value; break; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -26,7 +26,7 @@ static char *ngx_mail_core_resolver(ngx_ static ngx_conf_deprecated_t ngx_conf_deprecated_so_keepalive = { - ngx_conf_deprecated, "so_keepalive", + ngx_conf_deprecated, "so_keepalive", "so_keepalive\" parameter of the \"listen" }; diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -544,7 +544,7 @@ ngx_process_get_status(void) static void ngx_unlock_mutexes(ngx_pid_t pid) -{ +{ ngx_uint_t i; ngx_shm_zone_t *shm_zone; ngx_list_part_t *part;