diff options
| author | Chen Qi <Qi.Chen@windriver.com> | 2023-09-14 12:00:26 +0800 |
|---|---|---|
| committer | Armin Kuster <akuster808@gmail.com> | 2023-09-19 07:22:00 -0400 |
| commit | 5862e1090d9e928008d50e1acf557f94a9672adb (patch) | |
| tree | 73a74ecbdf3c1abf8da23a155d806b5045daf058 | |
| parent | 105cf623137fb61290a816e1629ee83793abd907 (diff) | |
| download | meta-openembedded-5862e1090d9e928008d50e1acf557f94a9672adb.tar.gz | |
grpc: fix CVE-2023-33953
Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
| -rw-r--r-- | meta-oe/recipes-devtools/grpc/grpc/0001-backport-iomgr-EventEngine-Improve-server-handling-o.patch | 224 | ||||
| -rw-r--r-- | meta-oe/recipes-devtools/grpc/grpc_1.50.1.bb | 1 |
2 files changed, 225 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/grpc/grpc/0001-backport-iomgr-EventEngine-Improve-server-handling-o.patch b/meta-oe/recipes-devtools/grpc/grpc/0001-backport-iomgr-EventEngine-Improve-server-handling-o.patch new file mode 100644 index 0000000000..4488df172f --- /dev/null +++ b/meta-oe/recipes-devtools/grpc/grpc/0001-backport-iomgr-EventEngine-Improve-server-handling-o.patch | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | From b3c105c59dfb7d932b36b0d9ac7ab62875ab23e8 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: AJ Heller <hork@google.com> | ||
| 3 | Date: Wed, 12 Jul 2023 18:42:09 -0700 | ||
| 4 | Subject: [PATCH] [backport][iomgr][EventEngine] Improve server handling of | ||
| 5 | file descriptor exhaustion (#33672) | ||
| 6 | |||
| 7 | Backport of #33656 | ||
| 8 | |||
| 9 | CVE: CVE-2023-33953 | ||
| 10 | |||
| 11 | Upstream-Status: Backport [1e86ca5834b94cae7d5e6d219056c0fc895cf95d] | ||
| 12 | The patch is backported with tweaks to fit 1.50.1. | ||
| 13 | |||
| 14 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> | ||
| 15 | --- | ||
| 16 | .../event_engine/posix_engine/posix_engine.h | 1 + | ||
| 17 | src/core/lib/iomgr/tcp_server_posix.cc | 51 ++++++++++++++----- | ||
| 18 | src/core/lib/iomgr/tcp_server_utils_posix.h | 14 ++++- | ||
| 19 | .../iomgr/tcp_server_utils_posix_common.cc | 22 ++++++++ | ||
| 20 | 4 files changed, 73 insertions(+), 15 deletions(-) | ||
| 21 | |||
| 22 | diff --git a/src/core/lib/event_engine/posix_engine/posix_engine.h b/src/core/lib/event_engine/posix_engine/posix_engine.h | ||
| 23 | index eac6dfb4c5..866c04bcfa 100644 | ||
| 24 | --- a/src/core/lib/event_engine/posix_engine/posix_engine.h | ||
| 25 | +++ b/src/core/lib/event_engine/posix_engine/posix_engine.h | ||
| 26 | @@ -97,6 +97,7 @@ class PosixEventEngine final : public EventEngine { | ||
| 27 | const DNSResolver::ResolverOptions& options) override; | ||
| 28 | void Run(Closure* closure) override; | ||
| 29 | void Run(absl::AnyInvocable<void()> closure) override; | ||
| 30 | + // Caution!! The timer implementation cannot create any fds. See #20418. | ||
| 31 | TaskHandle RunAfter(Duration when, Closure* closure) override; | ||
| 32 | TaskHandle RunAfter(Duration when, | ||
| 33 | absl::AnyInvocable<void()> closure) override; | ||
| 34 | diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc | ||
| 35 | index d43113fb03..32be997cff 100644 | ||
| 36 | --- a/src/core/lib/iomgr/tcp_server_posix.cc | ||
| 37 | +++ b/src/core/lib/iomgr/tcp_server_posix.cc | ||
| 38 | @@ -16,13 +16,17 @@ | ||
| 39 | * | ||
| 40 | */ | ||
| 41 | |||
| 42 | -/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */ | ||
| 43 | +#include <grpc/support/port_platform.h> | ||
| 44 | + | ||
| 45 | +#include <utility> | ||
| 46 | + | ||
| 47 | +#include <grpc/support/atm.h> | ||
| 48 | + | ||
| 49 | +// FIXME: "posix" files shouldn't be depending on _GNU_SOURCE | ||
| 50 | #ifndef _GNU_SOURCE | ||
| 51 | #define _GNU_SOURCE | ||
| 52 | #endif | ||
| 53 | |||
| 54 | -#include <grpc/support/port_platform.h> | ||
| 55 | - | ||
| 56 | #include "src/core/lib/iomgr/port.h" | ||
| 57 | |||
| 58 | #ifdef GRPC_POSIX_SOCKET_TCP_SERVER | ||
| 59 | @@ -44,6 +48,7 @@ | ||
| 60 | #include "absl/strings/str_format.h" | ||
| 61 | |||
| 62 | #include <grpc/event_engine/endpoint_config.h> | ||
| 63 | +#include <grpc/event_engine/event_engine.h> | ||
| 64 | #include <grpc/support/alloc.h> | ||
| 65 | #include <grpc/support/log.h> | ||
| 66 | #include <grpc/support/sync.h> | ||
| 67 | @@ -63,6 +68,8 @@ | ||
| 68 | #include "src/core/lib/resource_quota/api.h" | ||
| 69 | |||
| 70 | static std::atomic<int64_t> num_dropped_connections{0}; | ||
| 71 | +static constexpr grpc_core::Duration kRetryAcceptWaitTime{ | ||
| 72 | + grpc_core::Duration::Seconds(1)}; | ||
| 73 | |||
| 74 | using ::grpc_event_engine::experimental::EndpointConfig; | ||
| 75 | |||
| 76 | @@ -195,21 +202,35 @@ static void on_read(void* arg, grpc_error_handle err) { | ||
| 77 | if (fd < 0) { | ||
| 78 | if (errno == EINTR) { | ||
| 79 | continue; | ||
| 80 | - } else if (errno == EAGAIN || errno == ECONNABORTED || | ||
| 81 | - errno == EWOULDBLOCK) { | ||
| 82 | + } | ||
| 83 | + // When the process runs out of fds, accept4() returns EMFILE. When this | ||
| 84 | + // happens, the connection is left in the accept queue until either a | ||
| 85 | + // read event triggers the on_read callback, or time has passed and the | ||
| 86 | + // accept should be re-tried regardless. This callback is not cancelled, | ||
| 87 | + // so a spurious wakeup may occur even when there's nothing to accept. | ||
| 88 | + // This is not a performant code path, but if an fd limit has been | ||
| 89 | + // reached, the system is likely in an unhappy state regardless. | ||
| 90 | + if (errno == EMFILE) { | ||
| 91 | grpc_fd_notify_on_read(sp->emfd, &sp->read_closure); | ||
| 92 | + if (gpr_atm_full_xchg(&sp->retry_timer_armed, true)) return; | ||
| 93 | + grpc_timer_init(&sp->retry_timer, | ||
| 94 | + grpc_core::Timestamp::Now() + kRetryAcceptWaitTime, | ||
| 95 | + &sp->retry_closure); | ||
| 96 | return; | ||
| 97 | + } | ||
| 98 | + if (errno == EAGAIN || errno == ECONNABORTED || errno == EWOULDBLOCK) { | ||
| 99 | + grpc_fd_notify_on_read(sp->emfd, &sp->read_closure); | ||
| 100 | + return; | ||
| 101 | + } | ||
| 102 | + gpr_mu_lock(&sp->server->mu); | ||
| 103 | + if (!sp->server->shutdown_listeners) { | ||
| 104 | + gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); | ||
| 105 | } else { | ||
| 106 | - gpr_mu_lock(&sp->server->mu); | ||
| 107 | - if (!sp->server->shutdown_listeners) { | ||
| 108 | - gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); | ||
| 109 | - } else { | ||
| 110 | - /* if we have shutdown listeners, accept4 could fail, and we | ||
| 111 | - needn't notify users */ | ||
| 112 | - } | ||
| 113 | - gpr_mu_unlock(&sp->server->mu); | ||
| 114 | - goto error; | ||
| 115 | + // if we have shutdown listeners, accept4 could fail, and we | ||
| 116 | + // needn't notify users | ||
| 117 | } | ||
| 118 | + gpr_mu_unlock(&sp->server->mu); | ||
| 119 | + goto error; | ||
| 120 | } | ||
| 121 | |||
| 122 | if (sp->server->memory_quota->IsMemoryPressureHigh()) { | ||
| 123 | @@ -403,6 +424,7 @@ static grpc_error_handle clone_port(grpc_tcp_listener* listener, | ||
| 124 | sp->port_index = listener->port_index; | ||
| 125 | sp->fd_index = listener->fd_index + count - i; | ||
| 126 | GPR_ASSERT(sp->emfd); | ||
| 127 | + grpc_tcp_server_listener_initialize_retry_timer(sp); | ||
| 128 | while (listener->server->tail->next != nullptr) { | ||
| 129 | listener->server->tail = listener->server->tail->next; | ||
| 130 | } | ||
| 131 | @@ -575,6 +597,7 @@ static void tcp_server_shutdown_listeners(grpc_tcp_server* s) { | ||
| 132 | if (s->active_ports) { | ||
| 133 | grpc_tcp_listener* sp; | ||
| 134 | for (sp = s->head; sp; sp = sp->next) { | ||
| 135 | + grpc_timer_cancel(&sp->retry_timer); | ||
| 136 | grpc_fd_shutdown(sp->emfd, | ||
| 137 | GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown")); | ||
| 138 | } | ||
| 139 | diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h | ||
| 140 | index 94faa2c17e..2e78ce555f 100644 | ||
| 141 | --- a/src/core/lib/iomgr/tcp_server_utils_posix.h | ||
| 142 | +++ b/src/core/lib/iomgr/tcp_server_utils_posix.h | ||
| 143 | @@ -25,6 +25,7 @@ | ||
| 144 | #include "src/core/lib/iomgr/resolve_address.h" | ||
| 145 | #include "src/core/lib/iomgr/socket_utils_posix.h" | ||
| 146 | #include "src/core/lib/iomgr/tcp_server.h" | ||
| 147 | +#include "src/core/lib/iomgr/timer.h" | ||
| 148 | #include "src/core/lib/resource_quota/memory_quota.h" | ||
| 149 | |||
| 150 | /* one listening port */ | ||
| 151 | @@ -47,6 +48,11 @@ typedef struct grpc_tcp_listener { | ||
| 152 | identified while iterating through 'next'. */ | ||
| 153 | struct grpc_tcp_listener* sibling; | ||
| 154 | int is_sibling; | ||
| 155 | + // If an accept4() call fails, a timer is started to drain the accept queue in | ||
| 156 | + // case no further connection attempts reach the gRPC server. | ||
| 157 | + grpc_closure retry_closure; | ||
| 158 | + grpc_timer retry_timer; | ||
| 159 | + gpr_atm retry_timer_armed; | ||
| 160 | } grpc_tcp_listener; | ||
| 161 | |||
| 162 | /* the overall server */ | ||
| 163 | @@ -126,4 +132,10 @@ grpc_error_handle grpc_tcp_server_prepare_socket( | ||
| 164 | /* Ruturn true if the platform supports ifaddrs */ | ||
| 165 | bool grpc_tcp_server_have_ifaddrs(void); | ||
| 166 | |||
| 167 | -#endif /* GRPC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H */ | ||
| 168 | +// Initialize (but don't start) the timer and callback to retry accept4() on a | ||
| 169 | +// listening socket after file descriptors have been exhausted. This must be | ||
| 170 | +// called when creating a new listener. | ||
| 171 | +void grpc_tcp_server_listener_initialize_retry_timer( | ||
| 172 | + grpc_tcp_listener* listener); | ||
| 173 | + | ||
| 174 | +#endif // GRPC_SRC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H | ||
| 175 | diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc | ||
| 176 | index 73a6b943ec..0e671c6485 100644 | ||
| 177 | --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc | ||
| 178 | +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc | ||
| 179 | @@ -18,6 +18,8 @@ | ||
| 180 | |||
| 181 | #include <grpc/support/port_platform.h> | ||
| 182 | |||
| 183 | +#include <grpc/support/atm.h> | ||
| 184 | + | ||
| 185 | #include "src/core/lib/iomgr/port.h" | ||
| 186 | |||
| 187 | #ifdef GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON | ||
| 188 | @@ -80,6 +82,24 @@ static int get_max_accept_queue_size(void) { | ||
| 189 | return s_max_accept_queue_size; | ||
| 190 | } | ||
| 191 | |||
| 192 | +static void listener_retry_timer_cb(void* arg, grpc_error_handle err) { | ||
| 193 | + // Do nothing if cancelled. | ||
| 194 | + if (!err.ok()) return; | ||
| 195 | + grpc_tcp_listener* listener = static_cast<grpc_tcp_listener*>(arg); | ||
| 196 | + gpr_atm_no_barrier_store(&listener->retry_timer_armed, false); | ||
| 197 | + if (!grpc_fd_is_shutdown(listener->emfd)) { | ||
| 198 | + grpc_fd_set_readable(listener->emfd); | ||
| 199 | + } | ||
| 200 | +} | ||
| 201 | + | ||
| 202 | +void grpc_tcp_server_listener_initialize_retry_timer( | ||
| 203 | + grpc_tcp_listener* listener) { | ||
| 204 | + gpr_atm_no_barrier_store(&listener->retry_timer_armed, false); | ||
| 205 | + grpc_timer_init_unset(&listener->retry_timer); | ||
| 206 | + GRPC_CLOSURE_INIT(&listener->retry_closure, listener_retry_timer_cb, listener, | ||
| 207 | + grpc_schedule_on_exec_ctx); | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, int fd, | ||
| 211 | const grpc_resolved_address* addr, | ||
| 212 | unsigned port_index, | ||
| 213 | @@ -112,6 +132,8 @@ static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, int fd, | ||
| 214 | sp->server = s; | ||
| 215 | sp->fd = fd; | ||
| 216 | sp->emfd = grpc_fd_create(fd, name.c_str(), true); | ||
| 217 | + grpc_tcp_server_listener_initialize_retry_timer(sp); | ||
| 218 | + | ||
| 219 | memcpy(&sp->addr, addr, sizeof(grpc_resolved_address)); | ||
| 220 | sp->port = port; | ||
| 221 | sp->port_index = port_index; | ||
| 222 | -- | ||
| 223 | 2.34.1 | ||
| 224 | |||
diff --git a/meta-oe/recipes-devtools/grpc/grpc_1.50.1.bb b/meta-oe/recipes-devtools/grpc/grpc_1.50.1.bb index b3956ce40c..3cfd0210db 100644 --- a/meta-oe/recipes-devtools/grpc/grpc_1.50.1.bb +++ b/meta-oe/recipes-devtools/grpc/grpc_1.50.1.bb | |||
| @@ -27,6 +27,7 @@ SRC_URI = "gitsm://github.com/grpc/grpc.git;protocol=https;name=grpc;branch=${BR | |||
| 27 | file://0001-cmake-add-separate-export-for-plugin-targets.patch \ | 27 | file://0001-cmake-add-separate-export-for-plugin-targets.patch \ |
| 28 | file://0001-cmake-Link-with-libatomic-on-rv32-rv64.patch \ | 28 | file://0001-cmake-Link-with-libatomic-on-rv32-rv64.patch \ |
| 29 | file://0001-fix-CVE-2023-32732.patch \ | 29 | file://0001-fix-CVE-2023-32732.patch \ |
| 30 | file://0001-backport-iomgr-EventEngine-Improve-server-handling-o.patch \ | ||
| 30 | " | 31 | " |
| 31 | # Fixes build with older compilers 4.8 especially on ubuntu 14.04 | 32 | # Fixes build with older compilers 4.8 especially on ubuntu 14.04 |
| 32 | CXXFLAGS:append:class-native = " -Wl,--no-as-needed" | 33 | CXXFLAGS:append:class-native = " -Wl,--no-as-needed" |
