diff options
author | Chen Qi <Qi.Chen@windriver.com> | 2023-09-14 12:00:26 +0800 |
---|---|---|
committer | Armin Kuster <akuster808@gmail.com> | 2023-09-15 07:22:08 -0400 |
commit | 48b590afc4381cebc477d27a4d1efebed23c32e8 (patch) | |
tree | 73a74ecbdf3c1abf8da23a155d806b5045daf058 | |
parent | 63a9c4978136caa12f9a5dccb5123e5b9d09f7e8 (diff) | |
download | meta-openembedded-48b590afc4381cebc477d27a4d1efebed23c32e8.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" |