* [scarthgap][PATCH] libxml2: fix CVE-2025-49795
@ 2025-07-11 9:15 roland.kovacs
2025-07-16 15:04 ` [OE-core] " Steve Sakoman
0 siblings, 1 reply; 3+ messages in thread
From: roland.kovacs @ 2025-07-11 9:15 UTC (permalink / raw)
To: openembedded-core; +Cc: Roland Kovacs
From: Roland Kovacs <roland.kovacs@est.tech>
A NULL pointer dereference vulnerability was found in libxml2 when processing
XPath XML expressions. This flaw allows an attacker to craft a malicious XML
input to libxml2, leading to a denial of service.
Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
---
.../libxml/libxml2/CVE-2025-49795.patch | 238 ++++++++++++++++++
meta/recipes-core/libxml/libxml2_2.12.10.bb | 1 +
2 files changed, 239 insertions(+)
create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
new file mode 100644
index 0000000000..fd784ea45b
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
@@ -0,0 +1,238 @@
+From 68ce19940f8e08c85f9c8ce65180cdb90bf4b0d2 Mon Sep 17 00:00:00 2001
+From: Michael Mann <mmann78@netscape.net>
+Date: Sat, 21 Jun 2025 12:11:30 -0400
+Subject: [PATCH] Schematron: Fix null pointer dereference leading to DoS
+
+(CVE-2025-49795)
+
+Fixes #932
+
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667]
+CVE: CVE-2025-49795
+
+(cherry picked from commit c24909ba2601848825b49a60f988222da3019667)
+Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
+---
+ result/schematron/zvon16_0.err | 3 +
+ runtest.c | 139 +++++++++++++++++++++++++++++++++
+ schematron.c | 5 ++
+ test/schematron/zvon16.sct | 7 ++
+ test/schematron/zvon16_0.xml | 5 ++
+ 5 files changed, 159 insertions(+)
+ create mode 100644 result/schematron/zvon16_0.err
+ create mode 100644 test/schematron/zvon16.sct
+ create mode 100644 test/schematron/zvon16_0.xml
+
+diff --git a/result/schematron/zvon16_0.err b/result/schematron/zvon16_0.err
+new file mode 100644
+index 00000000..3d052409
+--- /dev/null
++++ b/result/schematron/zvon16_0.err
+@@ -0,0 +1,3 @@
++XPath error : Unregistered function
++./test/schematron/zvon16_0.xml:2: element book: schematron error : /library/book line 2: Book
++./test/schematron/zvon16_0.xml fails to validate
+diff --git a/runtest.c b/runtest.c
+index c78eec81..736cae5e 100644
+--- a/runtest.c
++++ b/runtest.c
+@@ -52,6 +52,10 @@
+ #include <libxml/xmlschemastypes.h>
+ #endif
+
++#ifdef LIBXML_SCHEMATRON_ENABLED
++#include <libxml/schematron.h>
++#endif
++
+ #ifdef LIBXML_PATTERN_ENABLED
+ #include <libxml/pattern.h>
+ #endif
+@@ -3881,6 +3885,136 @@ rngStreamTest(const char *filename,
+
+ #endif
+
++/************************************************************************
++ * *
++ * Schematron tests *
++ * *
++ ************************************************************************/
++
++#ifdef LIBXML_SCHEMATRON_ENABLED
++static int
++schematronOneTest(const char *sch, const char *filename, int options,
++ xmlSchematronPtr schematron) {
++ xmlDocPtr doc;
++ xmlSchematronValidCtxtPtr ctxt;
++ int ret;
++
++ doc = xmlReadFile(filename, NULL, options);
++ if (doc == NULL) {
++ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
++ return(-1);
++ }
++
++ ctxt = xmlSchematronNewValidCtxt(schematron, XML_SCHEMATRON_OUT_ERROR);
++ xmlSchematronSetValidStructuredErrors(ctxt, testStructuredErrorHandler,
++ NULL);
++ ret = xmlSchematronValidateDoc(ctxt, doc);
++ if (ret == 0) {
++ testErrorHandler(NULL, "%s validates\n", filename);
++ } else if (ret > 0) {
++ testErrorHandler(NULL, "%s fails to validate\n", filename);
++ } else {
++ testErrorHandler(NULL, "%s validation generated an internal error\n",
++ filename);
++ }
++
++ xmlSchematronFreeValidCtxt(ctxt);
++ xmlFreeDoc(doc);
++ return(0);
++}
++
++/**
++ * schematronTest:
++ * @filename: the schemas file
++ * @result: the file with expected result
++ * @err: the file with error messages
++ *
++ * Returns 0 in case of success, an error code otherwise
++ */
++static int
++schematronTest(const char *filename,
++ const char *resul ATTRIBUTE_UNUSED,
++ const char *errr ATTRIBUTE_UNUSED,
++ int options) {
++ const char *base = baseFilename(filename);
++ const char *base2;
++ const char *instance;
++ xmlSchematronParserCtxtPtr pctxt;
++ xmlSchematronPtr schematron;
++ int res = 0, len, ret = 0;
++ int parseErrorsSize;
++ char pattern[500];
++ char prefix[500];
++ char err[500];
++ glob_t globbuf;
++ size_t i;
++ char count = 0;
++
++ /* Redirect XPath errors */
++ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
++
++ pctxt = xmlSchematronNewParserCtxt(filename);
++ schematron = xmlSchematronParse(pctxt);
++ xmlSchematronFreeParserCtxt(pctxt);
++ if (schematron == NULL)
++ testErrorHandler(NULL, "Schematron schema %s failed to compile\n",
++ filename);
++ parseErrorsSize = testErrorsSize;
++
++ /*
++ * most of the mess is about the output filenames generated by the Makefile
++ */
++ len = strlen(base);
++ if ((len > 499) || (len < 5)) {
++ ret = -1;
++ goto done;
++ }
++ len -= 4; /* remove trailing .sct */
++ memcpy(prefix, base, len);
++ prefix[len] = 0;
++
++ if (snprintf(pattern, 499, "./test/schematron/%s_?.xml", prefix) >= 499)
++ pattern[499] = 0;
++
++ globbuf.gl_offs = 0;
++ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
++ for (i = 0;i < globbuf.gl_pathc;i++) {
++ testErrorsSize = parseErrorsSize;
++ testErrors[parseErrorsSize] = 0;
++ instance = globbuf.gl_pathv[i];
++ base2 = baseFilename(instance);
++ len = strlen(base2);
++ if ((len > 6) && (base2[len - 6] == '_')) {
++ count = base2[len - 5];
++ res = snprintf(err, 499, "result/schematron/%s_%c.err",
++ prefix, count);
++ if (res >= 499)
++ err[499] = 0;
++ } else {
++ fprintf(stderr, "don't know how to process %s\n", instance);
++ continue;
++ }
++ if (schematron != NULL) {
++ nb_tests++;
++ res = schematronOneTest(filename, instance, options, schematron);
++ if (res != 0)
++ ret = res;
++ }
++ if (compareFileMem(err, testErrors, testErrorsSize)) {
++ fprintf(stderr, "Error for %s on %s failed\n", instance,
++ filename);
++ ret = 1;
++ }
++ }
++ globfree(&globbuf);
++
++done:
++ xmlSchematronFree(schematron);
++ xmlSetStructuredErrorFunc(NULL, NULL);
++ return(ret);
++}
++#endif /* LIBXML_SCHEMATRON_ENABLED */
++
+ #ifdef LIBXML_PATTERN_ENABLED
+ #ifdef LIBXML_READER_ENABLED
+ /************************************************************************
+@@ -5117,6 +5251,11 @@ testDesc testDescriptions[] = {
+ rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
+ XML_PARSE_DTDATTR | XML_PARSE_NOENT },
+ #endif
++#if defined(LIBXML_SCHEMATRON_ENABLED)
++ { "Schematron regression tests" ,
++ schematronTest, "./test/schematron/*.sct", NULL, NULL, NULL,
++ 0 },
++#endif
+ #endif
+ #ifdef LIBXML_PATTERN_ENABLED
+ #ifdef LIBXML_READER_ENABLED
+diff --git a/schematron.c b/schematron.c
+index 411a515c..c970d31f 100644
+--- a/schematron.c
++++ b/schematron.c
+@@ -1484,6 +1484,11 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
+ select = xmlGetNoNsProp(child, BAD_CAST "select");
+ comp = xmlXPathCtxtCompile(ctxt->xctxt, select);
+ eval = xmlXPathCompiledEval(comp, ctxt->xctxt);
++ if (eval == NULL) {
++ xmlXPathFreeCompExpr(comp);
++ xmlFree(select);
++ return ret;
++ }
+
+ switch (eval->type) {
+ case XPATH_NODESET: {
+diff --git a/test/schematron/zvon16.sct b/test/schematron/zvon16.sct
+new file mode 100644
+index 00000000..f03848aa
+--- /dev/null
++++ b/test/schematron/zvon16.sct
+@@ -0,0 +1,7 @@
++<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
++ <sch:pattern id="TestPattern">
++ <sch:rule context="book">
++ <sch:report test="not(@available)">Book <sch:value-of select="falae()"/> test</sch:report>
++ </sch:rule>
++ </sch:pattern>
++</sch:schema>
+diff --git a/test/schematron/zvon16_0.xml b/test/schematron/zvon16_0.xml
+new file mode 100644
+index 00000000..551e2d65
+--- /dev/null
++++ b/test/schematron/zvon16_0.xml
+@@ -0,0 +1,5 @@
++<library>
++ <book title="Test Book" id="bk101">
++ <author>Test Author</author>
++ </book>
++</library>
diff --git a/meta/recipes-core/libxml/libxml2_2.12.10.bb b/meta/recipes-core/libxml/libxml2_2.12.10.bb
index 2eea65732b..ea40ca68ed 100644
--- a/meta/recipes-core/libxml/libxml2_2.12.10.bb
+++ b/meta/recipes-core/libxml/libxml2_2.12.10.bb
@@ -20,6 +20,7 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt
file://install-tests.patch \
file://CVE-2025-32414.patch \
file://CVE-2025-32415.patch \
+ file://CVE-2025-49795.patch \
"
SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [OE-core] [scarthgap][PATCH] libxml2: fix CVE-2025-49795
2025-07-11 9:15 [scarthgap][PATCH] libxml2: fix CVE-2025-49795 roland.kovacs
@ 2025-07-16 15:04 ` Steve Sakoman
2025-07-17 7:04 ` Roland Kovács
0 siblings, 1 reply; 3+ messages in thread
From: Steve Sakoman @ 2025-07-16 15:04 UTC (permalink / raw)
To: roland.kovacs; +Cc: openembedded-core
I'm getting ptest failures with this patch:
WARNING: core-image-ptest-libxml2-1.0-r0 do_testimage: There were
failing ptests.
Traceback (most recent call last):
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
line 35, in wrapped_f
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
line 35, in wrapped_f
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
line 35, in wrapped_f
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py",
line 27, in test_ptestrunner_expectfail
self.do_ptestrunner()
File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py",
line 120, in do_ptestrunner
self.fail(failmsg)
AssertionError:
Failed ptests:
{'libxml2': ['runtest']}
I'm seeing it on both x86-64 and arm64:
https://autobuilder.yoctoproject.org/valkyrie/?#/builders/73/builds/1900/steps/12/logs/stdio
https://autobuilder.yoctoproject.org/valkyrie/?#/builders/61/builds/1897/steps/12/logs/stdio
I do not see the same issue with the walnascar version of the patch,
so perhaps that is a clue that will aid your debugging.
Steve
On Fri, Jul 11, 2025 at 2:15 AM roland.kovacs via
lists.openembedded.org <roland.kovacs=est.tech@lists.openembedded.org>
wrote:
>
> From: Roland Kovacs <roland.kovacs@est.tech>
>
> A NULL pointer dereference vulnerability was found in libxml2 when processing
> XPath XML expressions. This flaw allows an attacker to craft a malicious XML
> input to libxml2, leading to a denial of service.
>
> Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
> ---
> .../libxml/libxml2/CVE-2025-49795.patch | 238 ++++++++++++++++++
> meta/recipes-core/libxml/libxml2_2.12.10.bb | 1 +
> 2 files changed, 239 insertions(+)
> create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
>
> diff --git a/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
> new file mode 100644
> index 0000000000..fd784ea45b
> --- /dev/null
> +++ b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
> @@ -0,0 +1,238 @@
> +From 68ce19940f8e08c85f9c8ce65180cdb90bf4b0d2 Mon Sep 17 00:00:00 2001
> +From: Michael Mann <mmann78@netscape.net>
> +Date: Sat, 21 Jun 2025 12:11:30 -0400
> +Subject: [PATCH] Schematron: Fix null pointer dereference leading to DoS
> +
> +(CVE-2025-49795)
> +
> +Fixes #932
> +
> +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667]
> +CVE: CVE-2025-49795
> +
> +(cherry picked from commit c24909ba2601848825b49a60f988222da3019667)
> +Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
> +---
> + result/schematron/zvon16_0.err | 3 +
> + runtest.c | 139 +++++++++++++++++++++++++++++++++
> + schematron.c | 5 ++
> + test/schematron/zvon16.sct | 7 ++
> + test/schematron/zvon16_0.xml | 5 ++
> + 5 files changed, 159 insertions(+)
> + create mode 100644 result/schematron/zvon16_0.err
> + create mode 100644 test/schematron/zvon16.sct
> + create mode 100644 test/schematron/zvon16_0.xml
> +
> +diff --git a/result/schematron/zvon16_0.err b/result/schematron/zvon16_0.err
> +new file mode 100644
> +index 00000000..3d052409
> +--- /dev/null
> ++++ b/result/schematron/zvon16_0.err
> +@@ -0,0 +1,3 @@
> ++XPath error : Unregistered function
> ++./test/schematron/zvon16_0.xml:2: element book: schematron error : /library/book line 2: Book
> ++./test/schematron/zvon16_0.xml fails to validate
> +diff --git a/runtest.c b/runtest.c
> +index c78eec81..736cae5e 100644
> +--- a/runtest.c
> ++++ b/runtest.c
> +@@ -52,6 +52,10 @@
> + #include <libxml/xmlschemastypes.h>
> + #endif
> +
> ++#ifdef LIBXML_SCHEMATRON_ENABLED
> ++#include <libxml/schematron.h>
> ++#endif
> ++
> + #ifdef LIBXML_PATTERN_ENABLED
> + #include <libxml/pattern.h>
> + #endif
> +@@ -3881,6 +3885,136 @@ rngStreamTest(const char *filename,
> +
> + #endif
> +
> ++/************************************************************************
> ++ * *
> ++ * Schematron tests *
> ++ * *
> ++ ************************************************************************/
> ++
> ++#ifdef LIBXML_SCHEMATRON_ENABLED
> ++static int
> ++schematronOneTest(const char *sch, const char *filename, int options,
> ++ xmlSchematronPtr schematron) {
> ++ xmlDocPtr doc;
> ++ xmlSchematronValidCtxtPtr ctxt;
> ++ int ret;
> ++
> ++ doc = xmlReadFile(filename, NULL, options);
> ++ if (doc == NULL) {
> ++ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
> ++ return(-1);
> ++ }
> ++
> ++ ctxt = xmlSchematronNewValidCtxt(schematron, XML_SCHEMATRON_OUT_ERROR);
> ++ xmlSchematronSetValidStructuredErrors(ctxt, testStructuredErrorHandler,
> ++ NULL);
> ++ ret = xmlSchematronValidateDoc(ctxt, doc);
> ++ if (ret == 0) {
> ++ testErrorHandler(NULL, "%s validates\n", filename);
> ++ } else if (ret > 0) {
> ++ testErrorHandler(NULL, "%s fails to validate\n", filename);
> ++ } else {
> ++ testErrorHandler(NULL, "%s validation generated an internal error\n",
> ++ filename);
> ++ }
> ++
> ++ xmlSchematronFreeValidCtxt(ctxt);
> ++ xmlFreeDoc(doc);
> ++ return(0);
> ++}
> ++
> ++/**
> ++ * schematronTest:
> ++ * @filename: the schemas file
> ++ * @result: the file with expected result
> ++ * @err: the file with error messages
> ++ *
> ++ * Returns 0 in case of success, an error code otherwise
> ++ */
> ++static int
> ++schematronTest(const char *filename,
> ++ const char *resul ATTRIBUTE_UNUSED,
> ++ const char *errr ATTRIBUTE_UNUSED,
> ++ int options) {
> ++ const char *base = baseFilename(filename);
> ++ const char *base2;
> ++ const char *instance;
> ++ xmlSchematronParserCtxtPtr pctxt;
> ++ xmlSchematronPtr schematron;
> ++ int res = 0, len, ret = 0;
> ++ int parseErrorsSize;
> ++ char pattern[500];
> ++ char prefix[500];
> ++ char err[500];
> ++ glob_t globbuf;
> ++ size_t i;
> ++ char count = 0;
> ++
> ++ /* Redirect XPath errors */
> ++ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
> ++
> ++ pctxt = xmlSchematronNewParserCtxt(filename);
> ++ schematron = xmlSchematronParse(pctxt);
> ++ xmlSchematronFreeParserCtxt(pctxt);
> ++ if (schematron == NULL)
> ++ testErrorHandler(NULL, "Schematron schema %s failed to compile\n",
> ++ filename);
> ++ parseErrorsSize = testErrorsSize;
> ++
> ++ /*
> ++ * most of the mess is about the output filenames generated by the Makefile
> ++ */
> ++ len = strlen(base);
> ++ if ((len > 499) || (len < 5)) {
> ++ ret = -1;
> ++ goto done;
> ++ }
> ++ len -= 4; /* remove trailing .sct */
> ++ memcpy(prefix, base, len);
> ++ prefix[len] = 0;
> ++
> ++ if (snprintf(pattern, 499, "./test/schematron/%s_?.xml", prefix) >= 499)
> ++ pattern[499] = 0;
> ++
> ++ globbuf.gl_offs = 0;
> ++ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
> ++ for (i = 0;i < globbuf.gl_pathc;i++) {
> ++ testErrorsSize = parseErrorsSize;
> ++ testErrors[parseErrorsSize] = 0;
> ++ instance = globbuf.gl_pathv[i];
> ++ base2 = baseFilename(instance);
> ++ len = strlen(base2);
> ++ if ((len > 6) && (base2[len - 6] == '_')) {
> ++ count = base2[len - 5];
> ++ res = snprintf(err, 499, "result/schematron/%s_%c.err",
> ++ prefix, count);
> ++ if (res >= 499)
> ++ err[499] = 0;
> ++ } else {
> ++ fprintf(stderr, "don't know how to process %s\n", instance);
> ++ continue;
> ++ }
> ++ if (schematron != NULL) {
> ++ nb_tests++;
> ++ res = schematronOneTest(filename, instance, options, schematron);
> ++ if (res != 0)
> ++ ret = res;
> ++ }
> ++ if (compareFileMem(err, testErrors, testErrorsSize)) {
> ++ fprintf(stderr, "Error for %s on %s failed\n", instance,
> ++ filename);
> ++ ret = 1;
> ++ }
> ++ }
> ++ globfree(&globbuf);
> ++
> ++done:
> ++ xmlSchematronFree(schematron);
> ++ xmlSetStructuredErrorFunc(NULL, NULL);
> ++ return(ret);
> ++}
> ++#endif /* LIBXML_SCHEMATRON_ENABLED */
> ++
> + #ifdef LIBXML_PATTERN_ENABLED
> + #ifdef LIBXML_READER_ENABLED
> + /************************************************************************
> +@@ -5117,6 +5251,11 @@ testDesc testDescriptions[] = {
> + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
> + XML_PARSE_DTDATTR | XML_PARSE_NOENT },
> + #endif
> ++#if defined(LIBXML_SCHEMATRON_ENABLED)
> ++ { "Schematron regression tests" ,
> ++ schematronTest, "./test/schematron/*.sct", NULL, NULL, NULL,
> ++ 0 },
> ++#endif
> + #endif
> + #ifdef LIBXML_PATTERN_ENABLED
> + #ifdef LIBXML_READER_ENABLED
> +diff --git a/schematron.c b/schematron.c
> +index 411a515c..c970d31f 100644
> +--- a/schematron.c
> ++++ b/schematron.c
> +@@ -1484,6 +1484,11 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
> + select = xmlGetNoNsProp(child, BAD_CAST "select");
> + comp = xmlXPathCtxtCompile(ctxt->xctxt, select);
> + eval = xmlXPathCompiledEval(comp, ctxt->xctxt);
> ++ if (eval == NULL) {
> ++ xmlXPathFreeCompExpr(comp);
> ++ xmlFree(select);
> ++ return ret;
> ++ }
> +
> + switch (eval->type) {
> + case XPATH_NODESET: {
> +diff --git a/test/schematron/zvon16.sct b/test/schematron/zvon16.sct
> +new file mode 100644
> +index 00000000..f03848aa
> +--- /dev/null
> ++++ b/test/schematron/zvon16.sct
> +@@ -0,0 +1,7 @@
> ++<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
> ++ <sch:pattern id="TestPattern">
> ++ <sch:rule context="book">
> ++ <sch:report test="not(@available)">Book <sch:value-of select="falae()"/> test</sch:report>
> ++ </sch:rule>
> ++ </sch:pattern>
> ++</sch:schema>
> +diff --git a/test/schematron/zvon16_0.xml b/test/schematron/zvon16_0.xml
> +new file mode 100644
> +index 00000000..551e2d65
> +--- /dev/null
> ++++ b/test/schematron/zvon16_0.xml
> +@@ -0,0 +1,5 @@
> ++<library>
> ++ <book title="Test Book" id="bk101">
> ++ <author>Test Author</author>
> ++ </book>
> ++</library>
> diff --git a/meta/recipes-core/libxml/libxml2_2.12.10.bb b/meta/recipes-core/libxml/libxml2_2.12.10.bb
> index 2eea65732b..ea40ca68ed 100644
> --- a/meta/recipes-core/libxml/libxml2_2.12.10.bb
> +++ b/meta/recipes-core/libxml/libxml2_2.12.10.bb
> @@ -20,6 +20,7 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt
> file://install-tests.patch \
> file://CVE-2025-32414.patch \
> file://CVE-2025-32415.patch \
> + file://CVE-2025-49795.patch \
> "
>
> SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#220138): https://lists.openembedded.org/g/openembedded-core/message/220138
> Mute This Topic: https://lists.openembedded.org/mt/114097487/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [OE-core] [scarthgap][PATCH] libxml2: fix CVE-2025-49795
2025-07-16 15:04 ` [OE-core] " Steve Sakoman
@ 2025-07-17 7:04 ` Roland Kovács
0 siblings, 0 replies; 3+ messages in thread
From: Roland Kovács @ 2025-07-17 7:04 UTC (permalink / raw)
To: steve@sakoman.com; +Cc: openembedded-core@lists.openembedded.org
On Wed, 2025-07-16 at 08:04 -0700, Steve Sakoman wrote:
> I'm getting ptest failures with this patch:
>
> WARNING: core-image-ptest-libxml2-1.0-r0 do_testimage: There were
> failing ptests.
> Traceback (most recent call last):
> File "/srv/pokybuild/yocto-worker/qemux86-64-
> ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
> line 35, in wrapped_f
> return func(*args, **kwargs)
> ^^^^^^^^^^^^^^^^^^^^^
> File "/srv/pokybuild/yocto-worker/qemux86-64-
> ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
> line 35, in wrapped_f
> return func(*args, **kwargs)
> ^^^^^^^^^^^^^^^^^^^^^
> File "/srv/pokybuild/yocto-worker/qemux86-64-
> ptest/build/meta/lib/oeqa/core/decorator/__init__.py",
> line 35, in wrapped_f
> return func(*args, **kwargs)
> ^^^^^^^^^^^^^^^^^^^^^
> File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py",
> line 27, in test_ptestrunner_expectfail
> self.do_ptestrunner()
> File "/srv/pokybuild/yocto-worker/qemux86-64-ptest/build/meta/lib/oeqa/runtime/cases/ptest.py",
> line 120, in do_ptestrunner
> self.fail(failmsg)
> AssertionError:
> Failed ptests:
> {'libxml2': ['runtest']}
>
> I'm seeing it on both x86-64 and arm64:
>
> https://autobuilder.yoctoproject.org/valkyrie/?#/builders/73/builds/1900/steps/12/logs/stdio
> https://autobuilder.yoctoproject.org/valkyrie/?#/builders/61/builds/1897/steps/12/logs/stdio
>
> I do not see the same issue with the walnascar version of the patch,
> so perhaps that is a clue that will aid your debugging.
>
> Steve
>
I'll look into it, and thanks for the pointers!
Cheers,
Roland
> On Fri, Jul 11, 2025 at 2:15 AM roland.kovacs via
> lists.openembedded.org <roland.kovacs=est.tech@lists.openembedded.org>
> wrote:
> >
> > From: Roland Kovacs <roland.kovacs@est.tech>
> >
> > A NULL pointer dereference vulnerability was found in libxml2 when processing
> > XPath XML expressions. This flaw allows an attacker to craft a malicious XML
> > input to libxml2, leading to a denial of service.
> >
> > Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
> > ---
> > .../libxml/libxml2/CVE-2025-49795.patch | 238 ++++++++++++++++++
> > meta/recipes-core/libxml/libxml2_2.12.10.bb | 1 +
> > 2 files changed, 239 insertions(+)
> > create mode 100644 meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
> >
> > diff --git a/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch b/meta/recipes-
> > core/libxml/libxml2/CVE-2025-49795.patch
> > new file mode 100644
> > index 0000000000..fd784ea45b
> > --- /dev/null
> > +++ b/meta/recipes-core/libxml/libxml2/CVE-2025-49795.patch
> > @@ -0,0 +1,238 @@
> > +From 68ce19940f8e08c85f9c8ce65180cdb90bf4b0d2 Mon Sep 17 00:00:00 2001
> > +From: Michael Mann <mmann78@netscape.net>
> > +Date: Sat, 21 Jun 2025 12:11:30 -0400
> > +Subject: [PATCH] Schematron: Fix null pointer dereference leading to DoS
> > +
> > +(CVE-2025-49795)
> > +
> > +Fixes #932
> > +
> > +Upstream-Status: Backport
> > [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667]
> > +CVE: CVE-2025-49795
> > +
> > +(cherry picked from commit c24909ba2601848825b49a60f988222da3019667)
> > +Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
> > +---
> > + result/schematron/zvon16_0.err | 3 +
> > + runtest.c | 139 +++++++++++++++++++++++++++++++++
> > + schematron.c | 5 ++
> > + test/schematron/zvon16.sct | 7 ++
> > + test/schematron/zvon16_0.xml | 5 ++
> > + 5 files changed, 159 insertions(+)
> > + create mode 100644 result/schematron/zvon16_0.err
> > + create mode 100644 test/schematron/zvon16.sct
> > + create mode 100644 test/schematron/zvon16_0.xml
> > +
> > +diff --git a/result/schematron/zvon16_0.err b/result/schematron/zvon16_0.err
> > +new file mode 100644
> > +index 00000000..3d052409
> > +--- /dev/null
> > ++++ b/result/schematron/zvon16_0.err
> > +@@ -0,0 +1,3 @@
> > ++XPath error : Unregistered function
> > ++./test/schematron/zvon16_0.xml:2: element book: schematron error : /library/book line 2: Book
> > ++./test/schematron/zvon16_0.xml fails to validate
> > +diff --git a/runtest.c b/runtest.c
> > +index c78eec81..736cae5e 100644
> > +--- a/runtest.c
> > ++++ b/runtest.c
> > +@@ -52,6 +52,10 @@
> > + #include <libxml/xmlschemastypes.h>
> > + #endif
> > +
> > ++#ifdef LIBXML_SCHEMATRON_ENABLED
> > ++#include <libxml/schematron.h>
> > ++#endif
> > ++
> > + #ifdef LIBXML_PATTERN_ENABLED
> > + #include <libxml/pattern.h>
> > + #endif
> > +@@ -3881,6 +3885,136 @@ rngStreamTest(const char *filename,
> > +
> > + #endif
> > +
> > ++/************************************************************************
> > ++ * *
> > ++ * Schematron tests *
> > ++ * *
> > ++ ************************************************************************/
> > ++
> > ++#ifdef LIBXML_SCHEMATRON_ENABLED
> > ++static int
> > ++schematronOneTest(const char *sch, const char *filename, int options,
> > ++ xmlSchematronPtr schematron) {
> > ++ xmlDocPtr doc;
> > ++ xmlSchematronValidCtxtPtr ctxt;
> > ++ int ret;
> > ++
> > ++ doc = xmlReadFile(filename, NULL, options);
> > ++ if (doc == NULL) {
> > ++ fprintf(stderr, "failed to parse instance %s for %s\n", filename, sch);
> > ++ return(-1);
> > ++ }
> > ++
> > ++ ctxt = xmlSchematronNewValidCtxt(schematron, XML_SCHEMATRON_OUT_ERROR);
> > ++ xmlSchematronSetValidStructuredErrors(ctxt, testStructuredErrorHandler,
> > ++ NULL);
> > ++ ret = xmlSchematronValidateDoc(ctxt, doc);
> > ++ if (ret == 0) {
> > ++ testErrorHandler(NULL, "%s validates\n", filename);
> > ++ } else if (ret > 0) {
> > ++ testErrorHandler(NULL, "%s fails to validate\n", filename);
> > ++ } else {
> > ++ testErrorHandler(NULL, "%s validation generated an internal error\n",
> > ++ filename);
> > ++ }
> > ++
> > ++ xmlSchematronFreeValidCtxt(ctxt);
> > ++ xmlFreeDoc(doc);
> > ++ return(0);
> > ++}
> > ++
> > ++/**
> > ++ * schematronTest:
> > ++ * @filename: the schemas file
> > ++ * @result: the file with expected result
> > ++ * @err: the file with error messages
> > ++ *
> > ++ * Returns 0 in case of success, an error code otherwise
> > ++ */
> > ++static int
> > ++schematronTest(const char *filename,
> > ++ const char *resul ATTRIBUTE_UNUSED,
> > ++ const char *errr ATTRIBUTE_UNUSED,
> > ++ int options) {
> > ++ const char *base = baseFilename(filename);
> > ++ const char *base2;
> > ++ const char *instance;
> > ++ xmlSchematronParserCtxtPtr pctxt;
> > ++ xmlSchematronPtr schematron;
> > ++ int res = 0, len, ret = 0;
> > ++ int parseErrorsSize;
> > ++ char pattern[500];
> > ++ char prefix[500];
> > ++ char err[500];
> > ++ glob_t globbuf;
> > ++ size_t i;
> > ++ char count = 0;
> > ++
> > ++ /* Redirect XPath errors */
> > ++ xmlSetStructuredErrorFunc(NULL, testStructuredErrorHandler);
> > ++
> > ++ pctxt = xmlSchematronNewParserCtxt(filename);
> > ++ schematron = xmlSchematronParse(pctxt);
> > ++ xmlSchematronFreeParserCtxt(pctxt);
> > ++ if (schematron == NULL)
> > ++ testErrorHandler(NULL, "Schematron schema %s failed to compile\n",
> > ++ filename);
> > ++ parseErrorsSize = testErrorsSize;
> > ++
> > ++ /*
> > ++ * most of the mess is about the output filenames generated by the Makefile
> > ++ */
> > ++ len = strlen(base);
> > ++ if ((len > 499) || (len < 5)) {
> > ++ ret = -1;
> > ++ goto done;
> > ++ }
> > ++ len -= 4; /* remove trailing .sct */
> > ++ memcpy(prefix, base, len);
> > ++ prefix[len] = 0;
> > ++
> > ++ if (snprintf(pattern, 499, "./test/schematron/%s_?.xml", prefix) >= 499)
> > ++ pattern[499] = 0;
> > ++
> > ++ globbuf.gl_offs = 0;
> > ++ glob(pattern, GLOB_DOOFFS, NULL, &globbuf);
> > ++ for (i = 0;i < globbuf.gl_pathc;i++) {
> > ++ testErrorsSize = parseErrorsSize;
> > ++ testErrors[parseErrorsSize] = 0;
> > ++ instance = globbuf.gl_pathv[i];
> > ++ base2 = baseFilename(instance);
> > ++ len = strlen(base2);
> > ++ if ((len > 6) && (base2[len - 6] == '_')) {
> > ++ count = base2[len - 5];
> > ++ res = snprintf(err, 499, "result/schematron/%s_%c.err",
> > ++ prefix, count);
> > ++ if (res >= 499)
> > ++ err[499] = 0;
> > ++ } else {
> > ++ fprintf(stderr, "don't know how to process %s\n", instance);
> > ++ continue;
> > ++ }
> > ++ if (schematron != NULL) {
> > ++ nb_tests++;
> > ++ res = schematronOneTest(filename, instance, options, schematron);
> > ++ if (res != 0)
> > ++ ret = res;
> > ++ }
> > ++ if (compareFileMem(err, testErrors, testErrorsSize)) {
> > ++ fprintf(stderr, "Error for %s on %s failed\n", instance,
> > ++ filename);
> > ++ ret = 1;
> > ++ }
> > ++ }
> > ++ globfree(&globbuf);
> > ++
> > ++done:
> > ++ xmlSchematronFree(schematron);
> > ++ xmlSetStructuredErrorFunc(NULL, NULL);
> > ++ return(ret);
> > ++}
> > ++#endif /* LIBXML_SCHEMATRON_ENABLED */
> > ++
> > + #ifdef LIBXML_PATTERN_ENABLED
> > + #ifdef LIBXML_READER_ENABLED
> > + /************************************************************************
> > +@@ -5117,6 +5251,11 @@ testDesc testDescriptions[] = {
> > + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL,
> > + XML_PARSE_DTDATTR | XML_PARSE_NOENT },
> > + #endif
> > ++#if defined(LIBXML_SCHEMATRON_ENABLED)
> > ++ { "Schematron regression tests" ,
> > ++ schematronTest, "./test/schematron/*.sct", NULL, NULL, NULL,
> > ++ 0 },
> > ++#endif
> > + #endif
> > + #ifdef LIBXML_PATTERN_ENABLED
> > + #ifdef LIBXML_READER_ENABLED
> > +diff --git a/schematron.c b/schematron.c
> > +index 411a515c..c970d31f 100644
> > +--- a/schematron.c
> > ++++ b/schematron.c
> > +@@ -1484,6 +1484,11 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
> > + select = xmlGetNoNsProp(child, BAD_CAST "select");
> > + comp = xmlXPathCtxtCompile(ctxt->xctxt, select);
> > + eval = xmlXPathCompiledEval(comp, ctxt->xctxt);
> > ++ if (eval == NULL) {
> > ++ xmlXPathFreeCompExpr(comp);
> > ++ xmlFree(select);
> > ++ return ret;
> > ++ }
> > +
> > + switch (eval->type) {
> > + case XPATH_NODESET: {
> > +diff --git a/test/schematron/zvon16.sct b/test/schematron/zvon16.sct
> > +new file mode 100644
> > +index 00000000..f03848aa
> > +--- /dev/null
> > ++++ b/test/schematron/zvon16.sct
> > +@@ -0,0 +1,7 @@
> > ++<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron">
> > ++ <sch:pattern id="TestPattern">
> > ++ <sch:rule context="book">
> > ++ <sch:report test="not(@available)">Book <sch:value-of select="falae()"/>
> > test</sch:report>
> > ++ </sch:rule>
> > ++ </sch:pattern>
> > ++</sch:schema>
> > +diff --git a/test/schematron/zvon16_0.xml b/test/schematron/zvon16_0.xml
> > +new file mode 100644
> > +index 00000000..551e2d65
> > +--- /dev/null
> > ++++ b/test/schematron/zvon16_0.xml
> > +@@ -0,0 +1,5 @@
> > ++<library>
> > ++ <book title="Test Book" id="bk101">
> > ++ <author>Test Author</author>
> > ++ </book>
> > ++</library>
> > diff --git a/meta/recipes-core/libxml/libxml2_2.12.10.bb b/meta/recipes-
> > core/libxml/libxml2_2.12.10.bb
> > index 2eea65732b..ea40ca68ed 100644
> > --- a/meta/recipes-core/libxml/libxml2_2.12.10.bb
> > +++ b/meta/recipes-core/libxml/libxml2_2.12.10.bb
> > @@ -20,6 +20,7 @@ SRC_URI +=
> > "http://www.w3.org/XML/Test/xmlts20130923.tar;subdir=${BP};name=testt
> > file://install-tests.patch \
> > file://CVE-2025-32414.patch \
> > file://CVE-2025-32415.patch \
> > + file://CVE-2025-49795.patch \
> > "
> >
> > SRC_URI[archive.sha256sum] = "c3d8c0c34aa39098f66576fe51969db12a5100b956233dc56506f7a8679be995"
> >
> > -=-=-=-=-=-=-=-=-=-=-=-
> > Links: You receive all messages sent to this group.
> > View/Reply Online (#220138): https://lists.openembedded.org/g/openembedded-core/message/220138
> > Mute This Topic: https://lists.openembedded.org/mt/114097487/3620601
> > Group Owner: openembedded-core+owner@lists.openembedded.org
> > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> > -=-=-=-=-=-=-=-=-=-=-=-
> >
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-17 7:05 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-11 9:15 [scarthgap][PATCH] libxml2: fix CVE-2025-49795 roland.kovacs
2025-07-16 15:04 ` [OE-core] " Steve Sakoman
2025-07-17 7:04 ` Roland Kovács
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.