[apache2] 04/05: Add more fixes for CVE-2015-3183 patch from upstream
Stefan Fritsch
sf at moszumanska.debian.org
Sat Aug 1 21:11:48 UTC 2015
This is an automated email from the git hooks/post-receive script.
sf pushed a commit to branch jessie
in repository apache2.
commit b4a381aa5d92f6cd84a3940219a9f86ea6aff32c
Author: Stefan Fritsch <sf at sfritsch.de>
Date: Sat Aug 1 22:38:33 2015 +0200
Add more fixes for CVE-2015-3183 patch from upstream
---
.../CVE-2015-3183-chunk-header-parsing.diff | 179 +++++++++++----------
1 file changed, 98 insertions(+), 81 deletions(-)
diff --git a/debian/patches/CVE-2015-3183-chunk-header-parsing.diff b/debian/patches/CVE-2015-3183-chunk-header-parsing.diff
index 238e650..2089c15 100644
--- a/debian/patches/CVE-2015-3183-chunk-header-parsing.diff
+++ b/debian/patches/CVE-2015-3183-chunk-header-parsing.diff
@@ -2,9 +2,11 @@
# https://svn.apache.org/r1685904
# https://svn.apache.org/r1685950
# https://svn.apache.org/r1686271
+# https://svn.apache.org/r1688935
+# https://svn.apache.org/r1689821
--- apache2.orig/modules/http/http_filters.c
+++ apache2/modules/http/http_filters.c
-@@ -57,24 +57,28 @@
+@@ -57,24 +57,29 @@
APLOG_USE_MODULE(http);
@@ -24,6 +26,7 @@
- BODY_CHUNK,
- BODY_CHUNK_PART
+ apr_int32_t chunk_used;
++ apr_int32_t chunk_bws;
+ apr_int32_t chunkbits;
+ enum
+ {
@@ -47,7 +50,7 @@
apr_bucket_brigade *bb;
} http_ctx_t;
-@@ -119,117 +123,148 @@ static apr_status_t bail_out_on_error(ht
+@@ -119,117 +124,154 @@ static apr_status_t bail_out_on_error(ht
return ap_pass_brigade(f->r->output_filters, bb);
}
@@ -143,6 +146,7 @@
+ ctx->remaining = 0;
+ ctx->chunkbits = sizeof(apr_off_t) * 8;
+ ctx->chunk_used = 0;
++ ctx->chunk_bws = 0;
}
- if (len > 0) {
- break; /* we got the data we want */
@@ -190,7 +194,12 @@
+ }
+ }
+ else if (c == ' ' || c == '\t') {
++ /* Be lenient up to 10 BWS (term from rfc7230 - 3.2.3).
++ */
+ ctx->state = BODY_CHUNK_CR;
++ if (++ctx->chunk_bws > 10) {
++ return APR_EINVAL;
++ }
+ }
+ else if (ctx->state == BODY_CHUNK_CR) {
+ /*
@@ -295,7 +304,7 @@
static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f,
apr_bucket_brigade *b, int merge)
-@@ -243,7 +278,6 @@ static apr_status_t read_chunked_trailer
+@@ -243,7 +285,6 @@ static apr_status_t read_chunked_trailer
r->status = HTTP_OK;
r->headers_in = r->trailers_in;
apr_table_clear(r->headers_in);
@@ -303,15 +312,18 @@
ap_get_mime_headers(r);
if(r->status == HTTP_OK) {
-@@ -290,6 +324,7 @@ apr_status_t ap_http_filter(ap_filter_t
- apr_off_t totalread;
+@@ -287,9 +328,9 @@ apr_status_t ap_http_filter(ap_filter_t
+ apr_bucket *e;
+ http_ctx_t *ctx = f->ctx;
+ apr_status_t rv;
+- apr_off_t totalread;
int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE;
apr_bucket_brigade *bb;
+ int again;
conf = (core_server_config *)
ap_get_module_config(f->r->server->module_config, &core_module);
-@@ -303,7 +338,6 @@ apr_status_t ap_http_filter(ap_filter_t
+@@ -303,7 +344,6 @@ apr_status_t ap_http_filter(ap_filter_t
const char *tenc, *lenp;
f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
ctx->state = BODY_NONE;
@@ -319,7 +331,7 @@
ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
bb = ctx->bb;
-@@ -335,14 +369,17 @@ apr_status_t ap_http_filter(ap_filter_t
+@@ -335,14 +375,17 @@ apr_status_t ap_http_filter(ap_filter_t
* reading the connection until it is closed by the server."
*/
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(02555)
@@ -340,7 +352,7 @@
}
lenp = NULL;
}
-@@ -361,7 +398,7 @@ apr_status_t ap_http_filter(ap_filter_t
+@@ -361,7 +404,7 @@ apr_status_t ap_http_filter(ap_filter_t
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01587)
"Invalid Content-Length");
@@ -349,7 +361,7 @@
}
/* If we have a limit in effect and we know the C-L ahead of
-@@ -403,7 +440,8 @@ apr_status_t ap_http_filter(ap_filter_t
+@@ -403,7 +446,8 @@ apr_status_t ap_http_filter(ap_filter_t
if (!ap_is_HTTP_SUCCESS(f->r->status)) {
ctx->state = BODY_NONE;
ctx->eos_sent = 1;
@@ -359,7 +371,7 @@
char *tmp;
int len;
-@@ -426,285 +464,194 @@ apr_status_t ap_http_filter(ap_filter_t
+@@ -426,285 +470,199 @@ apr_status_t ap_http_filter(ap_filter_t
ap_pass_brigade(f->c->output_filters, bb);
}
}
@@ -374,9 +386,7 @@
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ return APR_SUCCESS;
+ }
-
-- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
-- block, 0);
++
+ do {
+ apr_brigade_cleanup(b);
+ again = 0; /* until further notice */
@@ -386,10 +396,13 @@
+ case BODY_CHUNK:
+ case BODY_CHUNK_PART:
+ case BODY_CHUNK_EXT:
++ case BODY_CHUNK_CR:
+ case BODY_CHUNK_LF:
+ case BODY_CHUNK_END:
+ case BODY_CHUNK_END_LF: {
-+
+
+- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
+- block, 0);
+ rv = ap_get_brigade(f->next, b, AP_MODE_GETLINE, block, 0);
/* for timeout */
@@ -590,9 +603,22 @@
+ readbytes = ctx->remaining;
+ }
+ if (readbytes > 0) {
++ apr_off_t totalread;
++
++ rv = ap_get_brigade(f->next, b, mode, block, readbytes);
++
++ /* for timeout */
++ if (block == APR_NONBLOCK_READ
++ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b))
++ || (APR_STATUS_IS_EAGAIN(rv)))) {
++ return APR_EAGAIN;
++ }
- rv = ap_get_brigade(f->next, b, mode, block, readbytes);
-+ rv = ap_get_brigade(f->next, b, mode, block, readbytes);
++ if (rv == APR_EOF && ctx->state != BODY_NONE
++ && ctx->remaining > 0) {
++ return APR_INCOMPLETE;
++ }
- if (rv == APR_EOF && ctx->state != BODY_NONE &&
- ctx->remaining > 0) {
@@ -601,19 +627,14 @@
- if (rv != APR_SUCCESS) {
- return rv;
- }
-+ /* for timeout */
-+ if (block == APR_NONBLOCK_READ
-+ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b))
-+ || (APR_STATUS_IS_EAGAIN(rv)))) {
-+ return APR_EAGAIN;
++ if (rv != APR_SUCCESS) {
++ return rv;
+ }
- /* How many bytes did we just read? */
- apr_brigade_length(b, 0, &totalread);
-+ if (rv == APR_EOF && ctx->state != BODY_NONE
-+ && ctx->remaining > 0) {
-+ return APR_INCOMPLETE;
-+ }
++ /* How many bytes did we just read? */
++ apr_brigade_length(b, 0, &totalread);
- /* If this happens, we have a bucket of unknown length. Die because
- * it means our assumptions have changed. */
@@ -626,12 +647,47 @@
- if (APR_BUCKET_IS_EOS(e)) {
- apr_bucket_delete(e);
- return APR_INCOMPLETE;
-- }
++ /* If this happens, we have a bucket of unknown length. Die because
++ * it means our assumptions have changed. */
++ AP_DEBUG_ASSERT(totalread >= 0);
++
++ if (ctx->state != BODY_NONE) {
++ ctx->remaining -= totalread;
++ if (ctx->remaining > 0) {
++ e = APR_BRIGADE_LAST(b);
++ if (APR_BUCKET_IS_EOS(e)) {
++ apr_bucket_delete(e);
++ return APR_INCOMPLETE;
++ }
++ }
++ else if (ctx->state == BODY_CHUNK_DATA) {
++ /* next chunk please */
++ ctx->state = BODY_CHUNK_END;
++ ctx->chunk_used = 0;
++ }
++ }
++
++ /* We have a limit in effect. */
++ if (ctx->limit) {
++ /* FIXME: Note that we might get slightly confused on
++ * chunked inputs as we'd need to compensate for the chunk
++ * lengths which may not really count. This seems to be up
++ * for interpretation.
++ */
++ ctx->limit_used += totalread;
++ if (ctx->limit < ctx->limit_used) {
++ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r,
++ APLOGNO(01591) "Read content length of "
++ "%" APR_OFF_T_FMT " is larger than the "
++ "configured limit of %" APR_OFF_T_FMT,
++ ctx->limit_used, ctx->limit);
++ return bail_out_on_error(ctx, f,
++ HTTP_REQUEST_ENTITY_TOO_LARGE);
++ }
++ }
+ }
- }
- }
-+ if (rv != APR_SUCCESS) {
-+ return rv;
-+ }
- /* If we have no more bytes remaining on a C-L request,
- * save the callter a roundtrip to discover EOS.
@@ -640,8 +696,14 @@
- e = apr_bucket_eos_create(f->c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- }
-+ /* How many bytes did we just read? */
-+ apr_brigade_length(b, 0, &totalread);
++ /* If we have no more bytes remaining on a C-L request,
++ * save the caller a round trip to discover EOS.
++ */
++ if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
++ e = apr_bucket_eos_create(f->c->bucket_alloc);
++ APR_BRIGADE_INSERT_TAIL(b, e);
++ ctx->eos_sent = 1;
++ }
- /* We have a limit in effect. */
- if (ctx->limit) {
@@ -663,32 +725,13 @@
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ctx->eos_sent = 1;
- return ap_pass_brigade(f->r->output_filters, bb);
-- }
++ break;
+ }
- }
-+ /* If this happens, we have a bucket of unknown length. Die because
-+ * it means our assumptions have changed. */
-+ AP_DEBUG_ASSERT(totalread >= 0);
-+
-+ if (ctx->state != BODY_NONE) {
-+ ctx->remaining -= totalread;
-+ if (ctx->remaining > 0) {
-+ e = APR_BRIGADE_LAST(b);
-+ if (APR_BUCKET_IS_EOS(e)) {
-+ apr_bucket_delete(e);
-+ return APR_INCOMPLETE;
-+ }
-+ }
-+ else if (ctx->state == BODY_CHUNK_DATA) {
-+ /* next chunk please */
-+ ctx->state = BODY_CHUNK_END;
-+ ctx->chunk_used = 0;
-+ }
-+ }
-
+-
- return APR_SUCCESS;
-}
-+ }
-
+-
-/**
- * Parse a chunk extension, detect overflow.
- * There are two error cases:
@@ -702,30 +745,10 @@
-{
- long chunksize = 0;
- size_t chunkbits = sizeof(long) * 8;
-+ /* If we have no more bytes remaining on a C-L request,
-+ * save the caller a round trip to discover EOS.
-+ */
-+ if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {
-+ e = apr_bucket_eos_create(f->c->bucket_alloc);
-+ APR_BRIGADE_INSERT_TAIL(b, e);
-+ ctx->eos_sent = 1;
-+ }
++ case BODY_CHUNK_TRAILER: {
- ap_xlate_proto_from_ascii(b, strlen(b));
-+ /* We have a limit in effect. */
-+ if (ctx->limit) {
-+ /* FIXME: Note that we might get slightly confused on chunked inputs
-+ * as we'd need to compensate for the chunk lengths which may not
-+ * really count. This seems to be up for interpretation. */
-+ ctx->limit_used += totalread;
-+ if (ctx->limit < ctx->limit_used) {
-+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01591)
-+ "Read content-length of %" APR_OFF_T_FMT
-+ " is larger than the configured limit"
-+ " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit);
-+ return bail_out_on_error(ctx, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
-+ }
-+ }
++ rv = ap_get_brigade(f->next, b, mode, block, readbytes);
- if (!apr_isxdigit(*b)) {
- /*
@@ -738,12 +761,6 @@
- while (*b == '0') {
- ++b;
- }
-+ break;
-+ }
-+ case BODY_CHUNK_TRAILER: {
-+
-+ rv = ap_get_brigade(f->next, b, mode, block, readbytes);
-+
+ /* for timeout */
+ if (block == APR_NONBLOCK_READ
+ && ((rv == APR_SUCCESS && APR_BRIGADE_EMPTY(b))
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-apache/apache2.git
More information about the Pkg-apache-commits
mailing list