From: Peter Marko Date: Wed, 8 Oct 2025 18:49:01 +0000 (+0200) Subject: expat: follow-up for CVE-2024-8176 X-Git-Tag: 2024-04.13-scarthgap~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bbb9ee52674f5aa6eed5d6cf3f515704092994d;p=thirdparty%2Fopenembedded%2Fopenembedded-core.git expat: follow-up for CVE-2024-8176 Expat release 2.7.3 implemented a follow-up for this CVE. References: * https://github.com/libexpat/libexpat/blob/R_2_7_3/expat/Changes * https://security-tracker.debian.org/tracker/CVE-2024-8176 * https://github.com/libexpat/libexpat/pull/1059 Signed-off-by: Peter Marko Signed-off-by: Steve Sakoman --- diff --git a/meta/recipes-core/expat/expat/CVE-2024-8176-03.patch b/meta/recipes-core/expat/expat/CVE-2024-8176-03.patch new file mode 100644 index 00000000000..c9990d5547e --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2024-8176-03.patch @@ -0,0 +1,35 @@ +From ba80428c2207259103b73871d447dee34755340c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= +Date: Tue, 23 Sep 2025 11:22:14 +0200 +Subject: [PATCH] lib: Fix detection of asynchronous tags in entities + +According to the XML standard, tags must be closed within the same +element in which they are opened. Since the change of the entity +processing method in version 2.7.0, violations of this rule have not +been handled correctly for entities. + +This commit adds the required checks to detect any violations and +restores the correct behaviour. + +CVE: CVE-2024-8176 +Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1059] +Signed-off-by: Peter Marko +--- + lib/xmlparse.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/xmlparse.c b/lib/xmlparse.c +index ce29ab6f..ba4e3c48 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -6087,6 +6087,10 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end, + // process its possible inner entities (which are added to the + // m_openInternalEntities during doProlog or doContent calls above) + entity->hasMore = XML_FALSE; ++ if (! entity->is_param ++ && (openEntity->startTagLevel != parser->m_tagLevel)) { ++ return XML_ERROR_ASYNC_ENTITY; ++ } + triggerReenter(parser); + return result; + } // End of entity processing, "if" block will return here diff --git a/meta/recipes-core/expat/expat/CVE-2024-8176-04.patch b/meta/recipes-core/expat/expat/CVE-2024-8176-04.patch new file mode 100644 index 00000000000..9623467698f --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2024-8176-04.patch @@ -0,0 +1,115 @@ +From 81a114f7eebcd41a6993337128cda337986a26f4 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping +Date: Mon, 15 Sep 2025 21:57:07 +0200 +Subject: [PATCH] tests: Cover XML_ERROR_ASYNC_ENTITY cases + +CVE: CVE-2024-8176 +Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1059] +Signed-off-by: Peter Marko +--- + tests/misc_tests.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 87 insertions(+) + +diff --git a/tests/misc_tests.c b/tests/misc_tests.c +index 3346bce6..19f41df7 100644 +--- a/tests/misc_tests.c ++++ b/tests/misc_tests.c +@@ -621,6 +621,91 @@ START_TEST(test_misc_expected_event_ptr_issue_980) { + } + END_TEST + ++START_TEST(test_misc_sync_entity_tolerated) { ++ const char *const doc = "'>\n" ++ " two'>\n" ++ " threefourthree'>\n" ++ " &b;'>\n" ++ "]>\n" ++ "&a;&b;&c;&d;\n"; ++ XML_Parser parser = XML_ParserCreate(NULL); ++ ++ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), ++ /*isFinal=*/XML_TRUE) ++ == XML_STATUS_OK); ++ ++ XML_ParserFree(parser); ++} ++END_TEST ++ ++START_TEST(test_misc_async_entity_rejected) { ++ struct test_case { ++ const char *doc; ++ enum XML_Status expectedStatusNoGE; ++ enum XML_Error expectedErrorNoGE; ++ }; ++ const struct test_case cases[] = { ++ // Opened by one entity, closed by another ++ {"'>\n" ++ " '>\n" ++ "]>\n" ++ "&open;&close;\n", ++ XML_STATUS_OK, XML_ERROR_NONE}, ++ // Opened by tag, closed by entity (non-root case) ++ {"\n" ++ " '>\n" ++ "]>\n" ++ "&g1;\n", ++ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH}, ++ // Opened by tag, closed by entity (root case) ++ {"\n" ++ " '>\n" ++ "]>\n" ++ "&g1;\n", ++ XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS}, ++ // Opened by entity, closed by tag <-- regression from 2.7.0 ++ {"\n" ++ " &g0;'>\n" ++ "]>\n" ++ "&g1;\n", ++ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH}, ++ // Opened by tag, closed by entity; then the other way around ++ {"'>\n" ++ " '>\n" ++ "]>\n" ++ "&close;&open;\n", ++ XML_STATUS_OK, XML_ERROR_NONE}, ++ }; ++ ++ for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { ++ const struct test_case testCase = cases[i]; ++ set_subtest("cases[%d]", (int)i); ++ ++ const char *const doc = testCase.doc; ++#if XML_GE == 1 ++ const enum XML_Status expectedStatus = XML_STATUS_ERROR; ++ const enum XML_Error expectedError = XML_ERROR_ASYNC_ENTITY; ++#else ++ const enum XML_Status expectedStatus = testCase.expectedStatusNoGE; ++ const enum XML_Error expectedError = testCase.expectedErrorNoGE; ++#endif ++ ++ XML_Parser parser = XML_ParserCreate(NULL); ++ assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), ++ /*isFinal=*/XML_TRUE) ++ == expectedStatus); ++ assert_true(XML_GetErrorCode(parser) == expectedError); ++ XML_ParserFree(parser); ++ } ++} ++END_TEST ++ + void + make_miscellaneous_test_case(Suite *s) { + TCase *tc_misc = tcase_create("miscellaneous tests"); +@@ -649,4 +734,6 @@ make_miscellaneous_test_case(Suite *s) { + tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser); + tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content); + tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980); ++ tcase_add_test(tc_misc, test_misc_sync_entity_tolerated); ++ tcase_add_test(tc_misc, test_misc_async_entity_rejected); + } diff --git a/meta/recipes-core/expat/expat/CVE-2024-8176-05.patch b/meta/recipes-core/expat/expat/CVE-2024-8176-05.patch new file mode 100644 index 00000000000..063a590a118 --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2024-8176-05.patch @@ -0,0 +1,78 @@ +From a9aaf85cfc3025b7013b5adc4bef2ce32ecc7fb1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= +Date: Tue, 23 Sep 2025 12:12:50 +0200 +Subject: [PATCH] tests: Add line/column checks to async entity tests + +CVE: CVE-2024-8176 +Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1059] +Signed-off-by: Peter Marko +--- + tests/misc_tests.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/tests/misc_tests.c b/tests/misc_tests.c +index 19f41df7..7a4d2455 100644 +--- a/tests/misc_tests.c ++++ b/tests/misc_tests.c +@@ -644,6 +644,8 @@ START_TEST(test_misc_async_entity_rejected) { + const char *doc; + enum XML_Status expectedStatusNoGE; + enum XML_Error expectedErrorNoGE; ++ XML_Size expectedErrorLine; ++ XML_Size expectedErrorColumn; + }; + const struct test_case cases[] = { + // Opened by one entity, closed by another +@@ -652,35 +654,35 @@ START_TEST(test_misc_async_entity_rejected) { + " '>\n" + "]>\n" + "&open;&close;\n", +- XML_STATUS_OK, XML_ERROR_NONE}, ++ XML_STATUS_OK, XML_ERROR_NONE, 5, 4}, + // Opened by tag, closed by entity (non-root case) + {"\n" + " '>\n" + "]>\n" + "&g1;\n", +- XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH}, ++ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 8}, + // Opened by tag, closed by entity (root case) + {"\n" + " '>\n" + "]>\n" + "&g1;\n", +- XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS}, ++ XML_STATUS_ERROR, XML_ERROR_NO_ELEMENTS, 5, 4}, + // Opened by entity, closed by tag <-- regression from 2.7.0 + {"\n" + " &g0;'>\n" + "]>\n" + "&g1;\n", +- XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH}, ++ XML_STATUS_ERROR, XML_ERROR_TAG_MISMATCH, 5, 4}, + // Opened by tag, closed by entity; then the other way around + {"'>\n" + " '>\n" + "]>\n" + "&close;&open;\n", +- XML_STATUS_OK, XML_ERROR_NONE}, ++ XML_STATUS_OK, XML_ERROR_NONE, 5, 8}, + }; + + for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { +@@ -701,6 +703,11 @@ START_TEST(test_misc_async_entity_rejected) { + /*isFinal=*/XML_TRUE) + == expectedStatus); + assert_true(XML_GetErrorCode(parser) == expectedError); ++#if XML_GE == 1 ++ assert_true(XML_GetCurrentLineNumber(parser) == testCase.expectedErrorLine); ++ assert_true(XML_GetCurrentColumnNumber(parser) ++ == testCase.expectedErrorColumn); ++#endif + XML_ParserFree(parser); + } + } diff --git a/meta/recipes-core/expat/expat_2.6.4.bb b/meta/recipes-core/expat/expat_2.6.4.bb index ab0b1d54c13..816beaa8a3d 100644 --- a/meta/recipes-core/expat/expat_2.6.4.bb +++ b/meta/recipes-core/expat/expat_2.6.4.bb @@ -13,6 +13,9 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \ file://0001-tests-Cover-indirect-entity-recursion.patch;striplevel=2 \ file://CVE-2024-8176-01.patch;striplevel=2 \ file://CVE-2024-8176-02.patch;striplevel=2 \ + file://CVE-2024-8176-03.patch \ + file://CVE-2024-8176-04.patch \ + file://CVE-2024-8176-05.patch \ " GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"