diff --git a/0002-curl-8.10.1-CVE-2024-9681.patch b/0002-curl-8.10.1-CVE-2024-9681.patch new file mode 100644 index 0000000..9dff16d --- /dev/null +++ b/0002-curl-8.10.1-CVE-2024-9681.patch @@ -0,0 +1,115 @@ +From dd2859d77ddaf29516b8dce300b0b1fd4839d3f5 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 8 Oct 2024 11:20:40 +0200 +Subject: [PATCH] hsts: avoid the local buffer and memcpy on lookup + +Closes #15190 + +(cherry picked from commit 60d8663afb0fb7f113604404c50840dfe9320039) + +hsts: improve subdomain handling + +- on load, only replace existing HSTS entries if there is a full host + match + +- on matching, prefer a full host match and secondary the longest tail + subdomain match + +Closes #15210 + +(cherry picked from commit a94973805df96269bf3f3bf0a20ccb9887313316) +--- + lib/hsts.c | 30 ++++++++++++++++-------------- + tests/data/test1660 | 2 +- + 2 files changed, 17 insertions(+), 15 deletions(-) + +diff --git a/lib/hsts.c b/lib/hsts.c +index 8cd77ae3c..b4cced857 100644 +--- a/lib/hsts.c ++++ b/lib/hsts.c +@@ -249,24 +249,23 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname, + struct stsentry *Curl_hsts(struct hsts *h, const char *hostname, + bool subdomain) + { ++ struct stsentry *bestsub = NULL; + if(h) { +- char buffer[MAX_HSTS_HOSTLEN + 1]; + time_t now = time(NULL); + size_t hlen = strlen(hostname); + struct Curl_llist_element *e; + struct Curl_llist_element *n; ++ size_t blen = 0; + + if((hlen > MAX_HSTS_HOSTLEN) || !hlen) + return NULL; +- memcpy(buffer, hostname, hlen); + if(hostname[hlen-1] == '.') + /* remove the trailing dot */ + --hlen; +- buffer[hlen] = 0; +- hostname = buffer; + + for(e = h->list.head; e; e = n) { + struct stsentry *sts = e->ptr; ++ size_t ntail; + n = e->next; + if(sts->expires <= now) { + /* remove expired entries */ +@@ -274,20 +273,23 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname, + hsts_free(sts); + continue; + } +- if(subdomain && sts->includeSubDomains) { +- size_t ntail = strlen(sts->host); +- if(ntail < hlen) { +- size_t offs = hlen - ntail; +- if((hostname[offs-1] == '.') && +- strncasecompare(&hostname[offs], sts->host, ntail)) +- return sts; ++ ntail = strlen(sts->host); ++ if((subdomain && sts->includeSubDomains) && (ntail < hlen)) { ++ size_t offs = hlen - ntail; ++ if((hostname[offs-1] == '.') && ++ strncasecompare(&hostname[offs], sts->host, ntail) && ++ (ntail > blen)) { ++ /* save the tail match with the longest tail */ ++ bestsub = sts; ++ blen = ntail; + } + } +- if(strcasecompare(hostname, sts->host)) ++ /* avoid strcasecompare because the host name is not null terminated */ ++ if((hlen == ntail) && strncasecompare(hostname, sts->host, hlen)) + return sts; + } + } +- return NULL; /* no match */ ++ return bestsub; + } + + /* +@@ -439,7 +441,7 @@ static CURLcode hsts_add(struct hsts *h, char *line) + e = Curl_hsts(h, p, subdomain); + if(!e) + result = hsts_create(h, p, subdomain, expires); +- else { ++ else if(strcasecompare(p, e->host)) { + /* the same hostname, use the largest expire time */ + if(expires > e->expires) + e->expires = expires; +diff --git a/tests/data/test1660 b/tests/data/test1660 +index f86126d19..4b6f9615c 100644 +--- a/tests/data/test1660 ++++ b/tests/data/test1660 +@@ -52,7 +52,7 @@ this.example [this.example]: 1548400797 + Input 12: error 43 + Input 13: error 43 + Input 14: error 43 +-3.example.com [example.com]: 1569905261 includeSubDomains ++3.example.com [3.example.com]: 1569905261 includeSubDomains + 3.example.com [example.com]: 1569905261 includeSubDomains + foo.example.com [example.com]: 1569905261 includeSubDomains + 'foo.xample.com' is not HSTS +-- +2.47.1 + diff --git a/0003-curl-8.9.1-CVE-2025-9086.patch b/0003-curl-8.9.1-CVE-2025-9086.patch new file mode 100644 index 0000000..a5e486b --- /dev/null +++ b/0003-curl-8.9.1-CVE-2025-9086.patch @@ -0,0 +1,53 @@ +From 5dd433a190c1003bd78cc5a3e9f8a5827cd97516 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 11 Aug 2025 20:23:05 +0200 +Subject: [PATCH] cookie: don't treat the leading slash as trailing + +If there is only a leading slash in the path, keep that. Also add an +assert to make sure the path is never blank. + +Reported-by: Google Big Sleep +Closes #18266 + +(cherry picked from commit c6ae07c6a541e0e96d0040afb62b45dd37711300) +--- + lib/cookie.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index b0d8d84be..1db308372 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -317,7 +317,7 @@ static char *sanitize_cookie_path(const char *cookie_path) + } + + /* convert /hoge/ to /hoge */ +- if(len && new_path[len - 1] == '/') { ++ if(len > 1 && new_path[len - 1] == '/') { + new_path[len - 1] = 0x0; + } + +@@ -1076,7 +1076,7 @@ Curl_cookie_add(struct Curl_easy *data, + clist->spath && co->spath && /* both have paths */ + clist->secure && !co->secure && !secure) { + size_t cllen; +- const char *sep; ++ const char *sep = NULL; + + /* + * A non-secure cookie may not overlay an existing secure cookie. +@@ -1085,8 +1085,9 @@ Curl_cookie_add(struct Curl_easy *data, + * "/loginhelper" is ok. + */ + +- sep = strchr(clist->spath + 1, '/'); +- ++ DEBUGASSERT(clist->spath[0]); ++ if(clist->spath[0]) ++ sep = strchr(clist->spath + 1, '/'); + if(sep) + cllen = sep - clist->spath; + else +-- +2.51.0 + diff --git a/curl.spec b/curl.spec index 174562f..157a3e9 100644 --- a/curl.spec +++ b/curl.spec @@ -7,7 +7,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 8.9.1 -Release: 2%{?dist} +Release: 4%{?dist} License: curl Source0: https://curl.se/download/%{name}-%{version}.tar.xz Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc @@ -16,6 +16,16 @@ Source1: https://curl.se/download/%{name}-%{version}.tar.xz.asc # which points to the GPG key as of April 7th 2016 of https://daniel.haxx.se/mykey.asc Source2: mykey.asc +# fix crashes with transmission due to SIGPIPE +# https://github.com/curl/curl/commit/3eec5afbd0b6377eca893c392569b2faf094d970 +Patch001: 0001-curl-8.9.1-sigpipe.patch + +# fix HSTS subdomain overwrites parent cache entry (CVE-2024-9681) +Patch002: 0002-curl-8.10.1-CVE-2024-9681.patch + +# fix Out of bounds read for cookie path (CVE-2025-9086) +Patch003: 0003-curl-8.9.1-CVE-2025-9086.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -25,10 +35,6 @@ Patch102: 0102-curl-7.84.0-test3026.patch # do not fail on warnings in the upstream test driver Patch104: 0104-curl-7.88.0-tests-warnings.patch -# Fix crashes with transmission due to SIGPIPE -# https://github.com/curl/curl/commit/3eec5afbd0b6377eca893c392569b2faf094d970 -Patch001: 0001-curl-8.9.1-sigpipe.patch - Provides: curl-full = %{version}-%{release} # do not fail when trying to install curl-minimal after drop Provides: curl-minimal = %{version}-%{release} @@ -218,7 +224,7 @@ be installed. # disable test 1801 # -printf "1801\n" >> tests/data/DISABLED +printf "1801\n" >>tests/data/DISABLED # test3026: avoid pthread_create() failure due to resource exhaustion on i386 %ifarch %{ix86} @@ -238,10 +244,14 @@ sed -e 's|^35$|35,52|' -i tests/data/test323 eval "$cmd" ) +# avoid unnecessary arch-dependent line in the processed file +sed -e '/# Used in @libdir@/d' \ + -i curl-config.in + +%build # regenerate the configure script and Makefile.in files autoreconf -fiv -%build mkdir build-{full,minimal} export common_configure_opts=" \ --cache-file=../config.cache \ @@ -408,6 +418,12 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Wed Sep 17 2025 Jan Macku - 8.9.1-4 +- fix Out of bounds read for cookie path (CVE-2025-9086) + +* Thu Dec 12 2024 Jan Macku - 8.9.1-3 +- fix HSTS subdomain overwrites parent cache entry (CVE-2024-9681) + * Mon Aug 5 2024 voidanix - 8.9.1-2 - Apply SIGPIPE-related patch due to upstream regression