# HG changeset patch # User Igor Sysoev # Date 1254081600 -14400 # Node ID 4c5d2c627a6c0ad577b5e930782128fc7b082599 # Parent b8ac674b0ec95cf1d655aeb716a95101c39456f0 nginx 0.8.17 *) Security: now "/../" are disabled in "Destination" request header line. *) Change: now $host variable value is always low case. *) Feature: the $ssl_session_id variable. *) Bugfix: socket leak; the bug had appeared in 0.8.11. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,16 @@ +Changes with nginx 0.8.17 28 Sep 2009 + + *) Security: now "/../" are disabled in "Destination" request header + line. + + *) Change: now $host variable value is always low case. + + *) Feature: the $ssl_session_id variable. + + *) Bugfix: socket leak; the bug had appeared in 0.8.11. + + Changes with nginx 0.8.16 22 Sep 2009 *) Feature: the "image_filter_transparency" directive. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,16 @@ +Изменения в nginx 0.8.17 28.09.2009 + + *) Безопасность: теперь символы "/../" запрещены в строке "Destination" + в заголовке запроса. + + *) Изменение: теперь значение переменной $host всегда в нижнем регистре. + + *) Добавление: переменная $ssl_session_id. + + *) Исправление: утечки сокетов; ошибка появилась в 0.8.11. + + Изменения в nginx 0.8.16 22.09.2009 *) Добавление: директива image_filter_transparency. diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -25,10 +25,10 @@ if [ $OPENSSL != NONE ]; then have=NGX_OPENSSL . auto/have have=NGX_SSL . auto/have - CORE_INCS="$CORE_INCS $OPENSSL/openssl/include" - CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h" - CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libssl.a" - CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libcrypto.a" + CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include" + CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h" + CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a" + CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a" CORE_LIBS="$CORE_LIBS $NGX_LIBDL" ;; esac diff --git a/auto/lib/openssl/make b/auto/lib/openssl/make --- a/auto/lib/openssl/make +++ b/auto/lib/openssl/make @@ -46,13 +46,13 @@ END esac case $OPENSSL in - /*) ngx_prefix="$OPENSSL/openssl" ;; - *) ngx_prefix="$PWD/$OPENSSL/openssl" ;; + /*) ngx_prefix="$OPENSSL/.openssl" ;; + *) ngx_prefix="$PWD/$OPENSSL/.openssl" ;; esac cat << END >> $NGX_MAKEFILE -$OPENSSL/openssl/include/openssl/ssl.h: $NGX_MAKEFILE +$OPENSSL/.openssl/include/openssl/ssl.h: $NGX_MAKEFILE cd $OPENSSL \\ && \$(MAKE) clean \\ && ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\ diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 8016 -#define NGINX_VERSION "0.8.16" +#define nginx_version 8017 +#define NGINX_VERSION "0.8.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 @@ -917,12 +917,8 @@ ngx_connection_error(ngx_connection_t *c level = NGX_LOG_INFO; break; - case NGX_ERROR_ERR: + default: level = NGX_LOG_ERR; - break; - - default: - level = NGX_LOG_ALERT; } } else { diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -525,7 +525,7 @@ ngx_open_and_stat_file(u_char *name, ngx of->fd = fd; if (of->directio <= ngx_file_size(&fi)) { - if (ngx_directio_on(fd) == -1) { + if (ngx_directio_on(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_directio_on_n " \"%s\" failed", name); diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -514,7 +514,7 @@ ngx_output_chain_copy_buf(ngx_output_cha #if (NGX_HAVE_ALIGNED_DIRECTIO) if (ctx->unaligned) { - if (ngx_directio_off(src->file->fd) == -1) { + if (ngx_directio_off(src->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno, ngx_directio_off_n " \"%s\" failed", src->file->name.data); @@ -550,7 +550,7 @@ ngx_output_chain_copy_buf(ngx_output_cha err = ngx_errno; - if (ngx_directio_on(src->file->fd) == -1) { + if (ngx_directio_on(src->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno, ngx_directio_on_n " \"%s\" failed", src->file->name.data); 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 @@ -1588,7 +1588,7 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_ hash = ngx_crc32_short(sess->session_id, sess->session_id_length); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, - "http ssl new session: %08XD:%d:%d", + "ssl new session: %08XD:%d:%d", hash, sess->session_id_length, len); sess_id->node.key = hash; @@ -1651,7 +1651,7 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_ *copy = 0; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "http ssl get session: %08XD:%d", hash, len); + "ssl get session: %08XD:%d", hash, len); shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), ngx_ssl_session_cache_index); @@ -1765,7 +1765,7 @@ ngx_ssl_remove_session(SSL_CTX *ssl, ngx hash = ngx_crc32_short(id, len); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, - "http ssl remove session: %08XD:%uz", hash, len); + "ssl remove session: %08XD:%uz", hash, len); shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; @@ -1929,6 +1929,40 @@ ngx_ssl_get_cipher_name(ngx_connection_t ngx_int_t +ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + int len; + u_char *p, *buf; + SSL_SESSION *sess; + + sess = SSL_get0_session(c->ssl->connection); + + len = i2d_SSL_SESSION(sess, NULL); + + buf = ngx_alloc(len, c->log); + if (buf == NULL) { + return NGX_ERROR; + } + + s->len = 2 * len; + s->data = ngx_pnalloc(pool, 2 * len); + if (s->data == NULL) { + ngx_free(buf); + return NGX_ERROR; + } + + p = buf; + i2d_SSL_SESSION(sess, &p); + + ngx_hex_dump(s->data, buf, len); + + ngx_free(buf); + + return NGX_OK; +} + + +ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { size_t len; diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -118,6 +118,8 @@ ngx_int_t ngx_ssl_get_protocol(ngx_conne ngx_str_t *s); ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -516,8 +516,8 @@ ngx_http_dav_copy_move_handler(ngx_http_ size_t len, root; ngx_err_t err; ngx_int_t rc, depth; - ngx_uint_t overwrite, slash, dir; - ngx_str_t path, uri; + ngx_uint_t overwrite, slash, dir, flags; + ngx_str_t path, uri, duri, args; ngx_tree_ctx_t tree; ngx_copy_file_t cf; ngx_file_info_t fi; @@ -594,6 +594,14 @@ invalid_destination: destination_done: + duri.len = last - p; + duri.data = p; + flags = 0; + + if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) { + goto invalid_destination; + } + if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/') || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/')) { @@ -656,9 +664,7 @@ overwrite_done: "http copy from: \"%s\"", path.data); uri = r->uri; - - r->uri.len = last - p; - r->uri.data = p; + r->uri = duri; ngx_http_map_uri_to_path(r, ©.path, &root, 0); diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -222,7 +222,10 @@ ngx_http_index_handler(ngx_http_request_ return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (of.err == NGX_ENOTDIR || of.err == NGX_EACCES) { + if (of.err == NGX_ENOTDIR + || of.err == NGX_ENAMETOOLONG + || of.err == NGX_EACCES) + { return ngx_http_index_error(r, clcf, path.data, of.err); } 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 @@ -1908,7 +1908,7 @@ ngx_http_ssi_include(ngx_http_request_t args.len = 0; args.data = NULL; - flags = 0; + flags = NGX_HTTP_LOG_UNSAFE; if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { return NGX_HTTP_SSI_ERROR; diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -184,6 +184,9 @@ static ngx_http_variable_t ngx_http_ssl { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable, (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 }, 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 @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.16'; +our $VERSION = '0.8.17'; require XSLoader; XSLoader::load('nginx', $VERSION); 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 @@ -994,7 +994,6 @@ ngx_http_core_post_rewrite_phase(ngx_htt "rewrite or internal redirection cycle " "while processing \"%V\"", &r->uri); - r->main->count++; ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_OK; } @@ -1233,7 +1232,10 @@ ngx_http_core_try_files_phase(ngx_http_r if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { - if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) { + if (of.err != NGX_ENOENT + && of.err != NGX_ENOTDIR + && of.err != NGX_ENAMETOOLONG) + { ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, "%s \"%s\" failed", of.failed, path.data); } 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 @@ -1322,8 +1322,10 @@ ngx_http_parse_unsafe_uri(ngx_http_reque unsafe: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "unsafe URI \"%V\" was detected", uri); + if (*flags & NGX_HTTP_LOG_UNSAFE) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "unsafe URI \"%V\" was detected", uri); + } return NGX_ERROR; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -31,7 +31,8 @@ static ngx_int_t ngx_http_process_cookie static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r); static void ngx_http_process_request(ngx_http_request_t *r); -static ssize_t ngx_http_validate_host(u_char *host, size_t len); +static ssize_t ngx_http_validate_host(ngx_http_request_t *r, u_char **host, + size_t len, ngx_uint_t alloc); static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len); @@ -627,6 +628,7 @@ int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { size_t len; + u_char *host; const char *servername; ngx_connection_t *c; ngx_http_request_t *r; @@ -651,7 +653,15 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * r = c->data; - if (ngx_http_find_virtual_server(r, (u_char *) servername, len) != NGX_OK) { + host = (u_char *) servername; + + len = ngx_http_validate_host(r, &host, len, 1); + + if (len <= 0) { + return SSL_TLSEXT_ERR_NOACK; + } + + if (ngx_http_find_virtual_server(r, host, len) != NGX_OK) { return SSL_TLSEXT_ERR_NOACK; } @@ -670,6 +680,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * static void ngx_http_process_request_line(ngx_event_t *rev) { + u_char *host; ssize_t n; ngx_int_t rc, rv; ngx_connection_t *c; @@ -801,18 +812,25 @@ ngx_http_process_request_line(ngx_event_ "http exten: \"%V\"", &r->exten); if (r->host_start && r->host_end) { - n = ngx_http_validate_host(r->host_start, - r->host_end - r->host_start); - - if (n <= 0) { + + host = r->host_start; + n = ngx_http_validate_host(r, &host, + r->host_end - r->host_start, 0); + + if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent invalid host in request line"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } + if (n < 0) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + r->headers_in.server.len = n; - r->headers_in.server.data = r->host_start; + r->headers_in.server.data = host; } if (r->http_version < NGX_HTTP_VERSION_10) { @@ -1312,27 +1330,34 @@ static ngx_int_t ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ssize_t len; + u_char *host; + ssize_t len; if (r->headers_in.host == NULL) { r->headers_in.host = h; } - len = ngx_http_validate_host(h->value.data, h->value.len); - - if (len <= 0) { + host = h->value.data; + len = ngx_http_validate_host(r, &host, h->value.len, 0); + + if (len == 0) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent invalid host header"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } + if (len < 0) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + if (r->headers_in.server.len) { return NGX_OK; } r->headers_in.server.len = len; - r->headers_in.server.data = h->value.data; + r->headers_in.server.data = host; return NGX_OK; } @@ -1588,21 +1613,23 @@ ngx_http_process_request(ngx_http_reques static ssize_t -ngx_http_validate_host(u_char *host, size_t len) +ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, + ngx_uint_t alloc) { - u_char ch; - size_t i, last; - ngx_uint_t dot; + u_char *h, ch; + size_t i, last; + ngx_uint_t dot; last = len; + h = *host; dot = 0; for (i = 0; i < len; i++) { - ch = host[i]; + ch = h[i]; if (ch == '.') { if (dot) { - return -1; + return 0; } dot = 1; @@ -1617,7 +1644,11 @@ ngx_http_validate_host(u_char *host, siz } if (ngx_path_separator(ch) || ch == '\0') { - return -1; + return 0; + } + + if (ch >= 'A' || ch < 'Z') { + alloc = 1; } } @@ -1625,6 +1656,15 @@ ngx_http_validate_host(u_char *host, siz last--; } + if (alloc) { + *host = ngx_pnalloc(r->pool, last) ; + if (*host == NULL) { + return -1; + } + + ngx_strlow(*host, h, last); + } + return last; } @@ -1632,29 +1672,15 @@ ngx_http_validate_host(u_char *host, siz static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len) { - u_char *server; - ngx_uint_t hash; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - u_char buf[32]; if (r->virtual_names == NULL) { return NGX_DECLINED; } - if (len <= 32) { - server = buf; - - } else { - server = ngx_pnalloc(r->pool, len); - if (server == NULL) { - return NGX_ERROR; - } - } - - hash = ngx_hash_strlow(server, host, len); - - cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len); + cscf = ngx_hash_find_combined(&r->virtual_names->names, + ngx_hash_key(host, len), host, len); if (cscf) { goto found; @@ -1670,7 +1696,7 @@ ngx_http_find_virtual_server(ngx_http_re ngx_http_server_name_t *sn; name.len = len; - name.data = server; + name.data = host; ncaptures = 0; @@ -1686,16 +1712,6 @@ ngx_http_find_virtual_server(ngx_http_re if (r->captures == NULL) { return NGX_ERROR; } - - if (server == buf) { - server = ngx_pnalloc(r->pool, len); - if (server == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(server, buf, len); - name.data = server; - } } n = ngx_regex_exec(sn[i].regex, &name, r->captures, ncaptures); @@ -1717,7 +1733,7 @@ ngx_http_find_virtual_server(ngx_http_re cscf = sn[i].core_srv_conf; r->ncaptures = ncaptures; - r->captures_data = server; + r->captures_data = host; goto found; } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -60,6 +60,7 @@ #define NGX_HTTP_ZERO_IN_URI 1 #define NGX_HTTP_SUBREQUEST_IN_MEMORY 2 #define NGX_HTTP_SUBREQUEST_WAITED 4 +#define NGX_HTTP_LOG_UNSAFE 8 #define NGX_HTTP_OK 200 diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -477,8 +477,9 @@ ngx_http_discard_request_body(ngx_http_r return NGX_HTTP_INTERNAL_SERVER_ERROR; } - r->count++; - (void) ngx_http_read_discarded_request_body(r); + if (ngx_http_read_discarded_request_body(r) != NGX_OK) { + r->count++; + } return NGX_OK; } @@ -562,12 +563,16 @@ ngx_http_read_discarded_request_body(ngx ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http read discarded body"); - do { + for ( ;; ) { if (r->headers_in.content_length_n == 0) { r->read_event_handler = ngx_http_block_reading; return NGX_OK; } + if (!r->connection->read->ready) { + return NGX_AGAIN; + } + size = (r->headers_in.content_length_n > NGX_HTTP_DISCARD_BUFFER_SIZE) ? NGX_HTTP_DISCARD_BUFFER_SIZE: (size_t) r->headers_in.content_length_n; @@ -588,10 +593,7 @@ ngx_http_read_discarded_request_body(ngx } r->headers_in.content_length_n -= n; - - } while (r->connection->read->ready); - - return NGX_AGAIN; + } } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -1417,7 +1417,10 @@ ngx_http_script_file_code(ngx_http_scrip if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { - if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) { + if (of.err != NGX_ENOENT + && of.err != NGX_ENOTDIR + && of.err != NGX_ENAMETOOLONG) + { ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, "%s \"%s\" failed", of.failed, value->data); } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -532,7 +532,8 @@ ngx_http_upstream_init_request(ngx_http_ if (ngx_http_upstream_create_round_robin_peer(r, u->resolved) != NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -564,7 +565,8 @@ ngx_http_upstream_init_request(ngx_http_ ctx = ngx_resolve_start(clcf->resolver, &temp); if (ctx == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -572,7 +574,7 @@ ngx_http_upstream_init_request(ngx_http_ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no resolver defined to resolve %V", host); - ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); return; } @@ -586,7 +588,8 @@ ngx_http_upstream_init_request(ngx_http_ if (ngx_resolve_name(ctx) != NGX_OK) { u->resolved->ctx = NULL; - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -596,7 +599,8 @@ ngx_http_upstream_init_request(ngx_http_ found: if (uscf->peer.init(r, uscf) != NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -789,11 +793,13 @@ static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) { ngx_http_request_t *r; + ngx_http_upstream_t *u; ngx_http_upstream_resolved_t *ur; r = ctx->data; - r->upstream->resolved->ctx = NULL; + u = r->upstream; + ur = u->resolved; if (ctx->state) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -801,12 +807,10 @@ ngx_http_upstream_resolve_handler(ngx_re &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); - ngx_resolve_name_done(ctx); - ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); return; } - ur = r->upstream->resolved; ur->naddrs = ctx->naddrs; ur->addrs = ctx->addrs; @@ -827,14 +831,15 @@ ngx_http_upstream_resolve_handler(ngx_re #endif if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) { - ngx_resolve_name_done(ctx); - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_resolve_name_done(ctx); - - ngx_http_upstream_connect(r, r->upstream); + ur->ctx = NULL; + + ngx_http_upstream_connect(r, u); } @@ -921,10 +926,6 @@ ngx_http_upstream_check_broken_connectio return; } - if (u->peer.connection == NULL) { - return; - } - #if (NGX_HAVE_KQUEUE) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { @@ -956,7 +957,6 @@ ngx_http_upstream_check_broken_connectio if (u->peer.connection == NULL) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST); - return; } return; @@ -1019,7 +1019,6 @@ ngx_http_upstream_check_broken_connectio if (u->peer.connection == NULL) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST); - return; } } @@ -1797,7 +1796,7 @@ ngx_http_upstream_process_headers(ngx_ht uri = &u->headers_in.x_accel_redirect->value; args.len = 0; args.data = NULL; - flags = 0; + flags = NGX_HTTP_LOG_UNSAFE; if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); @@ -2837,6 +2836,7 @@ ngx_http_upstream_cleanup(void *data) if (u->resolved && u->resolved->ctx) { ngx_resolve_name_done(u->resolved->ctx); + u->resolved->ctx = NULL; } ngx_http_upstream_finalize_request(r, u, NGX_DONE); @@ -2856,6 +2856,11 @@ ngx_http_upstream_finalize_request(ngx_h *u->cleanup = NULL; } + if (u->resolved && u->resolved->ctx) { + ngx_resolve_name_done(u->resolved->ctx); + u->resolved->ctx = NULL; + } + if (u->state && u->state->response_sec) { tp = ngx_timeofday(); u->state->response_sec = tp->sec - u->state->response_sec; diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h --- a/src/os/unix/ngx_atomic.h +++ b/src/os/unix/ngx_atomic.h @@ -31,7 +31,7 @@ typedef int64_t ngx_atomic_int_t; typedef uint64_t ngx_atomic_uint_t; -#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) #define ngx_atomic_cmp_set(lock, old, new) \ OSAtomicCompareAndSwap64Barrier(old, new, (int64_t *) lock) @@ -43,7 +43,7 @@ typedef uint64_t ngx_ typedef int32_t ngx_atomic_int_t; typedef uint32_t ngx_atomic_uint_t; -#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) #define ngx_atomic_cmp_set(lock, old, new) \ OSAtomicCompareAndSwap32Barrier(old, new, (int32_t *) lock) @@ -68,7 +68,7 @@ typedef volatile ngx_atomic_uint_t ngx_ typedef int32_t ngx_atomic_int_t; typedef uint32_t ngx_atomic_uint_t; typedef volatile ngx_atomic_uint_t ngx_atomic_t; -#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) #if ( __SUNPRO_C ) @@ -109,7 +109,7 @@ ngx_cpu_pause(void); typedef int64_t ngx_atomic_int_t; typedef uint64_t ngx_atomic_uint_t; typedef volatile ngx_atomic_uint_t ngx_atomic_t; -#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) #if ( __SUNPRO_C ) @@ -151,13 +151,13 @@ ngx_cpu_pause(void); typedef int64_t ngx_atomic_int_t; typedef uint64_t ngx_atomic_uint_t; -#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) #else typedef int32_t ngx_atomic_int_t; typedef uint32_t ngx_atomic_uint_t; -#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) #endif @@ -188,13 +188,13 @@ typedef volatile ngx_atomic_uint_t ngx_ typedef int64_t ngx_atomic_int_t; typedef uint64_t ngx_atomic_uint_t; -#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-9223372036854775808") - 1) #else typedef int32_t ngx_atomic_int_t; typedef uint32_t ngx_atomic_uint_t; -#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) #endif @@ -216,7 +216,7 @@ typedef volatile ngx_atomic_uint_t ngx_ typedef int32_t ngx_atomic_int_t; typedef uint32_t ngx_atomic_uint_t; typedef volatile ngx_atomic_uint_t ngx_atomic_t; -#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 +#define NGX_ATOMIC_T_LEN (sizeof("-2147483648") - 1) static ngx_inline ngx_atomic_uint_t diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -22,7 +22,7 @@ ngx_read_file(ngx_file_t *file, u_char * if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, - "pread() failed, file \"%s\"", file->name.data); + "pread() \"%s\" failed", file->name.data); return NGX_ERROR; } @@ -30,7 +30,8 @@ ngx_read_file(ngx_file_t *file, u_char * if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } @@ -40,7 +41,8 @@ ngx_read_file(ngx_file_t *file, u_char * n = read(file->fd, buf, size); if (n == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed"); + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "read() \"%s\" failed", file->name.data); return NGX_ERROR; } @@ -57,57 +59,66 @@ ngx_read_file(ngx_file_t *file, u_char * ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset) { - ssize_t n; + ssize_t n, written; ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, "write: %d, %p, %uz, %O", file->fd, buf, size, offset); + written = 0; + #if (NGX_HAVE_PWRITE) - n = pwrite(file->fd, buf, size, offset); + for ( ;; ) { + n = pwrite(file->fd, buf, size, offset); + + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "pwrite() \"%s\" failed", file->name.data); + return NGX_ERROR; + } - if (n == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed"); - return NGX_ERROR; - } + file->offset += n; + written += n; - if ((size_t) n != size) { - ngx_log_error(NGX_LOG_CRIT, file->log, 0, - "pwrite() has written only %z of %uz", n, size); - return NGX_ERROR; + if ((size_t) n == size) { + return written; + } + + offset += n; + size -= n; } #else if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } file->sys_offset = offset; } - n = write(file->fd, buf, size); + for ( ;; ) { + n = write(file->fd, buf, size); - if (n == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed"); - return NGX_ERROR; - } + if (n == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, + "write() \"%s\" failed", file->name.data); + return NGX_ERROR; + } - if ((size_t) n != size) { - ngx_log_error(NGX_LOG_CRIT, file->log, 0, - "write() has written only %z of %uz", n, size); - return NGX_ERROR; - } + file->offset += n; + written += n; - file->sys_offset += n; - -#endif + if ((size_t) n == size) { + return written; + } - file->offset += n; - - return n; + size -= n; + } +#endif } @@ -191,7 +202,7 @@ ngx_write_chain_to_file(ngx_file_t *file if (file->sys_offset != offset) { if (lseek(file->fd, offset, SEEK_SET) == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, - "lseek() failed"); + "lseek() \"%s\" failed", file->name.data); return NGX_ERROR; } @@ -202,13 +213,14 @@ ngx_write_chain_to_file(ngx_file_t *file if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, - "writev() failed"); + "writev() \"%s\" failed", file->name.data); return NGX_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_CRIT, file->log, 0, - "writev() has written only %z of %uz", n, size); + "writev() \"%s\" has written only %z of %uz", + file->name.data, n, size); return NGX_ERROR; } @@ -394,7 +406,7 @@ ngx_directio_on(ngx_fd_t fd) flags = fcntl(fd, F_GETFL); if (flags == -1) { - return -1; + return NGX_FILE_ERROR; } return fcntl(fd, F_SETFL, flags | O_DIRECT); @@ -409,7 +421,7 @@ ngx_directio_off(ngx_fd_t fd) flags = fcntl(fd, F_GETFL); if (flags == -1) { - return -1; + return NGX_FILE_ERROR; } return fcntl(fd, F_SETFL, flags & ~O_DIRECT);