From a7f0464790beae93a859fd2d6d020feb9b396fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?= Date: Thu, 8 Aug 2024 21:34:04 +0200 Subject: [PATCH] Resolves: RHEL-53632 - RFE: httpd, add IP_FREEBIND support for Listen Resolves: RHEL-53722 - [RFE] ProxyWebsocketIdleTimeout from httpd mod_proxy_wstunnel --- httpd-2.4.62-freebind.patch | 124 +++++++++++++++++++++++ httpd-2.4.62-proxy-ws-idle-timeout.patch | 109 ++++++++++++++++++++ httpd.spec | 11 +- 3 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 httpd-2.4.62-freebind.patch create mode 100644 httpd-2.4.62-proxy-ws-idle-timeout.patch diff --git a/httpd-2.4.62-freebind.patch b/httpd-2.4.62-freebind.patch new file mode 100644 index 0000000..93a0143 --- /dev/null +++ b/httpd-2.4.62-freebind.patch @@ -0,0 +1,124 @@ +diff --git a/docs/manual/mod/mpm_common.html.en b/docs/manual/mod/mpm_common.html.en +index d7a2fea..c911a4e 100644 +--- a/docs/manual/mod/mpm_common.html.en ++++ b/docs/manual/mod/mpm_common.html.en +@@ -42,6 +42,7 @@ more than one multi-processing module (MPM) +
  • EnableExceptionHook
  • +
  • GracefulShutdownTimeout
  • +
  • Listen
  • ++
  • ListenFree
  • +
  • ListenBackLog
  • +
  • ListenCoresBucketsRatio
  • +
  • MaxConnectionsPerChild
  • +@@ -244,6 +245,31 @@ discussion of the Address already in use error message, + including other causes. + + ++ ++
    top
    ++

    ListenFree Directive

    ++ ++ ++ ++ ++ ++ ++ ++
    Description:IP addresses and ports that the server ++listens to. Doesn't require IP address to be up
    Syntax:ListenFree [IP-address:]portnumber [protocol]
    Context:server config
    Status:MPM
    Module:event, worker, prefork, mpm_winnt, mpm_netware, mpmt_os2
    Compatibility:This directive is currently available only in Red Hat Enterprise Linux
    ++

    The ListenFree directive is ++ identical to the Listen directive. ++ The only difference is in the usage of the IP_FREEBIND socket ++ option, which is enabled by default with ListenFree. ++ If IP_FREEBIND is enabled, it allows httpd to bind to an IP ++ address that is nonlocal or does not (yet) exist. This allows httpd to ++ listen on a socket without requiring the underlying network interface ++ or the specified dynamic IP address to be up at the time when httpd ++ is trying to bind to it. ++

    ++
    ++ ++ +
    top
    +

    ListenBackLog Directive

    + +diff --git a/include/ap_listen.h b/include/ap_listen.h +index d5ed968..be1a60c 100644 +--- a/include/ap_listen.h ++++ b/include/ap_listen.h +@@ -138,6 +138,9 @@ AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, void *dummy + AP_DECLARE_NONSTD(const char *) ap_set_listencbratio(cmd_parms *cmd, void *dummy, const char *arg); + AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + int argc, char *const argv[]); ++AP_DECLARE_NONSTD(const char *) ap_set_freelistener(cmd_parms *cmd, void *dummy, ++ int argc, char *const argv[]); ++ + AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd, void *dummy, + const char *arg); + AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd, +@@ -160,6 +163,8 @@ AP_INIT_TAKE1("ListenCoresBucketsRatio", ap_set_listencbratio, NULL, RSRC_CONF, + "Ratio between the number of CPU cores (online) and the number of listeners buckets"), \ + AP_INIT_TAKE_ARGV("Listen", ap_set_listener, NULL, RSRC_CONF, \ + "A port number or a numeric IP address and a port number, and an optional protocol"), \ ++AP_INIT_TAKE_ARGV("ListenFree", ap_set_freelistener, NULL, RSRC_CONF, \ ++ "A port number or a numeric IP address and a port number, and an optional protocol"), \ + AP_INIT_TAKE1("SendBufferSize", ap_set_send_buffer_size, NULL, RSRC_CONF, \ + "Send buffer size in bytes"), \ + AP_INIT_TAKE1("ReceiveBufferSize", ap_set_receive_buffer_size, NULL, \ +diff --git a/server/listen.c b/server/listen.c +index 2a4e87a..280bbe7 100644 +--- a/server/listen.c ++++ b/server/listen.c +@@ -60,6 +60,7 @@ static int ap_listenbacklog; + static int ap_listencbratio; + static int send_buffer_size; + static int receive_buffer_size; ++static int ap_listenfreebind; + #ifdef HAVE_SYSTEMD + static int use_systemd = -1; + #endif +@@ -159,6 +160,21 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server, int do_bind_ + } + #endif + ++ ++#if defined(APR_SO_FREEBIND) ++ if (ap_listenfreebind) { ++ if (apr_socket_opt_set(s, APR_SO_FREEBIND, one) < 0) { ++ stat = apr_get_netos_error(); ++ ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(02182) ++ "make_sock: apr_socket_opt_set: " ++ "error setting APR_SO_FREEBIND"); ++ apr_socket_close(s); ++ return stat; ++ } ++ } ++#endif ++ ++ + if (do_bind_listen) { + #if APR_HAVE_IPV6 + if (server->bind_addr->family == APR_INET6) { +@@ -971,6 +987,7 @@ AP_DECLARE(void) ap_listen_pre_config(void) + } + } + ++ + AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + int argc, char *const argv[]) + { +@@ -1044,6 +1061,14 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + scope_id, NULL, cmd->temp_pool); + } + ++AP_DECLARE_NONSTD(const char *) ap_set_freelistener(cmd_parms *cmd, void *dummy, ++ int argc, ++ char *const argv[]) ++{ ++ ap_listenfreebind = 1; ++ return ap_set_listener(cmd, dummy, argc, argv); ++} ++ + AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, + void *dummy, + const char *arg) diff --git a/httpd-2.4.62-proxy-ws-idle-timeout.patch b/httpd-2.4.62-proxy-ws-idle-timeout.patch new file mode 100644 index 0000000..1c37b3e --- /dev/null +++ b/httpd-2.4.62-proxy-ws-idle-timeout.patch @@ -0,0 +1,109 @@ +diff --git a/docs/manual/mod/mod_proxy_wstunnel.html.en b/docs/manual/mod/mod_proxy_wstunnel.html.en +index c5004b8..a0ae3c8 100644 +--- a/docs/manual/mod/mod_proxy_wstunnel.html.en ++++ b/docs/manual/mod/mod_proxy_wstunnel.html.en +@@ -96,6 +96,7 @@ WebSocket always happens. +
    Support Apache!

    Directives

    + +

    Bugfix checklist

    See also

    +
      +@@ -121,6 +122,23 @@ WebSocket always happens. + WebSocket requests as in httpd 2.4.46 and earlier.

      + +
    ++ ++
    ++ ++ ++ ++ ++ ++ ++
    Description:Sets the maximum amount of time to wait for data on the websockets tunnel
    Syntax:ProxyWebsocketIdleTimeout num[ms]
    Default:ProxyWebsocketIdleTimeout 0
    Context:server config, virtual host
    Status:Extension
    Module:mod_proxy_wstunnel
    ++

    This directive imposes a maximum amount of time for the tunnel to be ++ left open while idle. The timeout is considered in seconds by default, but ++ it is possible to increase the time resolution to milliseconds ++ adding the ms suffix.

    ++ ++
    ++ + +
    +

    Available Languages:  en  | +diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c +index 30ba1b4..e27e6f8 100644 +--- a/modules/proxy/mod_proxy_wstunnel.c ++++ b/modules/proxy/mod_proxy_wstunnel.c +@@ -22,6 +22,7 @@ module AP_MODULE_DECLARE_DATA proxy_wstunnel_module; + typedef struct { + unsigned int fallback_to_proxy_http :1, + fallback_to_proxy_http_set :1; ++ apr_time_t idle_timeout; + } proxyws_dir_conf; + + static int can_fallback_to_proxy_http; +@@ -176,6 +177,8 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, + conn_rec *c = r->connection; + apr_socket_t *sock = conn->sock; + conn_rec *backconn = conn->connection; ++ proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config, ++ &proxy_wstunnel_module); + char *buf; + apr_bucket_brigade *header_brigade; + apr_bucket *e; +@@ -253,10 +256,13 @@ static int proxy_wstunnel_request(apr_pool_t *p, request_rec *r, + c->keepalive = AP_CONN_CLOSE; + + do { /* Loop until done (one side closes the connection, or an error) */ +- rv = apr_pollset_poll(pollset, -1, &pollcnt, &signalled); ++ rv = apr_pollset_poll(pollset, dconf->idle_timeout, &pollcnt, &signalled); + if (rv != APR_SUCCESS) { + if (APR_STATUS_IS_EINTR(rv)) { + continue; ++ } else if(APR_STATUS_IS_TIMEUP(rv)){ ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "RH: the connection has timed out"); ++ return HTTP_REQUEST_TIME_OUT; + } + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02444) "error apr_poll()"); + return HTTP_INTERNAL_SERVER_ERROR; +@@ -442,11 +448,26 @@ cleanup: + return status; + } + ++static const char * proxyws_set_idle(cmd_parms *cmd, void *conf, const char *val) ++{ ++ proxyws_dir_conf *dconf = conf; ++ if (ap_timeout_parameter_parse(val, &(dconf->idle_timeout), "s") != APR_SUCCESS) ++ return "ProxyWebsocketIdleTimeout timeout has wrong format"; ++ ++ if (dconf->idle_timeout < 0) ++ return "ProxyWebsocketIdleTimeout timeout has to be a non-negative number"; ++ ++ if (!dconf->idle_timeout) dconf->idle_timeout = -1; /* loop indefinitely */ ++ ++ return NULL; ++} ++ + static void *create_proxyws_dir_config(apr_pool_t *p, char *dummy) + { + proxyws_dir_conf *new = + (proxyws_dir_conf *) apr_pcalloc(p, sizeof(proxyws_dir_conf)); + ++ new->idle_timeout = -1; /* no timeout */ + new->fallback_to_proxy_http = 1; + + return (void *) new; +@@ -489,7 +510,8 @@ static const command_rec ws_proxy_cmds[] = + proxyws_fallback_to_proxy_http, NULL, RSRC_CONF|ACCESS_CONF, + "whether to let mod_proxy_http handle the upgrade and tunneling, " + "On by default"), +- ++ AP_INIT_TAKE1("ProxyWebsocketIdleTimeout", proxyws_set_idle, NULL, RSRC_CONF|ACCESS_CONF, ++ "timeout for activity in either direction, unlimited by default."), + {NULL} + }; + diff --git a/httpd.spec b/httpd.spec index ead081b..b8acc3b 100644 --- a/httpd.spec +++ b/httpd.spec @@ -25,7 +25,7 @@ Summary: Apache HTTP Server Name: httpd Version: 2.4.62 -Release: 2%{?dist} +Release: 3%{?dist} URL: https://httpd.apache.org/ Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc @@ -96,6 +96,10 @@ Patch30: httpd-2.4.43-logjournal.patch Patch31: httpd-2.4.53-separate-systemd-fns.patch Patch32: httpd-2.4.58-r1912477+.patch Patch33: httpd-2.4.54-selinux.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1949606 +Patch34: httpd-2.4.62-freebind.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1947496 +Patch35: httpd-2.4.62-proxy-ws-idle-timeout.patch # Bug fixes # https://bugzilla.redhat.com/show_bug.cgi?id=1397243 @@ -827,6 +831,11 @@ exit $rv %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Thu Aug 08 2024 Luboš Uhliarik - 2.4.62-3 +- Resolves: RHEL-53632 - RFE: httpd, add IP_FREEBIND support for Listen +- Resolves: RHEL-53722 - [RFE] ProxyWebsocketIdleTimeout from + httpd mod_proxy_wstunnel + * Sat Aug 03 2024 Luboš Uhliarik - 2.4.62-2 - Resolves: RHEL-52722 - Regression introduced by CVE-2024-38474 fix