diff options
author | Yue Tao <Yue.Tao@windriver.com> | 2014-10-23 16:29:15 +0800 |
---|---|---|
committer | Martin Jansa <Martin.Jansa@gmail.com> | 2014-10-30 09:00:07 +0100 |
commit | 8d50adfe536f3dc94313318f834946e634441c8a (patch) | |
tree | 96e6f0c3769f2c6764c1e541ca283341313d9f15 /meta-webserver | |
parent | 700078d6646c79a784cec2cb0a491687e3edd21b (diff) | |
download | meta-openembedded-contrib-8d50adfe536f3dc94313318f834946e634441c8a.tar.gz |
modphp: Security Advisory - php - CVE-2014-3597
Multiple buffer overflows in the php_parserr function in
ext/standard/dns.c in PHP before 5.4.32 and 5.5.x before 5.5.16 allow
remote DNS servers to cause a denial of service (application crash) or
possibly execute arbitrary code via a crafted DNS record, related to the
dns_get_record function and the dn_expand function. NOTE: this issue
exists because of an incomplete fix for CVE-2014-4049.
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-3597
Signed-off-by: Yue Tao <Yue.Tao@windriver.com>
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
Diffstat (limited to 'meta-webserver')
-rw-r--r-- | meta-webserver/recipes-php/modphp/files/php-CVE-2014-3597.patch | 282 | ||||
-rw-r--r-- | meta-webserver/recipes-php/modphp/modphp5.inc | 1 |
2 files changed, 283 insertions, 0 deletions
diff --git a/meta-webserver/recipes-php/modphp/files/php-CVE-2014-3597.patch b/meta-webserver/recipes-php/modphp/files/php-CVE-2014-3597.patch new file mode 100644 index 00000000000..73f4e32c640 --- /dev/null +++ b/meta-webserver/recipes-php/modphp/files/php-CVE-2014-3597.patch @@ -0,0 +1,282 @@ +modphp: Security Advisory - php - CVE-2014-3597 + +Upstream-Status: Backport + +Signed-off-by: Yue Tao <yue.tao@windriver.com> + +From 2fefae47716d501aec41c1102f3fd4531f070b05 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@php.net> +Date: Tue, 19 Aug 2014 08:33:49 +0200 +Subject: [PATCH] Fixed Sec Bug #67717 segfault in dns_get_record + CVE-2014-3597 + +Incomplete fix for CVE-2014-4049 + +Check possible buffer overflow +- pass real buffer end to dn_expand calls +- check buffer len before each read +--- + ext/standard/dns.c | 84 +++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 60 insertions(+), 24 deletions(-) + +diff --git a/ext/standard/dns.c b/ext/standard/dns.c +index 214a7dc..0b5e69c 100644 +--- a/ext/standard/dns.c ++++ b/ext/standard/dns.c +@@ -412,8 +412,14 @@ PHP_FUNCTION(dns_check_record) + + #if HAVE_FULL_DNS_FUNCS + ++#define CHECKCP(n) do { \ ++ if (cp + n > end) { \ ++ return NULL; \ ++ } \ ++} while (0) ++ + /* {{{ php_parserr */ +-static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, int raw, zval **subarray) ++static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_to_fetch, int store, int raw, zval **subarray) + { + u_short type, class, dlen; + u_long ttl; +@@ -425,16 +431,18 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + + *subarray = NULL; + +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, sizeof(name) - 2); + if (n < 0) { + return NULL; + } + cp += n; + ++ CHECKCP(10); + GETSHORT(type, cp); + GETSHORT(class, cp); + GETLONG(ttl, cp); + GETSHORT(dlen, cp); ++ CHECKCP(dlen); + if (type_to_fetch != T_ANY && type != type_to_fetch) { + cp += dlen; + return cp; +@@ -461,12 +469,14 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + + switch (type) { + case DNS_T_A: ++ CHECKCP(4); + add_assoc_string(*subarray, "type", "A", 1); + snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); + add_assoc_string(*subarray, "ip", name, 1); + cp += dlen; + break; + case DNS_T_MX: ++ CHECKCP(2); + add_assoc_string(*subarray, "type", "MX", 1); + GETSHORT(n, cp); + add_assoc_long(*subarray, "pri", n); +@@ -485,7 +495,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + if (type == DNS_T_PTR) { + add_assoc_string(*subarray, "type", "PTR", 1); + } +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -495,18 +505,22 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + case DNS_T_HINFO: + /* See RFC 1010 for values */ + add_assoc_string(*subarray, "type", "HINFO", 1); ++ CHECKCP(1); + n = *cp & 0xFF; + cp++; ++ CHECKCP(n); + add_assoc_stringl(*subarray, "cpu", (char*)cp, n, 1); + cp += n; ++ CHECKCP(1); + n = *cp & 0xFF; + cp++; ++ CHECKCP(n); + add_assoc_stringl(*subarray, "os", (char*)cp, n, 1); + cp += n; + break; + case DNS_T_TXT: + { +- int ll = 0; ++ int l1 = 0, l2 = 0; + zval *entries = NULL; + + add_assoc_string(*subarray, "type", "TXT", 1); +@@ -515,37 +529,41 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + MAKE_STD_ZVAL(entries); + array_init(entries); + +- while (ll < dlen) { +- n = cp[ll]; +- if ((ll + n) >= dlen) { ++ while (l1 < dlen) { ++ n = cp[l1]; ++ if ((l1 + n) >= dlen) { + // Invalid chunk length, truncate +- n = dlen - (ll + 1); ++ n = dlen - (l1 + 1); ++ } ++ if (n) { ++ memcpy(tp + l2 , cp + l1 + 1, n); ++ add_next_index_stringl(entries, cp + l1 + 1, n, 1); + } +- memcpy(tp + ll , cp + ll + 1, n); +- add_next_index_stringl(entries, cp + ll + 1, n, 1); +- ll = ll + n + 1; ++ l1 = l1 + n + 1; ++ l2 = l2 + n; + } +- tp[dlen] = '\0'; ++ tp[l2] = '\0'; + cp += dlen; + +- add_assoc_stringl(*subarray, "txt", tp, (dlen>0)?dlen - 1:0, 0); ++ add_assoc_stringl(*subarray, "txt", tp, l2, 0); + add_assoc_zval(*subarray, "entries", entries); + } + break; + case DNS_T_SOA: + add_assoc_string(*subarray, "type", "SOA", 1); +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); + if (n < 0) { + return NULL; + } + cp += n; + add_assoc_string(*subarray, "mname", name, 1); +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); + if (n < 0) { + return NULL; + } + cp += n; + add_assoc_string(*subarray, "rname", name, 1); ++ CHECKCP(5*4); + GETLONG(n, cp); + add_assoc_long(*subarray, "serial", n); + GETLONG(n, cp); +@@ -559,6 +577,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + break; + case DNS_T_AAAA: + tp = (u_char*)name; ++ CHECKCP(8*2); + for(i=0; i < 8; i++) { + GETSHORT(s, cp); + if (s != 0) { +@@ -593,6 +612,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + case DNS_T_A6: + p = cp; + add_assoc_string(*subarray, "type", "A6", 1); ++ CHECKCP(1); + n = ((int)cp[0]) & 0xFF; + cp++; + add_assoc_long(*subarray, "masklen", n); +@@ -628,6 +648,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + cp++; + } + for (i = (n + 8) / 16; i < 8; i++) { ++ CHECKCP(2); + GETSHORT(s, cp); + if (s != 0) { + if (tp > (u_char *)name) { +@@ -657,7 +678,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + tp[0] = '\0'; + add_assoc_string(*subarray, "ipv6", name, 1); + if (cp < p + dlen) { +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -666,6 +687,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + } + break; + case DNS_T_SRV: ++ CHECKCP(3*2); + add_assoc_string(*subarray, "type", "SRV", 1); + GETSHORT(n, cp); + add_assoc_long(*subarray, "pri", n); +@@ -673,7 +695,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + add_assoc_long(*subarray, "weight", n); + GETSHORT(n, cp); + add_assoc_long(*subarray, "port", n); +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -681,21 +703,35 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int + add_assoc_string(*subarray, "target", name, 1); + break; + case DNS_T_NAPTR: ++ CHECKCP(2*2); + add_assoc_string(*subarray, "type", "NAPTR", 1); + GETSHORT(n, cp); + add_assoc_long(*subarray, "order", n); + GETSHORT(n, cp); + add_assoc_long(*subarray, "pref", n); ++ ++ CHECKCP(1); + n = (cp[0] & 0xFF); +- add_assoc_stringl(*subarray, "flags", (char*)++cp, n, 1); ++ cp++; ++ CHECKCP(n); ++ add_assoc_stringl(*subarray, "flags", (char*)cp, n, 1); + cp += n; ++ ++ CHECKCP(1); + n = (cp[0] & 0xFF); +- add_assoc_stringl(*subarray, "services", (char*)++cp, n, 1); ++ cp++; ++ CHECKCP(n); ++ add_assoc_stringl(*subarray, "services", (char*)cp, n, 1); + cp += n; ++ ++ CHECKCP(1); + n = (cp[0] & 0xFF); +- add_assoc_stringl(*subarray, "regex", (char*)++cp, n, 1); ++ cp++; ++ CHECKCP(n); ++ add_assoc_stringl(*subarray, "regex", (char*)cp, n, 1); + cp += n; +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -888,7 +924,7 @@ PHP_FUNCTION(dns_get_record) + while (an-- && cp && cp < end) { + zval *retval; + +- cp = php_parserr(cp, &answer, type_to_fetch, store_results, raw, &retval); ++ cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, raw, &retval); + if (retval != NULL && store_results) { + add_next_index_zval(return_value, retval); + } +@@ -901,7 +937,7 @@ PHP_FUNCTION(dns_get_record) + while (ns-- > 0 && cp && cp < end) { + zval *retval = NULL; + +- cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, raw, &retval); ++ cp = php_parserr(cp, end, &answer, DNS_T_ANY, authns != NULL, raw, &retval); + if (retval != NULL) { + add_next_index_zval(authns, retval); + } +@@ -913,7 +949,7 @@ PHP_FUNCTION(dns_get_record) + while (ar-- > 0 && cp && cp < end) { + zval *retval = NULL; + +- cp = php_parserr(cp, &answer, DNS_T_ANY, 1, raw, &retval); ++ cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, raw, &retval); + if (retval != NULL) { + add_next_index_zval(addtl, retval); + } +-- +1.7.9.5 + diff --git a/meta-webserver/recipes-php/modphp/modphp5.inc b/meta-webserver/recipes-php/modphp/modphp5.inc index 9c83ac044bd..dcafa4fc31d 100644 --- a/meta-webserver/recipes-php/modphp/modphp5.inc +++ b/meta-webserver/recipes-php/modphp/modphp5.inc @@ -11,6 +11,7 @@ SRC_URI = "http://www.php.net/distributions/php-${PV}.tar.bz2 \ file://0001-using-pkgconfig-to-check-libxml.patch \ file://php-CVE-2014-5120.patch \ file://php-CVE-2014-3587.patch \ + file://php-CVE-2014-3597.patch \ " S = "${WORKDIR}/php-${PV}" |