[apache2] 05/08: CVE-2018-1301: out of bound read after failure in reading HTTP request
Stefan Fritsch
sf at moszumanska.debian.org
Sat Mar 31 09:17:25 UTC 2018
This is an automated email from the git hooks/post-receive script.
sf pushed a commit to branch stretch
in repository apache2.
commit 354294200dbe3cbbc4e30fecbad81f0952706e0e
Author: Stefan Fritsch <sf at sfritsch.de>
Date: Fri Mar 30 16:19:15 2018 +0200
CVE-2018-1301: out of bound read after failure in reading HTTP request
---
debian/changelog | 2 +
...-2018-1301-HTTP-request-read-out-of-bounds.diff | 197 +++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 200 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 6a476d0..307c97c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,8 @@ apache2 (2.4.25-3+deb9u4) UNRELEASED; urgency=medium
newline characters. Behavior can be changed with new directive
'RegexDefaultOptions'.
* CVE-2018-1283: Tampering of mod_session data for CGI applications.
+ * CVE-2018-1301: Possible out of bound access after failure in reading the
+ HTTP request
-- Stefan Fritsch <sf at debian.org> Fri, 30 Mar 2018 16:01:25 +0200
diff --git a/debian/patches/CVE-2018-1301-HTTP-request-read-out-of-bounds.diff b/debian/patches/CVE-2018-1301-HTTP-request-read-out-of-bounds.diff
new file mode 100644
index 0000000..f1e14f7
--- /dev/null
+++ b/debian/patches/CVE-2018-1301-HTTP-request-read-out-of-bounds.diff
@@ -0,0 +1,197 @@
+# CVE-2018-1301
+# https://svn.apache.org/r1824469
+--- apache2.orig/server/protocol.c
++++ apache2/server/protocol.c
+@@ -225,6 +225,11 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ int fold = flags & AP_GETLINE_FOLD;
+ int crlf = flags & AP_GETLINE_CRLF;
+
++ if (!n) {
++ /* Needs room for NUL byte at least */
++ return APR_BADARG;
++ }
++
+ /*
+ * Initialize last_char as otherwise a random value will be compared
+ * against APR_ASCII_LF at the end of the loop if bb only contains
+@@ -238,14 +243,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE,
+ APR_BLOCK_READ, 0);
+ if (rv != APR_SUCCESS) {
+- return rv;
++ goto cleanup;
+ }
+
+ /* Something horribly wrong happened. Someone didn't block!
+ * (this also happens at the end of each keepalive connection)
+ */
+ if (APR_BRIGADE_EMPTY(bb)) {
+- return APR_EGENERAL;
++ rv = APR_EGENERAL;
++ goto cleanup;
+ }
+
+ for (e = APR_BRIGADE_FIRST(bb);
+@@ -263,7 +269,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+
+ rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+- return rv;
++ goto cleanup;
+ }
+
+ if (len == 0) {
+@@ -276,17 +282,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+
+ /* Would this overrun our buffer? If so, we'll die. */
+ if (n < bytes_handled + len) {
+- *read = bytes_handled;
+- if (*s) {
+- /* ensure this string is NUL terminated */
+- if (bytes_handled > 0) {
+- (*s)[bytes_handled-1] = '\0';
+- }
+- else {
+- (*s)[0] = '\0';
+- }
+- }
+- return APR_ENOSPC;
++ rv = APR_ENOSPC;
++ goto cleanup;
+ }
+
+ /* Do we have to handle the allocation ourselves? */
+@@ -294,7 +291,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ /* We'll assume the common case where one bucket is enough. */
+ if (!*s) {
+ current_alloc = len;
+- *s = apr_palloc(r->pool, current_alloc);
++ *s = apr_palloc(r->pool, current_alloc + 1);
+ }
+ else if (bytes_handled + len > current_alloc) {
+ /* Increase the buffer size */
+@@ -305,7 +302,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ new_size = (bytes_handled + len) * 2;
+ }
+
+- new_buffer = apr_palloc(r->pool, new_size);
++ new_buffer = apr_palloc(r->pool, new_size + 1);
+
+ /* Copy what we already had. */
+ memcpy(new_buffer, *s, bytes_handled);
+@@ -329,19 +326,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ }
+ }
+
+- if (crlf && (last_char <= *s || last_char[-1] != APR_ASCII_CR)) {
+- *last_char = '\0';
+- bytes_handled = last_char - *s;
+- *read = bytes_handled;
+- return APR_EINVAL;
+- }
+-
+- /* Now NUL-terminate the string at the end of the line;
++ /* Now terminate the string at the end of the line;
+ * if the last-but-one character is a CR, terminate there */
+ if (last_char > *s && last_char[-1] == APR_ASCII_CR) {
+ last_char--;
+ }
+- *last_char = '\0';
++ else if (crlf) {
++ rv = APR_EINVAL;
++ goto cleanup;
++ }
+ bytes_handled = last_char - *s;
+
+ /* If we're folding, we have more work to do.
+@@ -361,7 +354,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_SPECULATIVE,
+ APR_BLOCK_READ, 1);
+ if (rv != APR_SUCCESS) {
+- return rv;
++ goto cleanup;
+ }
+
+ if (APR_BRIGADE_EMPTY(bb)) {
+@@ -378,7 +371,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ apr_brigade_cleanup(bb);
+- return rv;
++ goto cleanup;
+ }
+
+ /* Found one, so call ourselves again to get the next line.
+@@ -395,10 +388,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) {
+ /* Do we have enough space? We may be full now. */
+ if (bytes_handled >= n) {
+- *read = n;
+- /* ensure this string is terminated */
+- (*s)[n-1] = '\0';
+- return APR_ENOSPC;
++ rv = APR_ENOSPC;
++ goto cleanup;
+ }
+ else {
+ apr_size_t next_size, next_len;
+@@ -411,7 +402,6 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ tmp = NULL;
+ }
+ else {
+- /* We're null terminated. */
+ tmp = last_char;
+ }
+
+@@ -420,7 +410,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ rv = ap_rgetline_core(&tmp, next_size,
+ &next_len, r, 0, bb);
+ if (rv != APR_SUCCESS) {
+- return rv;
++ goto cleanup;
+ }
+
+ if (do_alloc && next_len > 0) {
+@@ -434,7 +424,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ memcpy(new_buffer, *s, bytes_handled);
+
+ /* copy the new line, including the trailing null */
+- memcpy(new_buffer + bytes_handled, tmp, next_len + 1);
++ memcpy(new_buffer + bytes_handled, tmp, next_len);
+ *s = new_buffer;
+ }
+
+@@ -447,8 +437,21 @@ AP_DECLARE(apr_status_t) ap_rgetline_cor
+ }
+ }
+ }
++
++cleanup:
++ if (bytes_handled >= n) {
++ bytes_handled = n - 1;
++ }
++ if (*s) {
++ /* ensure the string is NUL terminated */
++ (*s)[bytes_handled] = '\0';
++ }
+ *read = bytes_handled;
+
++ if (rv != APR_SUCCESS) {
++ return rv;
++ }
++
+ /* PR#43039: We shouldn't accept NULL bytes within the line */
+ if (strlen(*s) < bytes_handled) {
+ return APR_EINVAL;
+@@ -487,6 +490,11 @@ AP_DECLARE(int) ap_getline(char *s, int
+ apr_size_t len;
+ apr_bucket_brigade *tmp_bb;
+
++ if (n < 1) {
++ /* Can't work since we always NUL terminate */
++ return -1;
++ }
++
+ tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ rv = ap_rgetline(&tmp_s, n, &len, r, flags, tmp_bb);
+ apr_brigade_destroy(tmp_bb);
diff --git a/debian/patches/series b/debian/patches/series
index 7f21218..b7667d1 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -22,3 +22,4 @@ core-Disallow-Methods-registration-at-run-time-.htac.patch
CVE-2017-15710-mod_authnz_ldap.diff
CVE-2017-15715-regex-line-endings.diff
CVE-2018-1283-mod_session.diff
+CVE-2018-1301-HTTP-request-read-out-of-bounds.diff
--
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