From: Stefan Fritsch Date: Fri, 1 Oct 2010 19:33:39 +0000 (+0000) Subject: Fix CVE-2010-1623 in mod_reqtimeout, too. It includes a non-blocking variant X-Git-Tag: 2.3.9~374 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d814b8320690cb668b158e4d04c1a94c440c5082;p=thirdparty%2Fapache%2Fhttpd.git Fix CVE-2010-1623 in mod_reqtimeout, too. It includes a non-blocking variant of apr_brigade_split_line(). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1003626 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 3c743cfb206..c6b02a24f98 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.3.9 + *) SECURITY: CVE-2010-1623 (cve.mitre.org) + Fix a denial of service attack against mod_reqtimeout. + [Stefan Fritsch] + *) mod_cache: Support the caching of HEAD requests. [Graham Leggett] *) htcacheclean: Allow the option to round up file sizes to a given diff --git a/modules/filters/mod_reqtimeout.c b/modules/filters/mod_reqtimeout.c index b0de997b8e7..adc4defc2c5 100644 --- a/modules/filters/mod_reqtimeout.c +++ b/modules/filters/mod_reqtimeout.c @@ -115,6 +115,41 @@ static apr_status_t have_lf_or_eos(apr_bucket_brigade *bb) return APR_INCOMPLETE; } +/* + * Append bbIn to bbOut and merge small buckets, to avoid DoS by high memory + * usage + */ +static apr_status_t brigade_append(apr_bucket_brigade *bbOut, apr_bucket_brigade *bbIn) +{ + while (!APR_BRIGADE_EMPTY(bbIn)) { + apr_bucket *e = APR_BRIGADE_FIRST(bbIn); + const char *str; + apr_size_t len; + apr_status_t rv; + + rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ); + if (rv != APR_SUCCESS) { + return rv; + } + + APR_BUCKET_REMOVE(e); + if (APR_BUCKET_IS_METADATA(e) || len > APR_BUCKET_BUFF_SIZE/4) { + APR_BRIGADE_INSERT_TAIL(bbOut, e); + } + else { + if (len > 0) { + rv = apr_brigade_write(bbOut, NULL, NULL, str, len); + if (rv != APR_SUCCESS) { + apr_bucket_destroy(e); + return rv; + } + } + apr_bucket_destroy(e); + } + } + return APR_SUCCESS; +} + #define MIN(x,y) ((x) < (y) ? (x) : (y)) static apr_status_t reqtimeout_filter(ap_filter_t *f, @@ -217,7 +252,9 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f, if (!ccfg->tmpbb) { ccfg->tmpbb = apr_brigade_create(f->c->pool, f->c->bucket_alloc); } - APR_BRIGADE_CONCAT(ccfg->tmpbb, bb); + rv = brigade_append(ccfg->tmpbb, bb); + if (rv != APR_SUCCESS) + break; } /* ... and wait for more */