comparison src/http/v2/ngx_http_v2.c @ 7354:1812f1d79d84

Fixed socket leak with "return 444" in error_page (ticket #274). Socket leak was observed in the following configuration: error_page 400 = /close; location = /close { return 444; } The problem is that "return 444" triggers termination of the request, and due to error_page termination thinks that it needs to use a posted request to clear stack. But at the early request processing where 400 errors are generated there are no ngx_http_run_posted_requests() calls, so the request is only terminated after an external event. Variants of the problem include "error_page 497" instead (ticket #695) and various other errors generated during early request processing (405, 414, 421, 494, 495, 496, 501, 505). The same problem can be also triggered with "return 499" and "return 408" as both codes trigger ngx_http_terminate_request(), much like "return 444". To fix this, the patch adds ngx_http_run_posted_requests() calls to ngx_http_process_request_line() and ngx_http_process_request_headers() functions, and to ngx_http_v2_run_request() and ngx_http_v2_push_stream() functions in HTTP/2. Since the ngx_http_process_request() function is now only called via other functions which call ngx_http_run_posted_requests(), the call there is no longer needed and was removed.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 21 Sep 2018 15:59:30 +0300
parents fbb683496705
children d4448892a294
comparison
equal deleted inserted replaced
7353:87d2ea860f38 7354:1812f1d79d84
2671 2671
2672 error: 2672 error:
2673 2673
2674 if (rc == NGX_ABORT) { 2674 if (rc == NGX_ABORT) {
2675 /* header handler has already finalized request */ 2675 /* header handler has already finalized request */
2676 ngx_http_run_posted_requests(fc);
2676 return NULL; 2677 return NULL;
2677 } 2678 }
2678 2679
2679 if (rc == NGX_DECLINED) { 2680 if (rc == NGX_DECLINED) {
2680 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 2681 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
2682 ngx_http_run_posted_requests(fc);
2681 return NULL; 2683 return NULL;
2682 } 2684 }
2683 2685
2684 close: 2686 close:
2685 2687
3740 3742
3741 3743
3742 static void 3744 static void
3743 ngx_http_v2_run_request(ngx_http_request_t *r) 3745 ngx_http_v2_run_request(ngx_http_request_t *r)
3744 { 3746 {
3747 ngx_connection_t *fc;
3748
3749 fc = r->connection;
3750
3745 if (ngx_http_v2_construct_request_line(r) != NGX_OK) { 3751 if (ngx_http_v2_construct_request_line(r) != NGX_OK) {
3746 return; 3752 goto failed;
3747 } 3753 }
3748 3754
3749 if (ngx_http_v2_construct_cookie_header(r) != NGX_OK) { 3755 if (ngx_http_v2_construct_cookie_header(r) != NGX_OK) {
3750 return; 3756 goto failed;
3751 } 3757 }
3752 3758
3753 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; 3759 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
3754 3760
3755 if (ngx_http_process_request_header(r) != NGX_OK) { 3761 if (ngx_http_process_request_header(r) != NGX_OK) {
3756 return; 3762 goto failed;
3757 } 3763 }
3758 3764
3759 if (r->headers_in.content_length_n > 0 && r->stream->in_closed) { 3765 if (r->headers_in.content_length_n > 0 && r->stream->in_closed) {
3760 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 3766 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
3761 "client prematurely closed stream"); 3767 "client prematurely closed stream");
3762 3768
3763 r->stream->skip_data = 1; 3769 r->stream->skip_data = 1;
3764 3770
3765 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 3771 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
3766 return; 3772 goto failed;
3767 } 3773 }
3768 3774
3769 if (r->headers_in.content_length_n == -1 && !r->stream->in_closed) { 3775 if (r->headers_in.content_length_n == -1 && !r->stream->in_closed) {
3770 r->headers_in.chunked = 1; 3776 r->headers_in.chunked = 1;
3771 } 3777 }
3772 3778
3773 ngx_http_process_request(r); 3779 ngx_http_process_request(r);
3780
3781 failed:
3782
3783 ngx_http_run_posted_requests(fc);
3774 } 3784 }
3775 3785
3776 3786
3777 static void 3787 static void
3778 ngx_http_v2_run_request_handler(ngx_event_t *ev) 3788 ngx_http_v2_run_request_handler(ngx_event_t *ev)