Browse code

apply libxml2 patch for CVE-2016-5131

Change-Id: I7348878ca91c3d001dbf073780edff9eaa6af9b4
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/1596
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: suezzelur <anishs@vmware.com>

Priyesh Padmavilasom authored on 2016/10/28 11:27:25
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,171 @@
0
+From 9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e Mon Sep 17 00:00:00 2001
1
+From: Nick Wellnhofer <wellnhofer@aevum.de>
2
+Date: Tue, 28 Jun 2016 14:22:23 +0200
3
+Subject: Fix XPointer paths beginning with range-to
4
+
5
+The old code would invoke the broken xmlXPtrRangeToFunction. range-to
6
+isn't really a function but a special kind of location step. Remove
7
+this function and always handle range-to in the XPath code.
8
+
9
+The old xmlXPtrRangeToFunction could also be abused to trigger a
10
+use-after-free error with the potential for remote code execution.
11
+
12
+Found with afl-fuzz.
13
+
14
+Fixes CVE-2016-5131.
15
+---
16
+ result/XPath/xptr/vidbase | 13 ++++++++
17
+ test/XPath/xptr/vidbase   |  1 +
18
+ xpath.c                   |  7 ++++-
19
+ xpointer.c                | 76 ++++-------------------------------------------
20
+ 4 files changed, 26 insertions(+), 71 deletions(-)
21
+
22
+diff --git a/result/XPath/xptr/vidbase b/result/XPath/xptr/vidbase
23
+index 8b9e92d..f19193e 100644
24
+--- a/result/XPath/xptr/vidbase
25
+@@ -17,3 +17,16 @@ Object is a Location Set:
26
+   To node
27
+     ELEMENT p
28
+ 
29
++
30
++========================
31
++Expression: xpointer(range-to(id('chapter2')))
32
++Object is a Location Set:
33
++1 :   Object is a range :
34
++  From node
35
++     /
36
++  To node
37
++    ELEMENT chapter
38
++      ATTRIBUTE id
39
++        TEXT
40
++          content=chapter2
41
++
42
+diff --git a/test/XPath/xptr/vidbase b/test/XPath/xptr/vidbase
43
+index b146383..884b106 100644
44
+--- a/test/XPath/xptr/vidbase
45
+@@ -1,2 +1,3 @@
46
+ xpointer(id('chapter1')/p)
47
+ xpointer(id('chapter1')/p[1]/range-to(following-sibling::p[2]))
48
++xpointer(range-to(id('chapter2')))
49
+diff --git a/xpath.c b/xpath.c
50
+index d992841..5a01b1b 100644
51
+--- a/xpath.c
52
+@@ -10691,13 +10691,18 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
53
+ 		    lc = 1;
54
+ 		    break;
55
+ 		} else if ((NXT(len) == '(')) {
56
+-		    /* Note Type or Function */
57
++		    /* Node Type or Function */
58
+ 		    if (xmlXPathIsNodeType(name)) {
59
+ #ifdef DEBUG_STEP
60
+ 		        xmlGenericError(xmlGenericErrorContext,
61
+ 				"PathExpr: Type search\n");
62
+ #endif
63
+ 			lc = 1;
64
++#ifdef LIBXML_XPTR_ENABLED
65
++                    } else if (ctxt->xptr &&
66
++                               xmlStrEqual(name, BAD_CAST "range-to")) {
67
++                        lc = 1;
68
++#endif
69
+ 		    } else {
70
+ #ifdef DEBUG_STEP
71
+ 		        xmlGenericError(xmlGenericErrorContext,
72
+diff --git a/xpointer.c b/xpointer.c
73
+index 676c510..d74174a 100644
74
+--- a/xpointer.c
75
+@@ -1332,8 +1332,6 @@ xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
76
+     ret->here = here;
77
+     ret->origin = origin;
78
+ 
79
+-    xmlXPathRegisterFunc(ret, (xmlChar *)"range-to",
80
+-	                 xmlXPtrRangeToFunction);
81
+     xmlXPathRegisterFunc(ret, (xmlChar *)"range",
82
+ 	                 xmlXPtrRangeFunction);
83
+     xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
84
+@@ -2243,76 +2241,14 @@ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
85
+  * @nargs:  the number of args
86
+  *
87
+  * Implement the range-to() XPointer function
88
++ *
89
++ * Obsolete. range-to is not a real function but a special type of location
90
++ * step which is handled in xpath.c.
91
+  */
92
+ void
93
+-xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) {
94
+-    xmlXPathObjectPtr range;
95
+-    const xmlChar *cur;
96
+-    xmlXPathObjectPtr res, obj;
97
+-    xmlXPathObjectPtr tmp;
98
+-    xmlLocationSetPtr newset = NULL;
99
+-    xmlNodeSetPtr oldset;
100
+-    int i;
101
+-
102
+-    if (ctxt == NULL) return;
103
+-    CHECK_ARITY(1);
104
+-    /*
105
+-     * Save the expression pointer since we will have to evaluate
106
+-     * it multiple times. Initialize the new set.
107
+-     */
108
+-    CHECK_TYPE(XPATH_NODESET);
109
+-    obj = valuePop(ctxt);
110
+-    oldset = obj->nodesetval;
111
+-    ctxt->context->node = NULL;
112
+-
113
+-    cur = ctxt->cur;
114
+-    newset = xmlXPtrLocationSetCreate(NULL);
115
+-
116
+-    for (i = 0; i < oldset->nodeNr; i++) {
117
+-	ctxt->cur = cur;
118
+-
119
+-	/*
120
+-	 * Run the evaluation with a node list made of a single item
121
+-	 * in the nodeset.
122
+-	 */
123
+-	ctxt->context->node = oldset->nodeTab[i];
124
+-	tmp = xmlXPathNewNodeSet(ctxt->context->node);
125
+-	valuePush(ctxt, tmp);
126
+-
127
+-	xmlXPathEvalExpr(ctxt);
128
+-	CHECK_ERROR;
129
+-
130
+-	/*
131
+-	 * The result of the evaluation need to be tested to
132
+-	 * decided whether the filter succeeded or not
133
+-	 */
134
+-	res = valuePop(ctxt);
135
+-	range = xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], res);
136
+-	if (range != NULL) {
137
+-	    xmlXPtrLocationSetAdd(newset, range);
138
+-	}
139
+-
140
+-	/*
141
+-	 * Cleanup
142
+-	 */
143
+-	if (res != NULL)
144
+-	    xmlXPathFreeObject(res);
145
+-	if (ctxt->value == tmp) {
146
+-	    res = valuePop(ctxt);
147
+-	    xmlXPathFreeObject(res);
148
+-	}
149
+-
150
+-	ctxt->context->node = NULL;
151
+-    }
152
+-
153
+-    /*
154
+-     * The result is used as the new evaluation set.
155
+-     */
156
+-    xmlXPathFreeObject(obj);
157
+-    ctxt->context->node = NULL;
158
+-    ctxt->context->contextSize = -1;
159
+-    ctxt->context->proximityPosition = -1;
160
+-    valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
161
++xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
162
++                       int nargs ATTRIBUTE_UNUSED) {
163
++    XP_ERROR(XPATH_EXPR_ERROR);
164
+ }
165
+ 
166
+ /**
0 167
new file mode 100644
... ...
@@ -0,0 +1,172 @@
0
+From d77e5fc4bcdb7da748c9cca116a601ae4df60d21
1
+To a005199330b86dada19d162cae15ef9bdcb6baa8
2
+Bring upstream patches to support CVE-2016-5131 fix
3
+as one of the tests failed with just applying the CVE fix.
4
+
5
+diff --git a/relaxng.c b/relaxng.c
6
+index 56a3344..3d3e69c 100644
7
+--- a/relaxng.c
8
+@@ -2088,6 +2088,7 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
9
+                          const xmlChar * arg2)
10
+ {
11
+     char msg[1000];
12
++    xmlChar *result;
13
+ 
14
+     if (arg1 == NULL)
15
+         arg1 = BAD_CAST "";
16
+@@ -2215,7 +2216,7 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
17
+         snprintf(msg, 1000, "Unknown error code %d\n", err);
18
+     }
19
+     msg[1000 - 1] = 0;
20
+-    xmlChar *result = xmlCharStrdup(msg);
21
++    result = xmlCharStrdup(msg);
22
+     return (xmlEscapeFormatString(&result));
23
+ }
24
+ 
25
+diff --git a/result/XPath/xptr/viderror b/result/XPath/xptr/viderror
26
+new file mode 100644
27
+index 0000000..d589882
28
+--- /dev/null
29
+@@ -0,0 +1,4 @@
30
++
31
++========================
32
++Expression: xpointer(non-existing-fn()/range-to(id('chapter2')))
33
++Object is empty (NULL)
34
+diff --git a/runtest.c b/runtest.c
35
+index bb74d2a..1861577 100644
36
+--- a/runtest.c
37
+@@ -2317,10 +2317,19 @@ static FILE *xpathOutput;
38
+ static xmlDocPtr xpathDocument;
39
+ 
40
+ static void
41
++ignoreGenericError(void *ctx ATTRIBUTE_UNUSED,
42
++        const char *msg ATTRIBUTE_UNUSED, ...) {
43
++}
44
++
45
++static void
46
+ testXPath(const char *str, int xptr, int expr) {
47
++    xmlGenericErrorFunc handler = ignoreGenericError;
48
+     xmlXPathObjectPtr res;
49
+     xmlXPathContextPtr ctxt;
50
+ 
51
++    /* Don't print generic errors to stderr. */
52
++    initGenericErrorDefaultFunc(&handler);
53
++
54
+     nb_tests++;
55
+ #if defined(LIBXML_XPTR_ENABLED)
56
+     if (xptr) {
57
+@@ -2349,6 +2358,9 @@ testXPath(const char *str, int xptr, int expr) {
58
+     xmlXPathDebugDumpObject(xpathOutput, res, 0);
59
+     xmlXPathFreeObject(res);
60
+     xmlXPathFreeContext(ctxt);
61
++
62
++    /* Reset generic error handler. */
63
++    initGenericErrorDefaultFunc(NULL);
64
+ }
65
+ 
66
+ /**
67
+diff --git a/test/XPath/xptr/viderror b/test/XPath/xptr/viderror
68
+new file mode 100644
69
+index 0000000..da8c53b
70
+--- /dev/null
71
+@@ -0,0 +1 @@
72
++xpointer(non-existing-fn()/range-to(id('chapter2')))
73
+diff --git a/xmlschemas.c b/xmlschemas.c
74
+index e1b3a4f..d42afb7 100644
75
+--- a/xmlschemas.c
76
+@@ -3168,8 +3168,8 @@ xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
77
+ 		"valid.");
78
+ 	}
79
+ 	if (expected) {
80
+-	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
81
+ 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
82
++	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
83
+ 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
84
+ 	    FREE_AND_NULL(expectedEscaped);
85
+ 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
86
+@@ -27391,6 +27391,7 @@ xmlSchemaSAXHandleStartElementNs(void *ctx,
87
+     * attributes yet.
88
+     */
89
+     if (nb_attributes != 0) {
90
++	int valueLen, k, l;
91
+ 	xmlChar *value;
92
+ 
93
+         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
94
+@@ -27400,12 +27401,31 @@ xmlSchemaSAXHandleStartElementNs(void *ctx,
95
+ 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
96
+ 	    * as &#38; instead of delivering the raw converted string. Changing the
97
+ 	    * behavior at this point would break applications that use this API, so
98
+-	    * we are forced to work around it. There is no danger of accidentally
99
+-	    * decoding some entity other than &#38; in this step because without
100
+-	    * unescaped ampersands there can be no other entities in the string.
101
++	    * we are forced to work around it.
102
+ 	    */
103
+-	    value = xmlStringLenDecodeEntities(vctxt->parserCtxt, attributes[j+3],
104
+-		attributes[j+4] - attributes[j+3], XML_SUBSTITUTE_REF, 0, 0, 0);
105
++	    valueLen = attributes[j+4] - attributes[j+3];
106
++	    value = xmlMallocAtomic(valueLen + 1);
107
++	    if (value == NULL) {
108
++		xmlSchemaVErrMemory(vctxt,
109
++		    "allocating string for decoded attribute",
110
++		    NULL);
111
++		goto internal_error;
112
++	    }
113
++	    for (k = 0, l = 0; k < valueLen; l++) {
114
++		if (k < valueLen - 4 &&
115
++		    attributes[j+3][k+0] == '&' &&
116
++		    attributes[j+3][k+1] == '#' &&
117
++		    attributes[j+3][k+2] == '3' &&
118
++		    attributes[j+3][k+3] == '8' &&
119
++		    attributes[j+3][k+4] == ';') {
120
++		    value[l] = '&';
121
++		    k += 5;
122
++		} else {
123
++		    value[l] = attributes[j+3][k];
124
++		    k++;
125
++		}
126
++	    }
127
++	    value[l] = '\0';
128
+ 	    /*
129
+ 	    * TODO: Set the node line.
130
+ 	    */
131
+diff --git a/xpath.c b/xpath.c
132
+index 113bce6..d992841 100644
133
+--- a/xpath.c
134
+@@ -3342,13 +3342,13 @@ xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
135
+      * compute depth to root
136
+      */
137
+     for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
138
+-	if (cur == node1)
139
++	if (cur->parent == node1)
140
+ 	    return(1);
141
+ 	depth2++;
142
+     }
143
+     root = cur;
144
+     for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
145
+-	if (cur == node2)
146
++	if (cur->parent == node2)
147
+ 	    return(-1);
148
+ 	depth1++;
149
+     }
150
+@@ -14005,9 +14005,14 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
151
+                 xmlNodeSetPtr oldset;
152
+                 int i, j;
153
+ 
154
+-                if (op->ch1 != -1)
155
++                if (op->ch1 != -1) {
156
+                     total +=
157
+                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
158
++                    CHECK_ERROR0;
159
++                }
160
++                if (ctxt->value == NULL) {
161
++                    XP_ERROR0(XPATH_INVALID_OPERAND);
162
++                }
163
+                 if (op->ch2 == -1)
164
+                     return (total);
165
+ 
... ...
@@ -1,13 +1,15 @@
1 1
 Summary:	Libxml2
2 2
 Name:		libxml2
3 3
 Version:	2.9.4
4
-Release:	2%{?dist}
4
+Release:	3%{?dist}
5 5
 License:	MIT
6 6
 URL:		http://xmlsoft.org/
7 7
 Group:		System Environment/General Libraries
8 8
 Vendor:		VMware, Inc.
9 9
 Distribution: 	Photon
10 10
 Source0:	ftp://xmlsoft.org/libxml2/%{name}-%{version}.tar.gz
11
+Patch0:         libxml2-2.9.4-support-cve-2016-5131.patch
12
+Patch1:         libxml2-2.9.4-cve-2016-5131.patch
11 13
 %define sha1 libxml2=958ae70baf186263a4bd801a81dd5d682aedd1db
12 14
 Requires:	python2
13 15
 BuildRequires:	python2-devel
... ...
@@ -37,6 +39,8 @@ Static libraries and header files for the support library for libxml
37 37
 
38 38
 %prep
39 39
 %setup -q
40
+%patch0 -p1
41
+%patch1 -p1
40 42
 sed \
41 43
   -e /xmlInitializeCatalog/d \
42 44
   -e 's/((ent->checked =.*&&/(((ent->checked == 0) ||\
... ...
@@ -86,6 +90,8 @@ rm -rf %{buildroot}/*
86 86
 
87 87
 
88 88
 %changelog
89
+*	Thu Oct 20 2016 Priyesh Padmavilasom <ppadmavilasom@vmware.com> 2.9.4-3
90
+-	Apply patch for CVE-2016-5131
89 91
 *       Mon Oct 03 2016 Chang Lee <changlee@vmware.com> 2.9.4-2
90 92
 -       Modified check
91 93
 *       Wed Jun 01 2016 Anish Swaminathan <anishs@vmware.com> 2.9.4-1