public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Akinori Hattori" <hattya@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] repo/gentoo:master commit in: www-servers/h2o/files/, www-servers/h2o/
Date: Sun, 22 Oct 2023 13:44:07 +0000 (UTC)	[thread overview]
Message-ID: <1697981918.24f20ce718815bfd0a2db32f9fb116ec81a9e58c.hattya@gentoo> (raw)

commit:     24f20ce718815bfd0a2db32f9fb116ec81a9e58c
Author:     Akinori Hattori <hattya <AT> gentoo <DOT> org>
AuthorDate: Sun Oct 22 13:38:38 2023 +0000
Commit:     Akinori Hattori <hattya <AT> gentoo <DOT> org>
CommitDate: Sun Oct 22 13:38:38 2023 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=24f20ce7

www-servers/h2o: fix CVE-2023-44487

Bug: https://bugs.gentoo.org/915567
Signed-off-by: Akinori Hattori <hattya <AT> gentoo.org>

 www-servers/h2o/files/h2o-2.2-CVE-2023-44487.patch | 225 +++++++++++++++++++++
 www-servers/h2o/h2o-2.2.6-r2.ebuild                | 107 ++++++++++
 2 files changed, 332 insertions(+)

diff --git a/www-servers/h2o/files/h2o-2.2-CVE-2023-44487.patch b/www-servers/h2o/files/h2o-2.2-CVE-2023-44487.patch
new file mode 100644
index 000000000000..71a511ac9ed2
--- /dev/null
+++ b/www-servers/h2o/files/h2o-2.2-CVE-2023-44487.patch
@@ -0,0 +1,225 @@
+https://github.com/h2o/h2o/pull/3293
+
+From 770208bbe3955c47e005a1e8cb08266e4a8dfc9a Mon Sep 17 00:00:00 2001
+From: Remi Gacogne <remi.gacogne@powerdns.com>
+Date: Tue, 10 Oct 2023 15:47:57 +0200
+Subject: [PATCH] [http2] delay processing requests upon observing suspicious
+ behavior
+
+Backport of 94fbc54b6c9309912fe3d53e7b63408bbe9a1b0d to v2.2.x
+---
+ include/h2o.h                |  8 +++++++
+ include/h2o/http2_internal.h |  8 +++++++
+ lib/core/config.c            |  1 +
+ lib/core/configurator.c      |  9 ++++++++
+ lib/core/context.c           |  2 ++
+ lib/http2/connection.c       | 41 ++++++++++++++++++++++++++++++++----
+ 6 files changed, 65 insertions(+), 4 deletions(-)
+
+diff --git a/include/h2o.h b/include/h2o.h
+index 57877bd12c..409cd5c21c 100644
+--- a/include/h2o.h
++++ b/include/h2o.h
+@@ -378,6 +378,10 @@ struct st_h2o_globalconf_t {
+          * list of callbacks
+          */
+         h2o_protocol_callbacks_t callbacks;
++        /**
++         * milliseconds to delay processing requests when suspicious behavior is detected
++         */
++        uint64_t dos_delay;
+     } http2;
+ 
+     struct {
+@@ -590,6 +594,10 @@ struct st_h2o_context_t {
+          * timeout entry used for graceful shutdown
+          */
+         h2o_timeout_entry_t _graceful_shutdown_timeout;
++        /*
++         * dos timeout
++         */
++        h2o_timeout_t dos_delay_timeout;
+         struct {
+             /**
+              * counter for http2 errors internally emitted by h2o
+diff --git a/include/h2o/http2_internal.h b/include/h2o/http2_internal.h
+index 5cfc4d8204..b9cf400929 100644
+--- a/include/h2o/http2_internal.h
++++ b/include/h2o/http2_internal.h
+@@ -179,6 +179,7 @@ struct st_h2o_http2_stream_t {
+         h2o_linklist_t link;
+         h2o_http2_scheduler_openref_t scheduler;
+     } _refs;
++    unsigned reset_by_peer : 1;
+     h2o_send_state_t send_state; /* state of the ostream, only used in push mode */
+     /* placed at last since it is large and has it's own ctor */
+     h2o_req_t req;
+@@ -232,6 +233,13 @@ struct st_h2o_http2_conn_t {
+     } _write;
+     h2o_cache_t *push_memo;
+     h2o_http2_casper_t *casper;
++    /**
++     * DoS mitigation; the idea here is to delay processing requests when observing suspicious behavior
++     */
++    struct {
++        h2o_timeout_entry_t process_delay;
++        size_t reset_budget; /* RST_STREAM frames are considered suspicious when this value goes down to zero */
++    } dos_mitigation;
+ };
+ 
+ int h2o_http2_update_peer_settings(h2o_http2_settings_t *settings, const uint8_t *src, size_t len, const char **err_desc);
+diff --git a/lib/core/config.c b/lib/core/config.c
+index ce1d320183..08e43a6d30 100644
+--- a/lib/core/config.c
++++ b/lib/core/config.c
+@@ -189,6 +189,7 @@ void h2o_config_init(h2o_globalconf_t *config)
+     config->http2.latency_optimization.min_rtt = 50; // milliseconds
+     config->http2.latency_optimization.max_additional_delay = 10;
+     config->http2.latency_optimization.max_cwnd = 65535;
++    config->http2.dos_delay = 100; /* 100ms processing delay when observing suspicious behavior */
+     config->http2.callbacks = H2O_HTTP2_CALLBACKS;
+     config->mimemap = h2o_mimemap_create();
+ 
+diff --git a/lib/core/configurator.c b/lib/core/configurator.c
+index 891770cc2d..4731ba2707 100644
+--- a/lib/core/configurator.c
++++ b/lib/core/configurator.c
+@@ -531,6 +531,12 @@ static int on_config_http2_casper(h2o_configurator_command_t *cmd, h2o_configura
+     return 0;
+ }
+ 
++
++static int on_config_http2_dos_delay(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
++{
++    return config_timeout(cmd, node, &ctx->globalconf->http2.dos_delay);
++}
++
+ static int assert_is_mimetype(h2o_configurator_command_t *cmd, yoml_t *node)
+ {
+     if (node->type != YOML_TYPE_SCALAR) {
+@@ -910,6 +916,9 @@ void h2o_configurator__init_core(h2o_globalconf_t *conf)
+                                         on_config_http2_push_preload);
+         h2o_configurator_define_command(&c->super, "http2-casper", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST,
+                                         on_config_http2_casper);
++        h2o_configurator_define_command(&c->super, "http2-dos-delay",
++                                        H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
++                                        on_config_http2_dos_delay);
+         h2o_configurator_define_command(&c->super, "file.mime.settypes",
+                                         (H2O_CONFIGURATOR_FLAG_ALL_LEVELS & ~H2O_CONFIGURATOR_FLAG_EXTENSION) |
+                                             H2O_CONFIGURATOR_FLAG_EXPECT_MAPPING,
+diff --git a/lib/core/context.c b/lib/core/context.c
+index 8d11013810..ac4b0aaf08 100644
+--- a/lib/core/context.c
++++ b/lib/core/context.c
+@@ -101,6 +101,7 @@ void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *co
+     h2o_linklist_init_anchor(&ctx->http1._conns);
+     h2o_timeout_init(ctx->loop, &ctx->http2.idle_timeout, config->http2.idle_timeout);
+     h2o_timeout_init(ctx->loop, &ctx->http2.graceful_shutdown_timeout, config->http2.graceful_shutdown_timeout);
++    h2o_timeout_init(ctx->loop, &ctx->http2.dos_delay_timeout, config->http2.dos_delay);
+     h2o_linklist_init_anchor(&ctx->http2._conns);
+     ctx->proxy.client_ctx.loop = loop;
+     h2o_timeout_init(ctx->loop, &ctx->proxy.io_timeout, config->proxy.io_timeout);
+@@ -146,6 +147,7 @@ void h2o_context_dispose(h2o_context_t *ctx)
+     h2o_timeout_dispose(ctx->loop, &ctx->http1.req_timeout);
+     h2o_timeout_dispose(ctx->loop, &ctx->http2.idle_timeout);
+     h2o_timeout_dispose(ctx->loop, &ctx->http2.graceful_shutdown_timeout);
++    h2o_timeout_dispose(ctx->loop, &ctx->http2.dos_delay_timeout);
+     h2o_timeout_dispose(ctx->loop, &ctx->proxy.io_timeout);
+     /* what should we do here? assert(!h2o_linklist_is_empty(&ctx->http2._conns); */
+ 
+diff --git a/lib/http2/connection.c b/lib/http2/connection.c
+index e2da293043..4910e33098 100644
+--- a/lib/http2/connection.c
++++ b/lib/http2/connection.c
+@@ -161,7 +161,6 @@ static void update_idle_timeout(h2o_http2_conn_t *conn)
+     h2o_timeout_unlink(&conn->_timeout_entry);
+ 
+     if (conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed == 0) {
+-        assert(h2o_linklist_is_empty(&conn->_pending_reqs));
+         conn->_timeout_entry.cb = on_idle_timeout;
+         h2o_timeout_link(conn->super.ctx->loop, &conn->super.ctx->http2.idle_timeout, &conn->_timeout_entry);
+     }
+@@ -175,6 +174,9 @@ static int can_run_requests(h2o_http2_conn_t *conn)
+ 
+ static void run_pending_requests(h2o_http2_conn_t *conn)
+ {
++    if (h2o_timeout_is_linked(&conn->dos_mitigation.process_delay))
++        return;
++
+     while (!h2o_linklist_is_empty(&conn->_pending_reqs) && can_run_requests(conn)) {
+         /* fetch and detach a pending stream */
+         h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _refs.link, conn->_pending_reqs.next);
+@@ -226,6 +228,16 @@ void h2o_http2_conn_unregister_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t
+     assert(h2o_http2_scheduler_is_open(&stream->_refs.scheduler));
+     h2o_http2_scheduler_close(&stream->_refs.scheduler);
+ 
++    /* Decrement reset_budget if the stream was reset by peer, otherwise increment. By doing so, we penalize connections that
++     * generate resets for >50% of requests. */
++    if (stream->reset_by_peer) {
++        if (conn->dos_mitigation.reset_budget > 0)
++            --conn->dos_mitigation.reset_budget;
++    } else {
++        if (conn->dos_mitigation.reset_budget < conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection)
++            ++conn->dos_mitigation.reset_budget;
++    }
++
+     switch (stream->state) {
+     case H2O_HTTP2_STREAM_STATE_IDLE:
+     case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
+@@ -272,6 +284,8 @@ void close_connection_now(h2o_http2_conn_t *conn)
+     h2o_hpack_dispose_header_table(&conn->_output_header_table);
+     assert(h2o_linklist_is_empty(&conn->_pending_reqs));
+     h2o_timeout_unlink(&conn->_timeout_entry);
++    if (h2o_timeout_is_linked(&conn->dos_mitigation.process_delay))
++        h2o_timeout_unlink(&conn->dos_mitigation.process_delay);
+     h2o_buffer_dispose(&conn->_write.buf);
+     if (conn->_write.buf_in_flight != NULL)
+         h2o_buffer_dispose(&conn->_write.buf_in_flight);
+@@ -797,11 +811,19 @@ static int handle_rst_stream_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *fr
+         return H2O_HTTP2_ERROR_PROTOCOL;
+     }
+ 
+-    stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
+-    if (stream != NULL) {
++    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL)
++        return 0;
++
+         /* reset the stream */
++    stream->reset_by_peer = 1;
+         h2o_http2_stream_reset(conn, stream);
+-    }
++
++    /* setup process delay if we've just ran out of reset budget */
++    if (conn->dos_mitigation.reset_budget == 0 && conn->super.ctx->globalconf->http2.dos_delay != 0 &&
++        !h2o_timeout_is_linked(&conn->dos_mitigation.process_delay))
++        h2o_timeout_link(conn->super.ctx->loop, &conn->super.ctx->http2.dos_delay_timeout,
++                       &conn->dos_mitigation.process_delay);
++
+     /* TODO log */
+ 
+     return 0;
+@@ -1204,6 +1226,14 @@ static h2o_iovec_t log_priority_actual_weight(h2o_req_t *req)
+     return h2o_iovec_init(s, len);
+ }
+ 
++static void on_dos_process_delay(h2o_timeout_entry_t *timer)
++{
++    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, dos_mitigation.process_delay, timer);
++
++    assert(!h2o_timeout_is_linked(&conn->dos_mitigation.process_delay));
++    run_pending_requests(conn);
++}
++
+ static h2o_http2_conn_t *create_conn(h2o_context_t *ctx, h2o_hostconf_t **hosts, h2o_socket_t *sock, struct timeval connected_at)
+ {
+     static const h2o_conn_callbacks_t callbacks = {
+@@ -1240,6 +1270,9 @@ static h2o_http2_conn_t *create_conn(h2o_context_t *ctx, h2o_hostconf_t **hosts,
+     conn->_write.timeout_entry.cb = emit_writereq;
+     h2o_http2_window_init(&conn->_write.window, &conn->peer_settings);
+ 
++    conn->dos_mitigation.process_delay.cb = on_dos_process_delay;
++    conn->dos_mitigation.reset_budget = conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
++
+     return conn;
+ }
+ 

diff --git a/www-servers/h2o/h2o-2.2.6-r2.ebuild b/www-servers/h2o/h2o-2.2.6-r2.ebuild
new file mode 100644
index 000000000000..36b649162128
--- /dev/null
+++ b/www-servers/h2o/h2o-2.2.6-r2.ebuild
@@ -0,0 +1,107 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="8"
+CMAKE_MAKEFILE_GENERATOR="emake"
+SSL_DEPS_SKIP=1
+USE_RUBY="ruby31 ruby32"
+
+inherit cmake ruby-single ssl-cert systemd toolchain-funcs
+
+DESCRIPTION="H2O - the optimized HTTP/1, HTTP/2 server"
+HOMEPAGE="https://h2o.examp1e.net/"
+SRC_URI="https://github.com/${PN}/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz"
+
+LICENSE="MIT"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="libh2o +mruby"
+
+RDEPEND="acct-group/h2o
+	acct-user/h2o
+	dev-lang/perl
+	dev-libs/openssl:0=
+	!sci-libs/libh2o
+	sys-libs/zlib
+	libh2o? ( dev-libs/libuv )"
+DEPEND="${RDEPEND}
+	mruby? (
+		${RUBY_DEPS}
+		|| (
+			dev-libs/onigmo
+			dev-libs/oniguruma
+		)
+	)"
+BDEPEND="libh2o? ( virtual/pkgconfig )
+	mruby? (
+		sys-devel/bison
+		virtual/pkgconfig
+	)"
+
+PATCHES=(
+	"${FILESDIR}"/${PN}-2.2-libressl.patch #903001
+	"${FILESDIR}"/${PN}-2.2-mruby.patch
+	"${FILESDIR}"/${PN}-2.2-ruby30.patch
+	"${FILESDIR}"/${PN}-2.2-CVE-2023-44487.patch
+)
+
+src_prepare() {
+	cmake_src_prepare
+
+	local ruby="ruby"
+	if use mruby; then
+		for ruby in ${RUBY_TARGETS_PREFERENCE}; do
+			if has_version dev-lang/ruby:${ruby:4:1}.${ruby:5}; then
+				break
+			fi
+			ruby=
+		done
+		[[ -z ${ruby} ]] && die "no suitable ruby version found"
+	fi
+
+	sed -i \
+		-e "/INSTALL/s:\(/doc/${PN}\) :\1/html :" \
+		-e "/INSTALL/s:\(/doc\)/${PN}:\1/${PF}:" \
+		-e "s: ruby: ${ruby}:" \
+		CMakeLists.txt
+
+	sed -i "s:pkg-config:$(tc-getPKG_CONFIG):g" deps/mruby/lib/mruby/gem.rb
+	tc-export CC
+	export LD="$(tc-getCC)"
+}
+
+src_configure() {
+	local mycmakeargs=(
+		-DCMAKE_INSTALL_SYSCONFDIR="${EPREFIX}"/etc/${PN}
+		-DWITH_MRUBY=$(usex mruby)
+		-DWITHOUT_LIBS=$(usex !libh2o)
+		-DBUILD_SHARED_LIBS=$(usex libh2o)
+	)
+	cmake_src_configure
+}
+
+src_install() {
+	cmake_src_install
+
+	keepdir /var/www/localhost/htdocs
+
+	insinto /etc/${PN}
+	doins "${FILESDIR}"/${PN}.conf
+
+	newinitd "${FILESDIR}"/${PN}.initd ${PN}
+	systemd_dounit "${FILESDIR}"/${PN}.service
+
+	insinto /etc/logrotate.d
+	newins "${FILESDIR}"/${PN}.logrotate ${PN}
+
+	keepdir /var/log/${PN}
+	fowners ${PN}:${PN} /var/log/${PN}
+	fperms 0750 /var/log/${PN}
+}
+
+pkg_postinst() {
+	if [[ ! -f "${EROOT}"/etc/ssl/${PN}/server.key ]]; then
+		install_cert /etc/ssl/${PN}/server
+		chown ${PN}:${PN} "${EROOT}"/etc/ssl/${PN}/server.*
+	fi
+}


             reply	other threads:[~2023-10-22 13:44 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-22 13:44 Akinori Hattori [this message]
  -- strict thread matches above, loose matches on Subject: below --
2025-02-22  5:34 [gentoo-commits] repo/gentoo:master commit in: www-servers/h2o/files/, www-servers/h2o/ Akinori Hattori
2022-08-06  0:45 Akinori Hattori
2018-07-04 13:57 Akinori Hattori
2018-07-04 13:24 Akinori Hattori
2017-07-05 19:51 Michał Górny

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1697981918.24f20ce718815bfd0a2db32f9fb116ec81a9e58c.hattya@gentoo \
    --to=hattya@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox