From 95cda88907ba3ad283ea61a5922b8c7899cc4f9c Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Fri, 20 Feb 2026 07:20:46 +0000 Subject: [PATCH] Patch libsoup for CVE-2026-2443 --- SPECS/libsoup/CVE-2026-2443.patch | 340 ++++++++++++++++++++++++++++++ SPECS/libsoup/libsoup.spec | 6 +- 2 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 SPECS/libsoup/CVE-2026-2443.patch diff --git a/SPECS/libsoup/CVE-2026-2443.patch b/SPECS/libsoup/CVE-2026-2443.patch new file mode 100644 index 00000000000..f25dd90b9bc --- /dev/null +++ b/SPECS/libsoup/CVE-2026-2443.patch @@ -0,0 +1,340 @@ +From f74004bdd775c41b2a395799a6219f0fa81729fd Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Fri, 19 Dec 2025 23:49:05 +0000 +Subject: [PATCH 1/7] soup-message-headers: Reject invalid Range ends longer + than the content + +If the `Range` header in a request specifies a range longer than the +full content, it should be rejected. Previously, only the start of the +range was validated, rather than the start and the end. This led to an +assertion failure in `g_bytes_new_from_bytes()` (or a buffer overflow if +GLib was compiled with `G_DISABLE_CHECKS`, which is not recommended). + +Add the missing check on the Range end, and add a unit test. + +Spotted by Codean Labs. + +Signed-off-by: Philip Withnall + +Fixes: #487 +--- + libsoup/soup-message-headers.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c +index 9a5e101..3d7157a 100644 +--- a/libsoup/soup-message-headers.c ++++ b/libsoup/soup-message-headers.c +@@ -1200,7 +1200,9 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + if (*end) { + status = SOUP_STATUS_OK; + break; +- } else if (check_satisfiable && cur.start >= total_length) { ++ } else if (check_satisfiable && ++ (cur.start >= total_length || ++ cur.end >= total_length)) { + if (status == SOUP_STATUS_OK) + status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + continue; +-- +2.45.4 + + +From bfefe646aedbe2d67dd1a90837b6f071fa0b66e2 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Fri, 19 Dec 2025 23:51:52 +0000 +Subject: [PATCH 2/7] soup-message-headers: Reject ranges where end is before + start + +Previously this returned HTTP status 200 OK, which is not what MDN says +should happen for an invalid range: +https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Range. + +Add a unit test. + +Signed-off-by: Philip Withnall +--- + libsoup/soup-message-headers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c +index 3d7157a..4d8f0b8 100644 +--- a/libsoup/soup-message-headers.c ++++ b/libsoup/soup-message-headers.c +@@ -1191,7 +1191,7 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + if (*end) { + cur.end = g_ascii_strtoull (end, &end, 10); + if (cur.end < cur.start) { +- status = SOUP_STATUS_OK; ++ status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + break; + } + } else +-- +2.45.4 + + +From b80120f89a4a2fa138ae2aa03807d363a9144098 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Sat, 20 Dec 2025 00:14:00 +0000 +Subject: [PATCH 3/7] soup-message-headers: Fix parsing of invalid Range suffix + lengths + +The way the parser for the `Range` header is implemented, this would +result in a range with an end 1 byte before its start. + +Add a unit test. + +Signed-off-by: Philip Withnall +--- + libsoup/soup-message-headers.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c +index 4d8f0b8..a4285a9 100644 +--- a/libsoup/soup-message-headers.c ++++ b/libsoup/soup-message-headers.c +@@ -1184,6 +1184,10 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + if (*spec == '-') { + cur.start = g_ascii_strtoll (spec, &end, 10) + total_length; + cur.end = total_length - 1; ++ if (cur.end < cur.start) { ++ status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; ++ break; ++ } + } else { + cur.start = g_ascii_strtoull (spec, &end, 10); + if (*end == '-') +-- +2.45.4 + + +From 0ffc98a5d3edcb0d92050a6e7fa3edb0f1fb0624 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Sat, 20 Dec 2025 00:18:25 +0000 +Subject: [PATCH 4/7] soup-message-headers: Fix rejection of Range headers with + trailing garbage +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If there’s unparseable content after a range, reject the header as +invalid rather than ignoring it and returning status 200 OK. + +Add a unit test. + +Signed-off-by: Philip Withnall +--- + libsoup/soup-message-headers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c +index a4285a9..7a33c5e 100644 +--- a/libsoup/soup-message-headers.c ++++ b/libsoup/soup-message-headers.c +@@ -1202,7 +1202,7 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + cur.end = total_length - 1; + } + if (*end) { +- status = SOUP_STATUS_OK; ++ status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + break; + } else if (check_satisfiable && + (cur.start >= total_length || +-- +2.45.4 + + +From c8b98212716b6c2ebe2bc943e062ac5ae2180440 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Thu, 25 Dec 2025 23:16:02 +0000 +Subject: [PATCH 5/7] tests: Allow range tests to check more response statuses + +Currently the tests can either assert that a response to a Range request +is HTTP 206 (Partial Content) or HTTP 416 (Range Not Satisfiable). +However, many of the states resulting from parsing a Range header +actually should have a HTTP 200 (OK) response, where the Range header is +ignored due to being completely invalid. This is what Apache does when, +for example, given a Range header where the end of the range is before +the start. + +Add some extra arguments to the helper functions in `range-test.c` to +allow the expected response status and expected response start and end +(of the full response) to be given by the test, and change the existing +tests to use these extra arguments. + +This introduces no behavioural changes for now, but will allow following +commits to test their status 200 responses. + +Signed-off-by: Philip Withnall +-- +2.45.4 + + +From de53063c742d4174ac03dfeb302bba4cdc3dc4b6 Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Thu, 25 Dec 2025 23:20:03 +0000 +Subject: [PATCH 6/7] soup-message-headers: Rework Range response statuses to + match Apache + +And for the parsing logic to more closely match the wording of the +HTTP specification (https://httpwg.org/specs/rfc9110.html#field.range). + +The previous behaviour (from my previous few commits) was potentially +correct according to the spec, but differed from what Apache implements, +so was inadvisable. Specifically, the code returned HTTP 416 for various +parsing errors on the Range header; whereas Apache ignores completely +invalid Range headers and returns HTTP 200 with the full response. For +partially invalid Range headers, it returns the valid ranges. + +Implement that behaviour instead, and rework the structure of the Range +parsing code to (hopefully) make that intent clearer. For example, +separate the string parsing code from the numeric range checks, and +separate those from the decision about which HTTP status to return. + +Signed-off-by: Philip Withnall + +Helps: #487 +--- + libsoup/soup-message-headers.c | 68 ++++++++++++++++++++++------------ + 1 file changed, 44 insertions(+), 24 deletions(-) + +diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c +index 7a33c5e..41d56b8 100644 +--- a/libsoup/soup-message-headers.c ++++ b/libsoup/soup-message-headers.c +@@ -1143,10 +1143,16 @@ sort_ranges (gconstpointer a, gconstpointer b) + } + + /* like soup_message_headers_get_ranges(), except it returns: +- * SOUP_STATUS_OK if there is no Range or it should be ignored. +- * SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range. +- * SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable +- * is %TRUE and the request is not satisfiable given @total_length. ++ * - SOUP_STATUS_OK if there is no Range or it should be ignored due to being ++ * entirely invalid. ++ * - SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range. ++ * - SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable ++ * is %TRUE, the Range is valid, but no part of the request is satisfiable ++ * given @total_length. ++ * ++ * @ranges and @length are only set if SOUP_STATUS_PARTIAL_CONTENT is returned. ++ * ++ * See https://httpwg.org/specs/rfc9110.html#field.range + */ + guint + soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, +@@ -1160,22 +1166,28 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + GArray *array; + char *spec, *end; + guint status = SOUP_STATUS_OK; ++ gboolean is_all_valid = TRUE; + + if (!range || strncmp (range, "bytes", 5) != 0) +- return status; ++ return SOUP_STATUS_OK; /* invalid header or unknown range unit */ + + range += 5; + while (g_ascii_isspace (*range)) + range++; + if (*range++ != '=') +- return status; ++ return SOUP_STATUS_OK; /* invalid header */ + while (g_ascii_isspace (*range)) + range++; + + range_list = soup_header_parse_list (range); + if (!range_list) +- return status; ++ return SOUP_STATUS_OK; /* invalid list */ + ++ /* Loop through the ranges and modify the status accordingly. Default to ++ * status 200 (OK, ignoring the ranges). Switch to status 206 (Partial ++ * Content) if there is at least one partially valid range. Switch to ++ * status 416 (Range Not Satisfiable) if there are no partially valid ++ * ranges at all. */ + array = g_array_new (FALSE, FALSE, sizeof (SoupRange)); + for (r = range_list; r; r = r->next) { + SoupRange cur; +@@ -1184,40 +1196,48 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + if (*spec == '-') { + cur.start = g_ascii_strtoll (spec, &end, 10) + total_length; + cur.end = total_length - 1; +- if (cur.end < cur.start) { +- status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; +- break; +- } + } else { + cur.start = g_ascii_strtoull (spec, &end, 10); + if (*end == '-') + end++; +- if (*end) { ++ if (*end) + cur.end = g_ascii_strtoull (end, &end, 10); +- if (cur.end < cur.start) { +- status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; +- break; +- } +- } else ++ else + cur.end = total_length - 1; + } ++ + if (*end) { +- status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; +- break; +- } else if (check_satisfiable && +- (cur.start >= total_length || +- cur.end >= total_length)) { +- if (status == SOUP_STATUS_OK) +- status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; ++ /* Junk after the range */ ++ is_all_valid = FALSE; + continue; + } + ++ if (cur.end < cur.start) { ++ is_all_valid = FALSE; ++ continue; ++ } ++ ++ g_assert (cur.start >= 0); ++ if (cur.end >= total_length) ++ cur.end = total_length - 1; ++ ++ if (cur.start >= total_length) { ++ /* Range is valid, but unsatisfiable */ ++ continue; ++ } ++ ++ /* We have at least one (at least partially) satisfiable range */ + g_array_append_val (array, cur); + status = SOUP_STATUS_PARTIAL_CONTENT; + } + soup_header_free_list (range_list); + + if (status != SOUP_STATUS_PARTIAL_CONTENT) { ++ g_assert (status == SOUP_STATUS_OK); ++ ++ if (is_all_valid && check_satisfiable) ++ status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; ++ + g_array_free (array, TRUE); + return status; + } +-- +2.45.4 + + +From a3633a263631348abd9c2036170bdfe9facef04d Mon Sep 17 00:00:00 2001 +From: Philip Withnall +Date: Thu, 25 Dec 2025 23:50:30 +0000 +Subject: [PATCH 7/7] tests: Add more tests for invalid Range headers + +This gives full line and branch coverage of +`soup_message_headers_get_ranges_internal()`. + +Signed-off-by: Philip Withnall +-- +2.45.4 + diff --git a/SPECS/libsoup/libsoup.spec b/SPECS/libsoup/libsoup.spec index 413c7f7b6dc..b48ec6d9a07 100644 --- a/SPECS/libsoup/libsoup.spec +++ b/SPECS/libsoup/libsoup.spec @@ -4,7 +4,7 @@ Summary: libsoup HTTP client/server library Name: libsoup Version: 3.4.4 -Release: 12%{?dist} +Release: 13%{?dist} License: GPLv2 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -74,6 +74,7 @@ Patch24: CVE-2026-1467.patch Patch25: CVE-2026-1536.patch Patch26: CVE-2026-1761.patch Patch27: CVE-2026-1801.patch +Patch28: CVE-2026-2443.patch %description libsoup is HTTP client/server library for GNOME @@ -141,6 +142,9 @@ find %{buildroot} -type f -name "*.la" -delete -print %defattr(-,root,root) %changelog +* Fri Feb 20 2026 Azure Linux Security Servicing Account - 3.4.4-13 +- Patch for CVE-2026-2443 + * Mon Feb 09 2026 Azure Linux Security Servicing Account - 3.4.4-12 - Patch for CVE-2026-1801, CVE-2026-1761, CVE-2026-1536, CVE-2025-32049, CVE-2026-1467