diff options
Diffstat (limited to 'meta/recipes-core')
19 files changed, 1745 insertions, 188 deletions
diff --git a/meta/recipes-core/expat/expat/CVE-2021-45960.patch b/meta/recipes-core/expat/expat/CVE-2021-45960.patch new file mode 100644 index 0000000000..523449e22c --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2021-45960.patch @@ -0,0 +1,65 @@ +From 0adcb34c49bee5b19bd29b16a578c510c23597ea Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Mon, 27 Dec 2021 20:15:02 +0100 +Subject: [PATCH] lib: Detect and prevent troublesome left shifts in function + storeAtts (CVE-2021-45960) + +Upstream-Status: Backport: +https://github.com/libexpat/libexpat/pull/534/commits/0adcb34c49bee5b19bd29b16a578c510c23597ea + +CVE: CVE-2021-45960 +Signed-off-by: Steve Sakoman <steve@sakoman.com> + +--- + expat/lib/xmlparse.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index d730f41c3..b47c31b05 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + if (nPrefixes) { + int j; /* hash table index */ + unsigned long version = parser->m_nsAttsVersion; +- int nsAttsSize = (int)1 << parser->m_nsAttsPower; ++ ++ /* Detect and prevent invalid shift */ ++ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ unsigned int nsAttsSize = 1u << parser->m_nsAttsPower; + unsigned char oldNsAttsPower = parser->m_nsAttsPower; + /* size of hash table must be at least 2 * (# of prefixed attributes) */ + if ((nPrefixes << 1) +@@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + ; + if (parser->m_nsAttsPower < 3) + parser->m_nsAttsPower = 3; +- nsAttsSize = (int)1 << parser->m_nsAttsPower; ++ ++ /* Detect and prevent invalid shift */ ++ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) { ++ /* Restore actual size of memory in m_nsAtts */ ++ parser->m_nsAttsPower = oldNsAttsPower; ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ nsAttsSize = 1u << parser->m_nsAttsPower; ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) { ++ /* Restore actual size of memory in m_nsAtts */ ++ parser->m_nsAttsPower = oldNsAttsPower; ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, + nsAttsSize * sizeof(NS_ATT)); + if (! temp) { diff --git a/meta/recipes-core/expat/expat/CVE-2021-46143.patch b/meta/recipes-core/expat/expat/CVE-2021-46143.patch new file mode 100644 index 0000000000..b1a726d9a8 --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2021-46143.patch @@ -0,0 +1,49 @@ +From 85ae9a2d7d0e9358f356b33977b842df8ebaec2b Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Sat, 25 Dec 2021 20:52:08 +0100 +Subject: [PATCH] lib: Prevent integer overflow on m_groupSize in function + doProlog (CVE-2021-46143) + +Upstream-Status: Backport: +https://github.com/libexpat/libexpat/pull/538/commits/85ae9a2d7d0e9358f356b33977b842df8ebaec2b + +CVE: CVE-2021-46143 + +Signed-off-by: Steve Sakoman <steve@sakoman.com> +--- + expat/lib/xmlparse.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index b47c31b0..8f243126 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -5046,6 +5046,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + if (parser->m_prologState.level >= parser->m_groupSize) { + if (parser->m_groupSize) { + { ++ /* Detect and prevent integer overflow */ ++ if (parser->m_groupSize > (unsigned int)(-1) / 2u) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + char *const new_connector = (char *)REALLOC( + parser, parser->m_groupConnector, parser->m_groupSize *= 2); + if (new_connector == NULL) { +@@ -5056,6 +5061,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + } + + if (dtd->scaffIndex) { ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + int *const new_scaff_index = (int *)REALLOC( + parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); + if (new_scaff_index == NULL) diff --git a/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch new file mode 100644 index 0000000000..e569fbc7ab --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch @@ -0,0 +1,257 @@ +From 9f93e8036e842329863bf20395b8fb8f73834d9e Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Thu, 30 Dec 2021 22:46:03 +0100 +Subject: [PATCH] lib: Prevent integer overflow at multiple places + (CVE-2022-22822 to CVE-2022-22827) + +The involved functions are: +- addBinding (CVE-2022-22822) +- build_model (CVE-2022-22823) +- defineAttribute (CVE-2022-22824) +- lookup (CVE-2022-22825) +- nextScaffoldPart (CVE-2022-22826) +- storeAtts (CVE-2022-22827) + +Upstream-Status: Backport: +https://github.com/libexpat/libexpat/pull/539/commits/9f93e8036e842329863bf20395b8fb8f73834d9e + +CVE: CVE-2022-22822 CVE-2022-22823 CVE-2022-22824 CVE-2022-22825 CVE-2022-22826 CVE-2022-22827 +Signed-off-by: Steve Sakoman <steve@sakoman.com> + +--- + expat/lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 151 insertions(+), 2 deletions(-) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index 8f243126..575e73ee 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3261,13 +3261,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts); ++ ++ /* Detect and prevent integer overflow */ ++ if (n > INT_MAX - nDefaultAtts) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + if (n + nDefaultAtts > parser->m_attsSize) { + int oldAttsSize = parser->m_attsSize; + ATTRIBUTE *temp; + #ifdef XML_ATTR_INFO + XML_AttrInfo *temp2; + #endif ++ ++ /* Detect and prevent integer overflow */ ++ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE) ++ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { ++ parser->m_attsSize = oldAttsSize; ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, + parser->m_attsSize * sizeof(ATTRIBUTE)); + if (temp == NULL) { +@@ -3276,6 +3301,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + } + parser->m_atts = temp; + #ifdef XML_ATTR_INFO ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++# if UINT_MAX >= SIZE_MAX ++ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { ++ parser->m_attsSize = oldAttsSize; ++ return XML_ERROR_NO_MEMORY; ++ } ++# endif ++ + temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, + parser->m_attsSize * sizeof(XML_AttrInfo)); + if (temp2 == NULL) { +@@ -3610,9 +3646,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + tagNamePtr->prefixLen = prefixLen; + for (i = 0; localPart[i++];) + ; /* i includes null terminator */ ++ ++ /* Detect and prevent integer overflow */ ++ if (binding->uriLen > INT_MAX - prefixLen ++ || i > INT_MAX - (binding->uriLen + prefixLen)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ + n = i + binding->uriLen + prefixLen; + if (n > binding->uriAlloc) { + TAG *p; ++ ++ /* Detect and prevent integer overflow */ ++ if (n > INT_MAX - EXPAND_SPARE) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); + if (! uri) + return XML_ERROR_NO_MEMORY; +@@ -3708,6 +3766,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + if (parser->m_freeBindingList) { + b = parser->m_freeBindingList; + if (len > b->uriAlloc) { ++ /* Detect and prevent integer overflow */ ++ if (len > INT_MAX - EXPAND_SPARE) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + XML_Char *temp = (XML_Char *)REALLOC( + parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (temp == NULL) +@@ -3720,6 +3793,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + b = (BINDING *)MALLOC(parser, sizeof(BINDING)); + if (! b) + return XML_ERROR_NO_MEMORY; ++ ++ /* Detect and prevent integer overflow */ ++ if (len > INT_MAX - EXPAND_SPARE) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { ++ return XML_ERROR_NO_MEMORY; ++ } ++#endif ++ + b->uri + = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (! b->uri) { +@@ -6141,7 +6229,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, + } + } else { + DEFAULT_ATTRIBUTE *temp; ++ ++ /* Detect and prevent integer overflow */ ++ if (type->allocDefaultAtts > INT_MAX / 2) { ++ return 0; ++ } ++ + int count = type->allocDefaultAtts * 2; ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { ++ return 0; ++ } ++#endif ++ + temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, + (count * sizeof(DEFAULT_ATTRIBUTE))); + if (temp == NULL) +@@ -6792,8 +6897,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { + /* check for overflow (table is half full) */ + if (table->used >> (table->power - 1)) { + unsigned char newPower = table->power + 1; ++ ++ /* Detect and prevent invalid shift */ ++ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) { ++ return NULL; ++ } ++ + size_t newSize = (size_t)1 << newPower; + unsigned long newMask = (unsigned long)newSize - 1; ++ ++ /* Detect and prevent integer overflow */ ++ if (newSize > (size_t)(-1) / sizeof(NAMED *)) { ++ return NULL; ++ } ++ + size_t tsize = newSize * sizeof(NAMED *); + NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize); + if (! newV) +@@ -7143,6 +7260,20 @@ nextScaffoldPart(XML_Parser parser) { + if (dtd->scaffCount >= dtd->scaffSize) { + CONTENT_SCAFFOLD *temp; + if (dtd->scaffold) { ++ /* Detect and prevent integer overflow */ ++ if (dtd->scaffSize > UINT_MAX / 2u) { ++ return -1; ++ } ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { ++ return -1; ++ } ++#endif ++ + temp = (CONTENT_SCAFFOLD *)REALLOC( + parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); + if (temp == NULL) +@@ -7212,8 +7343,26 @@ build_model(XML_Parser parser) { + XML_Content *ret; + XML_Content *cpos; + XML_Char *str; +- int allocsize = (dtd->scaffCount * sizeof(XML_Content) +- + (dtd->contentStringLen * sizeof(XML_Char))); ++ ++ /* Detect and prevent integer overflow. ++ * The preprocessor guard addresses the "always false" warning ++ * from -Wtype-limits on platforms where ++ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ ++#if UINT_MAX >= SIZE_MAX ++ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { ++ return NULL; ++ } ++ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { ++ return NULL; ++ } ++#endif ++ if (dtd->scaffCount * sizeof(XML_Content) ++ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { ++ return NULL; ++ } ++ ++ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) ++ + (dtd->contentStringLen * sizeof(XML_Char))); + + ret = (XML_Content *)MALLOC(parser, allocsize); + if (! ret) diff --git a/meta/recipes-core/expat/expat/CVE-2022-23852.patch b/meta/recipes-core/expat/expat/CVE-2022-23852.patch new file mode 100644 index 0000000000..41425c108b --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-23852.patch @@ -0,0 +1,33 @@ +From 847a645152f5ebc10ac63b74b604d0c1a79fae40 Mon Sep 17 00:00:00 2001 +From: Samanta Navarro <ferivoz@riseup.net> +Date: Sat, 22 Jan 2022 17:48:00 +0100 +Subject: [PATCH] lib: Detect and prevent integer overflow in XML_GetBuffer + (CVE-2022-23852) + +Upstream-Status: Backport: +https://github.com/libexpat/libexpat/commit/847a645152f5ebc10ac63b74b604d0c1a79fae40 + +CVE: CVE-2022-23852 + +Signed-off-by: Steve Sakoman <steve@sakoman.com> + +--- + expat/lib/xmlparse.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c +index d54af683..5ce31402 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -2067,6 +2067,11 @@ XML_GetBuffer(XML_Parser parser, int len) { + keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; ++ /* Detect and prevent integer overflow */ ++ if (keep > INT_MAX - neededSize) { ++ parser->m_errorCode = XML_ERROR_NO_MEMORY; ++ return NULL; ++ } + neededSize += keep; + #endif /* defined XML_CONTEXT_BYTES */ + if (neededSize diff --git a/meta/recipes-core/expat/expat/CVE-2022-23990.patch b/meta/recipes-core/expat/expat/CVE-2022-23990.patch new file mode 100644 index 0000000000..c599517b3e --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-23990.patch @@ -0,0 +1,49 @@ +From ede41d1e186ed2aba88a06e84cac839b770af3a1 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Wed, 26 Jan 2022 02:36:43 +0100 +Subject: [PATCH] lib: Prevent integer overflow in doProlog (CVE-2022-23990) + +The change from "int nameLen" to "size_t nameLen" +addresses the overflow on "nameLen++" in code +"for (; name[nameLen++];)" right above the second +change in the patch. + +Upstream-Status: Backport: +https://github.com/libexpat/libexpat/pull/551/commits/ede41d1e186ed2aba88a06e84cac839b770af3a1 + +CVE: CVE-2022-23990 + +Signed-off-by: Steve Sakoman <steve@sakoman.com> + +--- + lib/xmlparse.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/lib/xmlparse.c b/expat/lib/xmlparse.c +index 5ce31402..d1d17005 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -5372,7 +5372,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + if (dtd->in_eldecl) { + ELEMENT_TYPE *el; + const XML_Char *name; +- int nameLen; ++ size_t nameLen; + const char *nxt + = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar); + int myindex = nextScaffoldPart(parser); +@@ -5388,7 +5388,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, + nameLen = 0; + for (; name[nameLen++];) + ; +- dtd->contentStringLen += nameLen; ++ ++ /* Detect and prevent integer overflow */ ++ if (nameLen > UINT_MAX - dtd->contentStringLen) { ++ return XML_ERROR_NO_MEMORY; ++ } ++ ++ dtd->contentStringLen += (unsigned)nameLen; + if (parser->m_elementDeclHandler) + handleDefault = XML_FALSE; + } diff --git a/meta/recipes-core/expat/expat/CVE-2022-25235.patch b/meta/recipes-core/expat/expat/CVE-2022-25235.patch new file mode 100644 index 0000000000..9febeae609 --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-25235.patch @@ -0,0 +1,261 @@ +Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/306b721] +CVE: CVE-2022-25235 + +The commit is a merge commit, and this patch is created by: + +$ git show -m -p --stat 306b72134f157bbfd1637b20a22cabf4acfa136a + +Remove modification for expat/Changes which fails to be applied. + +Signed-off-by: Kai Kang <kai.kang@windriver.com> + +commit 306b72134f157bbfd1637b20a22cabf4acfa136a (from 2cc97e875ef84da4bcf55156c83599116f7523b4) +Merge: 2cc97e87 c16300f0 +Author: Sebastian Pipping <sebastian@pipping.org> +Date: Fri Feb 18 20:12:32 2022 +0100 + + Merge pull request #562 from libexpat/utf8-security + + [CVE-2022-25235] lib: Protect against malformed encoding (e.g. malformed UTF-8) +--- + expat/Changes | 7 ++++ + expat/lib/xmltok.c | 5 --- + expat/lib/xmltok_impl.c | 18 ++++---- + expat/tests/runtests.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 127 insertions(+), 12 deletions(-) + +diff --git a/lib/xmltok.c b/lib/xmltok.c +index a72200e8..3bddf125 100644 +--- a/lib/xmltok.c ++++ b/lib/xmltok.c +@@ -98,11 +98,6 @@ + + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \ + & (1u << (((byte)[2]) & 0x1F))) + +-#define UTF8_GET_NAMING(pages, p, n) \ +- ((n) == 2 \ +- ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ +- : ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0)) +- + /* Detection of invalid UTF-8 sequences is based on Table 3.1B + of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/ + with the additional restriction of not allowing the Unicode +diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c +index 0430591b..84ff35f9 100644 +--- a/lib/xmltok_impl.c ++++ b/lib/xmltok_impl.c +@@ -69,7 +69,7 @@ + case BT_LEAD##n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ +- if (! IS_NAME_CHAR(enc, ptr, n)) { \ ++ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ +@@ -98,7 +98,7 @@ + case BT_LEAD##n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ +- if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \ ++ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ +@@ -1142,6 +1142,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, + case BT_LEAD##n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ ++ if (IS_INVALID_CHAR(enc, ptr, n)) { \ ++ *nextTokPtr = ptr; \ ++ return XML_TOK_INVALID; \ ++ } \ + if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NAME; \ +@@ -1270,7 +1274,7 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, + switch (BYTE_TYPE(enc, ptr)) { + # define LEAD_CASE(n) \ + case BT_LEAD##n: \ +- ptr += n; \ ++ ptr += n; /* NOTE: The encoding has already been validated. */ \ + break; + LEAD_CASE(2) + LEAD_CASE(3) +@@ -1339,7 +1343,7 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, + switch (BYTE_TYPE(enc, ptr)) { + # define LEAD_CASE(n) \ + case BT_LEAD##n: \ +- ptr += n; \ ++ ptr += n; /* NOTE: The encoding has already been validated. */ \ + break; + LEAD_CASE(2) + LEAD_CASE(3) +@@ -1518,7 +1522,7 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax, + state = inName; \ + } + # define LEAD_CASE(n) \ +- case BT_LEAD##n: \ ++ case BT_LEAD##n: /* NOTE: The encoding has already been validated. */ \ + START_NAME ptr += (n - MINBPC(enc)); \ + break; + LEAD_CASE(2) +@@ -1730,7 +1734,7 @@ PREFIX(nameLength)(const ENCODING *enc, const char *ptr) { + switch (BYTE_TYPE(enc, ptr)) { + # define LEAD_CASE(n) \ + case BT_LEAD##n: \ +- ptr += n; \ ++ ptr += n; /* NOTE: The encoding has already been validated. */ \ + break; + LEAD_CASE(2) + LEAD_CASE(3) +@@ -1775,7 +1779,7 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, + switch (BYTE_TYPE(enc, ptr)) { + # define LEAD_CASE(n) \ + case BT_LEAD##n: \ +- ptr += n; \ ++ ptr += n; /* NOTE: The encoding has already been validated. */ \ + pos->columnNumber++; \ + break; + LEAD_CASE(2) +diff --git a/tests/runtests.c b/tests/runtests.c +index bc5344b1..9b155b82 100644 +--- a/tests/runtests.c ++++ b/tests/runtests.c +@@ -5998,6 +5998,105 @@ START_TEST(test_utf8_in_cdata_section_2) { + } + END_TEST + ++START_TEST(test_utf8_in_start_tags) { ++ struct test_case { ++ bool goodName; ++ bool goodNameStart; ++ const char *tagName; ++ }; ++ ++ // The idea with the tests below is this: ++ // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences ++ // go to isNever and are hence not a concern. ++ // ++ // We start with a character that is a valid name character ++ // (or even name-start character, see XML 1.0r4 spec) and then we flip ++ // single bits at places where (1) the result leaves the UTF-8 encoding space ++ // and (2) we stay in the same n-byte sequence family. ++ // ++ // The flipped bits are highlighted in angle brackets in comments, ++ // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped ++ // the most significant bit to 1 to leave UTF-8 encoding space. ++ struct test_case cases[] = { ++ // 1-byte UTF-8: [0xxx xxxx] ++ {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':' ++ {false, false, "\xBA"}, // [<1>011 1010] ++ {true, false, "\x39"}, // [0011 1001] = ASCII nine '9' ++ {false, false, "\xB9"}, // [<1>011 1001] ++ ++ // 2-byte UTF-8: [110x xxxx] [10xx xxxx] ++ {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] = ++ // Arabic small waw U+06E5 ++ {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101] ++ {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101] ++ {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101] ++ {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] = ++ // combining char U+0301 ++ {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001] ++ {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001] ++ {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001] ++ ++ // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx] ++ {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] = ++ // Devanagari Letter A U+0905 ++ {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101] ++ {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101] ++ {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101] ++ {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101] ++ {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101] ++ {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] = ++ // combining char U+0901 ++ {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001] ++ {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001] ++ {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001] ++ {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001] ++ {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001] ++ }; ++ const bool atNameStart[] = {true, false}; ++ ++ size_t i = 0; ++ char doc[1024]; ++ size_t failCount = 0; ++ ++ for (; i < sizeof(cases) / sizeof(cases[0]); i++) { ++ size_t j = 0; ++ for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) { ++ const bool expectedSuccess ++ = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName; ++ sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName); ++ XML_Parser parser = XML_ParserCreate(NULL); ++ ++ const enum XML_Status status ++ = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE); ++ ++ bool success = true; ++ if ((status == XML_STATUS_OK) != expectedSuccess) { ++ success = false; ++ } ++ if ((status == XML_STATUS_ERROR) ++ && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) { ++ success = false; ++ } ++ ++ if (! success) { ++ fprintf( ++ stderr, ++ "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n", ++ (unsigned)i + 1u, atNameStart[j] ? " " : "not ", ++ (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser)); ++ failCount++; ++ } ++ ++ XML_ParserFree(parser); ++ } ++ } ++ ++ if (failCount > 0) { ++ fail("UTF-8 regression detected"); ++ } ++} ++END_TEST ++ + /* Test trailing spaces in elements are accepted */ + static void XMLCALL + record_element_end_handler(void *userData, const XML_Char *name) { +@@ -6175,6 +6274,14 @@ START_TEST(test_bad_doctype) { + } + END_TEST + ++START_TEST(test_bad_doctype_utf8) { ++ const char *text = "<!DOCTYPE \xDB\x25" ++ "doc><doc/>"; // [1101 1011] [<0>010 0101] ++ expect_failure(text, XML_ERROR_INVALID_TOKEN, ++ "Invalid UTF-8 in DOCTYPE not faulted"); ++} ++END_TEST ++ + START_TEST(test_bad_doctype_utf16) { + const char text[] = + /* <!DOCTYPE doc [ \x06f2 ]><doc/> +@@ -11870,6 +11977,7 @@ make_suite(void) { + tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom); + tcase_add_test(tc_basic, test_utf8_in_cdata_section); + tcase_add_test(tc_basic, test_utf8_in_cdata_section_2); ++ tcase_add_test(tc_basic, test_utf8_in_start_tags); + tcase_add_test(tc_basic, test_trailing_spaces_in_elements); + tcase_add_test(tc_basic, test_utf16_attribute); + tcase_add_test(tc_basic, test_utf16_second_attr); +@@ -11878,6 +11986,7 @@ make_suite(void) { + tcase_add_test(tc_basic, test_bad_attr_desc_keyword); + tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16); + tcase_add_test(tc_basic, test_bad_doctype); ++ tcase_add_test(tc_basic, test_bad_doctype_utf8); + tcase_add_test(tc_basic, test_bad_doctype_utf16); + tcase_add_test(tc_basic, test_bad_doctype_plus); + tcase_add_test(tc_basic, test_bad_doctype_star); diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch b/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch new file mode 100644 index 0000000000..ab53d99c8f --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch @@ -0,0 +1,116 @@ +Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/2cc97e87] +CVE: CVE-2022-25236 + +The commit is a merge commit, and this patch is created by: + +$ git diff -p --stat 2cc97e87~ 2cc97e87 + +Remove modification for expat/Changes which fails to be applied. + +Signed-off-by: Kai Kang <kai.kang@windriver.com> + +commit 2cc97e875ef84da4bcf55156c83599116f7523b4 (from d477fdd284468f2ab822024e75702f2c1b254f42) +Merge: d477fdd2 e4d7e497 +Author: Sebastian Pipping <sebastian@pipping.org> +Date: Fri Feb 18 18:01:27 2022 +0100 + + Merge pull request #561 from libexpat/namesep-security + + [CVE-2022-25236] lib: Protect against insertion of namesep characters into namespace URIs + +--- + expat/Changes | 16 ++++++++++++++++ + expat/lib/xmlparse.c | 17 +++++++++++++---- + expat/tests/runtests.c | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 59 insertions(+), 4 deletions(-) + +diff --git a/lib/xmlparse.c b/lib/xmlparse.c +index 7376aab1..c98e2e9f 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -718,8 +718,7 @@ XML_ParserCreate(const XML_Char *encodingName) { + + XML_Parser XMLCALL + XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { +- XML_Char tmp[2]; +- *tmp = nsSep; ++ XML_Char tmp[2] = {nsSep, 0}; + return XML_ParserCreate_MM(encodingName, NULL, tmp); + } + +@@ -1344,8 +1343,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, + would be otherwise. + */ + if (parser->m_ns) { +- XML_Char tmp[2]; +- *tmp = parser->m_namespaceSeparator; ++ XML_Char tmp[2] = {parser->m_namespaceSeparator, 0}; + parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); + } else { + parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); +@@ -3761,6 +3759,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + if (! mustBeXML && isXMLNS + && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) + isXMLNS = XML_FALSE; ++ ++ // NOTE: While Expat does not validate namespace URIs against RFC 3986, ++ // we have to at least make sure that the XML processor on top of ++ // Expat (that is splitting tag names by namespace separator into ++ // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused ++ // by an attacker putting additional namespace separator characters ++ // into namespace declarations. That would be ambiguous and not to ++ // be expected. ++ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) { ++ return XML_ERROR_SYNTAX; ++ } + } + isXML = isXML && len == xmlLen; + isXMLNS = isXMLNS && len == xmlnsLen; +diff --git a/tests/runtests.c b/tests/runtests.c +index d07203f2..bc5344b1 100644 +--- a/tests/runtests.c ++++ b/tests/runtests.c +@@ -7220,6 +7220,35 @@ START_TEST(test_ns_double_colon_doctype) { + } + END_TEST + ++START_TEST(test_ns_separator_in_uri) { ++ struct test_case { ++ enum XML_Status expectedStatus; ++ const char *doc; ++ }; ++ struct test_case cases[] = { ++ {XML_STATUS_OK, "<doc xmlns='one_two' />"}, ++ {XML_STATUS_ERROR, "<doc xmlns='one
two' />"}, ++ }; ++ ++ size_t i = 0; ++ size_t failCount = 0; ++ for (; i < sizeof(cases) / sizeof(cases[0]); i++) { ++ XML_Parser parser = XML_ParserCreateNS(NULL, '\n'); ++ XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); ++ if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), ++ /*isFinal*/ XML_TRUE) ++ != cases[i].expectedStatus) { ++ failCount++; ++ } ++ XML_ParserFree(parser); ++ } ++ ++ if (failCount) { ++ fail("Namespace separator handling is broken"); ++ } ++} ++END_TEST ++ + /* Control variable; the number of times duff_allocator() will successfully + * allocate */ + #define ALLOC_ALWAYS_SUCCEED (-1) +@@ -11905,6 +11934,7 @@ make_suite(void) { + tcase_add_test(tc_namespace, test_ns_utf16_doctype); + tcase_add_test(tc_namespace, test_ns_invalid_doctype); + tcase_add_test(tc_namespace, test_ns_double_colon_doctype); ++ tcase_add_test(tc_namespace, test_ns_separator_in_uri); + + suite_add_tcase(s, tc_misc); + tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch b/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch new file mode 100644 index 0000000000..0f14c9631b --- /dev/null +++ b/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch @@ -0,0 +1,232 @@ +Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/f178826b] +CVE: CVE-2022-25236 + +The commit is a merge commit, and this patch is created by: + +$ git show -m -p --stat f178826b + +Remove changes for expat/Changes and reference.html which fail to be applied. + +Signed-off-by: Kai Kang <kai.kang@windriver.com> + +commit f178826bb1e9c8ee23202f1be55ad4ac7b649e84 (from c99e0e7f2b15b48848038992ecbb4480f957cfe9) +Merge: c99e0e7f 9579f7ea +Author: Sebastian Pipping <sebastian@pipping.org> +Date: Fri Mar 4 18:43:39 2022 +0100 + + Merge pull request #577 from libexpat/namesep + + lib: Relax fix to CVE-2022-25236 with regard to RFC 3986 URI characters (fixes #572) +--- + expat/Changes | 16 ++++++ + expat/doc/reference.html | 8 +++ + expat/lib/expat.h | 11 ++++ + expat/lib/xmlparse.c | 139 ++++++++++++++++++++++++++++++++++++++++++++--- + expat/tests/runtests.c | 8 ++- + 5 files changed, 171 insertions(+), 11 deletions(-) + +diff --git a/lib/expat.h b/lib/expat.h +index 5ab493f7..181fc960 100644 +--- a/lib/expat.h ++++ b/lib/expat.h +@@ -239,6 +239,17 @@ XML_ParserCreate(const XML_Char *encoding); + and the local part will be concatenated without any separator. + It is a programming error to use the separator '\0' with namespace + triplets (see XML_SetReturnNSTriplet). ++ If a namespace separator is chosen that can be part of a URI or ++ part of an XML name, splitting an expanded name back into its ++ 1, 2 or 3 original parts on application level in the element handler ++ may end up vulnerable, so these are advised against; sane choices for ++ a namespace separator are e.g. '\n' (line feed) and '|' (pipe). ++ ++ Note that Expat does not validate namespace URIs (beyond encoding) ++ against RFC 3986 today (and is not required to do so with regard to ++ the XML 1.0 namespaces specification) but it may start doing that ++ in future releases. Before that, an application using Expat must ++ be ready to receive namespace URIs containing non-URI characters. + */ + XMLPARSEAPI(XML_Parser) + XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); +diff --git a/lib/xmlparse.c b/lib/xmlparse.c +index 59da19c8..6fe2cf1e 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -3705,6 +3705,117 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, + return XML_ERROR_NONE; + } + ++static XML_Bool ++is_rfc3986_uri_char(XML_Char candidate) { ++ // For the RFC 3986 ANBF grammar see ++ // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A ++ ++ switch (candidate) { ++ // From rule "ALPHA" (uppercase half) ++ case 'A': ++ case 'B': ++ case 'C': ++ case 'D': ++ case 'E': ++ case 'F': ++ case 'G': ++ case 'H': ++ case 'I': ++ case 'J': ++ case 'K': ++ case 'L': ++ case 'M': ++ case 'N': ++ case 'O': ++ case 'P': ++ case 'Q': ++ case 'R': ++ case 'S': ++ case 'T': ++ case 'U': ++ case 'V': ++ case 'W': ++ case 'X': ++ case 'Y': ++ case 'Z': ++ ++ // From rule "ALPHA" (lowercase half) ++ case 'a': ++ case 'b': ++ case 'c': ++ case 'd': ++ case 'e': ++ case 'f': ++ case 'g': ++ case 'h': ++ case 'i': ++ case 'j': ++ case 'k': ++ case 'l': ++ case 'm': ++ case 'n': ++ case 'o': ++ case 'p': ++ case 'q': ++ case 'r': ++ case 's': ++ case 't': ++ case 'u': ++ case 'v': ++ case 'w': ++ case 'x': ++ case 'y': ++ case 'z': ++ ++ // From rule "DIGIT" ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ ++ // From rule "pct-encoded" ++ case '%': ++ ++ // From rule "unreserved" ++ case '-': ++ case '.': ++ case '_': ++ case '~': ++ ++ // From rule "gen-delims" ++ case ':': ++ case '/': ++ case '?': ++ case '#': ++ case '[': ++ case ']': ++ case '@': ++ ++ // From rule "sub-delims" ++ case '!': ++ case '$': ++ case '&': ++ case '\'': ++ case '(': ++ case ')': ++ case '*': ++ case '+': ++ case ',': ++ case ';': ++ case '=': ++ return XML_TRUE; ++ ++ default: ++ return XML_FALSE; ++ } ++} ++ + /* addBinding() overwrites the value of prefix->binding without checking. + Therefore one must keep track of the old value outside of addBinding(). + */ +@@ -3763,14 +3874,26 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, + && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) + isXMLNS = XML_FALSE; + +- // NOTE: While Expat does not validate namespace URIs against RFC 3986, +- // we have to at least make sure that the XML processor on top of +- // Expat (that is splitting tag names by namespace separator into +- // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused +- // by an attacker putting additional namespace separator characters +- // into namespace declarations. That would be ambiguous and not to +- // be expected. +- if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) { ++ // NOTE: While Expat does not validate namespace URIs against RFC 3986 ++ // today (and is not REQUIRED to do so with regard to the XML 1.0 ++ // namespaces specification) we have to at least make sure, that ++ // the application on top of Expat (that is likely splitting expanded ++ // element names ("qualified names") of form ++ // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces ++ // in its element handler code) cannot be confused by an attacker ++ // putting additional namespace separator characters into namespace ++ // declarations. That would be ambiguous and not to be expected. ++ // ++ // While the HTML API docs of function XML_ParserCreateNS have been ++ // advising against use of a namespace separator character that can ++ // appear in a URI for >20 years now, some widespread applications ++ // are using URI characters (':' (colon) in particular) for a ++ // namespace separator, in practice. To keep these applications ++ // functional, we only reject namespaces URIs containing the ++ // application-chosen namespace separator if the chosen separator ++ // is a non-URI character with regard to RFC 3986. ++ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator) ++ && ! is_rfc3986_uri_char(uri[len])) { + return XML_ERROR_SYNTAX; + } + } +diff --git a/tests/runtests.c b/tests/runtests.c +index 60da868e..712706c4 100644 +--- a/tests/runtests.c ++++ b/tests/runtests.c +@@ -7406,16 +7406,18 @@ START_TEST(test_ns_separator_in_uri) { + struct test_case { + enum XML_Status expectedStatus; + const char *doc; ++ XML_Char namesep; + }; + struct test_case cases[] = { +- {XML_STATUS_OK, "<doc xmlns='one_two' />"}, +- {XML_STATUS_ERROR, "<doc xmlns='one
two' />"}, ++ {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')}, ++ {XML_STATUS_ERROR, "<doc xmlns='one
two' />", XCS('\n')}, ++ {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')}, + }; + + size_t i = 0; + size_t failCount = 0; + for (; i < sizeof(cases) / sizeof(cases[0]); i++) { +- XML_Parser parser = XML_ParserCreateNS(NULL, '\n'); ++ XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep); + XML_SetElementHandler(parser, dummy_start_element, dummy_end_element); + if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc), + /*isFinal*/ XML_TRUE) diff --git a/meta/recipes-core/expat/expat_2.2.10.bb b/meta/recipes-core/expat/expat_2.2.10.bb index 08e8ff1cea..f99fa7edb6 100644 --- a/meta/recipes-core/expat/expat_2.2.10.bb +++ b/meta/recipes-core/expat/expat_2.2.10.bb @@ -10,9 +10,17 @@ VERSION_TAG = "${@d.getVar('PV').replace('.', '_')}" SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \ file://libtool-tag.patch \ - file://run-ptest \ - file://0001-Add-output-of-tests-result.patch \ - " + file://run-ptest \ + file://0001-Add-output-of-tests-result.patch \ + file://CVE-2022-22822-27.patch \ + file://CVE-2021-45960.patch \ + file://CVE-2021-46143.patch \ + file://CVE-2022-23852.patch \ + file://CVE-2022-23990.patch \ + file://CVE-2022-25235.patch \ + file://CVE-2022-25236-1.patch \ + file://CVE-2022-25236-2.patch \ + " UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/" diff --git a/meta/recipes-core/glibc/glibc-version.inc b/meta/recipes-core/glibc/glibc-version.inc index 4d69187961..e1eefdee49 100644 --- a/meta/recipes-core/glibc/glibc-version.inc +++ b/meta/recipes-core/glibc/glibc-version.inc @@ -1,6 +1,6 @@ SRCBRANCH ?= "release/2.33/master" PV = "2.33" -SRCREV_glibc ?= "6090cf1330faf2deb17285758f327cb23b89ebf1" +SRCREV_glibc ?= "3e2a15c666e40e5ee740e5079c56d83469280323" SRCREV_localedef ?= "bd644c9e6f3e20c5504da1488448173c69c56c28" GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" diff --git a/meta/recipes-core/glibc/glibc/0031-CVE-2021-43396.patch b/meta/recipes-core/glibc/glibc/0031-CVE-2021-43396.patch deleted file mode 100644 index 72fd68b302..0000000000 --- a/meta/recipes-core/glibc/glibc/0031-CVE-2021-43396.patch +++ /dev/null @@ -1,182 +0,0 @@ -From ff012870b2c02a62598c04daa1e54632e020fd7d Mon Sep 17 00:00:00 2001 -From: Nikita Popov <npv1310@gmail.com> -Date: Tue, 2 Nov 2021 13:21:42 +0500 -Subject: [PATCH] gconv: Do not emit spurious NUL character in ISO-2022-JP-3 - (bug 28524) - -Bugfix 27256 has introduced another issue: -In conversion from ISO-2022-JP-3 encoding, it is possible -to force iconv to emit extra NUL character on internal state reset. -To do this, it is sufficient to feed iconv with escape sequence -which switches active character set. -The simplified check 'data->__statep->__count != ASCII_set' -introduced by the aforementioned bugfix picks that case and -behaves as if '\0' character has been queued thus emitting it. - -To eliminate this issue, these steps are taken: -* Restore original condition -'(data->__statep->__count & ~7) != ASCII_set'. -It is necessary since bits 0-2 may contain -number of buffered input characters. -* Check that queued character is not NUL. -Similar step is taken for main conversion loop. - -Bundled test case follows following logic: -* Try to convert ISO-2022-JP-3 escape sequence -switching active character set -* Reset internal state by providing NULL as input buffer -* Ensure that nothing has been converted. - -Signed-off-by: Nikita Popov <npv1310@gmail.com> - -CVE: CVE-2021-43396 -Upstream-Status: Backport [ff012870b2c02a62598c04daa1e54632e020fd7d] ---- - iconvdata/Makefile | 5 +++- - iconvdata/bug-iconv15.c | 60 +++++++++++++++++++++++++++++++++++++++ - iconvdata/iso-2022-jp-3.c | 28 ++++++++++++------ - 3 files changed, 84 insertions(+), 9 deletions(-) - create mode 100644 iconvdata/bug-iconv15.c - -diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c -new file mode 100644 ---- /dev/null -+++ b/iconvdata/bug-iconv15.c -@@ -0,0 +1,60 @@ -+/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv -+ may emit spurious NUL character on state reset. -+ Copyright (C) The GNU Toolchain Authors. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <https://www.gnu.org/licenses/>. */ -+ -+#include <stddef.h> -+#include <iconv.h> -+#include <support/check.h> -+ -+static int -+do_test (void) -+{ -+ char in[] = "\x1b(I"; -+ char *inbuf = in; -+ size_t inleft = sizeof (in) - 1; -+ char out[1]; -+ char *outbuf = out; -+ size_t outleft = sizeof (out); -+ iconv_t cd; -+ -+ cd = iconv_open ("UTF8", "ISO-2022-JP-3"); -+ TEST_VERIFY_EXIT (cd != (iconv_t) -1); -+ -+ /* First call to iconv should alter internal state. -+ Now, JISX0201_Kana_set is selected and -+ state value != ASCII_set. */ -+ TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1); -+ -+ /* No bytes should have been added to -+ the output buffer at this point. */ -+ TEST_VERIFY (outbuf == out); -+ TEST_VERIFY (outleft == sizeof (out)); -+ -+ /* Second call shall emit spurious NUL character in unpatched glibc. */ -+ TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1); -+ -+ /* No characters are expected to be produced. */ -+ TEST_VERIFY (outbuf == out); -+ TEST_VERIFY (outleft == sizeof (out)); -+ -+ TEST_VERIFY_EXIT (iconv_close (cd) != -1); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c ---- a/iconvdata/iso-2022-jp-3.c -+++ b/iconvdata/iso-2022-jp-3.c -@@ -1,5 +1,6 @@ - /* Conversion module for ISO-2022-JP-3. - Copyright (C) 1998-2021 Free Software Foundation, Inc. -+ Copyright (C) The GNU Toolchain Authors. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998, - and Bruno Haible <bruno@clisp.org>, 2002. -@@ -81,20 +82,31 @@ enum - the output state to the initial state. This has to be done during the - flushing. */ - #define EMIT_SHIFT_TO_INIT \ -- if (data->__statep->__count != ASCII_set) \ -+ if ((data->__statep->__count & ~7) != ASCII_set) \ - { \ - if (FROM_DIRECTION) \ - { \ -- if (__glibc_likely (outbuf + 4 <= outend)) \ -+ uint32_t ch = data->__statep->__count >> 6; \ -+ \ -+ if (__glibc_unlikely (ch != 0)) \ - { \ -- /* Write out the last character. */ \ -- *((uint32_t *) outbuf) = data->__statep->__count >> 6; \ -- outbuf += sizeof (uint32_t); \ -- data->__statep->__count = ASCII_set; \ -+ if (__glibc_likely (outbuf + 4 <= outend)) \ -+ { \ -+ /* Write out the last character. */ \ -+ put32u (outbuf, ch); \ -+ outbuf += 4; \ -+ data->__statep->__count &= 7; \ -+ data->__statep->__count |= ASCII_set; \ -+ } \ -+ else \ -+ /* We don't have enough room in the output buffer. */ \ -+ status = __GCONV_FULL_OUTPUT; \ - } \ - else \ -- /* We don't have enough room in the output buffer. */ \ -- status = __GCONV_FULL_OUTPUT; \ -+ { \ -+ data->__statep->__count &= 7; \ -+ data->__statep->__count |= ASCII_set; \ -+ } \ - } \ - else \ - { \ -diff --git a/iconvdata/Makefile b/iconvdata/Makefile ---- a/iconvdata/Makefile -+++ b/iconvdata/Makefile -@@ -1,4 +1,5 @@ - # Copyright (C) 1997-2021 Free Software Foundation, Inc. -+# Copyright (C) The GNU Toolchain Authors. - # This file is part of the GNU C Library. - - # The GNU C Library is free software; you can redistribute it and/or -@@ -74,7 +75,7 @@ ifeq (yes,$(build-shared)) - tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ - tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ - bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \ -- bug-iconv13 bug-iconv14 -+ bug-iconv13 bug-iconv14 bug-iconv15 - ifeq ($(have-thread-library),yes) - tests += bug-iconv3 - endif -@@ -324,6 +325,8 @@ $(objpfx)bug-iconv12.out: $(objpfx)gconv - $(addprefix $(objpfx),$(modules.so)) - $(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \ - $(addprefix $(objpfx),$(modules.so)) -+$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ -+ $(addprefix $(objpfx),$(modules.so)) - - $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ - $(addprefix $(objpfx),$(modules.so)) \ diff --git a/meta/recipes-core/glibc/glibc_2.33.bb b/meta/recipes-core/glibc/glibc_2.33.bb index b7736359b1..a1e9eb3a16 100644 --- a/meta/recipes-core/glibc/glibc_2.33.bb +++ b/meta/recipes-core/glibc/glibc_2.33.bb @@ -56,7 +56,6 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ file://0028-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch \ file://0029-wordsize.h-Unify-the-header-between-arm-and-aarch64.patch \ file://0030-powerpc-Do-not-ask-compiler-for-finding-arch.patch \ - file://0031-CVE-2021-43396.patch \ " S = "${WORKDIR}/git" B = "${WORKDIR}/build-${TARGET_SYS}" diff --git a/meta/recipes-core/images/build-appliance-image_15.0.0.bb b/meta/recipes-core/images/build-appliance-image_15.0.0.bb index 455fe825c8..5631cd8ae6 100644 --- a/meta/recipes-core/images/build-appliance-image_15.0.0.bb +++ b/meta/recipes-core/images/build-appliance-image_15.0.0.bb @@ -24,7 +24,7 @@ IMAGE_FSTYPES = "wic.vmdk wic.vhd wic.vhdx" inherit core-image setuptools3 -SRCREV ?= "ec3ac9d883d53ebbf3c6b9a80694df69c9e9ccc7" +SRCREV ?= "2954fa87a4d325f1a3c722d6fb8bf13b17f9e7a0" SRC_URI = "git://git.yoctoproject.org/poky;branch=hardknott \ file://Yocto_Build_Appliance.vmx \ file://Yocto_Build_Appliance.vmxf \ diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/finish b/meta/recipes-core/initrdscripts/initramfs-framework/finish index 717383ebac..f08a920867 100755 --- a/meta/recipes-core/initrdscripts/initramfs-framework/finish +++ b/meta/recipes-core/initrdscripts/initramfs-framework/finish @@ -12,6 +12,18 @@ finish_run() { fatal "ERROR: There's no '/dev' on rootfs." fi + # Unmount anything that was automounted by busybox via mdev-mount.sh. + # We're about to switch_root, and leaving anything mounted will prevent + # the next rootfs from modifying the block device. Ignore ROOT_DISK, + # if it was set by setup-live, because it'll be mounted over loopback + # to ROOTFS_DIR. + local dev + for dev in /run/media/*; do + if mountpoint -q "${dev}" && [ "${dev##*/}" != "${ROOT_DISK}" ]; then + umount -f "${dev}" || debug "Failed to unmount ${dev}" + fi + done + info "Switching root to '$ROOTFS_DIR'..." debug "Moving /dev, /proc and /sys onto rootfs..." diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch new file mode 100644 index 0000000000..eefecb9adb --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch @@ -0,0 +1,99 @@ +From 646fe48d1c8a74310c409ddf81fe7df6700052af Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Tue, 22 Feb 2022 11:51:08 +0100 +Subject: [PATCH] Fix --without-valid build + +Regressed in commit 652dd12a. +--- + valid.c | 58 ++++++++++++++++++++++++++++----------------------------- + 1 file changed, 29 insertions(+), 29 deletions(-) +--- + +From https://github.com/GNOME/libxml2.git + commit 646fe48d1c8a74310c409ddf81fe7df6700052af + +CVE: CVE-2022-23308 +Upstream-status: Backport + +Signed-off-by: Joe Slater <joe.slater@windriver.com> + + +diff --git a/valid.c b/valid.c +index 8e596f1d..9684683a 100644 +--- a/valid.c ++++ b/valid.c +@@ -479,35 +479,6 @@ 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) { +@@ -2636,6 +2607,35 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + ++/** ++ * 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; ++} ++ + static int + xmlIsStreaming(xmlValidCtxtPtr ctxt) { + xmlParserCtxtPtr pctxt; +-- +2.35.1 + 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..708a98b45a --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch @@ -0,0 +1,209 @@ +From 652dd12a858989b14eed4e84e453059cd3ba340e Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Tue, 8 Feb 2022 03:29:24 +0100 +Subject: [PATCH] [CVE-2022-23308] Use-after-free of ID and IDREF attributes + +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(-) + --- + +From https://github.com/GNOME/libxml2.git + commit 652dd12a858989b14eed4e84e453059cd3ba340e + +Remove patch to ns1.xml.rdr which does not exist in version 2.9.10. + +CVE: CVE-2022-23308 +Upstream-status: Backport + +Signed-off-by: Joe Slater <joe.slater@windriver.com> + + +diff --git a/valid.c b/valid.c +index 5ee391c0..8e596f1d 100644 +--- 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, xmlNotationTablePtr table) { + (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 doc, const xmlChar *value, + 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 doc, const xmlChar *value, + */ + 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 attr) { + 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, xmlDocPtr doc, const xmlChar *value, + * 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(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + 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(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + 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(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + 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(xmlDocPtr doc, xmlNodePtr elem, + 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); + } + +-- +2.25.1 + diff --git a/meta/recipes-core/libxml/libxml2_2.9.10.bb b/meta/recipes-core/libxml/libxml2_2.9.10.bb index cabf911816..778312f662 100644 --- a/meta/recipes-core/libxml/libxml2_2.9.10.bb +++ b/meta/recipes-core/libxml/libxml2_2.9.10.bb @@ -30,6 +30,8 @@ SRC_URI = "http://www.xmlsoft.org/sources/libxml2-${PV}.tar.gz;name=libtar \ file://CVE-2021-3518-0002.patch \ file://CVE-2021-3537.patch \ file://CVE-2021-3541.patch \ + file://CVE-2022-23308.patch \ + file://CVE-2022-23308-fix-regression.patch \ " SRC_URI[libtar.md5sum] = "10942a1dc23137a8aa07f0639cbfece5" diff --git a/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch b/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch new file mode 100644 index 0000000000..5cb6183641 --- /dev/null +++ b/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch @@ -0,0 +1,347 @@ +CVE: CVE-2018-25032 +Upstream-Status: Backport +Signed-off-by: Ross Burton <ross.burton@arm.com> + +From 5c44459c3b28a9bd3283aaceab7c615f8020c531 Mon Sep 17 00:00:00 2001 +From: Mark Adler <madler@alumni.caltech.edu> +Date: Tue, 17 Apr 2018 22:09:22 -0700 +Subject: [PATCH] Fix a bug that can crash deflate on some input when using + Z_FIXED. + +This bug was reported by Danilo Ramos of Eideticom, Inc. It has +lain in wait 13 years before being found! The bug was introduced +in zlib 1.2.2.2, with the addition of the Z_FIXED option. That +option forces the use of fixed Huffman codes. For rare inputs with +a large number of distant matches, the pending buffer into which +the compressed data is written can overwrite the distance symbol +table which it overlays. That results in corrupted output due to +invalid distances, and can result in out-of-bound accesses, +crashing the application. + +The fix here combines the distance buffer and literal/length +buffers into a single symbol buffer. Now three bytes of pending +buffer space are opened up for each literal or length/distance +pair consumed, instead of the previous two bytes. This assures +that the pending buffer cannot overwrite the symbol table, since +the maximum fixed code compressed length/distance is 31 bits, and +since there are four bytes of pending space for every three bytes +of symbol space. +--- + deflate.c | 74 ++++++++++++++++++++++++++++++++++++++++--------------- + deflate.h | 25 +++++++++---------- + trees.c | 50 +++++++++++-------------------------- + 3 files changed, 79 insertions(+), 70 deletions(-) + +diff --git a/deflate.c b/deflate.c +index 425babc00..19cba873a 100644 +--- a/deflate.c ++++ b/deflate.c +@@ -255,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + +- ushf *overlay; +- /* We overlay pending_buf and d_buf+l_buf. This works since the average +- * output size for (length,distance) codes is <= 24 bits. +- */ +- + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; +@@ -329,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + +- overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); +- s->pending_buf = (uchf *) overlay; +- s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); ++ /* We overlay pending_buf and sym_buf. This works since the average size ++ * for length/distance pairs over any compressed block is assured to be 31 ++ * bits or less. ++ * ++ * Analysis: The longest fixed codes are a length code of 8 bits plus 5 ++ * extra bits, for lengths 131 to 257. The longest fixed distance codes are ++ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest ++ * possible fixed-codes length/distance pair is then 31 bits total. ++ * ++ * sym_buf starts one-fourth of the way into pending_buf. So there are ++ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol ++ * in sym_buf is three bytes -- two for the distance and one for the ++ * literal/length. As each symbol is consumed, the pointer to the next ++ * sym_buf value to read moves forward three bytes. From that symbol, up to ++ * 31 bits are written to pending_buf. The closest the written pending_buf ++ * bits gets to the next sym_buf symbol to read is just before the last ++ * code is written. At that time, 31*(n-2) bits have been written, just ++ * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at ++ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 ++ * symbols are written.) The closest the writing gets to what is unread is ++ * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and ++ * can range from 128 to 32768. ++ * ++ * Therefore, at a minimum, there are 142 bits of space between what is ++ * written and what is read in the overlain buffers, so the symbols cannot ++ * be overwritten by the compressed data. That space is actually 139 bits, ++ * due to the three-bit fixed-code block header. ++ * ++ * That covers the case where either Z_FIXED is specified, forcing fixed ++ * codes, or when the use of fixed codes is chosen, because that choice ++ * results in a smaller compressed block than dynamic codes. That latter ++ * condition then assures that the above analysis also covers all dynamic ++ * blocks. A dynamic-code block will only be chosen to be emitted if it has ++ * fewer bits than a fixed-code block would for the same set of symbols. ++ * Therefore its average symbol length is assured to be less than 31. So ++ * the compressed data for a dynamic block also cannot overwrite the ++ * symbols from which it is being constructed. ++ */ ++ ++ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); ++ s->pending_buf_size = (ulg)s->lit_bufsize * 4; + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { +@@ -340,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + deflateEnd (strm); + return Z_MEM_ERROR; + } +- s->d_buf = overlay + s->lit_bufsize/sizeof(ush); +- s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; ++ s->sym_buf = s->pending_buf + s->lit_bufsize; ++ s->sym_end = (s->lit_bufsize - 1) * 3; ++ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K ++ * on 16 bit machines and because stored blocks are restricted to ++ * 64K-1 bytes. ++ */ + + s->level = level; + s->strategy = strategy; +@@ -552,7 +589,7 @@ int ZEXPORT deflatePrime (strm, bits, value) + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; +- if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) ++ if (s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; +@@ -1113,7 +1150,6 @@ int ZEXPORT deflateCopy (dest, source) + #else + deflate_state *ds; + deflate_state *ss; +- ushf *overlay; + + + if (deflateStateCheck(source) || dest == Z_NULL) { +@@ -1133,8 +1169,7 @@ int ZEXPORT deflateCopy (dest, source) + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); +- overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); +- ds->pending_buf = (uchf *) overlay; ++ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4); + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { +@@ -1148,8 +1183,7 @@ int ZEXPORT deflateCopy (dest, source) + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); +- ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); +- ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ++ ds->sym_buf = ds->pending_buf + ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; +@@ -1925,7 +1959,7 @@ local block_state deflate_fast(s, flush) + FLUSH_BLOCK(s, 1); + return finish_done; + } +- if (s->last_lit) ++ if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; + } +@@ -2056,7 +2090,7 @@ local block_state deflate_slow(s, flush) + FLUSH_BLOCK(s, 1); + return finish_done; + } +- if (s->last_lit) ++ if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; + } +@@ -2131,7 +2165,7 @@ local block_state deflate_rle(s, flush) + FLUSH_BLOCK(s, 1); + return finish_done; + } +- if (s->last_lit) ++ if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; + } +@@ -2170,7 +2204,7 @@ local block_state deflate_huff(s, flush) + FLUSH_BLOCK(s, 1); + return finish_done; + } +- if (s->last_lit) ++ if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; + } +diff --git a/deflate.h b/deflate.h +index 23ecdd312..d4cf1a98b 100644 +--- a/deflate.h ++++ b/deflate.h +@@ -217,7 +217,7 @@ typedef struct internal_state { + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + +- uchf *l_buf; /* buffer for literals or lengths */ ++ uchf *sym_buf; /* buffer for distances and literals/lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for +@@ -239,13 +239,8 @@ typedef struct internal_state { + * - I can't count above 4 + */ + +- uInt last_lit; /* running index in l_buf */ +- +- ushf *d_buf; +- /* Buffer for distances. To simplify the code, d_buf and l_buf have +- * the same number of elements. To use different lengths, an extra flag +- * array would be necessary. +- */ ++ uInt sym_next; /* running index in sym_buf */ ++ uInt sym_end; /* symbol table full when sym_next reaches this */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ +@@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + + # define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ +- s->d_buf[s->last_lit] = 0; \ +- s->l_buf[s->last_lit++] = cc; \ ++ s->sym_buf[s->sym_next++] = 0; \ ++ s->sym_buf[s->sym_next++] = 0; \ ++ s->sym_buf[s->sym_next++] = cc; \ + s->dyn_ltree[cc].Freq++; \ +- flush = (s->last_lit == s->lit_bufsize-1); \ ++ flush = (s->sym_next == s->sym_end); \ + } + # define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ +- s->d_buf[s->last_lit] = dist; \ +- s->l_buf[s->last_lit++] = len; \ ++ s->sym_buf[s->sym_next++] = dist; \ ++ s->sym_buf[s->sym_next++] = dist >> 8; \ ++ s->sym_buf[s->sym_next++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ +- flush = (s->last_lit == s->lit_bufsize-1); \ ++ flush = (s->sym_next == s->sym_end); \ + } + #else + # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +diff --git a/trees.c b/trees.c +index 4f4a65011..decaeb7c3 100644 +--- a/trees.c ++++ b/trees.c +@@ -416,7 +416,7 @@ local void init_block(s) + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; +- s->last_lit = s->matches = 0; ++ s->sym_next = s->matches = 0; + } + + #define SMALLEST 1 +@@ -948,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, +- s->last_lit)); ++ s->sym_next / 3)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + +@@ -1017,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + { +- s->d_buf[s->last_lit] = (ush)dist; +- s->l_buf[s->last_lit++] = (uch)lc; ++ s->sym_buf[s->sym_next++] = dist; ++ s->sym_buf[s->sym_next++] = dist >> 8; ++ s->sym_buf[s->sym_next++] = lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; +@@ -1033,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } +- +-#ifdef TRUNCATE_BLOCK +- /* Try to guess if it is profitable to stop the current block here */ +- if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { +- /* Compute an upper bound for the compressed length */ +- ulg out_length = (ulg)s->last_lit*8L; +- ulg in_length = (ulg)((long)s->strstart - s->block_start); +- int dcode; +- for (dcode = 0; dcode < D_CODES; dcode++) { +- out_length += (ulg)s->dyn_dtree[dcode].Freq * +- (5L+extra_dbits[dcode]); +- } +- out_length >>= 3; +- Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", +- s->last_lit, in_length, out_length, +- 100L - out_length*100L/in_length)); +- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; +- } +-#endif +- return (s->last_lit == s->lit_bufsize-1); +- /* We avoid equality with lit_bufsize because of wraparound at 64K +- * on 16 bit machines and because stored blocks are restricted to +- * 64K-1 bytes. +- */ ++ return (s->sym_next == s->sym_end); + } + + /* =========================================================================== +@@ -1069,13 +1047,14 @@ local void compress_block(s, ltree, dtree) + { + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ +- unsigned lx = 0; /* running index in l_buf */ ++ unsigned sx = 0; /* running index in sym_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + +- if (s->last_lit != 0) do { +- dist = s->d_buf[lx]; +- lc = s->l_buf[lx++]; ++ if (s->sym_next != 0) do { ++ dist = s->sym_buf[sx++] & 0xff; ++ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; ++ lc = s->sym_buf[sx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); +@@ -1100,11 +1079,10 @@ local void compress_block(s, ltree, dtree) + } + } /* literal or match pair ? */ + +- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ +- Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, +- "pendingBuf overflow"); ++ /* Check that the overlay between pending_buf and sym_buf is ok: */ ++ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); + +- } while (lx < s->last_lit); ++ } while (sx < s->sym_next); + + send_code(s, END_BLOCK, ltree); + } diff --git a/meta/recipes-core/zlib/zlib_1.2.11.bb b/meta/recipes-core/zlib/zlib_1.2.11.bb index ef9431ae47..bc42cd64e9 100644 --- a/meta/recipes-core/zlib/zlib_1.2.11.bb +++ b/meta/recipes-core/zlib/zlib_1.2.11.bb @@ -8,6 +8,7 @@ LIC_FILES_CHKSUM = "file://zlib.h;beginline=6;endline=23;md5=5377232268e952e9ef6 SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/${BPN}/${PV}/${BPN}-${PV}.tar.xz \ file://ldflags-tests.patch \ + file://CVE-2018-25032.patch \ file://run-ptest \ " UPSTREAM_CHECK_URI = "http://zlib.net/" |