diff options
author | Andrej Valek <andrej.valek@siemens.com> | 2017-06-14 14:58:47 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-06-23 11:44:13 +0100 |
commit | 371ba8c74332b6ab2d9062edadc93c688751e4ab (patch) | |
tree | a4cac38d29cf01a6c85890f05a7984e7a35a5f81 | |
parent | 1a4f1ccdcc51b7d97ab66214675357b6c2c075f8 (diff) | |
download | poky-371ba8c74332b6ab2d9062edadc93c688751e4ab.tar.gz |
libxml2: Fix CVE-2017-9049 and CVE-2017-9050
Fix handling of parameter-entity references
There were two bugs where parameter-entity references could lead to an
unexpected change of the input buffer in xmlParseNameComplex and
xmlDictLookup being called with an invalid pointer.
Fixes bug 781205 and bug 781361
CVE: CVE-2017-9049 CVE-2017-9050
(From OE-Core rev: 2300762fef8fc8e3e56fb07fd4076c1deeba0a9b)
Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/recipes-core/libxml/libxml2/libxml2-CVE-2017-9049_CVE-2017-9050.patch | 291 | ||||
-rw-r--r-- | meta/recipes-core/libxml/libxml2_2.9.4.bb | 1 |
2 files changed, 292 insertions, 0 deletions
diff --git a/meta/recipes-core/libxml/libxml2/libxml2-CVE-2017-9049_CVE-2017-9050.patch b/meta/recipes-core/libxml/libxml2/libxml2-CVE-2017-9049_CVE-2017-9050.patch new file mode 100644 index 0000000000..591075de3c --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/libxml2-CVE-2017-9049_CVE-2017-9050.patch | |||
@@ -0,0 +1,291 @@ | |||
1 | libxml2-2.9.4: Fix CVE-2017-9049 and CVE-2017-9050 | ||
2 | |||
3 | [No upstream tracking] -- https://bugzilla.gnome.org/show_bug.cgi?id=781205 | ||
4 | -- https://bugzilla.gnome.org/show_bug.cgi?id=781361 | ||
5 | |||
6 | parser: Fix handling of parameter-entity references | ||
7 | |||
8 | There were two bugs where parameter-entity references could lead to an | ||
9 | unexpected change of the input buffer in xmlParseNameComplex and | ||
10 | xmlDictLookup being called with an invalid pointer. | ||
11 | |||
12 | Percent sign in DTD Names | ||
13 | ========================= | ||
14 | |||
15 | The NEXTL macro used to call xmlParserHandlePEReference. When parsing | ||
16 | "complex" names inside the DTD, this could result in entity expansion | ||
17 | which created a new input buffer. The fix is to simply remove the call | ||
18 | to xmlParserHandlePEReference from the NEXTL macro. This is safe because | ||
19 | no users of the macro require expansion of parameter entities. | ||
20 | |||
21 | - xmlParseNameComplex | ||
22 | - xmlParseNCNameComplex | ||
23 | - xmlParseNmtoken | ||
24 | |||
25 | The percent sign is not allowed in names, which are grammatical tokens. | ||
26 | |||
27 | - xmlParseEntityValue | ||
28 | |||
29 | Parameter-entity references in entity values are expanded but this | ||
30 | happens in a separate step in this function. | ||
31 | |||
32 | - xmlParseSystemLiteral | ||
33 | |||
34 | Parameter-entity references are ignored in the system literal. | ||
35 | |||
36 | - xmlParseAttValueComplex | ||
37 | - xmlParseCharDataComplex | ||
38 | - xmlParseCommentComplex | ||
39 | - xmlParsePI | ||
40 | - xmlParseCDSect | ||
41 | |||
42 | Parameter-entity references are ignored outside the DTD. | ||
43 | |||
44 | - xmlLoadEntityContent | ||
45 | |||
46 | This function is only called from xmlStringLenDecodeEntities and | ||
47 | entities are replaced in a separate step immediately after the function | ||
48 | call. | ||
49 | |||
50 | This bug could also be triggered with an internal subset and double | ||
51 | entity expansion. | ||
52 | |||
53 | This fixes bug 766956 initially reported by Wei Lei and independently by | ||
54 | Chromium's ClusterFuzz, Hanno Böck, and Marco Grassi. Thanks to everyone | ||
55 | involved. | ||
56 | |||
57 | xmlParseNameComplex with XML_PARSE_OLD10 | ||
58 | ======================================== | ||
59 | |||
60 | When parsing Names inside an expanded parameter entity with the | ||
61 | XML_PARSE_OLD10 option, xmlParseNameComplex would call xmlGROW via the | ||
62 | GROW macro if the input buffer was exhausted. At the end of the | ||
63 | parameter entity's replacement text, this function would then call | ||
64 | xmlPopInput which invalidated the input buffer. | ||
65 | |||
66 | There should be no need to invoke GROW in this situation because the | ||
67 | buffer is grown periodically every XML_PARSER_CHUNK_SIZE characters and, | ||
68 | at least for UTF-8, in xmlCurrentChar. This also matches the code path | ||
69 | executed when XML_PARSE_OLD10 is not set. | ||
70 | |||
71 | This fixes bugs 781205 (CVE-2017-9049) and 781361 (CVE-2017-9050). | ||
72 | Thanks to Marcel Böhme and Thuan Pham for the report. | ||
73 | |||
74 | Additional hardening | ||
75 | ==================== | ||
76 | |||
77 | A separate check was added in xmlParseNameComplex to validate the | ||
78 | buffer size. | ||
79 | |||
80 | Fixes bug 781205 and bug 781361 | ||
81 | |||
82 | Upstream-Status: Backport [https://git.gnome.org/browse/libxml2/commit/?id=932cc9896ab41475d4aa429c27d9afd175959d74] | ||
83 | CVE: CVE-2017-9049 CVE-2017-9050 | ||
84 | Signed-off-by: Andrej Valek <andrej.valek@siemens.com> | ||
85 | |||
86 | diff --git a/Makefile.am b/Makefile.am | ||
87 | index 9f988b0..dab15a4 100644 | ||
88 | --- a/Makefile.am | ||
89 | +++ b/Makefile.am | ||
90 | @@ -422,6 +422,24 @@ Errtests : xmllint$(EXEEXT) | ||
91 | if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \ | ||
92 | rm result.$$name error.$$name ; \ | ||
93 | fi ; fi ; done) | ||
94 | + @echo "## Error cases regression tests (old 1.0)" | ||
95 | + -@(for i in $(srcdir)/test/errors10/*.xml ; do \ | ||
96 | + name=`basename $$i`; \ | ||
97 | + if [ ! -d $$i ] ; then \ | ||
98 | + if [ ! -f $(srcdir)/result/errors10/$$name ] ; then \ | ||
99 | + echo New test file $$name ; \ | ||
100 | + $(CHECKER) $(top_builddir)/xmllint --oldxml10 $$i \ | ||
101 | + 2> $(srcdir)/result/errors10/$$name.err \ | ||
102 | + > $(srcdir)/result/errors10/$$name ; \ | ||
103 | + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ | ||
104 | + else \ | ||
105 | + log=`$(CHECKER) $(top_builddir)/xmllint --oldxml10 $$i 2> error.$$name > result.$$name ; \ | ||
106 | + grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0"; \ | ||
107 | + diff $(srcdir)/result/errors10/$$name result.$$name ; \ | ||
108 | + diff $(srcdir)/result/errors10/$$name.err error.$$name` ; \ | ||
109 | + if [ -n "$$log" ] ; then echo $$name result ; echo "$$log" ; fi ; \ | ||
110 | + rm result.$$name error.$$name ; \ | ||
111 | + fi ; fi ; done) | ||
112 | @echo "## Error cases stream regression tests" | ||
113 | -@(for i in $(srcdir)/test/errors/*.xml ; do \ | ||
114 | name=`basename $$i`; \ | ||
115 | diff --git a/parser.c b/parser.c | ||
116 | index 609a270..8e11c12 100644 | ||
117 | --- a/parser.c | ||
118 | +++ b/parser.c | ||
119 | @@ -2115,7 +2115,6 @@ static void xmlGROW (xmlParserCtxtPtr ctxt) { | ||
120 | ctxt->input->line++; ctxt->input->col = 1; \ | ||
121 | } else ctxt->input->col++; \ | ||
122 | ctxt->input->cur += l; \ | ||
123 | - if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ | ||
124 | } while (0) | ||
125 | |||
126 | #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l) | ||
127 | @@ -3406,13 +3405,6 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { | ||
128 | len += l; | ||
129 | NEXTL(l); | ||
130 | c = CUR_CHAR(l); | ||
131 | - if (c == 0) { | ||
132 | - count = 0; | ||
133 | - GROW; | ||
134 | - if (ctxt->instate == XML_PARSER_EOF) | ||
135 | - return(NULL); | ||
136 | - c = CUR_CHAR(l); | ||
137 | - } | ||
138 | } | ||
139 | } | ||
140 | if ((len > XML_MAX_NAME_LENGTH) && | ||
141 | @@ -3420,6 +3412,16 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { | ||
142 | xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); | ||
143 | return(NULL); | ||
144 | } | ||
145 | + if (ctxt->input->cur - ctxt->input->base < len) { | ||
146 | + /* | ||
147 | + * There were a couple of bugs where PERefs lead to to a change | ||
148 | + * of the buffer. Check the buffer size to avoid passing an invalid | ||
149 | + * pointer to xmlDictLookup. | ||
150 | + */ | ||
151 | + xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, | ||
152 | + "unexpected change of input buffer"); | ||
153 | + return (NULL); | ||
154 | + } | ||
155 | if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r')) | ||
156 | return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len)); | ||
157 | return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len)); | ||
158 | diff --git a/result/errors10/781205.xml b/result/errors10/781205.xml | ||
159 | new file mode 100644 | ||
160 | index 0000000..e69de29 | ||
161 | diff --git a/result/errors10/781205.xml.err b/result/errors10/781205.xml.err | ||
162 | new file mode 100644 | ||
163 | index 0000000..da15c3f | ||
164 | --- /dev/null | ||
165 | +++ b/result/errors10/781205.xml.err | ||
166 | @@ -0,0 +1,21 @@ | ||
167 | +Entity: line 1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration | ||
168 | + | ||
169 | + %a; | ||
170 | + ^ | ||
171 | +Entity: line 1: | ||
172 | +<:0000 | ||
173 | +^ | ||
174 | +Entity: line 1: parser error : DOCTYPE improperly terminated | ||
175 | + %a; | ||
176 | + ^ | ||
177 | +Entity: line 1: | ||
178 | +<:0000 | ||
179 | +^ | ||
180 | +namespace error : Failed to parse QName ':0000' | ||
181 | + %a; | ||
182 | + ^ | ||
183 | +<:0000 | ||
184 | + ^ | ||
185 | +./test/errors10/781205.xml:4: parser error : Couldn't find end of Start Tag :0000 line 1 | ||
186 | + | ||
187 | +^ | ||
188 | diff --git a/result/errors10/781361.xml b/result/errors10/781361.xml | ||
189 | new file mode 100644 | ||
190 | index 0000000..e69de29 | ||
191 | diff --git a/result/errors10/781361.xml.err b/result/errors10/781361.xml.err | ||
192 | new file mode 100644 | ||
193 | index 0000000..655f41a | ||
194 | --- /dev/null | ||
195 | +++ b/result/errors10/781361.xml.err | ||
196 | @@ -0,0 +1,13 @@ | ||
197 | +./test/errors10/781361.xml:4: parser error : xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected | ||
198 | + | ||
199 | +^ | ||
200 | +./test/errors10/781361.xml:4: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration | ||
201 | + | ||
202 | + | ||
203 | +^ | ||
204 | +./test/errors10/781361.xml:4: parser error : DOCTYPE improperly terminated | ||
205 | + | ||
206 | +^ | ||
207 | +./test/errors10/781361.xml:4: parser error : Start tag expected, '<' not found | ||
208 | + | ||
209 | +^ | ||
210 | diff --git a/result/valid/766956.xml b/result/valid/766956.xml | ||
211 | new file mode 100644 | ||
212 | index 0000000..e69de29 | ||
213 | diff --git a/result/valid/766956.xml.err b/result/valid/766956.xml.err | ||
214 | new file mode 100644 | ||
215 | index 0000000..34b1dae | ||
216 | --- /dev/null | ||
217 | +++ b/result/valid/766956.xml.err | ||
218 | @@ -0,0 +1,9 @@ | ||
219 | +test/valid/dtds/766956.dtd:2: parser error : PEReference: expecting ';' | ||
220 | +%ä%ent; | ||
221 | + ^ | ||
222 | +Entity: line 1: parser error : Content error in the external subset | ||
223 | + %ent; | ||
224 | + ^ | ||
225 | +Entity: line 1: | ||
226 | +value | ||
227 | +^ | ||
228 | diff --git a/result/valid/766956.xml.err.rdr b/result/valid/766956.xml.err.rdr | ||
229 | new file mode 100644 | ||
230 | index 0000000..7760346 | ||
231 | --- /dev/null | ||
232 | +++ b/result/valid/766956.xml.err.rdr | ||
233 | @@ -0,0 +1,10 @@ | ||
234 | +test/valid/dtds/766956.dtd:2: parser error : PEReference: expecting ';' | ||
235 | +%ä%ent; | ||
236 | + ^ | ||
237 | +Entity: line 1: parser error : Content error in the external subset | ||
238 | + %ent; | ||
239 | + ^ | ||
240 | +Entity: line 1: | ||
241 | +value | ||
242 | +^ | ||
243 | +./test/valid/766956.xml : failed to parse | ||
244 | diff --git a/runtest.c b/runtest.c | ||
245 | index bb74d2a..63e8c20 100644 | ||
246 | --- a/runtest.c | ||
247 | +++ b/runtest.c | ||
248 | @@ -4202,6 +4202,9 @@ testDesc testDescriptions[] = { | ||
249 | { "Error cases regression tests", | ||
250 | errParseTest, "./test/errors/*.xml", "result/errors/", "", ".err", | ||
251 | 0 }, | ||
252 | + { "Error cases regression tests (old 1.0)", | ||
253 | + errParseTest, "./test/errors10/*.xml", "result/errors10/", "", ".err", | ||
254 | + XML_PARSE_OLD10 }, | ||
255 | #ifdef LIBXML_READER_ENABLED | ||
256 | { "Error cases stream regression tests", | ||
257 | streamParseTest, "./test/errors/*.xml", "result/errors/", NULL, ".str", | ||
258 | diff --git a/test/errors10/781205.xml b/test/errors10/781205.xml | ||
259 | new file mode 100644 | ||
260 | index 0000000..d9e9e83 | ||
261 | --- /dev/null | ||
262 | +++ b/test/errors10/781205.xml | ||
263 | @@ -0,0 +1,3 @@ | ||
264 | +<!DOCTYPE D [ | ||
265 | + <!ENTITY % a "<:0000"> | ||
266 | + %a; | ||
267 | diff --git a/test/errors10/781361.xml b/test/errors10/781361.xml | ||
268 | new file mode 100644 | ||
269 | index 0000000..67476bc | ||
270 | --- /dev/null | ||
271 | +++ b/test/errors10/781361.xml | ||
272 | @@ -0,0 +1,3 @@ | ||
273 | +<!DOCTYPE doc [ | ||
274 | + <!ENTITY % elem "<!ELEMENT e0000000000"> | ||
275 | + %elem; | ||
276 | diff --git a/test/valid/766956.xml b/test/valid/766956.xml | ||
277 | new file mode 100644 | ||
278 | index 0000000..19a95a0 | ||
279 | --- /dev/null | ||
280 | +++ b/test/valid/766956.xml | ||
281 | @@ -0,0 +1,2 @@ | ||
282 | +<!DOCTYPE test SYSTEM "dtds/766956.dtd"> | ||
283 | +<test/> | ||
284 | diff --git a/test/valid/dtds/766956.dtd b/test/valid/dtds/766956.dtd | ||
285 | new file mode 100644 | ||
286 | index 0000000..dddde68 | ||
287 | --- /dev/null | ||
288 | +++ b/test/valid/dtds/766956.dtd | ||
289 | @@ -0,0 +1,2 @@ | ||
290 | +<!ENTITY % ent "value"> | ||
291 | +%ä%ent; | ||
diff --git a/meta/recipes-core/libxml/libxml2_2.9.4.bb b/meta/recipes-core/libxml/libxml2_2.9.4.bb index dd2e034e2a..3f78c2de63 100644 --- a/meta/recipes-core/libxml/libxml2_2.9.4.bb +++ b/meta/recipes-core/libxml/libxml2_2.9.4.bb | |||
@@ -25,6 +25,7 @@ SRC_URI = "ftp://xmlsoft.org/libxml2/libxml2-${PV}.tar.gz;name=libtar \ | |||
25 | file://libxml2-fix_NULL_pointer_derefs.patch \ | 25 | file://libxml2-fix_NULL_pointer_derefs.patch \ |
26 | file://libxml2-fix_and_simplify_xmlParseStartTag2.patch \ | 26 | file://libxml2-fix_and_simplify_xmlParseStartTag2.patch \ |
27 | file://libxml2-CVE-2017-9047_CVE-2017-9048.patch \ | 27 | file://libxml2-CVE-2017-9047_CVE-2017-9048.patch \ |
28 | file://libxml2-CVE-2017-9049_CVE-2017-9050.patch \ | ||
28 | file://CVE-2016-9318.patch \ | 29 | file://CVE-2016-9318.patch \ |
29 | file://0001-Make-ptest-run-the-python-tests-if-python-is-enabled.patch \ | 30 | file://0001-Make-ptest-run-the-python-tests-if-python-is-enabled.patch \ |
30 | " | 31 | " |