From aacc784adb951d72ad6d2df25618f874a96e95d1 Mon Sep 17 00:00:00 2001 From: yangjinlin01 Date: Wed, 9 Jul 2025 16:26:54 +0800 Subject: [PATCH] [CVE] FIX CVE-2025-4035 to #20740 Commit fix cve-2025-4035 Project: TC2024080204 Signed-off-by: yangjinlin01 --- 0001-CVE-2025-4035.patch | 231 +++++++++++++++++++++++++++++++++++++++ libsoup3.spec | 6 +- 2 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 0001-CVE-2025-4035.patch diff --git a/0001-CVE-2025-4035.patch b/0001-CVE-2025-4035.patch new file mode 100644 index 0000000..06e0291 --- /dev/null +++ b/0001-CVE-2025-4035.patch @@ -0,0 +1,231 @@ +From 845e198402377f8644e9ae5200f1715df1ddfc08 Mon Sep 17 00:00:00 2001 +From: Patrick Griffis +Date: Thu, 27 Mar 2025 14:43:26 -0500 +Subject: [PATCH 1/3] cookie: Always normalize domain value + +In order for libpsl to give accurate results the domain must be lowercased. + +To make it easiest we normalize it at construction time of the cookie. +--- + libsoup/cookies/soup-cookie-jar.c | 11 ++++++++--- + libsoup/cookies/soup-cookie.c | 22 +++++++++++++++++++--- + libsoup/soup-tld.c | 11 ++++++++++- + libsoup/soup-uri-utils-private.h | 2 ++ + libsoup/soup-uri-utils.c | 18 ++++++++++++++++++ + tests/cookies-test.c | 19 +++++++++++++++++++ + 6 files changed, 76 insertions(+), 7 deletions(-) + +diff --git a/libsoup/cookies/soup-cookie-jar.c b/libsoup/cookies/soup-cookie-jar.c +index fac53a5f9..7f92ace1f 100644 +--- a/libsoup/cookies/soup-cookie-jar.c ++++ b/libsoup/cookies/soup-cookie-jar.c +@@ -519,6 +519,7 @@ incoming_cookie_is_third_party (SoupCookieJar *jar, + { + SoupCookieJarPrivate *priv; + const char *normalized_cookie_domain; ++ char *normalized_first_party_host; + const char *cookie_base_domain; + const char *first_party_base_domain; + const char *first_party_host; +@@ -540,12 +541,16 @@ incoming_cookie_is_third_party (SoupCookieJar *jar, + if (cookie_base_domain == NULL) + cookie_base_domain = soup_cookie_get_domain (cookie); + +- first_party_base_domain = soup_tld_get_base_domain (first_party_host, NULL); ++ normalized_first_party_host = soup_uri_normalize_domain (first_party_host); ++ first_party_base_domain = soup_tld_get_base_domain (normalized_first_party_host, NULL); + if (first_party_base_domain == NULL) +- first_party_base_domain = first_party_host; ++ first_party_base_domain = normalized_first_party_host; + +- if (soup_host_matches_host (cookie_base_domain, first_party_base_domain)) ++ if (soup_host_matches_host (cookie_base_domain, first_party_base_domain)) { ++ g_free (normalized_first_party_host); + return FALSE; ++ } ++ g_free (normalized_first_party_host); + + if (policy == SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY) + return TRUE; +diff --git a/libsoup/cookies/soup-cookie.c b/libsoup/cookies/soup-cookie.c +index cc80d001f..b6d771646 100644 +--- a/libsoup/cookies/soup-cookie.c ++++ b/libsoup/cookies/soup-cookie.c +@@ -168,6 +168,16 @@ parse_date (const char **val_p) + return date; + } + ++static gboolean ++is_lowercase_ascii_string (const char *str) ++{ ++ for (; *str; str++) { ++ if (!g_ascii_islower (*str)) ++ return FALSE; ++ } ++ return TRUE; ++} ++ + #define MAX_AGE_CAP_IN_SECONDS 31536000 // 1 year + #define MAX_ATTRIBUTE_SIZE 1024 + +@@ -311,6 +321,12 @@ parse_one_cookie (const char *header, GUri *origin) + g_free (cookie->domain); + cookie->domain = tmp; + } ++ ++ if (!is_lowercase_ascii_string (cookie->domain)) { ++ char *tmp = soup_uri_normalize_domain (cookie->domain); ++ g_free (cookie->domain); ++ cookie->domain = tmp; ++ } + } + + if (origin) { +@@ -321,7 +337,7 @@ parse_one_cookie (const char *header, GUri *origin) + return NULL; + } + } else +- cookie->domain = g_strdup (g_uri_get_host (origin)); ++ cookie->domain = soup_uri_normalize_domain (g_uri_get_host (origin)); + + /* The original cookie spec didn't say that pages + * could only set cookies for paths they were under. +@@ -364,7 +380,7 @@ cookie_new_internal (const char *name, const char *value, + cookie = g_slice_new0 (SoupCookie); + cookie->name = g_strdup (name); + cookie->value = g_strdup (value); +- cookie->domain = g_strdup (domain); ++ cookie->domain = soup_uri_normalize_domain (domain); + cookie->path = g_strdup (path); + soup_cookie_set_max_age (cookie, max_age); + cookie->same_site_policy = SOUP_SAME_SITE_POLICY_LAX; +@@ -537,7 +553,7 @@ void + soup_cookie_set_domain (SoupCookie *cookie, const char *domain) + { + g_free (cookie->domain); +- cookie->domain = g_strdup (domain); ++ cookie->domain = soup_uri_normalize_domain (domain); + } + + /** +diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c +index 2d8151662..71fac5749 100644 +--- a/libsoup/soup-tld.c ++++ b/libsoup/soup-tld.c +@@ -15,6 +15,7 @@ + #include + + #include "soup-tld.h" ++#include "soup-uri-utils-private.h" + #include "soup.h" + + static const char *soup_tld_get_base_domain_internal (const char *hostname, +@@ -41,6 +42,8 @@ static const char *soup_tld_get_base_domain_internal (const char *hostname, + * UTF-8 or ASCII format (and the return value will be in the same + * format). + * ++ * For accurate results @hostname must be lowercase. ++ * + * Returns: a pointer to the start of the base domain in @hostname. If + * an error occurs, %NULL will be returned and @error set. + **/ +@@ -80,6 +83,8 @@ gboolean + soup_tld_domain_is_public_suffix (const char *domain) + { + const psl_ctx_t* psl = soup_psl_context (); ++ char *normalized; ++ gboolean is_public_suffix; + + g_return_val_if_fail (domain, FALSE); + +@@ -88,7 +93,11 @@ soup_tld_domain_is_public_suffix (const char *domain) + return FALSE; + } + +- return psl_is_public_suffix2 (psl, domain, PSL_TYPE_ANY | PSL_TYPE_NO_STAR_RULE); ++ normalized = soup_uri_normalize_domain (domain); ++ is_public_suffix = psl_is_public_suffix2 (psl, normalized, PSL_TYPE_ANY | PSL_TYPE_NO_STAR_RULE); ++ g_free (normalized); ++ ++ return is_public_suffix; + } + + /** +diff --git a/libsoup/soup-uri-utils-private.h b/libsoup/soup-uri-utils-private.h +index 0119f0814..c2f984f86 100644 +--- a/libsoup/soup-uri-utils-private.h ++++ b/libsoup/soup-uri-utils-private.h +@@ -28,6 +28,8 @@ GUri *soup_uri_copy_with_normalized_flags (GUri *uri); + + char *soup_uri_get_host_for_headers (GUri *uri); + ++char *soup_uri_normalize_domain (const char *domain); ++ + #define SOUP_URI_IS_VALID(x) ((x) && g_uri_get_host(x) && g_uri_get_host(x)[0]) + + G_END_DECLS +diff --git a/libsoup/soup-uri-utils.c b/libsoup/soup-uri-utils.c +index 0963a1143..1f65faede 100644 +--- a/libsoup/soup-uri-utils.c ++++ b/libsoup/soup-uri-utils.c +@@ -506,3 +506,21 @@ soup_uri_get_host_for_headers (GUri *uri) + + return g_strdup (host); + } ++ ++char * ++soup_uri_normalize_domain (const char *domain) ++{ ++ char *lower; ++ char *normalized; ++ ++ g_assert (domain); ++ ++ if (g_str_is_ascii (domain)) ++ return g_ascii_strdown (domain, -1); ++ ++ lower = g_utf8_casefold (domain, -1); ++ normalized = g_utf8_normalize (lower, -1, G_NORMALIZE_NFKC); ++ g_free (lower); ++ ++ return normalized; ++} +diff --git a/tests/cookies-test.c b/tests/cookies-test.c +index 1d2d45630..7007aaf59 100644 +--- a/tests/cookies-test.c ++++ b/tests/cookies-test.c +@@ -695,6 +695,24 @@ do_cookies_threads_test (void) + soup_test_session_abort_unref (session); + } + ++static void ++do_cookies_public_suffix_test (void) ++{ ++ SoupCookieJar *jar = soup_cookie_jar_new (); ++ GUri *uri = g_uri_parse ("http://example.CO.uk", SOUP_HTTP_URI_FLAGS, NULL); ++ GSList *cookies; ++ ++ soup_cookie_jar_set_cookie (jar, uri, "value=1; domain=.co.uk"); ++ soup_cookie_jar_set_cookie (jar, uri, "value=1; domain=.CO.uk"); ++ soup_cookie_jar_set_cookie (jar, uri, "value=1; domain=.CO.UK"); ++ ++ cookies = soup_cookie_jar_all_cookies (jar); ++ g_assert_cmpint (g_slist_length (cookies), ==, 0); ++ ++ g_uri_unref (uri); ++ g_object_unref (jar); ++} ++ + int + main (int argc, char **argv) + { +@@ -726,6 +744,7 @@ main (int argc, char **argv) + g_test_add_func ("/cookies/secure-cookies", do_cookies_strict_secure_test); + g_test_add_func ("/cookies/prefix", do_cookies_prefix_test); + g_test_add_func ("/cookies/threads", do_cookies_threads_test); ++ g_test_add_func ("/cookies/public-suffix", do_cookies_public_suffix_test); + + ret = g_test_run (); + +-- +GitLab diff --git a/libsoup3.spec b/libsoup3.spec index cf503d0..0229857 100644 --- a/libsoup3.spec +++ b/libsoup3.spec @@ -1,4 +1,4 @@ -%define anolis_release 2 +%define anolis_release 3 %global glib2_version 2.69.1 %{!?with_docs: %global with_docs 1} @@ -14,6 +14,7 @@ URL: https://wiki.gnome.org/Projects/libsoup Source0: https://download.gnome.org/sources/libsoup/3.6/libsoup-%{version}.tar.xz # From https://gitlab.com/redhat/centos-stream/rpms/libsoup3/-/tree/c10s?ref_type=heads Patch0: 1000-CVE-2025-4948.patch +Patch1: 0001-CVE-2025-4035.patch BuildRequires: gcc BuildRequires: gettext BuildRequires: glib-networking @@ -110,6 +111,9 @@ install -m 644 -D tests/libsoup.supp %{buildroot}%{_datadir}/libsoup-3.0/libsoup %doc README NEWS AUTHORS %changelog +* Wed Jul 9 2025 yangjinlin01 - 3.6.5-3 +- add patch to fix CVE-2025-4035 + * Mon Jun 23 2025 lzq11122 - 3.6.5-2 - add patch to fix CVE-2025-4948 -- Gitee