diff options
| author | Andrej Valek <andrej.valek@siemens.com> | 2017-06-14 14:58:47 +0200 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-07-27 22:36:44 +0100 |
| commit | 93b0d29184419318cda433bb0a764f8f2a7eeb6a (patch) | |
| tree | 5e9aae8aad7adec32de8526277b2b4418c54acef | |
| parent | b611c4c7c04935d22a8a36bc0eabdbfe5b85aafd (diff) | |
| download | poky-93b0d29184419318cda433bb0a764f8f2a7eeb6a.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)
(From OE-Core rev: a409c50a09b12caa434b2b06bdcfb6beba43f67f)
Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.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 8eaefd4fe0..09a74451d8 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 | " | 30 | " |
| 30 | 31 | ||
