diff --git a/SOURCES/mod_http2-1.15.7-CVE-2020-11993.patch b/SOURCES/mod_http2-1.15.7-CVE-2020-11993.patch new file mode 100644 index 0000000..a0ffc08 --- /dev/null +++ b/SOURCES/mod_http2-1.15.7-CVE-2020-11993.patch @@ -0,0 +1,119 @@ +diff --git a/mod_http2/h2_mplx.c b/mod_http2/h2_mplx.c +index c3d590d..33ea45e 100644 +--- a/mod_http2/h2_mplx.c ++++ b/mod_http2/h2_mplx.c +@@ -56,7 +56,7 @@ typedef struct { + apr_size_t count; + } stream_iter_ctx; + +-static apr_status_t mplx_be_happy(h2_mplx *m); ++static apr_status_t mplx_be_happy(h2_mplx *m, h2_task *task); + static apr_status_t mplx_be_annoyed(h2_mplx *m); + + apr_status_t h2_mplx_child_init(apr_pool_t *pool, server_rec *s) +@@ -526,10 +526,10 @@ static apr_status_t out_open(h2_mplx *m, int stream_id, h2_bucket_beam *beam) + stream->output = beam; + + if (APLOGctrace2(m->c)) { +- h2_beam_log(beam, m->c, APLOG_TRACE2, "out_open"); ++ h2_beam_log(beam, stream->task->c, APLOG_TRACE2, "out_open"); + } + else { +- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->task->c, + "h2_mplx(%s): out open", stream->task->id); + } + +@@ -579,10 +579,10 @@ static apr_status_t out_close(h2_mplx *m, h2_task *task) + return APR_ECONNABORTED; + } + +- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, task->c, + "h2_mplx(%s): close", task->id); + status = h2_beam_close(task->output.beam); +- h2_beam_log(task->output.beam, m->c, APLOG_TRACE2, "out_close"); ++ h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "out_close"); + output_consumed_signal(m, task); + check_data_for(m, stream, 1); + return status; +@@ -782,18 +782,18 @@ static void task_done(h2_mplx *m, h2_task *task) + { + h2_stream *stream; + +- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c, + "h2_mplx(%ld): task(%s) done", m->id, task->id); + out_close(m, task); + + task->worker_done = 1; + task->done_at = apr_time_now(); +- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c, + "h2_mplx(%s): request done, %f ms elapsed", task->id, + (task->done_at - task->started_at) / 1000.0); + + if (task->c && !task->c->aborted && task->started_at > m->last_mood_change) { +- mplx_be_happy(m); ++ mplx_be_happy(m, task); + } + + ap_assert(task->done_done == 0); +@@ -805,13 +805,13 @@ static void task_done(h2_mplx *m, h2_task *task) + /* reset and schedule again */ + h2_task_redo(task); + h2_iq_add(m->q, stream->id, NULL, NULL); +- ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, task->c, + H2_STRM_MSG(stream, "redo, added to q")); + } + else { + /* stream not cleaned up, stay around */ + task->done_done = 1; +- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c, + H2_STRM_MSG(stream, "task_done, stream open")); + if (stream->input) { + h2_beam_leave(stream->input); +@@ -824,7 +824,7 @@ static void task_done(h2_mplx *m, h2_task *task) + else if ((stream = h2_ihash_get(m->shold, task->stream_id)) != NULL) { + /* stream is done, was just waiting for this. */ + task->done_done = 1; +- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, task->c, + H2_STRM_MSG(stream, "task_done, in hold")); + if (stream->input) { + h2_beam_leave(stream->input); +@@ -832,12 +832,12 @@ static void task_done(h2_mplx *m, h2_task *task) + stream_joined(m, stream); + } + else if ((stream = h2_ihash_get(m->spurge, task->stream_id)) != NULL) { +- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, task->c, + H2_STRM_LOG(APLOGNO(03517), stream, "already in spurge")); + ap_assert("stream should not be in spurge" == NULL); + } + else { +- ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(03518) ++ ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, task->c, APLOGNO(03518) + "h2_mplx(%s): task_done, stream not found", + task->id); + ap_assert("stream should still be available" == NULL); +@@ -963,7 +963,7 @@ static apr_status_t unschedule_slow_tasks(h2_mplx *m) + return rv; + } + +-static apr_status_t mplx_be_happy(h2_mplx *m) ++static apr_status_t mplx_be_happy(h2_mplx *m, h2_task *task) + { + apr_time_t now; + +@@ -975,7 +975,7 @@ static apr_status_t mplx_be_happy(h2_mplx *m) + m->limit_active = H2MIN(m->limit_active * 2, m->max_active); + m->last_mood_change = now; + m->irritations_since = 0; +- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, m->c, ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, task->c, + "h2_mplx(%ld): mood update, increasing worker limit to %d", + m->id, m->limit_active); + } diff --git a/SOURCES/mod_http2-1.15.7-CVE-2021-33193.patch b/SOURCES/mod_http2-1.15.7-CVE-2021-33193.patch new file mode 100644 index 0000000..cb9a610 --- /dev/null +++ b/SOURCES/mod_http2-1.15.7-CVE-2021-33193.patch @@ -0,0 +1,81 @@ +diff --git a/mod_http2/h2_request.c b/mod_http2/h2_request.c +index 5893c8b..1131440 100644 +--- a/mod_http2/h2_request.c ++++ b/mod_http2/h2_request.c +@@ -206,75 +206,13 @@ h2_request *h2_request_clone(apr_pool_t *p, const h2_request *src) + return dst; + } + +-#if !AP_MODULE_MAGIC_AT_LEAST(20150222, 13) +-static request_rec *my_ap_create_request(conn_rec *c) +-{ +- apr_pool_t *p; +- request_rec *r; +- +- apr_pool_create(&p, c->pool); +- apr_pool_tag(p, "request"); +- r = apr_pcalloc(p, sizeof(request_rec)); +- AP_READ_REQUEST_ENTRY((intptr_t)r, (uintptr_t)c); +- r->pool = p; +- r->connection = c; +- r->server = c->base_server; +- +- r->user = NULL; +- r->ap_auth_type = NULL; +- +- r->allowed_methods = ap_make_method_list(p, 2); +- +- r->headers_in = apr_table_make(r->pool, 5); +- r->trailers_in = apr_table_make(r->pool, 5); +- r->subprocess_env = apr_table_make(r->pool, 25); +- r->headers_out = apr_table_make(r->pool, 12); +- r->err_headers_out = apr_table_make(r->pool, 5); +- r->trailers_out = apr_table_make(r->pool, 5); +- r->notes = apr_table_make(r->pool, 5); +- +- r->request_config = ap_create_request_config(r->pool); +- /* Must be set before we run create request hook */ +- +- r->proto_output_filters = c->output_filters; +- r->output_filters = r->proto_output_filters; +- r->proto_input_filters = c->input_filters; +- r->input_filters = r->proto_input_filters; +- ap_run_create_request(r); +- r->per_dir_config = r->server->lookup_defaults; +- +- r->sent_bodyct = 0; /* bytect isn't for body */ +- +- r->read_length = 0; +- r->read_body = REQUEST_NO_BODY; +- +- r->status = HTTP_OK; /* Until further notice */ +- r->header_only = 0; +- r->the_request = NULL; +- +- /* Begin by presuming any module can make its own path_info assumptions, +- * until some module interjects and changes the value. +- */ +- r->used_path_info = AP_REQ_DEFAULT_PATH_INFO; +- +- r->useragent_addr = c->client_addr; +- r->useragent_ip = c->client_ip; +- +- return r; +-} +-#endif +- + request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c) + { +- int access_status = HTTP_OK; ++ int access_status = HTTP_OK; + const char *rpath; + const char *s; + +-#if AP_MODULE_MAGIC_AT_LEAST(20150222, 13) + request_rec *r = ap_create_request(c); +-#else +- request_rec *r = my_ap_create_request(c); +-#endif + + r->headers_in = apr_table_clone(r->pool, req->headers); + diff --git a/SOURCES/mod_http2-1.15.7-CVE-2021-44224.patch b/SOURCES/mod_http2-1.15.7-CVE-2021-44224.patch new file mode 100644 index 0000000..1e28bad --- /dev/null +++ b/SOURCES/mod_http2-1.15.7-CVE-2021-44224.patch @@ -0,0 +1,13 @@ +diff --git a/mod_http2/h2_request.c b/mod_http2/h2_request.c +index 1131440..89a0b47 100644 +--- a/mod_http2/h2_request.c ++++ b/mod_http2/h2_request.c +@@ -267,7 +267,7 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c) + NULL, r, r->connection); + + if (access_status != HTTP_OK +- || (access_status = ap_run_post_read_request(r))) { ++ || (access_status = ap_post_read_request(r))) { + /* Request check post hooks failed. An example of this would be a + * request for a vhost where h2 is disabled --> 421. + */ diff --git a/SPECS/mod_http2.spec b/SPECS/mod_http2.spec index 97e8299..2665178 100644 --- a/SPECS/mod_http2.spec +++ b/SPECS/mod_http2.spec @@ -3,13 +3,16 @@ Name: mod_http2 Version: 1.15.7 -Release: 2%{?dist} +Release: 5%{?dist} Summary: module implementing HTTP/2 for Apache 2 Group: System Environment/Daemons License: ASL 2.0 URL: https://icing.github.io/mod_h2/ Source0: https://github.com/icing/mod_h2/releases/download/v%{version}/mod_http2-%{version}.tar.gz Patch1: mod_http2-1.15.7-CVE-2020-9490.patch +Patch2: mod_http2-1.15.7-CVE-2020-11993.patch +Patch3: mod_http2-1.15.7-CVE-2021-33193.patch +Patch4: mod_http2-1.15.7-CVE-2021-44224.patch BuildRequires: pkgconfig, httpd-devel >= 2.4.20, libnghttp2-devel >= 1.7.0, openssl-devel >= 1.0.2 Requires: httpd-mmn = %{_httpd_mmn} Conflicts: httpd < 2.4.25-8 @@ -22,6 +25,9 @@ top of libnghttp2 for httpd 2.4 servers. %prep %setup -q %patch1 -p1 -b .CVE-2020-9490 +%patch2 -p1 -b .CVE-2020-11993 +%patch3 -p1 -b .CVE-2021-33193 +%patch4 -p1 -b .CVE-2021-44224 %build %configure @@ -48,6 +54,18 @@ make check %{_httpd_moddir}/mod_proxy_http2.so %changelog +* Mon Jan 24 2022 Luboš Uhliarik - 1.15.7-5 +- Resolves: #2035030 - CVE-2021-44224 httpd:2.4/httpd: possible NULL dereference + or SSRF in forward proxy configurations + +* Thu Jan 06 2022 Luboš Uhliarik - 1.15.7-4 +- Resolves: #1966728 - CVE-2021-33193 httpd:2.4/mod_http2: httpd: + Request splitting via HTTP/2 method injection and mod_proxy + +* Fri Oct 30 2020 Lubos Uhliarik - 1.15.7-3 +- Resolves: #1869077 - CVE-2020-11993 httpd:2.4/mod_http2: httpd: + mod_http2 concurrent pool usage + * Mon Aug 17 2020 Lubos Uhliarik - 1.15.7-2 - Resolves: #1869073 - CVE-2020-9490 httpd:2.4/mod_http2: httpd: Push diary crash on specifically crafted HTTP/2 header