From patchwork Fri Feb 14 05:00:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: yurade X-Patchwork-Id: 57306 X-Patchwork-Delegate: steve@sakoman.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17FCDC021A4 for ; Fri, 14 Feb 2025 05:01:07 +0000 (UTC) Received: from mx0a-0064b401.pphosted.com (mx0a-0064b401.pphosted.com [205.220.166.238]) by mx.groups.io with SMTP id smtpd.web11.14281.1739509261841146627 for ; Thu, 13 Feb 2025 21:01:01 -0800 Authentication-Results: mx.groups.io; dkim=none (message not signed); spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: windriver.com, ip: 205.220.166.238, mailfrom: prvs=4140961d8f=yogita.urade@windriver.com) Received: from pps.filterd (m0250809.ppops.net [127.0.0.1]) by mx0a-0064b401.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 51E4W6d8024015 for ; Thu, 13 Feb 2025 21:01:01 -0800 Received: from ala-exchng01.corp.ad.wrs.com (ala-exchng01.wrs.com [147.11.82.252]) by mx0a-0064b401.pphosted.com (PPS) with ESMTPS id 44qwy6kvuw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Thu, 13 Feb 2025 21:01:01 -0800 (PST) Received: from blr-linux-engg1.wrs.com (147.11.136.210) by ala-exchng01.corp.ad.wrs.com (147.11.82.252) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.43; Thu, 13 Feb 2025 21:00:59 -0800 From: yurade To: Subject: [OE-core][scarthgap][PATCH 3/3] curl: fix CVE-2025-0725 Date: Fri, 14 Feb 2025 05:00:35 +0000 Message-ID: <20250214050035.1049565-3-yogita.urade@windriver.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20250214050035.1049565-1-yogita.urade@windriver.com> References: <20250214050035.1049565-1-yogita.urade@windriver.com> MIME-Version: 1.0 X-Originating-IP: [147.11.136.210] X-ClientProxiedBy: ALA-EXCHNG02.corp.ad.wrs.com (147.11.82.254) To ala-exchng01.corp.ad.wrs.com (147.11.82.252) X-Proofpoint-GUID: PARDr141d4bQJjUyIzAYQCBqqQBb84OA X-Proofpoint-ORIG-GUID: PARDr141d4bQJjUyIzAYQCBqqQBb84OA X-Authority-Analysis: v=2.4 cv=G8nmE8k5 c=1 sm=1 tr=0 ts=67aece0d cx=c_pps a=/ZJR302f846pc/tyiSlYyQ==:117 a=/ZJR302f846pc/tyiSlYyQ==:17 a=HCiNrPZc1L8A:10 a=T2h4t0Lz3GQA:10 a=PYnjg3YJAAAA:8 a=NEAV23lmAAAA:8 a=t7CeM3EgAAAA:8 a=QHnSCRzsTXmcUY5KeVkA:9 a=FdTzh2GWekK77mhwV6Dw:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-14_01,2025-02-13_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 adultscore=0 priorityscore=1501 mlxlogscore=999 malwarescore=0 impostorscore=0 spamscore=0 mlxscore=0 suspectscore=0 bulkscore=0 phishscore=0 clxscore=1015 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.21.0-2501170000 definitions=main-2502140034 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Fri, 14 Feb 2025 05:01:07 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/211374 From: Yogita Urade When libcurl is asked to perform automatic gzip decompression of content-encoded HTTP responses with the `CURLOPT_ACCEPT_ENCODING` option, **using zlib 1.2.0.3 or older**, an attacker-controlled integer overflow would make libcurl perform a buffer overflow. Reference: https://nvd.nist.gov/vuln/detail/CVE-2025-0725 Upstream patch: https://github.com/curl/curl/commit/76f83f0db23846e254d940ec7 Signed-off-by: Yogita Urade --- .../curl/curl/CVE-2025-0725.patch | 477 ++++++++++++++++++ meta/recipes-support/curl/curl_8.7.1.bb | 1 + 2 files changed, 478 insertions(+) create mode 100644 meta/recipes-support/curl/curl/CVE-2025-0725.patch diff --git a/meta/recipes-support/curl/curl/CVE-2025-0725.patch b/meta/recipes-support/curl/curl/CVE-2025-0725.patch new file mode 100644 index 0000000000..9a0b64766d --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2025-0725.patch @@ -0,0 +1,477 @@ +From 76f83f0db23846e254d940ec7fe141010077eb88 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 24 Jan 2025 11:13:24 +0100 +Subject: [PATCH] content_encoding: drop support for zlib before 1.2.0.4 + +zlib 1.2.0.4 was released on 10 August 2003 + +Closes #16079 + +CVE: CVE-2025-0725 +Upstream-Status: Backport [https://github.com/curl/curl/commit/76f83f0db23846e254d940ec7fe141010077eb88] + +Signed-off-by: Yogita Urade +--- + docs/INTERNALS.md | 2 +- + lib/content_encoding.c | 274 ++++------------------------------------- + 2 files changed, 25 insertions(+), 251 deletions(-) + +diff --git a/docs/INTERNALS.md b/docs/INTERNALS.md +index b1a095f..d030b83 100644 +--- a/docs/INTERNALS.md ++++ b/docs/INTERNALS.md +@@ -20,7 +20,7 @@ versions of libs and build tools. + + - OpenSSL 0.9.7 + - GnuTLS 3.1.10 +- - zlib 1.1.4 ++ - zlib 1.2.0.4 + - libssh2 1.0 + - c-ares 1.16.0 + - libidn2 2.0.0 +diff --git a/lib/content_encoding.c b/lib/content_encoding.c +index c1abf24..d38bce8 100644 +--- a/lib/content_encoding.c ++++ b/lib/content_encoding.c +@@ -68,31 +68,13 @@ + + #define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */ + +- + #ifdef HAVE_LIBZ + +-/* Comment this out if zlib is always going to be at least ver. 1.2.0.4 +- (doing so will reduce code size slightly). */ +-#define OLD_ZLIB_SUPPORT 1 +- +-#define GZIP_MAGIC_0 0x1f +-#define GZIP_MAGIC_1 0x8b +- +-/* gzip flag byte */ +-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +-#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +-#define COMMENT 0x10 /* bit 4 set: file comment present */ +-#define RESERVED 0xE0 /* bits 5..7: reserved */ +- + typedef enum { + ZLIB_UNINIT, /* uninitialized */ + ZLIB_INIT, /* initialized */ + ZLIB_INFLATING, /* inflating started. */ + ZLIB_EXTERNAL_TRAILER, /* reading external trailer */ +- ZLIB_GZIP_HEADER, /* reading gzip header */ +- ZLIB_GZIP_INFLATING, /* inflating gzip stream */ + ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ + } zlibInitState; + +@@ -137,9 +119,6 @@ static CURLcode + exit_zlib(struct Curl_easy *data, + z_stream *z, zlibInitState *zlib_init, CURLcode result) + { +- if(*zlib_init == ZLIB_GZIP_HEADER) +- Curl_safefree(z->next_in); +- + if(*zlib_init != ZLIB_UNINIT) { + if(inflateEnd(z) != Z_OK && result == CURLE_OK) + result = process_zlib_error(data, z); +@@ -188,8 +167,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, + /* Check state. */ + if(zp->zlib_init != ZLIB_INIT && + zp->zlib_init != ZLIB_INFLATING && +- zp->zlib_init != ZLIB_INIT_GZIP && +- zp->zlib_init != ZLIB_GZIP_INFLATING) ++ zp->zlib_init != ZLIB_INIT_GZIP) + return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR); + + /* Dynamically allocate a buffer for decompression because it's uncommonly +@@ -278,7 +256,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, + + /* Deflate handler. */ + static CURLcode deflate_do_init(struct Curl_easy *data, +- struct Curl_cwriter *writer) ++ struct Curl_cwriter *writer) + { + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ +@@ -294,8 +272,8 @@ static CURLcode deflate_do_init(struct Curl_easy *data, + } + + static CURLcode deflate_do_write(struct Curl_easy *data, +- struct Curl_cwriter *writer, int type, +- const char *buf, size_t nbytes) ++ struct Curl_cwriter *writer, int type, ++ const char *buf, size_t nbytes) + { + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ +@@ -315,7 +293,7 @@ static CURLcode deflate_do_write(struct Curl_easy *data, + } + + static void deflate_do_close(struct Curl_easy *data, +- struct Curl_cwriter *writer) ++ struct Curl_cwriter *writer) + { + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ +@@ -335,124 +313,34 @@ static const struct Curl_cwtype deflate_encoding = { + + /* Gzip handler. */ + static CURLcode gzip_do_init(struct Curl_easy *data, +- struct Curl_cwriter *writer) ++ struct Curl_cwriter *writer) + { + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ ++ const char *v = zlibVersion(); + + /* Initialize zlib */ + z->zalloc = (alloc_func) zalloc_cb; + z->zfree = (free_func) zfree_cb; + +- if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { +- /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ ++ if(strcmp(v, "1.2.0.4") >= 0) { ++ /* zlib version >= 1.2.0.4 supports transparent gzip decompressing */ + if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) { + return process_zlib_error(data, z); + } + zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ + } + else { +- /* we must parse the gzip header and trailer ourselves */ +- if(inflateInit2(z, -MAX_WBITS) != Z_OK) { +- return process_zlib_error(data, z); +- } +- zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */ +- zp->zlib_init = ZLIB_INIT; /* Initial call state */ ++ failf(data, "too old zlib version: %s", v); ++ return CURLE_FAILED_INIT; + } + + return CURLE_OK; + } + +-#ifdef OLD_ZLIB_SUPPORT +-/* Skip over the gzip header */ +-typedef enum { +- GZIP_OK, +- GZIP_BAD, +- GZIP_UNDERFLOW +-} gzip_status; +- +-static gzip_status check_gzip_header(unsigned char const *data, ssize_t len, +- ssize_t *headerlen) +-{ +- int method, flags; +- const ssize_t totallen = len; +- +- /* The shortest header is 10 bytes */ +- if(len < 10) +- return GZIP_UNDERFLOW; +- +- if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1)) +- return GZIP_BAD; +- +- method = data[2]; +- flags = data[3]; +- +- if(method != Z_DEFLATED || (flags & RESERVED) != 0) { +- /* Can't handle this compression method or unknown flag */ +- return GZIP_BAD; +- } +- +- /* Skip over time, xflags, OS code and all previous bytes */ +- len -= 10; +- data += 10; +- +- if(flags & EXTRA_FIELD) { +- ssize_t extra_len; +- +- if(len < 2) +- return GZIP_UNDERFLOW; +- +- extra_len = (data[1] << 8) | data[0]; +- +- if(len < (extra_len + 2)) +- return GZIP_UNDERFLOW; +- +- len -= (extra_len + 2); +- data += (extra_len + 2); +- } +- +- if(flags & ORIG_NAME) { +- /* Skip over NUL-terminated file name */ +- while(len && *data) { +- --len; +- ++data; +- } +- if(!len || *data) +- return GZIP_UNDERFLOW; +- +- /* Skip over the NUL */ +- --len; +- ++data; +- } +- +- if(flags & COMMENT) { +- /* Skip over NUL-terminated comment */ +- while(len && *data) { +- --len; +- ++data; +- } +- if(!len || *data) +- return GZIP_UNDERFLOW; +- +- /* Skip over the NUL */ +- --len; +- } +- +- if(flags & HEAD_CRC) { +- if(len < 2) +- return GZIP_UNDERFLOW; +- +- len -= 2; +- } +- +- *headerlen = totallen - len; +- return GZIP_OK; +-} +-#endif +- + static CURLcode gzip_do_write(struct Curl_easy *data, +- struct Curl_cwriter *writer, int type, +- const char *buf, size_t nbytes) ++ struct Curl_cwriter *writer, int type, ++ const char *buf, size_t nbytes) + { + struct zlib_writer *zp = (struct zlib_writer *) writer; + z_stream *z = &zp->z; /* zlib state structure */ +@@ -468,117 +356,8 @@ static CURLcode gzip_do_write(struct Curl_easy *data, + return inflate_stream(data, writer, type, ZLIB_INIT_GZIP); + } + +-#ifndef OLD_ZLIB_SUPPORT +- /* Support for old zlib versions is compiled away and we are running with +- an old version, so return an error. */ ++ /* We are running with an old version: return error. */ + return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR); +- +-#else +- /* This next mess is to get around the potential case where there isn't +- * enough data passed in to skip over the gzip header. If that happens, we +- * malloc a block and copy what we have then wait for the next call. If +- * there still isn't enough (this is definitely a worst-case scenario), we +- * make the block bigger, copy the next part in and keep waiting. +- * +- * This is only required with zlib versions < 1.2.0.4 as newer versions +- * can handle the gzip header themselves. +- */ +- +- switch(zp->zlib_init) { +- /* Skip over gzip header? */ +- case ZLIB_INIT: +- { +- /* Initial call state */ +- ssize_t hlen; +- +- switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) { +- case GZIP_OK: +- z->next_in = (Bytef *) buf + hlen; +- z->avail_in = (uInt) (nbytes - hlen); +- zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ +- break; +- +- case GZIP_UNDERFLOW: +- /* We need more data so we can find the end of the gzip header. It's +- * possible that the memory block we malloc here will never be freed if +- * the transfer abruptly aborts after this point. Since it's unlikely +- * that circumstances will be right for this code path to be followed in +- * the first place, and it's even more unlikely for a transfer to fail +- * immediately afterwards, it should seldom be a problem. +- */ +- z->avail_in = (uInt) nbytes; +- z->next_in = malloc(z->avail_in); +- if(!z->next_in) { +- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); +- } +- memcpy(z->next_in, buf, z->avail_in); +- zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ +- /* We don't have any data to inflate yet */ +- return CURLE_OK; +- +- case GZIP_BAD: +- default: +- return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); +- } +- +- } +- break; +- +- case ZLIB_GZIP_HEADER: +- { +- /* Need more gzip header data state */ +- ssize_t hlen; +- z->avail_in += (uInt) nbytes; +- z->next_in = Curl_saferealloc(z->next_in, z->avail_in); +- if(!z->next_in) { +- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); +- } +- /* Append the new block of data to the previous one */ +- memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes); +- +- switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) { +- case GZIP_OK: +- /* This is the zlib stream data */ +- free(z->next_in); +- /* Don't point into the malloced block since we just freed it */ +- z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in; +- z->avail_in = (uInt) (z->avail_in - hlen); +- zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */ +- break; +- +- case GZIP_UNDERFLOW: +- /* We still don't have any data to inflate! */ +- return CURLE_OK; +- +- case GZIP_BAD: +- default: +- return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z)); +- } +- +- } +- break; +- +- case ZLIB_EXTERNAL_TRAILER: +- z->next_in = (Bytef *) buf; +- z->avail_in = (uInt) nbytes; +- return process_trailer(data, zp); +- +- case ZLIB_GZIP_INFLATING: +- default: +- /* Inflating stream state */ +- z->next_in = (Bytef *) buf; +- z->avail_in = (uInt) nbytes; +- break; +- } +- +- if(z->avail_in == 0) { +- /* We don't have any data to inflate; wait until next time */ +- return CURLE_OK; +- } +- +- /* We've parsed the header, now uncompress the data */ +- return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING); +-#endif + } + + static void gzip_do_close(struct Curl_easy *data, +@@ -601,7 +380,6 @@ static const struct Curl_cwtype gzip_encoding = { + + #endif /* HAVE_LIBZ */ + +- + #ifdef HAVE_BROTLI + /* Brotli writer. */ + struct brotli_writer { +@@ -648,7 +426,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) + } + + static CURLcode brotli_do_init(struct Curl_easy *data, +- struct Curl_cwriter *writer) ++ struct Curl_cwriter *writer) + { + struct brotli_writer *bp = (struct brotli_writer *) writer; + (void) data; +@@ -658,8 +436,8 @@ static CURLcode brotli_do_init(struct Curl_easy *data, + } + + static CURLcode brotli_do_write(struct Curl_easy *data, +- struct Curl_cwriter *writer, int type, +- const char *buf, size_t nbytes) ++ struct Curl_cwriter *writer, int type, ++ const char *buf, size_t nbytes) + { + struct brotli_writer *bp = (struct brotli_writer *) writer; + const uint8_t *src = (const uint8_t *) buf; +@@ -731,7 +509,6 @@ static const struct Curl_cwtype brotli_encoding = { + }; + #endif + +- + #ifdef HAVE_ZSTD + /* Zstd writer. */ + struct zstd_writer { +@@ -741,7 +518,7 @@ struct zstd_writer { + }; + + static CURLcode zstd_do_init(struct Curl_easy *data, +- struct Curl_cwriter *writer) ++ struct Curl_cwriter *writer) + { + struct zstd_writer *zp = (struct zstd_writer *) writer; + +@@ -753,8 +530,8 @@ static CURLcode zstd_do_init(struct Curl_easy *data, + } + + static CURLcode zstd_do_write(struct Curl_easy *data, +- struct Curl_cwriter *writer, int type, +- const char *buf, size_t nbytes) ++ struct Curl_cwriter *writer, int type, ++ const char *buf, size_t nbytes) + { + CURLcode result = CURLE_OK; + struct zstd_writer *zp = (struct zstd_writer *) writer; +@@ -785,7 +562,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, + } + if(out.pos > 0) { + result = Curl_cwriter_write(data, writer->next, type, +- zp->decomp, out.pos); ++ zp->decomp, out.pos); + if(result) + break; + } +@@ -823,7 +600,6 @@ static const struct Curl_cwtype zstd_encoding = { + }; + #endif + +- + /* Identity handler. */ + static const struct Curl_cwtype identity_encoding = { + "identity", +@@ -834,7 +610,6 @@ static const struct Curl_cwtype identity_encoding = { + sizeof(struct Curl_cwriter) + }; + +- + /* supported general content decoders. */ + static const struct Curl_cwtype * const general_unencoders[] = { + &identity_encoding, +@@ -898,7 +673,7 @@ void Curl_all_content_encodings(char *buf, size_t blen) + + /* Deferred error dummy writer. */ + static CURLcode error_do_init(struct Curl_easy *data, +- struct Curl_cwriter *writer) ++ struct Curl_cwriter *writer) + { + (void)data; + (void)writer; +@@ -906,8 +681,8 @@ static CURLcode error_do_init(struct Curl_easy *data, + } + + static CURLcode error_do_write(struct Curl_easy *data, +- struct Curl_cwriter *writer, int type, +- const char *buf, size_t nbytes) ++ struct Curl_cwriter *writer, int type, ++ const char *buf, size_t nbytes) + { + char all[256]; + (void)Curl_all_content_encodings(all, sizeof(all)); +@@ -1048,5 +823,4 @@ void Curl_all_content_encodings(char *buf, size_t blen) + strcpy(buf, CONTENT_ENCODING_DEFAULT); + } + +- + #endif /* CURL_DISABLE_HTTP */ +-- +2.40.0 diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb index 86e307cfd6..b7a669fb57 100644 --- a/meta/recipes-support/curl/curl_8.7.1.bb +++ b/meta/recipes-support/curl/curl_8.7.1.bb @@ -24,6 +24,7 @@ SRC_URI = " \ file://CVE-2024-11053-0002.patch \ file://CVE-2024-11053-0003.patch \ file://CVE-2025-0167.patch \ + file://CVE-2025-0725.patch \ " SRC_URI[sha256sum] = "6fea2aac6a4610fbd0400afb0bcddbe7258a64c63f1f68e5855ebc0c659710cd"