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 | |
| parent | 700078d6646c79a784cec2cb0a491687e3edd21b (diff) | |
| download | meta-openembedded-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>
| -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 0000000000..73f4e32c64 --- /dev/null +++ b/meta-webserver/recipes-php/modphp/files/php-CVE-2014-3597.patch | |||
| @@ -0,0 +1,282 @@ | |||
| 1 | modphp: Security Advisory - php - CVE-2014-3597 | ||
| 2 | |||
| 3 | Upstream-Status: Backport | ||
| 4 | |||
| 5 | Signed-off-by: Yue Tao <yue.tao@windriver.com> | ||
| 6 | |||
| 7 | From 2fefae47716d501aec41c1102f3fd4531f070b05 Mon Sep 17 00:00:00 2001 | ||
| 8 | From: Remi Collet <remi@php.net> | ||
| 9 | Date: Tue, 19 Aug 2014 08:33:49 +0200 | ||
| 10 | Subject: [PATCH] Fixed Sec Bug #67717 segfault in dns_get_record | ||
| 11 | CVE-2014-3597 | ||
| 12 | |||
| 13 | Incomplete fix for CVE-2014-4049 | ||
| 14 | |||
| 15 | Check possible buffer overflow | ||
| 16 | - pass real buffer end to dn_expand calls | ||
| 17 | - check buffer len before each read | ||
| 18 | --- | ||
| 19 | ext/standard/dns.c | 84 +++++++++++++++++++++++++++++++++++++--------------- | ||
| 20 | 1 file changed, 60 insertions(+), 24 deletions(-) | ||
| 21 | |||
| 22 | diff --git a/ext/standard/dns.c b/ext/standard/dns.c | ||
| 23 | index 214a7dc..0b5e69c 100644 | ||
| 24 | --- a/ext/standard/dns.c | ||
| 25 | +++ b/ext/standard/dns.c | ||
| 26 | @@ -412,8 +412,14 @@ PHP_FUNCTION(dns_check_record) | ||
| 27 | |||
| 28 | #if HAVE_FULL_DNS_FUNCS | ||
| 29 | |||
| 30 | +#define CHECKCP(n) do { \ | ||
| 31 | + if (cp + n > end) { \ | ||
| 32 | + return NULL; \ | ||
| 33 | + } \ | ||
| 34 | +} while (0) | ||
| 35 | + | ||
| 36 | /* {{{ php_parserr */ | ||
| 37 | -static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, int raw, zval **subarray) | ||
| 38 | +static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_to_fetch, int store, int raw, zval **subarray) | ||
| 39 | { | ||
| 40 | u_short type, class, dlen; | ||
| 41 | u_long ttl; | ||
| 42 | @@ -425,16 +431,18 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 43 | |||
| 44 | *subarray = NULL; | ||
| 45 | |||
| 46 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2); | ||
| 47 | + n = dn_expand(answer->qb2, end, cp, name, sizeof(name) - 2); | ||
| 48 | if (n < 0) { | ||
| 49 | return NULL; | ||
| 50 | } | ||
| 51 | cp += n; | ||
| 52 | |||
| 53 | + CHECKCP(10); | ||
| 54 | GETSHORT(type, cp); | ||
| 55 | GETSHORT(class, cp); | ||
| 56 | GETLONG(ttl, cp); | ||
| 57 | GETSHORT(dlen, cp); | ||
| 58 | + CHECKCP(dlen); | ||
| 59 | if (type_to_fetch != T_ANY && type != type_to_fetch) { | ||
| 60 | cp += dlen; | ||
| 61 | return cp; | ||
| 62 | @@ -461,12 +469,14 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 63 | |||
| 64 | switch (type) { | ||
| 65 | case DNS_T_A: | ||
| 66 | + CHECKCP(4); | ||
| 67 | add_assoc_string(*subarray, "type", "A", 1); | ||
| 68 | snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); | ||
| 69 | add_assoc_string(*subarray, "ip", name, 1); | ||
| 70 | cp += dlen; | ||
| 71 | break; | ||
| 72 | case DNS_T_MX: | ||
| 73 | + CHECKCP(2); | ||
| 74 | add_assoc_string(*subarray, "type", "MX", 1); | ||
| 75 | GETSHORT(n, cp); | ||
| 76 | add_assoc_long(*subarray, "pri", n); | ||
| 77 | @@ -485,7 +495,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 78 | if (type == DNS_T_PTR) { | ||
| 79 | add_assoc_string(*subarray, "type", "PTR", 1); | ||
| 80 | } | ||
| 81 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | ||
| 82 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | ||
| 83 | if (n < 0) { | ||
| 84 | return NULL; | ||
| 85 | } | ||
| 86 | @@ -495,18 +505,22 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 87 | case DNS_T_HINFO: | ||
| 88 | /* See RFC 1010 for values */ | ||
| 89 | add_assoc_string(*subarray, "type", "HINFO", 1); | ||
| 90 | + CHECKCP(1); | ||
| 91 | n = *cp & 0xFF; | ||
| 92 | cp++; | ||
| 93 | + CHECKCP(n); | ||
| 94 | add_assoc_stringl(*subarray, "cpu", (char*)cp, n, 1); | ||
| 95 | cp += n; | ||
| 96 | + CHECKCP(1); | ||
| 97 | n = *cp & 0xFF; | ||
| 98 | cp++; | ||
| 99 | + CHECKCP(n); | ||
| 100 | add_assoc_stringl(*subarray, "os", (char*)cp, n, 1); | ||
| 101 | cp += n; | ||
| 102 | break; | ||
| 103 | case DNS_T_TXT: | ||
| 104 | { | ||
| 105 | - int ll = 0; | ||
| 106 | + int l1 = 0, l2 = 0; | ||
| 107 | zval *entries = NULL; | ||
| 108 | |||
| 109 | add_assoc_string(*subarray, "type", "TXT", 1); | ||
| 110 | @@ -515,37 +529,41 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 111 | MAKE_STD_ZVAL(entries); | ||
| 112 | array_init(entries); | ||
| 113 | |||
| 114 | - while (ll < dlen) { | ||
| 115 | - n = cp[ll]; | ||
| 116 | - if ((ll + n) >= dlen) { | ||
| 117 | + while (l1 < dlen) { | ||
| 118 | + n = cp[l1]; | ||
| 119 | + if ((l1 + n) >= dlen) { | ||
| 120 | // Invalid chunk length, truncate | ||
| 121 | - n = dlen - (ll + 1); | ||
| 122 | + n = dlen - (l1 + 1); | ||
| 123 | + } | ||
| 124 | + if (n) { | ||
| 125 | + memcpy(tp + l2 , cp + l1 + 1, n); | ||
| 126 | + add_next_index_stringl(entries, cp + l1 + 1, n, 1); | ||
| 127 | } | ||
| 128 | - memcpy(tp + ll , cp + ll + 1, n); | ||
| 129 | - add_next_index_stringl(entries, cp + ll + 1, n, 1); | ||
| 130 | - ll = ll + n + 1; | ||
| 131 | + l1 = l1 + n + 1; | ||
| 132 | + l2 = l2 + n; | ||
| 133 | } | ||
| 134 | - tp[dlen] = '\0'; | ||
| 135 | + tp[l2] = '\0'; | ||
| 136 | cp += dlen; | ||
| 137 | |||
| 138 | - add_assoc_stringl(*subarray, "txt", tp, (dlen>0)?dlen - 1:0, 0); | ||
| 139 | + add_assoc_stringl(*subarray, "txt", tp, l2, 0); | ||
| 140 | add_assoc_zval(*subarray, "entries", entries); | ||
| 141 | } | ||
| 142 | break; | ||
| 143 | case DNS_T_SOA: | ||
| 144 | add_assoc_string(*subarray, "type", "SOA", 1); | ||
| 145 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); | ||
| 146 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); | ||
| 147 | if (n < 0) { | ||
| 148 | return NULL; | ||
| 149 | } | ||
| 150 | cp += n; | ||
| 151 | add_assoc_string(*subarray, "mname", name, 1); | ||
| 152 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); | ||
| 153 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); | ||
| 154 | if (n < 0) { | ||
| 155 | return NULL; | ||
| 156 | } | ||
| 157 | cp += n; | ||
| 158 | add_assoc_string(*subarray, "rname", name, 1); | ||
| 159 | + CHECKCP(5*4); | ||
| 160 | GETLONG(n, cp); | ||
| 161 | add_assoc_long(*subarray, "serial", n); | ||
| 162 | GETLONG(n, cp); | ||
| 163 | @@ -559,6 +577,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 164 | break; | ||
| 165 | case DNS_T_AAAA: | ||
| 166 | tp = (u_char*)name; | ||
| 167 | + CHECKCP(8*2); | ||
| 168 | for(i=0; i < 8; i++) { | ||
| 169 | GETSHORT(s, cp); | ||
| 170 | if (s != 0) { | ||
| 171 | @@ -593,6 +612,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 172 | case DNS_T_A6: | ||
| 173 | p = cp; | ||
| 174 | add_assoc_string(*subarray, "type", "A6", 1); | ||
| 175 | + CHECKCP(1); | ||
| 176 | n = ((int)cp[0]) & 0xFF; | ||
| 177 | cp++; | ||
| 178 | add_assoc_long(*subarray, "masklen", n); | ||
| 179 | @@ -628,6 +648,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 180 | cp++; | ||
| 181 | } | ||
| 182 | for (i = (n + 8) / 16; i < 8; i++) { | ||
| 183 | + CHECKCP(2); | ||
| 184 | GETSHORT(s, cp); | ||
| 185 | if (s != 0) { | ||
| 186 | if (tp > (u_char *)name) { | ||
| 187 | @@ -657,7 +678,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 188 | tp[0] = '\0'; | ||
| 189 | add_assoc_string(*subarray, "ipv6", name, 1); | ||
| 190 | if (cp < p + dlen) { | ||
| 191 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | ||
| 192 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | ||
| 193 | if (n < 0) { | ||
| 194 | return NULL; | ||
| 195 | } | ||
| 196 | @@ -666,6 +687,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 197 | } | ||
| 198 | break; | ||
| 199 | case DNS_T_SRV: | ||
| 200 | + CHECKCP(3*2); | ||
| 201 | add_assoc_string(*subarray, "type", "SRV", 1); | ||
| 202 | GETSHORT(n, cp); | ||
| 203 | add_assoc_long(*subarray, "pri", n); | ||
| 204 | @@ -673,7 +695,7 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 205 | add_assoc_long(*subarray, "weight", n); | ||
| 206 | GETSHORT(n, cp); | ||
| 207 | add_assoc_long(*subarray, "port", n); | ||
| 208 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | ||
| 209 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | ||
| 210 | if (n < 0) { | ||
| 211 | return NULL; | ||
| 212 | } | ||
| 213 | @@ -681,21 +703,35 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int | ||
| 214 | add_assoc_string(*subarray, "target", name, 1); | ||
| 215 | break; | ||
| 216 | case DNS_T_NAPTR: | ||
| 217 | + CHECKCP(2*2); | ||
| 218 | add_assoc_string(*subarray, "type", "NAPTR", 1); | ||
| 219 | GETSHORT(n, cp); | ||
| 220 | add_assoc_long(*subarray, "order", n); | ||
| 221 | GETSHORT(n, cp); | ||
| 222 | add_assoc_long(*subarray, "pref", n); | ||
| 223 | + | ||
| 224 | + CHECKCP(1); | ||
| 225 | n = (cp[0] & 0xFF); | ||
| 226 | - add_assoc_stringl(*subarray, "flags", (char*)++cp, n, 1); | ||
| 227 | + cp++; | ||
| 228 | + CHECKCP(n); | ||
| 229 | + add_assoc_stringl(*subarray, "flags", (char*)cp, n, 1); | ||
| 230 | cp += n; | ||
| 231 | + | ||
| 232 | + CHECKCP(1); | ||
| 233 | n = (cp[0] & 0xFF); | ||
| 234 | - add_assoc_stringl(*subarray, "services", (char*)++cp, n, 1); | ||
| 235 | + cp++; | ||
| 236 | + CHECKCP(n); | ||
| 237 | + add_assoc_stringl(*subarray, "services", (char*)cp, n, 1); | ||
| 238 | cp += n; | ||
| 239 | + | ||
| 240 | + CHECKCP(1); | ||
| 241 | n = (cp[0] & 0xFF); | ||
| 242 | - add_assoc_stringl(*subarray, "regex", (char*)++cp, n, 1); | ||
| 243 | + cp++; | ||
| 244 | + CHECKCP(n); | ||
| 245 | + add_assoc_stringl(*subarray, "regex", (char*)cp, n, 1); | ||
| 246 | cp += n; | ||
| 247 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | ||
| 248 | + | ||
| 249 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | ||
| 250 | if (n < 0) { | ||
| 251 | return NULL; | ||
| 252 | } | ||
| 253 | @@ -888,7 +924,7 @@ PHP_FUNCTION(dns_get_record) | ||
| 254 | while (an-- && cp && cp < end) { | ||
| 255 | zval *retval; | ||
| 256 | |||
| 257 | - cp = php_parserr(cp, &answer, type_to_fetch, store_results, raw, &retval); | ||
| 258 | + cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, raw, &retval); | ||
| 259 | if (retval != NULL && store_results) { | ||
| 260 | add_next_index_zval(return_value, retval); | ||
| 261 | } | ||
| 262 | @@ -901,7 +937,7 @@ PHP_FUNCTION(dns_get_record) | ||
| 263 | while (ns-- > 0 && cp && cp < end) { | ||
| 264 | zval *retval = NULL; | ||
| 265 | |||
| 266 | - cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, raw, &retval); | ||
| 267 | + cp = php_parserr(cp, end, &answer, DNS_T_ANY, authns != NULL, raw, &retval); | ||
| 268 | if (retval != NULL) { | ||
| 269 | add_next_index_zval(authns, retval); | ||
| 270 | } | ||
| 271 | @@ -913,7 +949,7 @@ PHP_FUNCTION(dns_get_record) | ||
| 272 | while (ar-- > 0 && cp && cp < end) { | ||
| 273 | zval *retval = NULL; | ||
| 274 | |||
| 275 | - cp = php_parserr(cp, &answer, DNS_T_ANY, 1, raw, &retval); | ||
| 276 | + cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, raw, &retval); | ||
| 277 | if (retval != NULL) { | ||
| 278 | add_next_index_zval(addtl, retval); | ||
| 279 | } | ||
| 280 | -- | ||
| 281 | 1.7.9.5 | ||
| 282 | |||
diff --git a/meta-webserver/recipes-php/modphp/modphp5.inc b/meta-webserver/recipes-php/modphp/modphp5.inc index 9c83ac044b..dcafa4fc31 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 \ | |||
| 11 | file://0001-using-pkgconfig-to-check-libxml.patch \ | 11 | file://0001-using-pkgconfig-to-check-libxml.patch \ |
| 12 | file://php-CVE-2014-5120.patch \ | 12 | file://php-CVE-2014-5120.patch \ |
| 13 | file://php-CVE-2014-3587.patch \ | 13 | file://php-CVE-2014-3587.patch \ |
| 14 | file://php-CVE-2014-3597.patch \ | ||
| 14 | " | 15 | " |
| 15 | 16 | ||
| 16 | S = "${WORKDIR}/php-${PV}" | 17 | S = "${WORKDIR}/php-${PV}" |
