Package: release.debian.org Severity: normal Tags: buster User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: car...@debian.org,j...@debian.org
Hi Stable release managers, libxml2 in buster (as in bullseye, cf #1007878) is affected by CVE-2022-23308, which can result in denial of service, or potentially though the execution of arbitrary code if a malformed xml file is processed. But given the near timeline for the point release, I'm proposing to upload the fix via the upcoming point release instead. I verified the fix agains the POC from https://gitlab.gnome.org/GNOME/libxml2/-/issues/327 . Full debdiff is attached. Regards, Salvatore
diff -Nru libxml2-2.9.4+dfsg1/debian/changelog libxml2-2.9.4+dfsg1/debian/changelog --- libxml2-2.9.4+dfsg1/debian/changelog 2021-06-11 18:57:11.000000000 +0200 +++ libxml2-2.9.4+dfsg1/debian/changelog 2022-03-17 22:04:26.000000000 +0100 @@ -1,3 +1,11 @@ +libxml2 (2.9.4+dfsg1-7+deb10u3) buster; urgency=medium + + * Non-maintainer upload. + * Use-after-free of ID and IDREF attributes (CVE-2022-23308) + (Closes: #1006489) + + -- Salvatore Bonaccorso <car...@debian.org> Thu, 17 Mar 2022 22:04:26 +0100 + libxml2 (2.9.4+dfsg1-7+deb10u2) buster; urgency=medium * Non-maintainer upload. diff -Nru libxml2-2.9.4+dfsg1/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch libxml2-2.9.4+dfsg1/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch --- libxml2-2.9.4+dfsg1/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch 1970-01-01 01:00:00.000000000 +0100 +++ libxml2-2.9.4+dfsg1/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch 2022-03-17 22:04:26.000000000 +0100 @@ -0,0 +1,195 @@ +From: Nick Wellnhofer <wellnho...@aevum.de> +Date: Tue, 8 Feb 2022 03:29:24 +0100 +Subject: [CVE-2022-23308] Use-after-free of ID and IDREF attributes +Origin: https://gitlab.gnome.org/GNOME/libxml2/-/commit/652dd12a858989b14eed4e84e453059cd3ba340e +Bug-Debian: https://bugs.debian.org/1006489 +Bug: https://gitlab.gnome.org/GNOME/libxml2/-/issues/327 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2022-23308 + +If a document is parsed with XML_PARSE_DTDVALID and without +XML_PARSE_NOENT, the value of ID attributes has to be normalized after +potentially expanding entities in xmlRemoveID. Otherwise, later calls +to xmlGetID can return a pointer to previously freed memory. + +ID attributes which are empty or contain only whitespace after +entity expansion are affected in a similar way. This is fixed by +not storing such attributes in the ID table. + +The test to detect streaming mode when validating against a DTD was +broken. In connection with the defects above, this could result in a +use-after-free when using the xmlReader interface with validation. +Fix detection of streaming mode to avoid similar issues. (This changes +the expected result of a test case. But as far as I can tell, using the +XML reader with XIncludes referencing the root document never worked +properly, anyway.) + +All of these issues can result in denial of service. Using xmlReader +with validation could result in disclosure of memory via the error +channel, typically stderr. The security impact of xmlGetID returning +a pointer to freed memory depends on the application. The typical use +case of calling xmlGetID on an unmodified document is not affected. +--- + result/XInclude/ns1.xml.rdr | 2 +- + valid.c | 88 +++++++++++++++++++++++-------------- + 2 files changed, 56 insertions(+), 34 deletions(-) + +--- a/valid.c ++++ b/valid.c +@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt) + return (ret); + } + ++/** ++ * xmlValidNormalizeString: ++ * @str: a string ++ * ++ * Normalize a string in-place. ++ */ ++static void ++xmlValidNormalizeString(xmlChar *str) { ++ xmlChar *dst; ++ const xmlChar *src; ++ ++ if (str == NULL) ++ return; ++ src = str; ++ dst = str; ++ ++ while (*src == 0x20) src++; ++ while (*src != 0) { ++ if (*src == 0x20) { ++ while (*src == 0x20) src++; ++ if (*src != 0) ++ *dst++ = 0x20; ++ } else { ++ *dst++ = *src++; ++ } ++ } ++ *dst = 0; ++} ++ + #ifdef DEBUG_VALID_ALGO + static void + xmlValidPrintNode(xmlNodePtr cur) { +@@ -2546,6 +2575,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, x + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + ++static int ++xmlIsStreaming(xmlValidCtxtPtr ctxt) { ++ xmlParserCtxtPtr pctxt; ++ ++ if (ctxt == NULL) ++ return(0); ++ /* ++ * These magic values are also abused to detect whether we're validating ++ * while parsing a document. In this case, userData points to the parser ++ * context. ++ */ ++ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) && ++ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1)) ++ return(0); ++ pctxt = ctxt->userData; ++ return(pctxt->parseMode == XML_PARSE_READER); ++} ++ + /** + * xmlFreeID: + * @not: A id +@@ -2589,7 +2636,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr + if (doc == NULL) { + return(NULL); + } +- if (value == NULL) { ++ if ((value == NULL) || (value[0] == 0)) { + return(NULL); + } + if (attr == NULL) { +@@ -2620,7 +2667,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr + */ + ret->value = xmlStrdup(value); + ret->doc = doc; +- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { ++ if (xmlIsStreaming(ctxt)) { + /* + * Operating in streaming mode, attr is gonna disapear + */ +@@ -2754,6 +2801,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr at + ID = xmlNodeListGetString(doc, attr->children, 1); + if (ID == NULL) + return(-1); ++ xmlValidNormalizeString(ID); + + id = xmlHashLookup(table, ID); + if (id == NULL || id->attr != attr) { +@@ -2942,7 +2990,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPt + * fill the structure. + */ + ret->value = xmlStrdup(value); +- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { ++ if (xmlIsStreaming(ctxt)) { + /* + * Operating in streaming mode, attr is gonna disapear + */ +@@ -3962,8 +4010,7 @@ xmlValidateAttributeValue2(xmlValidCtxtP + xmlChar * + xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { +- xmlChar *ret, *dst; +- const xmlChar *src; ++ xmlChar *ret; + xmlAttributePtr attrDecl = NULL; + int extsubset = 0; + +@@ -4004,19 +4051,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlV + ret = xmlStrdup(value); + if (ret == NULL) + return(NULL); +- src = value; +- dst = ret; +- while (*src == 0x20) src++; +- while (*src != 0) { +- if (*src == 0x20) { +- while (*src == 0x20) src++; +- if (*src != 0) +- *dst++ = 0x20; +- } else { +- *dst++ = *src++; +- } +- } +- *dst = 0; ++ xmlValidNormalizeString(ret); + if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE, + "standalone: %s on %s value had to be normalized based on external subset declaration\n", +@@ -4048,8 +4083,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlV + xmlChar * + xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, + const xmlChar *name, const xmlChar *value) { +- xmlChar *ret, *dst; +- const xmlChar *src; ++ xmlChar *ret; + xmlAttributePtr attrDecl = NULL; + + if (doc == NULL) return(NULL); +@@ -4079,19 +4113,7 @@ xmlValidNormalizeAttributeValue(xmlDocPt + ret = xmlStrdup(value); + if (ret == NULL) + return(NULL); +- src = value; +- dst = ret; +- while (*src == 0x20) src++; +- while (*src != 0) { +- if (*src == 0x20) { +- while (*src == 0x20) src++; +- if (*src != 0) +- *dst++ = 0x20; +- } else { +- *dst++ = *src++; +- } +- } +- *dst = 0; ++ xmlValidNormalizeString(ret); + return(ret); + } + diff -Nru libxml2-2.9.4+dfsg1/debian/patches/series libxml2-2.9.4+dfsg1/debian/patches/series --- libxml2-2.9.4+dfsg1/debian/patches/series 2021-06-11 18:57:11.000000000 +0200 +++ libxml2-2.9.4+dfsg1/debian/patches/series 2022-03-17 22:04:26.000000000 +0100 @@ -29,3 +29,4 @@ Fix-user-after-free-with-xmllint-xinclude-dropdtd.patch Propagate-error-in-xmlParseElementChildrenContentDec.patch Patch-for-security-issue-CVE-2021-3541.patch +CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch