Bug#1007878: bullseye-pu: package libxml2/2.9.10+dfsg-6.7+deb11u1
Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: carnil@debian.org,jmm@debian.org
Hi Stable release managers,
libxml2 in bullseye 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 think we could additionally benefit from
autopkgtest runs. So I'm proposing to upload the fix via the upcoming
point release.
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.10+dfsg/debian/changelog libxml2-2.9.10+dfsg/debian/changelog
--- libxml2-2.9.10+dfsg/debian/changelog 2021-05-22 08:21:29.000000000 +0200
+++ libxml2-2.9.10+dfsg/debian/changelog 2022-03-17 21:52:53.000000000 +0100
@@ -1,3 +1,11 @@
+libxml2 (2.9.10+dfsg-6.7+deb11u1) bullseye; urgency=medium
+
+ * Non-maintainer upload.
+ * Use-after-free of ID and IDREF attributes (CVE-2022-23308)
+ (Closes: #1006489)
+
+ -- Salvatore Bonaccorso <carnil@debian.org> Thu, 17 Mar 2022 21:52:53 +0100
+
libxml2 (2.9.10+dfsg-6.7) unstable; urgency=medium
* Non-maintainer upload.
diff -Nru libxml2-2.9.10+dfsg/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch libxml2-2.9.10+dfsg/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch
--- libxml2-2.9.10+dfsg/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.10+dfsg/debian/patches/CVE-2022-23308-Use-after-free-of-ID-and-IDREF-attrib.patch 2022-03-17 21:52:53.000000000 +0100
@@ -0,0 +1,195 @@
+From: Nick Wellnhofer <wellnhofer@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) {
+@@ -2607,6 +2636,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
+@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr
+ if (doc == NULL) {
+ return(NULL);
+ }
+- if (value == NULL) {
++ if ((value == NULL) || (value[0] == 0)) {
+ return(NULL);
+ }
+ if (attr == NULL) {
+@@ -2681,7 +2728,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 disappear
+ */
+@@ -2820,6 +2867,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) {
+@@ -3009,7 +3057,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 disappear
+ */
+@@ -4028,8 +4076,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;
+
+@@ -4070,19 +4117,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",
+@@ -4114,8 +4149,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);
+@@ -4145,19 +4179,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.10+dfsg/debian/patches/series libxml2-2.9.10+dfsg/debian/patches/series
--- libxml2-2.9.10+dfsg/debian/patches/series 2021-05-22 08:21:29.000000000 +0200
+++ libxml2-2.9.10+dfsg/debian/patches/series 2022-03-17 21:52:53.000000000 +0100
@@ -10,3 +10,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
Reply to: