Mercurial > hg > nginx
comparison src/http/ngx_http_request.c @ 6926:e662cbf1b932
Converted hc->busy/hc->free to use chain links.
Most notably, this fixes possible buffer overflows if number of large
client header buffers in a virtual server is different from the one in
the default server.
Reported by Daniil Bondarev.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 07 Mar 2017 18:49:31 +0300 |
parents | 72bb626484a4 |
children | 1c43ac026c1d |
comparison
equal
deleted
inserted
replaced
6925:b3c5b4312667 | 6926:e662cbf1b932 |
---|---|
547 | 547 |
548 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 548 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
549 | 549 |
550 ngx_set_connection_log(r->connection, clcf->error_log); | 550 ngx_set_connection_log(r->connection, clcf->error_log); |
551 | 551 |
552 r->header_in = hc->nbusy ? hc->busy[0] : c->buffer; | 552 r->header_in = hc->busy ? hc->busy->buf : c->buffer; |
553 | 553 |
554 if (ngx_list_init(&r->headers_out.headers, r->pool, 20, | 554 if (ngx_list_init(&r->headers_out.headers, r->pool, 20, |
555 sizeof(ngx_table_elt_t)) | 555 sizeof(ngx_table_elt_t)) |
556 != NGX_OK) | 556 != NGX_OK) |
557 { | 557 { |
1429 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, | 1429 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, |
1430 ngx_uint_t request_line) | 1430 ngx_uint_t request_line) |
1431 { | 1431 { |
1432 u_char *old, *new; | 1432 u_char *old, *new; |
1433 ngx_buf_t *b; | 1433 ngx_buf_t *b; |
1434 ngx_chain_t *cl; | |
1434 ngx_http_connection_t *hc; | 1435 ngx_http_connection_t *hc; |
1435 ngx_http_core_srv_conf_t *cscf; | 1436 ngx_http_core_srv_conf_t *cscf; |
1436 | 1437 |
1437 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1438 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1438 "http alloc large header buffer"); | 1439 "http alloc large header buffer"); |
1458 return NGX_DECLINED; | 1459 return NGX_DECLINED; |
1459 } | 1460 } |
1460 | 1461 |
1461 hc = r->http_connection; | 1462 hc = r->http_connection; |
1462 | 1463 |
1463 if (hc->nfree) { | 1464 if (hc->free) { |
1464 b = hc->free[--hc->nfree]; | 1465 cl = hc->free; |
1466 hc->free = cl->next; | |
1467 | |
1468 b = cl->buf; | |
1465 | 1469 |
1466 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1470 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1467 "http large header free: %p %uz", | 1471 "http large header free: %p %uz", |
1468 b->pos, b->end - b->last); | 1472 b->pos, b->end - b->last); |
1469 | 1473 |
1470 } else if (hc->nbusy < cscf->large_client_header_buffers.num) { | 1474 } else if (hc->nbusy < cscf->large_client_header_buffers.num) { |
1471 | |
1472 if (hc->busy == NULL) { | |
1473 hc->busy = ngx_palloc(r->connection->pool, | |
1474 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); | |
1475 if (hc->busy == NULL) { | |
1476 return NGX_ERROR; | |
1477 } | |
1478 } | |
1479 | 1475 |
1480 b = ngx_create_temp_buf(r->connection->pool, | 1476 b = ngx_create_temp_buf(r->connection->pool, |
1481 cscf->large_client_header_buffers.size); | 1477 cscf->large_client_header_buffers.size); |
1482 if (b == NULL) { | 1478 if (b == NULL) { |
1483 return NGX_ERROR; | 1479 return NGX_ERROR; |
1484 } | 1480 } |
1485 | 1481 |
1482 cl = ngx_alloc_chain_link(r->connection->pool); | |
1483 if (cl == NULL) { | |
1484 return NGX_ERROR; | |
1485 } | |
1486 | |
1487 cl->buf = b; | |
1488 | |
1486 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1489 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1487 "http large header alloc: %p %uz", | 1490 "http large header alloc: %p %uz", |
1488 b->pos, b->end - b->last); | 1491 b->pos, b->end - b->last); |
1489 | 1492 |
1490 } else { | 1493 } else { |
1491 return NGX_DECLINED; | 1494 return NGX_DECLINED; |
1492 } | 1495 } |
1493 | 1496 |
1494 hc->busy[hc->nbusy++] = b; | 1497 cl->next = hc->busy; |
1498 hc->busy = cl; | |
1499 hc->nbusy++; | |
1495 | 1500 |
1496 if (r->state == 0) { | 1501 if (r->state == 0) { |
1497 /* | 1502 /* |
1498 * r->state == 0 means that a header line was parsed successfully | 1503 * r->state == 0 means that a header line was parsed successfully |
1499 * and we do not need to copy incomplete header line and | 1504 * and we do not need to copy incomplete header line and |
2833 | 2838 |
2834 static void | 2839 static void |
2835 ngx_http_set_keepalive(ngx_http_request_t *r) | 2840 ngx_http_set_keepalive(ngx_http_request_t *r) |
2836 { | 2841 { |
2837 int tcp_nodelay; | 2842 int tcp_nodelay; |
2838 ngx_int_t i; | |
2839 ngx_buf_t *b, *f; | 2843 ngx_buf_t *b, *f; |
2844 ngx_chain_t *cl, *ln; | |
2840 ngx_event_t *rev, *wev; | 2845 ngx_event_t *rev, *wev; |
2841 ngx_connection_t *c; | 2846 ngx_connection_t *c; |
2842 ngx_http_connection_t *hc; | 2847 ngx_http_connection_t *hc; |
2843 ngx_http_core_srv_conf_t *cscf; | |
2844 ngx_http_core_loc_conf_t *clcf; | 2848 ngx_http_core_loc_conf_t *clcf; |
2845 | 2849 |
2846 c = r->connection; | 2850 c = r->connection; |
2847 rev = c->read; | 2851 rev = c->read; |
2848 | 2852 |
2874 * the pipelined request (see ngx_http_create_request()). | 2878 * the pipelined request (see ngx_http_create_request()). |
2875 * | 2879 * |
2876 * Now we would move the large header buffers to the free list. | 2880 * Now we would move the large header buffers to the free list. |
2877 */ | 2881 */ |
2878 | 2882 |
2879 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | 2883 for (cl = hc->busy; cl; /* void */) { |
2880 | 2884 ln = cl; |
2881 if (hc->free == NULL) { | 2885 cl = cl->next; |
2882 hc->free = ngx_palloc(c->pool, | 2886 |
2883 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); | 2887 if (ln->buf == b) { |
2884 | 2888 ngx_free_chain(c->pool, ln); |
2885 if (hc->free == NULL) { | 2889 continue; |
2886 ngx_http_close_request(r, 0); | |
2887 return; | |
2888 } | 2890 } |
2889 } | 2891 |
2890 | 2892 f = ln->buf; |
2891 for (i = 0; i < hc->nbusy - 1; i++) { | |
2892 f = hc->busy[i]; | |
2893 hc->free[hc->nfree++] = f; | |
2894 f->pos = f->start; | 2893 f->pos = f->start; |
2895 f->last = f->start; | 2894 f->last = f->start; |
2896 } | 2895 |
2897 | 2896 ln->next = hc->free; |
2898 hc->busy[0] = b; | 2897 hc->free = ln; |
2898 } | |
2899 | |
2900 cl = ngx_alloc_chain_link(c->pool); | |
2901 if (cl == NULL) { | |
2902 ngx_http_close_request(r, 0); | |
2903 return; | |
2904 } | |
2905 | |
2906 cl->buf = b; | |
2907 | |
2908 hc->busy = cl; | |
2899 hc->nbusy = 1; | 2909 hc->nbusy = 1; |
2900 } | 2910 } |
2901 } | 2911 } |
2902 | 2912 |
2903 /* guard against recursive call from ngx_http_finalize_connection() */ | 2913 /* guard against recursive call from ngx_http_finalize_connection() */ |
2964 } else { | 2974 } else { |
2965 b->pos = b->start; | 2975 b->pos = b->start; |
2966 b->last = b->start; | 2976 b->last = b->start; |
2967 } | 2977 } |
2968 | 2978 |
2969 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %i", | 2979 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p", |
2970 hc->free, hc->nfree); | 2980 hc->free); |
2971 | 2981 |
2972 if (hc->free) { | 2982 if (hc->free) { |
2973 for (i = 0; i < hc->nfree; i++) { | 2983 for (cl = hc->free; cl; /* void */) { |
2974 ngx_pfree(c->pool, hc->free[i]->start); | 2984 ln = cl; |
2975 hc->free[i] = NULL; | 2985 cl = cl->next; |
2976 } | 2986 ngx_pfree(c->pool, ln->buf->start); |
2977 | 2987 ngx_free_chain(c->pool, ln); |
2978 hc->nfree = 0; | 2988 } |
2989 | |
2990 hc->free = NULL; | |
2979 } | 2991 } |
2980 | 2992 |
2981 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i", | 2993 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i", |
2982 hc->busy, hc->nbusy); | 2994 hc->busy, hc->nbusy); |
2983 | 2995 |
2984 if (hc->busy) { | 2996 if (hc->busy) { |
2985 for (i = 0; i < hc->nbusy; i++) { | 2997 for (cl = hc->busy; cl; /* void */) { |
2986 ngx_pfree(c->pool, hc->busy[i]->start); | 2998 ln = cl; |
2987 hc->busy[i] = NULL; | 2999 cl = cl->next; |
2988 } | 3000 ngx_pfree(c->pool, ln->buf->start); |
2989 | 3001 ngx_free_chain(c->pool, ln); |
3002 } | |
3003 | |
3004 hc->busy = NULL; | |
2990 hc->nbusy = 0; | 3005 hc->nbusy = 0; |
2991 } | 3006 } |
2992 | 3007 |
2993 #if (NGX_HTTP_SSL) | 3008 #if (NGX_HTTP_SSL) |
2994 if (c->ssl) { | 3009 if (c->ssl) { |