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/recipes-php/modphp/files | |
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>
Diffstat (limited to 'meta-webserver/recipes-php/modphp/files')
-rw-r--r-- | meta-webserver/recipes-php/modphp/files/php-CVE-2014-3597.patch | 282 |
1 files changed, 282 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 000000000..73f4e32c6 --- /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 | |||