Skip to content

Commit 4f1ec4f

Browse files
author
Raúl Gutiérrez Segalés
authoredMar 6, 2021
server: add --enable-core-dump flag (#15245)
This ensures Envoy can core dump when the dumpability bit might have been unset (e.g.: running inside a container with fewer capabilities than the ones Envoy itself has). Fixes #15242.
1 parent 2bb2038 commit 4f1ec4f

File tree

27 files changed

+234
-37
lines changed

27 files changed

+234
-37
lines changed
 

‎api/envoy/admin/v3/server_info.proto

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ message ServerInfo {
5858
config.core.v3.Node node = 7;
5959
}
6060

61-
// [#next-free-field: 37]
61+
// [#next-free-field: 38]
6262
message CommandLineOptions {
6363
option (udpa.annotations.versioning).previous_message_type =
6464
"envoy.admin.v2alpha.CommandLineOptions";
@@ -189,4 +189,7 @@ message CommandLineOptions {
189189

190190
// See :option:`--socket-mode` for details.
191191
uint32 socket_mode = 36;
192+
193+
// See :option:`--enable-core-dump` for details.
194+
bool enable_core_dump = 37;
192195
}

‎api/envoy/admin/v4alpha/server_info.proto

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎bazel/envoy_build_system.bzl

+14
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ load(
88
_envoy_basic_cc_library = "envoy_basic_cc_library",
99
_envoy_cc_extension = "envoy_cc_extension",
1010
_envoy_cc_library = "envoy_cc_library",
11+
_envoy_cc_linux_library = "envoy_cc_linux_library",
1112
_envoy_cc_posix_library = "envoy_cc_posix_library",
13+
_envoy_cc_posix_without_linux_library = "envoy_cc_posix_without_linux_library",
1214
_envoy_cc_win32_library = "envoy_cc_win32_library",
1315
_envoy_include_prefix = "envoy_include_prefix",
1416
_envoy_proto_library = "envoy_proto_library",
@@ -145,6 +147,16 @@ def envoy_cc_platform_dep(name):
145147
"//conditions:default": [name + "_posix"],
146148
})
147149

150+
# Used to select a dependency that has different implementations on Linux vs rest of POSIX vs Windows.
151+
# The platform-specific implementations should be specified with envoy_cc_linux_library,
152+
# envoy_cc_posix_without_library and envoy_cc_win32_library respectively
153+
def envoy_cc_platform_specific_dep(name):
154+
return select({
155+
"@envoy//bazel:windows_x86_64": [name + "_win32"],
156+
"@envoy//bazel:linux": [name + "_linux"],
157+
"//conditions:default": [name + "_posix"],
158+
})
159+
148160
# Envoy proto descriptor targets should be specified with this function.
149161
# This is used for testing only.
150162
def envoy_proto_descriptor(name, out, srcs = [], external_deps = []):
@@ -202,7 +214,9 @@ envoy_cc_binary = _envoy_cc_binary
202214
envoy_basic_cc_library = _envoy_basic_cc_library
203215
envoy_cc_extension = _envoy_cc_extension
204216
envoy_cc_library = _envoy_cc_library
217+
envoy_cc_linux_library = _envoy_cc_linux_library
205218
envoy_cc_posix_library = _envoy_cc_posix_library
219+
envoy_cc_posix_without_linux_library = _envoy_cc_posix_without_linux_library
206220
envoy_cc_win32_library = _envoy_cc_win32_library
207221
envoy_include_prefix = _envoy_include_prefix
208222
envoy_proto_library = _envoy_proto_library

‎bazel/envoy_library.bzl

+32
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,38 @@ def envoy_cc_posix_library(name, srcs = [], hdrs = [], **kargs):
220220
**kargs
221221
)
222222

223+
# Used to specify a library that only builds on POSIX excluding Linux
224+
def envoy_cc_posix_without_linux_library(name, srcs = [], hdrs = [], **kargs):
225+
envoy_cc_library(
226+
name = name + "_posix",
227+
srcs = select({
228+
"@envoy//bazel:windows_x86_64": [],
229+
"@envoy//bazel:linux": [],
230+
"//conditions:default": srcs,
231+
}),
232+
hdrs = select({
233+
"@envoy//bazel:windows_x86_64": [],
234+
"@envoy//bazel:linux": [],
235+
"//conditions:default": hdrs,
236+
}),
237+
**kargs
238+
)
239+
240+
# Used to specify a library that only builds on Linux
241+
def envoy_cc_linux_library(name, srcs = [], hdrs = [], **kargs):
242+
envoy_cc_library(
243+
name = name + "_linux",
244+
srcs = select({
245+
"@envoy//bazel:linux": srcs,
246+
"//conditions:default": [],
247+
}),
248+
hdrs = select({
249+
"@envoy//bazel:linux": hdrs,
250+
"//conditions:default": [],
251+
}),
252+
**kargs
253+
)
254+
223255
# Used to specify a library that only builds on Windows
224256
def envoy_cc_win32_library(name, srcs = [], hdrs = [], **kargs):
225257
envoy_cc_library(

‎docs/root/operations/cli.rst

+7
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,10 @@ following are the command line options that Envoy supports.
351351
* build mode - either ``RELEASE`` or ``DEBUG``,
352352

353353
* TLS library - either ``BoringSSL`` or ``BoringSSL-FIPS``.
354+
355+
.. option:: --enable-core-dump
356+
357+
*(optional)* This flag is intended for Linux-based systems and it's a no-op for all other platforms.
358+
It enables core dumps by invoking `prctl <https://man7.org/linux/man-pages/man2/prctl.2.html>`_ using the
359+
PR_SET_DUMPABLE option. This is useful for container environments when using capabilities, given that when
360+
Envoy has more capabilities than its base environment core dumping will be disabled by the kernel.

‎docs/root/version_history/current.rst

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ New Features
125125
* route config: added :ref:`allow_post field <envoy_v3_api_field_config.route.v3.RouteAction.UpgradeConfig.ConnectConfig.allow_post>` for allowing POST payload as raw TCP.
126126
* route config: added :ref:`max_direct_response_body_size_bytes <envoy_v3_api_field_config.route.v3.RouteConfiguration.max_direct_response_body_size_bytes>` to set maximum :ref:`direct response body <envoy_v3_api_field_config.route.v3.DirectResponseAction.body>` size in bytes. If not specified the default remains 4096 bytes.
127127
* server: added *fips_mode* to :ref:`server compilation settings <server_compilation_settings_statistics>` related statistic.
128+
* server: added :option:`--enable-core-dump` flag to enable core dumps via prctl (Linux-based systems only).
128129
* tcp_proxy: add support for converting raw TCP streams into HTTP/1.1 CONNECT requests. See :ref:`upgrade documentation <tunneling-tcp-over-http>` for details.
129130
* tcp_proxy: added a :ref:`use_post field <envoy_v3_api_field_extensions.filters.network.tcp_proxy.v3.TcpProxy.TunnelingConfig.use_post>` for using HTTP POST to proxy TCP streams.
130131
* tcp_proxy: added a :ref:`headers_to_add field <envoy_v3_api_field_extensions.filters.network.tcp_proxy.v3.TcpProxy.TunnelingConfig.headers_to_add>` for setting additional headers to the HTTP requests for TCP proxing.

‎generated_api_shadow/envoy/admin/v3/server_info.proto

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎generated_api_shadow/envoy/admin/v4alpha/server_info.proto

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎include/envoy/server/options.h

+5
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ class Options {
234234
*/
235235
virtual bool mutexTracingEnabled() const PURE;
236236

237+
/**
238+
* @return bool indicating whether core dumps have been enabled.
239+
*/
240+
virtual bool coreDumpEnabled() const PURE;
241+
237242
/**
238243
* @return bool indicating whether cpuset size should determine the number of worker threads.
239244
*/

‎source/exe/BUILD

+15-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ load(
22
"//bazel:envoy_build_system.bzl",
33
"envoy_cc_binary",
44
"envoy_cc_library",
5-
"envoy_cc_platform_dep",
6-
"envoy_cc_posix_library",
5+
"envoy_cc_linux_library",
6+
"envoy_cc_platform_specific_dep",
7+
"envoy_cc_posix_without_linux_library",
78
"envoy_cc_win32_library",
89
"envoy_package",
910
)
@@ -142,7 +143,7 @@ envoy_cc_library(
142143
envoy_cc_library(
143144
name = "platform_impl_lib",
144145
deps = [":platform_header_lib"] +
145-
envoy_cc_platform_dep("platform_impl_lib"),
146+
envoy_cc_platform_specific_dep("platform_impl_lib"),
146147
)
147148

148149
envoy_cc_library(
@@ -154,7 +155,7 @@ envoy_cc_library(
154155
],
155156
)
156157

157-
envoy_cc_posix_library(
158+
envoy_cc_posix_without_linux_library(
158159
name = "platform_impl_lib",
159160
srcs = ["posix/platform_impl.cc"],
160161
deps = [
@@ -164,6 +165,16 @@ envoy_cc_posix_library(
164165
],
165166
)
166167

168+
envoy_cc_linux_library(
169+
name = "platform_impl_lib",
170+
srcs = ["linux/platform_impl.cc"],
171+
deps = [
172+
":platform_header_lib",
173+
"//source/common/common:thread_lib",
174+
"//source/common/filesystem:filesystem_lib",
175+
],
176+
)
177+
167178
envoy_cc_win32_library(
168179
name = "platform_impl_lib",
169180
srcs = ["win32/platform_impl.cc"],

‎source/exe/linux/platform_impl.cc

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#if !defined(__linux__)
2+
#error "Linux platform file is part of non-Linux build."
3+
#endif
4+
5+
#include <sys/prctl.h>
6+
7+
#include "common/common/thread_impl.h"
8+
#include "common/filesystem/filesystem_impl.h"
9+
10+
#include "exe/platform_impl.h"
11+
12+
namespace Envoy {
13+
14+
PlatformImpl::PlatformImpl()
15+
: thread_factory_(std::make_unique<Thread::ThreadFactoryImplPosix>()),
16+
file_system_(std::make_unique<Filesystem::InstanceImplPosix>()) {}
17+
18+
PlatformImpl::~PlatformImpl() = default;
19+
20+
bool PlatformImpl::enableCoreDump() { return prctl(PR_SET_DUMPABLE, 1) != -1; }
21+
22+
} // namespace Envoy

‎source/exe/main_common.cc

+20-11
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,25 @@ Runtime::LoaderPtr ProdComponentFactory::createRuntime(Server::Instance& server,
4545
MainCommonBase::MainCommonBase(const Server::Options& options, Event::TimeSystem& time_system,
4646
ListenerHooks& listener_hooks,
4747
Server::ComponentFactory& component_factory,
48+
std::unique_ptr<PlatformImpl> platform_impl,
4849
std::unique_ptr<Random::RandomGenerator>&& random_generator,
49-
Thread::ThreadFactory& thread_factory,
50-
Filesystem::Instance& file_system,
5150
std::unique_ptr<ProcessContext> process_context)
52-
: options_(options), component_factory_(component_factory), thread_factory_(thread_factory),
53-
file_system_(file_system), stats_allocator_(symbol_table_) {
51+
: platform_impl_(std::move(platform_impl)), options_(options),
52+
component_factory_(component_factory), stats_allocator_(symbol_table_) {
5453
// Process the option to disable extensions as early as possible,
5554
// before we do any configuration loading.
5655
OptionsImpl::disableExtensions(options.disabledExtensions());
5756

57+
// Enable core dumps as early as possible.
58+
if (options_.coreDumpEnabled()) {
59+
const auto ret = platform_impl_->enableCoreDump();
60+
if (ret) {
61+
ENVOY_LOG_MISC(info, "core dump enabled");
62+
} else {
63+
ENVOY_LOG_MISC(warn, "failed to enable core dump");
64+
}
65+
}
66+
5867
switch (options_.mode()) {
5968
case Server::Mode::InitOnly:
6069
case Server::Mode::Serve: {
@@ -79,7 +88,7 @@ MainCommonBase::MainCommonBase(const Server::Options& options, Event::TimeSystem
7988
server_ = std::make_unique<Server::InstanceImpl>(
8089
*init_manager_, options_, time_system, local_address, listener_hooks, *restarter_,
8190
*stats_store_, access_log_lock, component_factory, std::move(random_generator), *tls_,
82-
thread_factory_, file_system_, std::move(process_context));
91+
platform_impl_->threadFactory(), platform_impl_->fileSystem(), std::move(process_context));
8392

8493
break;
8594
}
@@ -163,8 +172,8 @@ bool MainCommonBase::run() {
163172
return true;
164173
case Server::Mode::Validate: {
165174
auto local_address = Network::Utility::getLocalAddress(options_.localAddressIpVersion());
166-
return Server::validateConfig(options_, local_address, component_factory_, thread_factory_,
167-
file_system_);
175+
return Server::validateConfig(options_, local_address, component_factory_,
176+
platform_impl_->threadFactory(), platform_impl_->fileSystem());
168177
}
169178
case Server::Mode::InitOnly:
170179
PERF_DUMP();
@@ -188,14 +197,14 @@ void MainCommonBase::adminRequest(absl::string_view path_and_query, absl::string
188197
MainCommon::MainCommon(const std::vector<std::string>& args)
189198
: options_(args, &MainCommon::hotRestartVersion, spdlog::level::info),
190199
base_(options_, real_time_system_, default_listener_hooks_, prod_component_factory_,
191-
std::make_unique<Random::RandomGeneratorImpl>(), platform_impl_.threadFactory(),
192-
platform_impl_.fileSystem(), nullptr) {}
200+
std::make_unique<PlatformImpl>(), std::make_unique<Random::RandomGeneratorImpl>(),
201+
nullptr) {}
193202

194203
MainCommon::MainCommon(int argc, const char* const* argv)
195204
: options_(argc, argv, &MainCommon::hotRestartVersion, spdlog::level::info),
196205
base_(options_, real_time_system_, default_listener_hooks_, prod_component_factory_,
197-
std::make_unique<Random::RandomGeneratorImpl>(), platform_impl_.threadFactory(),
198-
platform_impl_.fileSystem(), nullptr) {}
206+
std::make_unique<PlatformImpl>(), std::make_unique<Random::RandomGeneratorImpl>(),
207+
nullptr) {}
199208

200209
std::string MainCommon::hotRestartVersion(bool hot_restart_enabled) {
201210
#ifdef ENVOY_HOT_RESTART

‎source/exe/main_common.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class MainCommonBase {
3838
// destructed.
3939
MainCommonBase(const Server::Options& options, Event::TimeSystem& time_system,
4040
ListenerHooks& listener_hooks, Server::ComponentFactory& component_factory,
41+
std::unique_ptr<PlatformImpl> platform_impl,
4142
std::unique_ptr<Random::RandomGenerator>&& random_generator,
42-
Thread::ThreadFactory& thread_factory, Filesystem::Instance& file_system,
4343
std::unique_ptr<ProcessContext> process_context);
4444

4545
bool run();
@@ -66,15 +66,14 @@ class MainCommonBase {
6666
const AdminRequestFn& handler);
6767

6868
protected:
69+
std::unique_ptr<PlatformImpl> platform_impl_;
6970
ProcessWide process_wide_; // Process-wide state setup/teardown (excluding grpc).
7071
// We instantiate this class regardless of ENVOY_GOOGLE_GRPC, to avoid having
7172
// an ifdef in a header file exposed in a C++ library. It is too easy to have
7273
// the ifdef be inconsistent across build-system boundaries.
7374
Grpc::GoogleGrpcContext google_grpc_context_;
7475
const Envoy::Server::Options& options_;
7576
Server::ComponentFactory& component_factory_;
76-
Thread::ThreadFactory& thread_factory_;
77-
Filesystem::Instance& file_system_;
7877
Stats::SymbolTableImpl symbol_table_;
7978
Stats::AllocatorImpl stats_allocator_;
8079

@@ -146,7 +145,6 @@ class MainCommon {
146145
Envoy::TerminateHandler log_on_terminate_;
147146
#endif
148147

149-
PlatformImpl platform_impl_;
150148
Envoy::OptionsImpl options_;
151149
Event::RealTimeSystem real_time_system_;
152150
DefaultListenerHooks default_listener_hooks_;

‎source/exe/platform_impl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ namespace Envoy {
88
class PlatformImpl {
99
public:
1010
PlatformImpl();
11-
~PlatformImpl();
11+
virtual ~PlatformImpl();
1212
Thread::ThreadFactory& threadFactory() { return *thread_factory_; }
1313
Filesystem::Instance& fileSystem() { return *file_system_; }
14+
virtual bool enableCoreDump();
1415

1516
private:
1617
Thread::ThreadFactoryPtr thread_factory_;

‎source/exe/posix/platform_impl.cc

+2
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ PlatformImpl::PlatformImpl()
1111

1212
PlatformImpl::~PlatformImpl() = default;
1313

14+
bool PlatformImpl::enableCoreDump() { return false; }
15+
1416
} // namespace Envoy

‎source/exe/win32/platform_impl.cc

+2
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,6 @@ PlatformImpl::PlatformImpl()
5858

5959
PlatformImpl::~PlatformImpl() { ::WSACleanup(); }
6060

61+
bool PlatformImpl::enableCoreDump() { return false; }
62+
6163
} // namespace Envoy

‎source/server/options_impl.cc

+2
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ OptionsImpl::OptionsImpl(std::vector<std::string> args,
156156

157157
TCLAP::ValueArg<std::string> socket_mode("", "socket-mode", "Socket file permission", false,
158158
"600", "string", cmd);
159+
TCLAP::SwitchArg enable_core_dump("", "enable-core-dump", "Enable core dumps", cmd, false);
159160

160161
cmd.setExceptionHandling(false);
161162
try {
@@ -177,6 +178,7 @@ OptionsImpl::OptionsImpl(std::vector<std::string> args,
177178

178179
hot_restart_disabled_ = disable_hot_restart.getValue();
179180
mutex_tracing_enabled_ = enable_mutex_tracing.getValue();
181+
core_dump_enabled_ = enable_core_dump.getValue();
180182

181183
cpuset_threads_ = cpuset_threads.getValue();
182184

0 commit comments

Comments
 (0)