diff options
Diffstat (limited to 'meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch')
-rw-r--r-- | meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch new file mode 100644 index 0000000000..bf5604e81a --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch | |||
@@ -0,0 +1,204 @@ | |||
1 | From 8b66850de350f0fcd786ae776a65ba15a5999e50 Mon Sep 17 00:00:00 2001 | ||
2 | From: Nick Wellnhofer <wellnhofer@aevum.de> | ||
3 | Date: Tue, 8 Feb 2022 03:29:24 +0100 | ||
4 | Subject: [PATCH] Use-after-free of ID and IDREF attributes | ||
5 | |||
6 | If a document is parsed with XML_PARSE_DTDVALID and without | ||
7 | XML_PARSE_NOENT, the value of ID attributes has to be normalized after | ||
8 | potentially expanding entities in xmlRemoveID. Otherwise, later calls | ||
9 | to xmlGetID can return a pointer to previously freed memory. | ||
10 | |||
11 | ID attributes which are empty or contain only whitespace after | ||
12 | entity expansion are affected in a similar way. This is fixed by | ||
13 | not storing such attributes in the ID table. | ||
14 | |||
15 | The test to detect streaming mode when validating against a DTD was | ||
16 | broken. In connection with the defects above, this could result in a | ||
17 | use-after-free when using the xmlReader interface with validation. | ||
18 | Fix detection of streaming mode to avoid similar issues. (This changes | ||
19 | the expected result of a test case. But as far as I can tell, using the | ||
20 | XML reader with XIncludes referencing the root document never worked | ||
21 | properly, anyway.) | ||
22 | |||
23 | All of these issues can result in denial of service. Using xmlReader | ||
24 | with validation could result in disclosure of memory via the error | ||
25 | channel, typically stderr. The security impact of xmlGetID returning | ||
26 | a pointer to freed memory depends on the application. The typical use | ||
27 | case of calling xmlGetID on an unmodified document is not affected. | ||
28 | |||
29 | Upstream-Status: Backport | ||
30 | [https://gitlab.gnome.org/GNOME/libxml2/-/commit/652dd12a858989b14eed4e84e453059cd3ba340e] | ||
31 | |||
32 | The upstream patch 652dd12a858989b14eed4e84e453059cd3ba340e has been modified | ||
33 | to skip the patch to the testsuite result (result/XInclude/ns1.xml.rdr), as | ||
34 | this particular test does not exist in v2.9.10 (it was added later). | ||
35 | |||
36 | CVE: CVE-2022-23308 | ||
37 | Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org> | ||
38 | |||
39 | --- | ||
40 | valid.c | 88 +++++++++++++++++++++++++++++++++++---------------------- | ||
41 | 1 file changed, 55 insertions(+), 33 deletions(-) | ||
42 | |||
43 | diff --git a/valid.c b/valid.c | ||
44 | index 07963e7..ee75311 100644 | ||
45 | --- a/valid.c | ||
46 | +++ b/valid.c | ||
47 | @@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt) | ||
48 | return (ret); | ||
49 | } | ||
50 | |||
51 | +/** | ||
52 | + * xmlValidNormalizeString: | ||
53 | + * @str: a string | ||
54 | + * | ||
55 | + * Normalize a string in-place. | ||
56 | + */ | ||
57 | +static void | ||
58 | +xmlValidNormalizeString(xmlChar *str) { | ||
59 | + xmlChar *dst; | ||
60 | + const xmlChar *src; | ||
61 | + | ||
62 | + if (str == NULL) | ||
63 | + return; | ||
64 | + src = str; | ||
65 | + dst = str; | ||
66 | + | ||
67 | + while (*src == 0x20) src++; | ||
68 | + while (*src != 0) { | ||
69 | + if (*src == 0x20) { | ||
70 | + while (*src == 0x20) src++; | ||
71 | + if (*src != 0) | ||
72 | + *dst++ = 0x20; | ||
73 | + } else { | ||
74 | + *dst++ = *src++; | ||
75 | + } | ||
76 | + } | ||
77 | + *dst = 0; | ||
78 | +} | ||
79 | + | ||
80 | #ifdef DEBUG_VALID_ALGO | ||
81 | static void | ||
82 | xmlValidPrintNode(xmlNodePtr cur) { | ||
83 | @@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { | ||
84 | (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ | ||
85 | xmlFree((char *)(str)); | ||
86 | |||
87 | +static int | ||
88 | +xmlIsStreaming(xmlValidCtxtPtr ctxt) { | ||
89 | + xmlParserCtxtPtr pctxt; | ||
90 | + | ||
91 | + if (ctxt == NULL) | ||
92 | + return(0); | ||
93 | + /* | ||
94 | + * These magic values are also abused to detect whether we're validating | ||
95 | + * while parsing a document. In this case, userData points to the parser | ||
96 | + * context. | ||
97 | + */ | ||
98 | + if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) && | ||
99 | + (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1)) | ||
100 | + return(0); | ||
101 | + pctxt = ctxt->userData; | ||
102 | + return(pctxt->parseMode == XML_PARSE_READER); | ||
103 | +} | ||
104 | + | ||
105 | /** | ||
106 | * xmlFreeID: | ||
107 | * @not: A id | ||
108 | @@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, | ||
109 | if (doc == NULL) { | ||
110 | return(NULL); | ||
111 | } | ||
112 | - if (value == NULL) { | ||
113 | + if ((value == NULL) || (value[0] == 0)) { | ||
114 | return(NULL); | ||
115 | } | ||
116 | if (attr == NULL) { | ||
117 | @@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, | ||
118 | */ | ||
119 | ret->value = xmlStrdup(value); | ||
120 | ret->doc = doc; | ||
121 | - if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { | ||
122 | + if (xmlIsStreaming(ctxt)) { | ||
123 | /* | ||
124 | * Operating in streaming mode, attr is gonna disappear | ||
125 | */ | ||
126 | @@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { | ||
127 | ID = xmlNodeListGetString(doc, attr->children, 1); | ||
128 | if (ID == NULL) | ||
129 | return(-1); | ||
130 | + xmlValidNormalizeString(ID); | ||
131 | |||
132 | id = xmlHashLookup(table, ID); | ||
133 | if (id == NULL || id->attr != attr) { | ||
134 | @@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, | ||
135 | * fill the structure. | ||
136 | */ | ||
137 | ret->value = xmlStrdup(value); | ||
138 | - if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { | ||
139 | + if (xmlIsStreaming(ctxt)) { | ||
140 | /* | ||
141 | * Operating in streaming mode, attr is gonna disappear | ||
142 | */ | ||
143 | @@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
144 | xmlChar * | ||
145 | xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
146 | xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { | ||
147 | - xmlChar *ret, *dst; | ||
148 | - const xmlChar *src; | ||
149 | + xmlChar *ret; | ||
150 | xmlAttributePtr attrDecl = NULL; | ||
151 | int extsubset = 0; | ||
152 | |||
153 | @@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
154 | ret = xmlStrdup(value); | ||
155 | if (ret == NULL) | ||
156 | return(NULL); | ||
157 | - src = value; | ||
158 | - dst = ret; | ||
159 | - while (*src == 0x20) src++; | ||
160 | - while (*src != 0) { | ||
161 | - if (*src == 0x20) { | ||
162 | - while (*src == 0x20) src++; | ||
163 | - if (*src != 0) | ||
164 | - *dst++ = 0x20; | ||
165 | - } else { | ||
166 | - *dst++ = *src++; | ||
167 | - } | ||
168 | - } | ||
169 | - *dst = 0; | ||
170 | + xmlValidNormalizeString(ret); | ||
171 | if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) { | ||
172 | xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE, | ||
173 | "standalone: %s on %s value had to be normalized based on external subset declaration\n", | ||
174 | @@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, | ||
175 | xmlChar * | ||
176 | xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, | ||
177 | const xmlChar *name, const xmlChar *value) { | ||
178 | - xmlChar *ret, *dst; | ||
179 | - const xmlChar *src; | ||
180 | + xmlChar *ret; | ||
181 | xmlAttributePtr attrDecl = NULL; | ||
182 | |||
183 | if (doc == NULL) return(NULL); | ||
184 | @@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, | ||
185 | ret = xmlStrdup(value); | ||
186 | if (ret == NULL) | ||
187 | return(NULL); | ||
188 | - src = value; | ||
189 | - dst = ret; | ||
190 | - while (*src == 0x20) src++; | ||
191 | - while (*src != 0) { | ||
192 | - if (*src == 0x20) { | ||
193 | - while (*src == 0x20) src++; | ||
194 | - if (*src != 0) | ||
195 | - *dst++ = 0x20; | ||
196 | - } else { | ||
197 | - *dst++ = *src++; | ||
198 | - } | ||
199 | - } | ||
200 | - *dst = 0; | ||
201 | + xmlValidNormalizeString(ret); | ||
202 | return(ret); | ||
203 | } | ||
204 | |||