Skip to content

Commit 00880a7

Browse files
CBL-Mariner-Botkgodara912Kshitiz Godara
authored
[AUTO-CHERRYPICK] Patch libsoup for CVE-2025-2784 [HIGH], CVE-2025-32050, CVE-2025-32051, CVE-2025-32052, CVE-2025-46420, CVE-2025-46421 [MEDIUM] - branch main (#13677)
Co-authored-by: kgodara912 <[email protected]> Co-authored-by: Kshitiz Godara <[email protected]>
1 parent c0b9c09 commit 00880a7

File tree

7 files changed

+452
-1
lines changed

7 files changed

+452
-1
lines changed

SPECS/libsoup/CVE-2025-2784.patch

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
From 88639d13cbcc4e9ccdb1d35c2c0b4a859f84e3f9 Mon Sep 17 00:00:00 2001
2+
From: Kshitiz Godara <[email protected]>
3+
Date: Sun, 4 May 2025 12:46:20 +0000
4+
Subject: [PATCH 1/2] Combined two patches to address CVE-2025-2784
5+
6+
Upstream references:
7+
https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/435/diffs
8+
https://gitlab.gnome.org/GNOME/libsoup/-/commit/c415ad0b6771992e66c70edf373566c6e247089d
9+
---
10+
.../content-sniffer/soup-content-sniffer.c | 10 +--
11+
libsoup/soup-session.c | 6 ++
12+
tests/auth-test.c | 76 +++++++++++++++++++
13+
tests/meson.build | 3 +
14+
tests/sniffing-test.c | 48 ++++++++++++
15+
5 files changed, 138 insertions(+), 5 deletions(-)
16+
17+
diff --git a/libsoup/content-sniffer/soup-content-sniffer.c b/libsoup/content-sniffer/soup-content-sniffer.c
18+
index f6629ad..3c072c1 100644
19+
--- a/libsoup/content-sniffer/soup-content-sniffer.c
20+
+++ b/libsoup/content-sniffer/soup-content-sniffer.c
21+
@@ -630,8 +630,11 @@ sniff_text_or_binary (SoupContentSniffer *sniffer, GBytes *buffer)
22+
}
23+
24+
static gboolean
25+
-skip_insignificant_space (const char *resource, int *pos, int resource_length)
26+
+skip_insignificant_space (const char *resource, gsize *pos, gsize resource_length)
27+
{
28+
+ if (*pos >= resource_length)
29+
+ return TRUE;
30+
+
31+
while ((resource[*pos] == '\x09') ||
32+
(resource[*pos] == '\x20') ||
33+
(resource[*pos] == '\x0A') ||
34+
@@ -651,7 +654,7 @@ sniff_feed_or_html (SoupContentSniffer *sniffer, GBytes *buffer)
35+
gsize resource_length;
36+
const char *resource = g_bytes_get_data (buffer, &resource_length);
37+
resource_length = MIN (512, resource_length);
38+
- int pos = 0;
39+
+ gsize pos = 0;
40+
41+
if (resource_length < 3)
42+
goto text_html;
43+
@@ -661,9 +664,6 @@ sniff_feed_or_html (SoupContentSniffer *sniffer, GBytes *buffer)
44+
pos = 3;
45+
46+
look_for_tag:
47+
- if (pos > resource_length)
48+
- goto text_html;
49+
-
50+
if (skip_insignificant_space (resource, &pos, resource_length))
51+
goto text_html;
52+
53+
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
54+
index ce9bbf9..185644a 100644
55+
--- a/libsoup/soup-session.c
56+
+++ b/libsoup/soup-session.c
57+
@@ -1264,6 +1264,12 @@ soup_session_redirect_message (SoupSession *session,
58+
SOUP_ENCODING_NONE);
59+
}
60+
61+
+ /* Strip all credentials on cross-origin redirect. */
62+
+ if (!soup_uri_host_equal (soup_message_get_uri (msg), new_uri)) {
63+
+ soup_message_headers_remove_common (soup_message_get_request_headers (msg), SOUP_HEADER_AUTHORIZATION);
64+
+ soup_message_set_auth (msg, NULL);
65+
+ }
66+
+
67+
soup_message_set_request_host_from_uri (msg, new_uri);
68+
soup_message_set_uri (msg, new_uri);
69+
g_uri_unref (new_uri);
70+
diff --git a/tests/auth-test.c b/tests/auth-test.c
71+
index 5dbc319..51431f2 100644
72+
--- a/tests/auth-test.c
73+
+++ b/tests/auth-test.c
74+
@@ -1,6 +1,7 @@
75+
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
76+
77+
#include "test-utils.h"
78+
+#include "soup-uri-utils-private.h"
79+
80+
static const char *base_uri;
81+
static GMainLoop *loop;
82+
@@ -1830,6 +1831,81 @@ do_multiple_digest_algorithms (void)
83+
soup_test_server_quit_unref (server);
84+
}
85+
86+
+static void
87+
+redirect_server_callback (SoupServer *server,
88+
+ SoupServerMessage *msg,
89+
+ const char *path,
90+
+ GHashTable *query,
91+
+ gpointer user_data)
92+
+{
93+
+ static gboolean redirected = FALSE;
94+
+
95+
+ if (!redirected) {
96+
+ char *redirect_uri = g_uri_to_string (user_data);
97+
+ soup_server_message_set_redirect (msg, SOUP_STATUS_MOVED_PERMANENTLY, redirect_uri);
98+
+ g_free (redirect_uri);
99+
+ redirected = TRUE;
100+
+ return;
101+
+ }
102+
+
103+
+ g_assert_not_reached ();
104+
+}
105+
+
106+
+static gboolean
107+
+auth_for_redirect_callback (SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data)
108+
+{
109+
+ GUri *known_server_uri = user_data;
110+
+
111+
+ if (!soup_uri_host_equal (known_server_uri, soup_message_get_uri (msg)))
112+
+ return FALSE;
113+
+
114+
+ soup_auth_authenticate (auth, "user", "good-basic");
115+
+
116+
+ return TRUE;
117+
+}
118+
+
119+
+static void
120+
+do_strip_on_crossorigin_redirect (void)
121+
+{
122+
+ SoupSession *session;
123+
+ SoupMessage *msg;
124+
+ SoupServer *server1, *server2;
125+
+ SoupAuthDomain *auth_domain;
126+
+ GUri *uri;
127+
+ gint status;
128+
+
129+
+ server1 = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
130+
+ server2 = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
131+
+
132+
+ /* Both servers have the same credentials. */
133+
+ auth_domain = soup_auth_domain_basic_new ("realm", "auth-test", "auth-callback", server_basic_auth_callback, NULL);
134+
+ soup_auth_domain_add_path (auth_domain, "/");
135+
+ soup_server_add_auth_domain (server1, auth_domain);
136+
+ soup_server_add_auth_domain (server2, auth_domain);
137+
+ g_object_unref (auth_domain);
138+
+
139+
+ /* Server 1 asks for auth, then redirects to Server 2. */
140+
+ soup_server_add_handler (server1, NULL,
141+
+ redirect_server_callback,
142+
+ soup_test_server_get_uri (server2, "http", NULL), (GDestroyNotify)g_uri_unref);
143+
+ /* Server 2 requires auth. */
144+
+ soup_server_add_handler (server2, NULL, server_callback, NULL, NULL);
145+
+
146+
+ session = soup_test_session_new (NULL);
147+
+ uri = soup_test_server_get_uri (server1, "http", NULL);
148+
+ msg = soup_message_new_from_uri ("GET", uri);
149+
+ /* The client only sends credentials for the host it knows. */
150+
+ g_signal_connect (msg, "authenticate", G_CALLBACK (auth_for_redirect_callback), uri);
151+
+
152+
+ status = soup_test_session_send_message (session, msg);
153+
+
154+
+ g_assert_cmpint (status, ==, SOUP_STATUS_UNAUTHORIZED);
155+
+
156+
+ g_uri_unref (uri);
157+
+ soup_test_server_quit_unref (server1);
158+
+ soup_test_server_quit_unref (server2);
159+
+}
160+
+
161+
int
162+
main (int argc, char **argv)
163+
{
164+
diff --git a/tests/meson.build b/tests/meson.build
165+
index fc1cb3f..ff94a4f 100644
166+
--- a/tests/meson.build
167+
+++ b/tests/meson.build
168+
@@ -91,6 +91,9 @@ tests = [
169+
{'name': 'server-auth'},
170+
{'name': 'server'},
171+
{'name': 'sniffing'},
172+
+ {'name': 'sniffing',
173+
+ 'depends': [test_resources],
174+
+ },
175+
{'name': 'socket'},
176+
{'name': 'ssl',
177+
'dependencies': [gnutls_dep],
178+
diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c
179+
index 6116719..7857732 100644
180+
--- a/tests/sniffing-test.c
181+
+++ b/tests/sniffing-test.c
182+
@@ -342,6 +342,52 @@ test_disabled (gconstpointer data)
183+
g_uri_unref (uri);
184+
}
185+
186+
+static const gsize MARKUP_LENGTH = strlen ("<!--") + strlen ("-->");
187+
+
188+
+static void
189+
+do_skip_whitespace_test (void)
190+
+{
191+
+ SoupContentSniffer *sniffer = soup_content_sniffer_new ();
192+
+ SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "http://example.org");
193+
+ const char *test_cases[] = {
194+
+ "",
195+
+ "<rdf:RDF",
196+
+ "<rdf:RDFxmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"",
197+
+ "<rdf:RDFxmlns=\"http://purl.org/rss/1.0/\"",
198+
+ };
199+
+
200+
+ soup_message_headers_set_content_type (soup_message_get_response_headers (msg), "text/html", NULL);
201+
+
202+
+ for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) {
203+
+ const char *trailing_data = test_cases[i];
204+
+ gsize leading_zeros = 512 - MARKUP_LENGTH - strlen (trailing_data);
205+
+ gsize testsize = MARKUP_LENGTH + leading_zeros + strlen (trailing_data);
206+
+ guint8 *data = g_malloc0 (testsize);
207+
+ guint8 *p = data;
208+
+ char *content_type;
209+
+ GBytes *buffer;
210+
+
211+
+ // Format of <!--[0x00 * $leading_zeros]-->$trailing_data
212+
+ memcpy (p, "<!--", strlen ("<!--"));
213+
+ p += strlen ("<!--");
214+
+ p += leading_zeros;
215+
+ memcpy (p, "-->", strlen ("-->"));
216+
+ p += strlen ("-->");
217+
+ if (strlen (trailing_data))
218+
+ memcpy (p, trailing_data, strlen (trailing_data));
219+
+ // Purposefully not NUL terminated.
220+
+
221+
+ buffer = g_bytes_new_take (g_steal_pointer (&data), testsize);
222+
+ content_type = soup_content_sniffer_sniff (sniffer, msg, buffer, NULL);
223+
+
224+
+ g_free (content_type);
225+
+ g_bytes_unref (buffer);
226+
+ }
227+
+
228+
+ g_object_unref (msg);
229+
+ g_object_unref (sniffer);
230+
+}
231+
+
232+
int
233+
main (int argc, char **argv)
234+
{
235+
@@ -517,6 +563,8 @@ main (int argc, char **argv)
236+
"/text_or_binary/home.gif",
237+
test_disabled);
238+
239+
+ g_test_add_func ("/sniffing/whitespace", do_skip_whitespace_test);
240+
+
241+
ret = g_test_run ();
242+
243+
g_uri_unref (base_uri);
244+
--
245+
2.45.3
246+

SPECS/libsoup/CVE-2025-32050.patch

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
From 2825634dd081a3af1800d6967ba0991f3def3347 Mon Sep 17 00:00:00 2001
2+
From: Patrick Griffis <[email protected]>
3+
Date: Mon, 28 Oct 2024 12:29:48 -0500
4+
Subject: [PATCH 3/6] Fix using int instead of size_t for strcspn return
5+
6+
Upstream reference:
7+
https://gitlab.gnome.org/GNOME/libsoup/-/commit/9bb0a55de55c6940ced811a64fbca82fe93a9323
8+
---
9+
libsoup/soup-headers.c | 2 +-
10+
1 file changed, 1 insertion(+), 1 deletion(-)
11+
12+
diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c
13+
index 8382b8f..4468415 100644
14+
--- a/libsoup/soup-headers.c
15+
+++ b/libsoup/soup-headers.c
16+
@@ -907,7 +907,7 @@ append_param_quoted (GString *string,
17+
const char *name,
18+
const char *value)
19+
{
20+
- int len;
21+
+ gsize len;
22+
23+
g_string_append (string, name);
24+
g_string_append (string, "=\"");
25+
--
26+
2.45.3
27+

SPECS/libsoup/CVE-2025-32051.patch

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
From 206e54eb90bdc53faed29e04d26373433b6605f6 Mon Sep 17 00:00:00 2001
2+
From: Patrick Griffis <[email protected]>
3+
Date: Fri, 22 Nov 2024 13:39:51 -0600
4+
Subject: [PATCH 4/6] soup_uri_decode_data_uri(): Handle URIs with a path
5+
starting with //
6+
7+
Upstream reference:
8+
https://gitlab.gnome.org/GNOME/libsoup/-/commit/79cfd65c9bd8024cd45dd725c284766329873709
9+
https://gitlab.gnome.org/GNOME/libsoup/-/commit/0713ba4a719da938dc8facc89fca99cd0aa3069f
10+
---
11+
libsoup/soup-uri-utils.c | 11 +++++++++++
12+
1 file changed, 11 insertions(+)
13+
14+
diff --git a/libsoup/soup-uri-utils.c b/libsoup/soup-uri-utils.c
15+
index be2b79b..ad70fe6 100644
16+
--- a/libsoup/soup-uri-utils.c
17+
+++ b/libsoup/soup-uri-utils.c
18+
@@ -286,6 +286,7 @@ soup_uri_decode_data_uri (const char *uri,
19+
gboolean base64 = FALSE;
20+
char *uri_string;
21+
GBytes *bytes;
22+
+ const char *path;
23+
24+
g_return_val_if_fail (uri != NULL, NULL);
25+
26+
@@ -300,9 +301,19 @@ soup_uri_decode_data_uri (const char *uri,
27+
28+
if (content_type)
29+
*content_type = NULL;
30+
+ /* g_uri_to_string() is picky about paths that start with `//` and will assert. */
31+
+ path = g_uri_get_path (soup_uri);
32+
+ if (path[0] == '/' && path[1] == '/') {
33+
+ g_uri_unref (soup_uri);
34+
+ return NULL;
35+
+ }
36+
+
37+
38+
uri_string = g_uri_to_string (soup_uri);
39+
g_uri_unref (soup_uri);
40+
+ if (!uri_string)
41+
+ return NULL;
42+
+
43+
44+
start = uri_string + 5;
45+
comma = strchr (start, ',');
46+
--
47+
2.45.3
48+

SPECS/libsoup/CVE-2025-32052.patch

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
From 81ae25238849867f6197e22ec42f5bb4dcb7b8ad Mon Sep 17 00:00:00 2001
2+
From: Patrick Griffis <[email protected]>
3+
Date: Sat, 16 Nov 2024 12:07:30 -0600
4+
Subject: [PATCH 2/6] Fix heap buffer overflow in soup_content_sniffer_sniff
5+
6+
Co-Author: Ar Jun <[email protected]>
7+
8+
Upstream reference:
9+
https://gitlab.gnome.org/GNOME/libsoup/-/commit/f182429e5b1fc034050510da20c93256c4fa9652
10+
---
11+
libsoup/content-sniffer/soup-content-sniffer.c | 2 +-
12+
1 file changed, 1 insertion(+), 1 deletion(-)
13+
14+
diff --git a/libsoup/content-sniffer/soup-content-sniffer.c b/libsoup/content-sniffer/soup-content-sniffer.c
15+
index 150d285..a772c7c 100644
16+
--- a/libsoup/content-sniffer/soup-content-sniffer.c
17+
+++ b/libsoup/content-sniffer/soup-content-sniffer.c
18+
@@ -529,7 +529,7 @@ sniff_unknown (SoupContentSniffer *sniffer, GBytes *buffer,
19+
guint index_pattern = 0;
20+
gboolean skip_row = FALSE;
21+
22+
- while ((index_stream < resource_length) &&
23+
+ while ((index_stream < resource_length - 1) &&
24+
(index_pattern <= type_row->pattern_length)) {
25+
/* Skip insignificant white space ("WS" in the spec) */
26+
if (type_row->pattern[index_pattern] == ' ') {
27+
--
28+
2.45.3
29+

0 commit comments

Comments
 (0)