From 843199ca919c1127f1b89f365896e3f171bb38b6 Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Tue, 17 Feb 2026 06:12:42 +0000 Subject: [PATCH] Patch libsoup for CVE-2026-1760, CVE-2026-0716 --- SPECS/libsoup/CVE-2026-0716.patch | 102 +++++++++++++++++++ SPECS/libsoup/CVE-2026-1760.patch | 159 ++++++++++++++++++++++++++++++ SPECS/libsoup/libsoup.spec | 7 +- 3 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 SPECS/libsoup/CVE-2026-0716.patch create mode 100644 SPECS/libsoup/CVE-2026-1760.patch diff --git a/SPECS/libsoup/CVE-2026-0716.patch b/SPECS/libsoup/CVE-2026-0716.patch new file mode 100644 index 00000000000..00f5badb0ef --- /dev/null +++ b/SPECS/libsoup/CVE-2026-0716.patch @@ -0,0 +1,102 @@ +From 88ed9cc700ff5d1a40b1e09918c6f09d435da76b Mon Sep 17 00:00:00 2001 +From: Mike Gorse +Date: Mon, 2 Feb 2026 10:46:00 -0600 +Subject: [PATCH] websocket: Fix out-of-bounds read in process_frame + +If the maximum incoming payload size is unset, then a malicious frame could +cause an overflow when calculating the needed amount of data, leading to an +out-of-bounds read later. + +This is CVE-2026-0716. + +Closes #476 + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/494.patch +--- + libsoup/websocket/soup-websocket-connection.c | 6 +++ + tests/websocket-test.c | 44 +++++++++++++++++++ + 2 files changed, 50 insertions(+) + +diff --git a/libsoup/websocket/soup-websocket-connection.c b/libsoup/websocket/soup-websocket-connection.c +index ef54ab6..5d14006 100644 +--- a/libsoup/websocket/soup-websocket-connection.c ++++ b/libsoup/websocket/soup-websocket-connection.c +@@ -1096,6 +1096,12 @@ process_frame (SoupWebsocketConnection *self) + payload += 4; + at += 4; + ++ /* at has a maximum value of 10 + 4 = 14 */ ++ if (payload_len > G_MAXSIZE - 14) { ++ bad_data_error_and_close (self); ++ return FALSE; ++ } ++ + if (len < at + payload_len) + return FALSE; /* need more data */ + +diff --git a/tests/websocket-test.c b/tests/websocket-test.c +index a7fc7e9..bd866d4 100644 +--- a/tests/websocket-test.c ++++ b/tests/websocket-test.c +@@ -2170,6 +2170,41 @@ test_connection_error (void) + soup_test_session_abort_unref (session); + } + ++static void ++test_cve_2026_0716 (Test *test, ++ gconstpointer unused) ++{ ++ GError *error = NULL; ++ GIOStream *io; ++ gsize written; ++ const char *frame; ++ gboolean close_event = FALSE; ++ ++ g_signal_handlers_disconnect_by_func (test->server, on_error_not_reached, NULL); ++ g_signal_connect (test->server, "error", G_CALLBACK (on_error_copy), &error); ++ g_signal_connect (test->client, "closed", G_CALLBACK (on_close_set_flag), &close_event); ++ ++ io = soup_websocket_connection_get_io_stream (test->client); ++ ++ soup_websocket_connection_set_max_incoming_payload_size (test->server, 0); ++ ++ // Malicious masked frame header (10-byte header + 4-byte mask) */ ++ frame = "\x82\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xaa\xbb\xcc\xdd"; ++ if (!g_output_stream_write_all (g_io_stream_get_output_stream (io), ++ frame, 14, &written, NULL, NULL)) ++ g_assert_cmpstr ("This code", ==, "should not be reached"); ++ g_assert_cmpuint (written, ==, 14); ++ ++ WAIT_UNTIL (error != NULL); ++ g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_CLOSE_BAD_DATA); ++ g_clear_error (&error); ++ ++ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED); ++ g_assert_true (close_event); ++ ++ g_assert_cmpuint (soup_websocket_connection_get_close_code (test->client), ==, SOUP_WEBSOCKET_CLOSE_BAD_DATA); ++} ++ + int + main (int argc, + char *argv[]) +@@ -2441,6 +2476,15 @@ main (int argc, + + g_test_add_func ("/websocket/soup/connection-error", test_connection_error); + ++ g_test_add ("/websocket/direct/cve-2026-0716", Test, NULL, ++ setup_direct_connection, ++ test_cve_2026_0716, ++ teardown_direct_connection); ++ g_test_add ("/websocket/soup/cve-2026-0716", Test, NULL, ++ setup_soup_connection, ++ test_cve_2026_0716, ++ teardown_soup_connection); ++ + ret = g_test_run (); + + test_cleanup (); +-- +2.45.4 + diff --git a/SPECS/libsoup/CVE-2026-1760.patch b/SPECS/libsoup/CVE-2026-1760.patch new file mode 100644 index 00000000000..50f81a3fb01 --- /dev/null +++ b/SPECS/libsoup/CVE-2026-1760.patch @@ -0,0 +1,159 @@ +From 88e2c97ac8bd202de4a8b8357fe88e7e4d5afe66 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 17 Feb 2026 02:44:11 +0000 +Subject: [PATCH] server: close the connection after responsing a request + containing Content-Length and Transfer-Encoding + +Closes #475 + +- Recompute encoding lazily prioritizing Transfer-Encoding over Content-Length. +- Ensure server closes connection when both headers are present by setting Connection: close. + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport from existing Build 1050366 of https://gitlab.gnome.org/GNOME/libsoup/-/commit/30b682af333402eeef4fad3acbc865771f85281a.patch +--- + libsoup/server/soup-server-io.c | 9 ++++ + libsoup/soup-message-headers.c | 88 +++++++++++++++------------------ + 2 files changed, 50 insertions(+), 47 deletions(-) + +diff --git a/libsoup/server/soup-server-io.c b/libsoup/server/soup-server-io.c +index 7e9cc45..0efb9b7 100644 +--- a/libsoup/server/soup-server-io.c ++++ b/libsoup/server/soup-server-io.c +@@ -599,6 +599,15 @@ parse_headers (SoupServerMessage *msg, + return SOUP_STATUS_BAD_REQUEST; + } + ++ /* A server MAY reject a request that contains both Content-Length and ++ * Transfer-Encoding or process such a request in accordance with the ++ * Transfer-Encoding alone. Regardless, the server MUST close the connection ++ * after responding to such a request to avoid the potential attacks ++ */ ++ if (*encoding == SOUP_ENCODING_CHUNKED && soup_message_headers_get_one_common (request_headers, SOUP_HEADER_CONTENT_LENGTH)) ++ soup_message_headers_replace_common (request_headers, SOUP_HEADER_CONNECTION, "close", TRUE); ++ ++ + /* Generate correct context for request */ + req_host = soup_message_headers_get_one_common (request_headers, SOUP_HEADER_HOST); + if (req_host && strchr (req_host, '/')) { +diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c +index d71a2cf..1a6be25 100644 +--- a/libsoup/soup-message-headers.c ++++ b/libsoup/soup-message-headers.c +@@ -155,19 +155,8 @@ soup_message_headers_set (SoupMessageHeaders *hdrs, + { + switch (name) { + case SOUP_HEADER_CONTENT_LENGTH: +- if (hdrs->encoding == SOUP_ENCODING_CHUNKED) +- return; +- +- if (value) { +- char *end; +- +- hdrs->content_length = g_ascii_strtoull (value, &end, 10); +- if (*end) +- hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED; +- else +- hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH; +- } else +- hdrs->encoding = -1; ++ case SOUP_HEADER_TRANSFER_ENCODING: ++ hdrs->encoding = -1; + break; + case SOUP_HEADER_CONTENT_TYPE: + g_clear_pointer (&hdrs->content_type, g_free); +@@ -193,21 +182,7 @@ soup_message_headers_set (SoupMessageHeaders *hdrs, + } else + hdrs->expectations = 0; + break; +- case SOUP_HEADER_TRANSFER_ENCODING: +- if (value) { +- /* "identity" is a wrong value according to RFC errata 408, +- * and RFC 7230 does not list it as valid transfer-coding. +- * Nevertheless, the obsolete RFC 2616 stated "identity" +- * as valid, so we can't handle it as unrecognized here +- * for compatibility reasons. +- */ +- if (g_ascii_strcasecmp (value, "chunked") == 0) +- hdrs->encoding = SOUP_ENCODING_CHUNKED; +- else if (g_ascii_strcasecmp (value, "identity") != 0) +- hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED; +- } else +- hdrs->encoding = -1; +- break; ++ /* SOUP_HEADER_TRANSFER_ENCODING handled by recomputing encoding lazily */ + default: + break; + } +@@ -951,30 +926,49 @@ soup_message_headers_foreach (SoupMessageHeaders *hdrs, + SoupEncoding + soup_message_headers_get_encoding (SoupMessageHeaders *hdrs) + { +- const char *header; ++ const char *content_length; ++ const char *transfer_encoding; + + if (hdrs->encoding != -1) + return hdrs->encoding; + +- /* If Transfer-Encoding was set, hdrs->encoding would already +- * be set. So we don't need to check that possibility. +- */ +- header = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_LENGTH); +- if (header) { +- soup_message_headers_set (hdrs, SOUP_HEADER_CONTENT_LENGTH, header); +- if (hdrs->encoding != -1) +- return hdrs->encoding; +- } ++ /* Transfer-Encoding is checked first because it overrides the Content-Length */ ++ transfer_encoding = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_TRANSFER_ENCODING); ++ if (transfer_encoding) { ++ /* "identity" is a wrong value according to RFC errata 408, ++ * and RFC 7230 does not list it as valid transfer-coding. ++ * Nevertheless, the obsolete RFC 2616 stated "identity" ++ * as valid, so we can't handle it as unrecognized here ++ * for compatibility reasons. ++ */ ++ if (g_ascii_strcasecmp (transfer_encoding, "chunked") == 0) ++ hdrs->encoding = SOUP_ENCODING_CHUNKED; ++ else if (g_ascii_strcasecmp (transfer_encoding, "identity") != 0) ++ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED; ++ } else { ++ content_length = soup_message_headers_get_one_common (hdrs, SOUP_HEADER_CONTENT_LENGTH); ++ if (content_length) { ++ char *end; + +- /* Per RFC 2616 4.4, a response body that doesn't indicate its +- * encoding otherwise is terminated by connection close, and a +- * request that doesn't indicate otherwise has no body. Note +- * that SoupMessage calls soup_message_headers_set_encoding() +- * to override the response body default for our own +- * server-side messages. +- */ +- hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ? +- SOUP_ENCODING_EOF : SOUP_ENCODING_NONE; ++ hdrs->content_length = g_ascii_strtoull (content_length, &end, 10); ++ if (*end) ++ hdrs->encoding = SOUP_ENCODING_UNRECOGNIZED; ++ else ++ hdrs->encoding = SOUP_ENCODING_CONTENT_LENGTH; ++ } ++ } ++ ++ if (hdrs->encoding == -1) { ++ /* Per RFC 2616 4.4, a response body that doesn't indicate its ++ * encoding otherwise is terminated by connection close, and a ++ * request that doesn't indicate otherwise has no body. Note ++ * that SoupMessage calls soup_message_headers_set_encoding() ++ * to override the response body default for our own ++ * server-side messages. ++ */ ++ hdrs->encoding = (hdrs->type == SOUP_MESSAGE_HEADERS_RESPONSE) ? ++ SOUP_ENCODING_EOF : SOUP_ENCODING_NONE; ++ } + return hdrs->encoding; + } + +-- +2.45.4 + diff --git a/SPECS/libsoup/libsoup.spec b/SPECS/libsoup/libsoup.spec index 685c43945aa..689ea830a36 100644 --- a/SPECS/libsoup/libsoup.spec +++ b/SPECS/libsoup/libsoup.spec @@ -2,7 +2,7 @@ Summary: libsoup HTTP client/server library Name: libsoup Version: %{BaseVersion}.4 -Release: 11%{?dist} +Release: 12%{?dist} License: GPLv2 Vendor: Microsoft Corporation Distribution: Mariner @@ -38,6 +38,8 @@ Patch19: CVE-2025-4969.patch Patch20: CVE-2025-11021.patch Patch21: CVE-2025-32049.patch Patch22: CVE-2026-1536.patch +Patch23: CVE-2026-0716.patch +Patch24: CVE-2026-1760.patch BuildRequires: meson @@ -150,6 +152,9 @@ find %{buildroot} -type f -name "*.la" -delete -print %defattr(-,root,root) %changelog +* Tue Feb 17 2026 Azure Linux Security Servicing Account - 3.0.4-12 +- Patch for CVE-2026-1760, CVE-2026-0716 + * Thu Feb 12 2026 Jyoti Kanase - 3.0.4-11 - Patch for CVE-2025-32049, CVE-2025-1536