From c4a8f2350f25d60031c20e6811cf99c9296e65c4 Mon Sep 17 00:00:00 2001 From: chengyechun Date: Fri, 3 Nov 2023 16:46:22 +0800 Subject: [PATCH] fix CVE-2023-31122 and CVe-2023-45802 and CVE-2023-43622 --- ...ort-CVE-2023-31122-out-of-bound-Read.patch | 28 ++++ ...a-bug-in-handling-of-stream-timeouts.patch | 134 +++++++++++++++++ ...02-improved-early-cleanup-of-streams.patch | 139 ++++++++++++++++++ httpd.spec | 11 +- 4 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2023-31122-out-of-bound-Read.patch create mode 100644 backport-CVE-2023-43622-fixed-a-bug-in-handling-of-stream-timeouts.patch create mode 100644 backport-CVE-2023-45802-improved-early-cleanup-of-streams.patch diff --git a/backport-CVE-2023-31122-out-of-bound-Read.patch b/backport-CVE-2023-31122-out-of-bound-Read.patch new file mode 100644 index 0000000..aebeaeb --- /dev/null +++ b/backport-CVE-2023-31122-out-of-bound-Read.patch @@ -0,0 +1,28 @@ +From c41eb3b14a3d1eb2e3c42c4728cc52a22748851a Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Mon, 16 Oct 2023 06:39:44 +0000 +Subject: [PATCH] mod_macro: out of bounds Read + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/c41eb3b14a3d1eb2e3c42c4728cc52a22748851a + +--- + modules/core/mod_macro.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/modules/core/mod_macro.c b/modules/core/mod_macro.c +index 04af43b..cc42d0b 100644 +--- a/modules/core/mod_macro.c ++++ b/modules/core/mod_macro.c +@@ -465,7 +465,7 @@ static const char *process_content(apr_pool_t * pool, + for (i = 0; i < contents->nelts; i++) { + const char *errmsg; + /* copy the line and substitute macro parameters */ +- strncpy(line, ((char **) contents->elts)[i], MAX_STRING_LEN - 1); ++ apr_cpystrn(line, ((char **) contents->elts)[i], MAX_STRING_LEN); + errmsg = substitute_macro_args(line, MAX_STRING_LEN, + macro, replacements, used); + if (errmsg) { +-- +2.23.0 + diff --git a/backport-CVE-2023-43622-fixed-a-bug-in-handling-of-stream-timeouts.patch b/backport-CVE-2023-43622-fixed-a-bug-in-handling-of-stream-timeouts.patch new file mode 100644 index 0000000..da2f8bc --- /dev/null +++ b/backport-CVE-2023-43622-fixed-a-bug-in-handling-of-stream-timeouts.patch @@ -0,0 +1,134 @@ +From 582c533c1728459eef5f8ec1a64b81fb093b26a8 Mon Sep 17 00:00:00 2001 +From: SteFan Eissing +Date: Mon, 16 Oct 2023 06:18:30 +0000 +Subject: [PATCH] mod_http2: fixed a bug in handling of stream timeouts. + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/582c533c1728459eef5f8ec1a64b81fb093b26a8 + +--- + changes-entries/h2_stream_timeout.txt | 2 ++ + modules/http2/h2_mplx.c | 25 +++++++++++++++++++++++++ + modules/http2/h2_mplx.h | 5 +++++ + modules/http2/h2_session.c | 10 +++++++++- + modules/http2/h2_stream.c | 8 ++++++++ + modules/http2/h2_stream.h | 2 ++ + 6 files changed, 51 insertions(+), 1 deletion(-) + create mode 100644 changes-entries/h2_stream_timeout.txt + +diff --git a/changes-entries/h2_stream_timeout.txt b/changes-entries/h2_stream_timeout.txt +new file mode 100644 +index 0000000..ab39b42 +--- /dev/null ++++ b/changes-entries/h2_stream_timeout.txt +@@ -0,0 +1,2 @@ ++* mod_http2: fixed a bug in handing of stream timeouts. ++ [Stefan Eissing] +diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c +index b4855af..e150cc3 100644 +--- a/modules/http2/h2_mplx.c ++++ b/modules/http2/h2_mplx.c +@@ -394,6 +394,31 @@ apr_status_t h2_mplx_c1_streams_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx) + return APR_SUCCESS; + } + ++typedef struct { ++ int stream_count; ++ int stream_want_send; ++} stream_iter_aws_t; ++ ++static int m_stream_want_send_data(void *ctx, void *stream) ++{ ++ stream_iter_aws_t *x = ctx; ++ ++x->stream_count; ++ if (h2_stream_wants_send_data(stream)) ++ ++x->stream_want_send; ++ return 1; ++} ++ ++int h2_mplx_c1_all_streams_want_send_data(h2_mplx *m) ++{ ++ stream_iter_aws_t x; ++ x.stream_count = 0; ++ x.stream_want_send = 0; ++ H2_MPLX_ENTER(m); ++ h2_ihash_iter(m->streams, m_stream_want_send_data, &x); ++ H2_MPLX_LEAVE(m); ++ return x.stream_count && (x.stream_count == x.stream_want_send); ++} ++ + static int m_report_stream_iter(void *ctx, void *val) { + h2_mplx *m = ctx; + h2_stream *stream = val; +diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h +index f565a09..730bb16 100644 +--- a/modules/http2/h2_mplx.h ++++ b/modules/http2/h2_mplx.h +@@ -193,6 +193,11 @@ typedef int h2_mplx_stream_cb(struct h2_stream *s, void *userdata); + */ + apr_status_t h2_mplx_c1_streams_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx); + ++/** ++ * Return != 0 iff all open streams want to send data ++ */ ++int h2_mplx_c1_all_streams_want_send_data(h2_mplx *m) ++ + /** + * A stream has been RST_STREAM by the client. Abort + * any processing going on and remove from processing +diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c +index f740373..8aeff3c 100644 +--- a/modules/http2/h2_session.c ++++ b/modules/http2/h2_session.c +@@ -1931,7 +1931,15 @@ apr_status_t h2_session_process(h2_session *session, int async) + status = h2_mplx_c1_poll(session->mplx, session->s->timeout, + on_stream_input, on_stream_output, session); + if (APR_STATUS_IS_TIMEUP(status)) { +- if (session->open_streams == 0) { ++ /* If we timeout without streams open, no new request from client ++ * arrived. ++ * If we timeout without nghttp2 wanting to write something, bug ++ * all open streams have something to send, it means we are ++ * blocked on HTTP/2 flow control and the client did not send ++ * WINDOW_UPDATEs to us. */ ++ if (session->open_stream == 0 || ++ (!h2_session_want_send(session) && ++ h2_mplx_c1_all_streams_want_send_data(session->m))) { + h2_session_dispatch_event(session, H2_SESSION_EV_CONN_TIMEOUT, status, NULL); + break; + } +diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c +index 17e5d34..c81c3e4 100644 +--- a/modules/http2/h2_stream.c ++++ b/modules/http2/h2_stream.c +@@ -1185,6 +1185,14 @@ int h2_stream_is_ready(h2_stream *stream) + return 0; + } + ++int h2_stream_wants_send_data(h2_stream *stream) ++{ ++ H2_STRM_ASSERT_MAGIC(stream, H2_STRM_MAGIC_OK); ++ return h2_stream_is_ready(stream) && ++ ((stream->out_buffer && !APR_BRIGADE_EMPTY(stream->out_buffer)) || ++ (stream->output && !h2_beam_empty(stream->output))); ++} ++ + int h2_stream_is_at(const h2_stream *stream, h2_stream_state_t state) + { + return stream->state == state; +diff --git a/modules/http2/h2_stream.h b/modules/http2/h2_stream.h +index 695d56a..647ef2d 100644 +--- a/modules/http2/h2_stream.h ++++ b/modules/http2/h2_stream.h +@@ -317,6 +317,8 @@ const char *h2_stream_state_str(const h2_stream *stream); + */ + int h2_stream_is_ready(h2_stream *stream); + ++int h2_stream_wants_send_data(h2_stream *stream); ++ + #define H2_STRM_MSG(s, msg) \ + "h2_stream(%d-%lu-%d,%s): "msg, s->session->child_num, \ + (unsigned long)s->session->id, s->id, h2_stream_state_str(s) +-- +2.23.0 + diff --git a/backport-CVE-2023-45802-improved-early-cleanup-of-streams.patch b/backport-CVE-2023-45802-improved-early-cleanup-of-streams.patch new file mode 100644 index 0000000..652fc02 --- /dev/null +++ b/backport-CVE-2023-45802-improved-early-cleanup-of-streams.patch @@ -0,0 +1,139 @@ +From decce82a706abd78dfc32821a03ad93841d7758a Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Mon, 16 Oct 2023 09:05:00 +0000 +Subject: [PATCH] mod_http2: improved early cleanup of streams + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/decce82a706abd78dfc32821a03ad93841d7758a + +--- + changes-entries/h2_cleanup.txt | 2 ++ + modules/http2/h2_mplx.c | 26 ++++++++++++++++++++++---- + modules/http2/h2_mplx.h | 3 ++- + modules/http2/h2_session.c | 18 +++++++++++++++++- + modules/http2/h2_stream.c | 2 +- + 5 files changed, 44 insertions(+), 7 deletions(-) + create mode 100644 changes-entries/h2_cleanup.txt + +diff --git a/changes-entries/h2_cleanup.txt b/changes-entries/h2_cleanup.txt +new file mode 100644 +index 0000000..305f24a +--- /dev/null ++++ b/changes-entries/h2_cleanup.txt +@@ -0,0 +1,2 @@ ++* mod_http2: improved early cleanup of streams. ++ [Stefan Eissing] +diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c +index 99c47ea..b4855af 100644 +--- a/modules/http2/h2_mplx.c ++++ b/modules/http2/h2_mplx.c +@@ -1064,14 +1064,32 @@ static int reset_is_acceptable(h2_stream *stream) + return 1; /* otherwise, be forgiving */ + } + +-apr_status_t h2_mplx_c1_client_rst(h2_mplx *m, int stream_id) ++apr_status_t h2_mplx_c1_client_rst(h2_mplx *m, int stream_id, h2_stream * stream) + { +- h2_stream *stream; + apr_status_t status = APR_SUCCESS; ++ int registered; + + H2_MPLX_ENTER_ALWAYS(m); +- stream = h2_ihash_get(m->streams, stream_id); +- if (stream && !reset_is_acceptable(stream)) { ++ registered = (h2_ihash_get(m->streams, stream_id) != NULL); ++ if (!stream) { ++ /* a RST might arrive so late, we have already forgotten ++ * about it. Seems ok. */ ++ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c1, ++ H2_MPLX_MSG(m, "RST on unknown stream %d"), stream_id); ++ AP_DEBUG_ASSERT(!registered); ++ } ++ else if (!registered) { ++ /* a RST on a stream that mplx has not been told about, but ++ * which the session knows. Very early and annoying. */ ++ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c1 ++ H2_STRM_MSG(stream, "very early RST, drop")); ++ h2_stream_set_monitor(stream, NULL); ++ h2_stream_rst(stream, H2_ERR_STREAM_CLOSED); ++ h2_stream_dispatch(stream, H2_SEV_EOS_SENT); ++ m_stream_cleanup(m, stream); ++ m_be_annoyed(m); ++ } ++ else if (!reset_is_acceptable(stream)) { + m_be_annoyed(m); + } + H2_MPLX_LEAVE(m); +diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h +index 1f79aa8..f565a09 100644 +--- a/modules/http2/h2_mplx.h ++++ b/modules/http2/h2_mplx.h +@@ -198,7 +198,8 @@ apr_status_t h2_mplx_c1_streams_do(h2_mplx *m, h2_mplx_stream_cb *cb, void *ctx) + * any processing going on and remove from processing + * queue. + */ +-apr_status_t h2_mplx_c1_client_rst(h2_mplx *m, int stream_id); ++apr_status_t h2_mplx_c1_client_rst(h2_mplx *m, int stream_id, ++ struct h2_stream *stream); + + /** + * Get readonly access to a stream for a secondary connection. +diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c +index 7ba49cf..f740373 100644 +--- a/modules/http2/h2_session.c ++++ b/modules/http2/h2_session.c +@@ -402,6 +402,10 @@ static int on_frame_recv_cb(nghttp2_session *ng2s, + H2_SSSN_STRM_MSG(session, frame->hd.stream_id, + "RST_STREAM by client, error=%d"), + (int)frame->rst_stream.error_code); ++ if (stream) { ++ rv = h2_stream_recv_frame(stream, NGHTTP2_RST_STREAM, frame->hd.flags, ++ frame->hd.length + H2_FRAME_HDR_LEN); ++ } + if (stream && stream->initiated_on) { + /* A stream reset on a request we sent it. Normal, when the + * client does not want it. */ +@@ -410,7 +414,8 @@ static int on_frame_recv_cb(nghttp2_session *ng2s, + else { + /* A stream reset on a request it sent us. Could happen in a browser + * when the user navigates away or cancels loading - maybe. */ +- h2_mplx_c1_client_rst(session->mplx, frame->hd.stream_id); ++ h2_mplx_c1_client_rst(session->mplx, frame->hd.stream_id, ++ stream); + } + ++session->streams_reset; + break; +@@ -813,6 +818,17 @@ static apr_status_t session_cleanup(h2_session *session, const char *trigger) + "goodbye, clients will be confused, should not happen")); + } + ++ if (!h2_iq_empty(session->ready_to_process)) { ++ int sid; ++ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, ++ H2_SSSN_LOG(APLOG(), session, ++ "cleanup, resetting %d stream in ready-to-process"), ++ h2_iq_count(session->ready_to_process)); ++ while ((sid = h2_iq_shift(session->ready_to_process)) > 0) { ++ h2_mplx_c1_client_rst(session->mplx, sid, get_stream(session, sid)); ++ } ++ } ++ + transit(session, trigger, H2_SESSION_ST_CLEANUP); + h2_mplx_c1_destroy(session->mplx); + session->mplx = NULL; +diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c +index cf6f798..17e5d34 100644 +--- a/modules/http2/h2_stream.c ++++ b/modules/http2/h2_stream.c +@@ -125,7 +125,7 @@ static int trans_on_event[][H2_SS_MAX] = { + { S_XXX, S_ERR, S_ERR, S_CL_L, S_CLS, S_XXX, S_XXX, S_XXX, },/* EV_CLOSED_L*/ + { S_ERR, S_ERR, S_ERR, S_CL_R, S_ERR, S_CLS, S_NOP, S_NOP, },/* EV_CLOSED_R*/ + { S_CLS, S_CLS, S_CLS, S_CLS, S_CLS, S_CLS, S_NOP, S_NOP, },/* EV_CANCELLED*/ +-{ S_NOP, S_XXX, S_XXX, S_XXX, S_XXX, S_CLS, S_CLN, S_XXX, },/* EV_EOS_SENT*/ ++{ S_NOP, S_XXX, S_XXX, S_XXX, S_XXX, S_CLS, S_CLN, S_NOP, },/* EV_EOS_SENT*/ + { S_NOP, S_XXX, S_CLS, S_XXX, S_XXX, S_CLS, S_XXX, S_XXX, },/* EV_IN_ERROR*/ + }; + +-- +2.23.0 + diff --git a/httpd.spec b/httpd.spec index f6ada19..de2a481 100644 --- a/httpd.spec +++ b/httpd.spec @@ -8,7 +8,7 @@ Name: httpd Summary: Apache HTTP Server Version: 2.4.55 -Release: 4 +Release: 5 License: ASL 2.0 URL: https://httpd.apache.org/ Source0: https://archive.apache.org/dist/httpd/httpd-%{version}.tar.bz2 @@ -72,6 +72,9 @@ Patch18: backport-httpd-2.4.46-htcacheclean-dont-break.patch Patch19: backport-CVE-2023-27522.patch Patch20: backport-CVE-2023-25690.patch Patch21: backport-fix-memory-leak-in-calc_sha256_hash.patch +Patch22: backport-CVE-2023-31122-out-of-bound-Read.patch +Patch23: backport-CVE-2023-45802-improved-early-cleanup-of-streams.patch +Patch24: backport-CVE-2023-43622-fixed-a-bug-in-handling-of-stream-timeouts.patch BuildRequires: gcc autoconf pkgconfig findutils xmlto perl-interpreter perl-generators systemd-devel BuildRequires: zlib-devel libselinux-devel lua-devel brotli-devel @@ -508,6 +511,12 @@ exit $rv %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Fri Nov 03 2023 chengyechun - 2.4.55-5 +- Type:CVE +- ID:CVE-2023-31122, CVE-2023-45802, CVE-2023-43622 +- SUG:NA +- DESC:fix CVE-2023-31122 and CVE-2023-45802 and CVE-2023-43622 + * Mon Aug 14 2023 chengyechun - 2.4.55-4 - Type:bugfix - ID:NA