From b02de62633234972b57f3ec76660646efcceefb1 Mon Sep 17 00:00:00 2001 From: wenxin Date: Thu, 14 Aug 2025 16:50:26 +0800 Subject: [PATCH] Add patch to fix CVE-2024-42516, CVE-2925-49812 --- fix-CVE-2024-42516.patch | 303 +++++++++++++++++++++++++++++++++++++++ fix-CVE-2025-49812.patch | 198 +++++++++++++++++++++++++ httpd.spec | 9 +- 3 files changed, 509 insertions(+), 1 deletion(-) create mode 100644 fix-CVE-2024-42516.patch create mode 100644 fix-CVE-2025-49812.patch diff --git a/fix-CVE-2024-42516.patch b/fix-CVE-2024-42516.patch new file mode 100644 index 0000000..19891cc --- /dev/null +++ b/fix-CVE-2024-42516.patch @@ -0,0 +1,303 @@ +From a7a9d814c7c23e990283277230ddd5a9efec27c7 Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 11:59:38 +0000 +Subject: [PATCH] fix header merging + +Reviewed By: rpluem, jorton, ylavic + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927039 13f79535-47bb-0310-9956-ffa450edef68 +--- + modules/http/http_filters.c | 248 +++++++++++++++++++----------------- + 1 file changed, 128 insertions(+), 120 deletions(-) + +diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c +index 60b44d78580..732fb8eb6a7 100644 +--- a/modules/http/http_filters.c ++++ b/modules/http/http_filters.c +@@ -1300,107 +1300,10 @@ typedef struct header_filter_ctx { + int headers_sent; + } header_filter_ctx; + +-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, +- apr_bucket_brigade *b) ++static void merge_response_headers(request_rec *r, const char **protocol) + { +- request_rec *r = f->r; +- conn_rec *c = r->connection; +- const char *clheader; +- int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)); +- const char *protocol = NULL; +- apr_bucket *e; +- apr_bucket_brigade *b2; +- header_struct h; +- header_filter_ctx *ctx = f->ctx; +- const char *ctype; +- ap_bucket_error *eb = NULL; +- apr_status_t rv = APR_SUCCESS; +- int recursive_error = 0; +- +- AP_DEBUG_ASSERT(!r->main); +- +- if (!ctx) { +- ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx)); +- } +- else if (ctx->headers_sent) { +- /* Eat body if response must not have one. */ +- if (header_only) { +- /* Still next filters may be waiting for EOS, so pass it (alone) +- * when encountered and be done with this filter. +- */ +- e = APR_BRIGADE_LAST(b); +- if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { +- APR_BUCKET_REMOVE(e); +- apr_brigade_cleanup(b); +- APR_BRIGADE_INSERT_HEAD(b, e); +- ap_remove_output_filter(f); +- rv = ap_pass_brigade(f->next, b); +- } +- apr_brigade_cleanup(b); +- return rv; +- } +- } +- +- for (e = APR_BRIGADE_FIRST(b); +- e != APR_BRIGADE_SENTINEL(b); +- e = APR_BUCKET_NEXT(e)) +- { +- if (AP_BUCKET_IS_ERROR(e) && !eb) { +- eb = e->data; +- continue; +- } +- /* +- * If we see an EOC bucket it is a signal that we should get out +- * of the way doing nothing. +- */ +- if (AP_BUCKET_IS_EOC(e)) { +- ap_remove_output_filter(f); +- return ap_pass_brigade(f->next, b); +- } +- } +- +- if (!ctx->headers_sent && !check_headers(r)) { +- /* We may come back here from ap_die() below, +- * so clear anything from this response. +- */ +- apr_table_clear(r->headers_out); +- apr_table_clear(r->err_headers_out); +- r->content_type = r->content_encoding = NULL; +- r->content_languages = NULL; +- r->clength = r->chunked = 0; +- apr_brigade_cleanup(b); +- +- /* Don't recall ap_die() if we come back here (from its own internal +- * redirect or error response), otherwise we can end up in infinite +- * recursion; better fall through with 500, minimal headers and an +- * empty body (EOS only). +- */ +- if (!check_headers_recursion(r)) { +- ap_die(HTTP_INTERNAL_SERVER_ERROR, r); +- return AP_FILTER_ERROR; +- } +- r->status = HTTP_INTERNAL_SERVER_ERROR; +- e = ap_bucket_eoc_create(c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- e = apr_bucket_eos_create(c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- ap_set_content_length(r, 0); +- recursive_error = 1; +- } +- else if (eb) { +- int status; +- status = eb->status; +- apr_brigade_cleanup(b); +- ap_die(status, r); +- return AP_FILTER_ERROR; +- } +- +- if (r->assbackwards) { +- r->sent_bodyct = 1; +- ap_remove_output_filter(f); +- rv = ap_pass_brigade(f->next, b); +- goto out; +- } ++ const char *ctype = NULL; ++ const char *clheader = NULL; + + /* + * Now that we are ready to send a response, we need to combine the two +@@ -1430,6 +1333,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, + fixup_vary(r); + } + ++ /* determine the protocol and whether we should use keepalives. */ ++ basic_http_header_check(r, protocol); ++ ap_set_keepalive(r); + + /* + * Control cachability for non-cacheable responses if not already set by +@@ -1449,10 +1355,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, + apr_table_unset(r->headers_out, "ETag"); + } + +- /* determine the protocol and whether we should use keepalives. */ +- basic_http_header_check(r, &protocol); +- ap_set_keepalive(r); +- + /* 204/304 responses don't have content related headers */ + if (AP_STATUS_IS_HEADER_ONLY(r->status)) { + apr_table_unset(r->headers_out, "Transfer-Encoding"); +@@ -1513,30 +1415,136 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, + && !strcmp(clheader, "0")) { + apr_table_unset(r->headers_out, "Content-Length"); + } ++} + +- b2 = apr_brigade_create(r->pool, c->bucket_alloc); +- basic_http_header(r, b2, protocol); +- +- h.pool = r->pool; +- h.bb = b2; ++AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ++ apr_bucket_brigade *b) ++{ ++ request_rec *r = f->r; ++ conn_rec *c = r->connection; ++ int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)); ++ apr_bucket *e; ++ apr_bucket_brigade *b2; ++ header_struct h; ++ header_filter_ctx *ctx = f->ctx; ++ ap_bucket_error *eb = NULL; ++ apr_status_t rv = APR_SUCCESS; ++ int recursive_error = 0; ++ const char *protocol; + +- send_all_header_fields(&h, r); ++ AP_DEBUG_ASSERT(!r->main); + +- terminate_header(b2); ++ if (!ctx) { ++ ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx)); ++ } ++ else if (ctx->headers_sent) { ++ /* Eat body if response must not have one. */ ++ if (header_only) { ++ /* Still next filters may be waiting for EOS, so pass it (alone) ++ * when encountered and be done with this filter. ++ */ ++ e = APR_BRIGADE_LAST(b); ++ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { ++ APR_BUCKET_REMOVE(e); ++ apr_brigade_cleanup(b); ++ APR_BRIGADE_INSERT_HEAD(b, e); ++ ap_remove_output_filter(f); ++ rv = ap_pass_brigade(f->next, b); ++ } ++ apr_brigade_cleanup(b); ++ return rv; ++ } ++ } + +- if (header_only) { +- e = APR_BRIGADE_LAST(b); +- if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { +- APR_BUCKET_REMOVE(e); +- APR_BRIGADE_INSERT_TAIL(b2, e); ++ for (e = APR_BRIGADE_FIRST(b); ++ e != APR_BRIGADE_SENTINEL(b); ++ e = APR_BUCKET_NEXT(e)) ++ { ++ if (AP_BUCKET_IS_ERROR(e) && !eb) { ++ eb = e->data; ++ continue; ++ } ++ /* ++ * If we see an EOC bucket it is a signal that we should get out ++ * of the way doing nothing. ++ */ ++ if (AP_BUCKET_IS_EOC(e)) { + ap_remove_output_filter(f); ++ return ap_pass_brigade(f->next, b); ++ } ++ } ++ ++ if (!ctx->headers_sent) { ++ merge_response_headers(r, &protocol); ++ if (!check_headers(r)) { ++ /* We may come back here from ap_die() below, ++ * so clear anything from this response. ++ */ ++ apr_table_clear(r->headers_out); ++ apr_table_clear(r->err_headers_out); ++ r->content_type = r->content_encoding = NULL; ++ r->content_languages = NULL; ++ r->clength = r->chunked = 0; ++ apr_brigade_cleanup(b); ++ ++ /* Don't recall ap_die() if we come back here (from its own internal ++ * redirect or error response), otherwise we can end up in infinite ++ * recursion; better fall through with 500, minimal headers and an ++ * empty body (EOS only). ++ */ ++ if (!check_headers_recursion(r)) { ++ ap_die(HTTP_INTERNAL_SERVER_ERROR, r); ++ return AP_FILTER_ERROR; ++ } ++ r->status = HTTP_INTERNAL_SERVER_ERROR; ++ e = ap_bucket_eoc_create(c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(b, e); ++ e = apr_bucket_eos_create(c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(b, e); ++ ap_set_content_length(r, 0); ++ recursive_error = 1; ++ } ++ else if (eb) { ++ int status; ++ status = eb->status; ++ apr_brigade_cleanup(b); ++ ap_die(status, r); ++ return AP_FILTER_ERROR; + } +- apr_brigade_cleanup(b); + } + +- rv = ap_pass_brigade(f->next, b2); +- apr_brigade_cleanup(b2); +- ctx->headers_sent = 1; ++ if (r->assbackwards) { ++ r->sent_bodyct = 1; ++ ap_remove_output_filter(f); ++ rv = ap_pass_brigade(f->next, b); ++ goto out; ++ } ++ ++ if (!ctx->headers_sent) { ++ b2 = apr_brigade_create(r->pool, c->bucket_alloc); ++ basic_http_header(r, b2, protocol); ++ ++ h.pool = r->pool; ++ h.bb = b2; ++ ++ send_all_header_fields(&h, r); ++ ++ terminate_header(b2); ++ ++ if (header_only) { ++ e = APR_BRIGADE_LAST(b); ++ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { ++ APR_BUCKET_REMOVE(e); ++ APR_BRIGADE_INSERT_TAIL(b2, e); ++ ap_remove_output_filter(f); ++ } ++ apr_brigade_cleanup(b); ++ } ++ ++ rv = ap_pass_brigade(f->next, b2); ++ apr_brigade_cleanup(b2); ++ ctx->headers_sent = 1; ++ } + + if (rv != APR_SUCCESS || header_only) { + goto out; diff --git a/fix-CVE-2025-49812.patch b/fix-CVE-2025-49812.patch new file mode 100644 index 0000000..16bb79c --- /dev/null +++ b/fix-CVE-2025-49812.patch @@ -0,0 +1,198 @@ +From 87a7351c755c9ef8ab386e3090e44838c2a06d48 Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 12:09:30 +0000 +Subject: [PATCH] backport 1927037 from trunk + + remove antiquated 'SSLEngine optional' TLS upgrade + +Reviewed By: rpluem, jorton, covener + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927045 13f79535-47bb-0310-9956-ffa450edef68 +--- + modules/ssl/ssl_engine_config.c | 6 ++- + modules/ssl/ssl_engine_init.c | 6 +-- + modules/ssl/ssl_engine_kernel.c | 86 --------------------------------- + modules/ssl/ssl_private.h | 1 - + 4 files changed, 7 insertions(+), 92 deletions(-) + +diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c +index 9af6f70fd03..d1f4fad8e23 100644 +--- a/modules/ssl/ssl_engine_config.c ++++ b/modules/ssl/ssl_engine_config.c +@@ -741,11 +741,13 @@ const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg) + return NULL; + } + else if (!strcasecmp(arg, "Optional")) { +- sc->enabled = SSL_ENABLED_OPTIONAL; ++ sc->enabled = SSL_ENABLED_FALSE; ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server, APLOGNO(10510) ++ "'SSLEngine optional' is no longer supported"); + return NULL; + } + +- return "Argument must be On, Off, or Optional"; ++ return "Argument must be On or Off"; + } + + const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag) +diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c +index f9eca79e462..94cc2772e01 100644 +--- a/modules/ssl/ssl_engine_init.c ++++ b/modules/ssl/ssl_engine_init.c +@@ -427,7 +427,7 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, + &ssl_module); + + sc = mySrvConfig(s); +- if (sc->enabled == SSL_ENABLED_TRUE || sc->enabled == SSL_ENABLED_OPTIONAL) { ++ if (sc->enabled == SSL_ENABLED_TRUE) { + if ((rv = ssl_run_init_server(s, p, 0, sc->server->ssl_ctx)) != APR_SUCCESS) { + return rv; + } +@@ -2126,9 +2126,9 @@ apr_status_t ssl_init_ConfigureServer(server_rec *s, + &ssl_module); + apr_status_t rv; + +- /* Initialize the server if SSL is enabled or optional. ++ /* Initialize the server if SSL is enabled. + */ +- if ((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) { ++ if (sc->enabled == SSL_ENABLED_TRUE) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01914) + "Configuring server %s for SSL protocol", sc->vhost_id); + if ((rv = ssl_init_server_ctx(s, p, ptemp, sc, pphrases)) +diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c +index d912a874dd9..33aa1f71dc7 100644 +--- a/modules/ssl/ssl_engine_kernel.c ++++ b/modules/ssl/ssl_engine_kernel.c +@@ -38,59 +38,6 @@ static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); + static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s); + #endif + +-#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols" +-#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1" +-#define CONNECTION_HEADER "Connection: Upgrade" +- +-/* Perform an upgrade-to-TLS for the given request, per RFC 2817. */ +-static apr_status_t upgrade_connection(request_rec *r) +-{ +- struct conn_rec *conn = r->connection; +- apr_bucket_brigade *bb; +- SSLConnRec *sslconn; +- apr_status_t rv; +- SSL *ssl; +- +- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02028) +- "upgrading connection to TLS"); +- +- bb = apr_brigade_create(r->pool, conn->bucket_alloc); +- +- rv = ap_fputs(conn->output_filters, bb, SWITCH_STATUS_LINE CRLF +- UPGRADE_HEADER CRLF CONNECTION_HEADER CRLF CRLF); +- if (rv == APR_SUCCESS) { +- APR_BRIGADE_INSERT_TAIL(bb, +- apr_bucket_flush_create(conn->bucket_alloc)); +- rv = ap_pass_brigade(conn->output_filters, bb); +- } +- +- if (rv) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02029) +- "failed to send 101 interim response for connection " +- "upgrade"); +- return rv; +- } +- +- ssl_init_ssl_connection(conn, r); +- +- sslconn = myConnConfig(conn); +- ssl = sslconn->ssl; +- +- /* Perform initial SSL handshake. */ +- SSL_set_accept_state(ssl); +- SSL_do_handshake(ssl); +- +- if (!SSL_is_init_finished(ssl)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02030) +- "TLS upgrade handshake failed"); +- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); +- +- return APR_ECONNABORTED; +- } +- +- return APR_SUCCESS; +-} +- + /* Perform a speculative (and non-blocking) read from the connection + * filters for the given request, to determine whether there is any + * pending data to read. Return non-zero if there is, else zero. */ +@@ -270,40 +217,17 @@ int ssl_hook_ReadReq(request_rec *r) + { + SSLSrvConfigRec *sc = mySrvConfig(r->server); + SSLConnRec *sslconn; +- const char *upgrade; + #ifdef HAVE_TLSEXT + const char *servername; + #endif + SSL *ssl; + +- /* Perform TLS upgrade here if "SSLEngine optional" is configured, +- * SSL is not already set up for this connection, and the client +- * has sent a suitable Upgrade header. */ +- if (sc->enabled == SSL_ENABLED_OPTIONAL && !myConnConfig(r->connection) +- && (upgrade = apr_table_get(r->headers_in, "Upgrade")) != NULL +- && ap_find_token(r->pool, upgrade, "TLS/1.0")) { +- if (upgrade_connection(r)) { +- return AP_FILTER_ERROR; +- } +- } +- + /* If we are on a slave connection, we do not expect to have an SSLConnRec, + * but our master connection might. */ + sslconn = myConnConfig(r->connection); + if (!(sslconn && sslconn->ssl) && r->connection->master) { + sslconn = myConnConfig(r->connection->master); + } +- +- /* If "SSLEngine optional" is configured, this is not an SSL +- * connection, and this isn't a subrequest, send an Upgrade +- * response header. Note this must happen before map_to_storage +- * and OPTIONS * request processing is completed. +- */ +- if (sc->enabled == SSL_ENABLED_OPTIONAL && !(sslconn && sslconn->ssl) +- && !r->main) { +- apr_table_setn(r->headers_out, "Upgrade", "TLS/1.0, HTTP/1.1"); +- apr_table_mergen(r->headers_out, "Connection", "upgrade"); +- } + + if (!sslconn) { + return DECLINED; +@@ -1238,16 +1162,6 @@ int ssl_hook_Access(request_rec *r) + * Support for SSLRequireSSL directive + */ + if (dc->bSSLRequired && !ssl) { +- if ((sc->enabled == SSL_ENABLED_OPTIONAL) && !r->connection->master) { +- /* This vhost was configured for optional SSL, just tell the +- * client that we need to upgrade. +- */ +- apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1"); +- apr_table_setn(r->err_headers_out, "Connection", "Upgrade"); +- +- return HTTP_UPGRADE_REQUIRED; +- } +- + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02219) + "access to %s failed, reason: %s", + r->filename, "SSL connection required"); +diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h +index fb9edaa5eeb..794e51aa937 100644 +--- a/modules/ssl/ssl_private.h ++++ b/modules/ssl/ssl_private.h +@@ -526,7 +526,6 @@ typedef enum { + SSL_ENABLED_UNSET = UNSET, + SSL_ENABLED_FALSE = 0, + SSL_ENABLED_TRUE = 1, +- SSL_ENABLED_OPTIONAL = 3 + } ssl_enabled_t; + + /** diff --git a/httpd.spec b/httpd.spec index b48b5f7..c4a919c 100644 --- a/httpd.spec +++ b/httpd.spec @@ -1,4 +1,4 @@ -%define anolis_release 2 +%define anolis_release 3 %define contentdir %{_datadir}/%{name} %define docroot /var/www %define suexec_caller apache @@ -93,6 +93,10 @@ Patch1000: 1000-httpd-anolis-rebrand.patch #Patch1002: fix-cve-2024-38472.patch #https://github.com/apache/httpd/commit/9494aa8d52e3c263bc0413b77ac8a73b0d524388 #Patch1003: fix-cve-2024-39573.patch +# https://github.com/apache/httpd/commit/a7a9d814c7c23e990283277230ddd5a9efec27c7 +Patch1004: fix-CVE-2024-42516.patch +# https://github.com/apache/httpd/commit/87a7351c755c9ef8ab386e3090e44838c2a06d48 +Patch1005: fix-CVE-2025-49812.patch BuildRequires: gcc > 12.0 BuildRequires: autoconf @@ -765,6 +769,9 @@ exit $rv %changelog +* Thu Aug 14 2025 wenxin - 2.4.62-3 +- Add patch to fix CVE-2024-42516, CVE-2925-49812 + * Fri Dec 13 2024 Chang Gao - 2.4.62-2 - Add compatiblility with old type system-logos provides -- Gitee