From: Willy Tarreau Date: Mon, 15 Apr 2019 17:38:50 +0000 (+0200) Subject: MINOR: init: add a "set-dumpable" global directive to enable core dumps X-Git-Tag: v2.0-dev3~257 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=636848aa86fc9f75610be769de2ae414944784de;p=thirdparty%2Fhaproxy.git MINOR: init: add a "set-dumpable" global directive to enable core dumps It's always a pain to get a core dump when enabling user/group setting (which disables the dumpable flag on Linux), when using a chroot and/or when haproxy is started by a service management tool which requires complex operations to just raise the core dump limit. This patch introduces a new "set-dumpable" global directive to work around these troubles by doing the following : - remove file size limits (equivalent of ulimit -f unlimited) - remove core size limits (equivalent of ulimit -c unlimited) - mark the process dumpable again (equivalent of suid_dumpable=1) Some of these will depend on the operating system. This way it becomes much easier to retrieve a core file. Temporarily moving the chroot to a user-writable place generally enough. --- diff --git a/Makefile b/Makefile index 0c62ca849b..35772be90d 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ # USE_FUTEX : enable use of futex on kernel 2.6. Automatic. # USE_ACCEPT4 : enable use of accept4() on linux. Automatic. # USE_MY_ACCEPT4 : use own implemention of accept4() if glibc < 2.10. +# USE_PRCTL : enable use of prctl(). Automatic. # USE_ZLIB : enable zlib library support. # USE_SLZ : enable slz library instead of zlib (pick at most one). # USE_CPU_AFFINITY : enable pinning processes to CPU on Linux. Automatic. @@ -281,7 +282,7 @@ use_opts = USE_EPOLL USE_KQUEUE USE_MY_EPOLL USE_MY_SPLICE USE_NETFILTER \ USE_GETADDRINFO USE_OPENSSL USE_LUA USE_FUTEX USE_ACCEPT4 \ USE_MY_ACCEPT4 USE_ZLIB USE_SLZ USE_CPU_AFFINITY USE_TFO USE_NS \ USE_DL USE_RT USE_DEVICEATLAS USE_51DEGREES USE_SYSTEMD \ - USE_OBSOLETE_LINKER + USE_OBSOLETE_LINKER USE_PRCTL #### Target system options # Depending on the target platform, some options are set, as well as some @@ -332,7 +333,7 @@ endif ifeq ($(TARGET),linux26) set_target_defaults = $(call default_opts, \ USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \ - USE_EPOLL USE_FUTEX) + USE_EPOLL USE_FUTEX USE_PRCTL) endif # Standard Linux >= 2.6.28 with netfilter, epoll, tproxy and splice @@ -340,7 +341,7 @@ ifeq ($(TARGET),linux2628) set_target_defaults = $(call default_opts, \ USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \ USE_CPU_AFFINITY USE_THREAD USE_EPOLL USE_FUTEX USE_LINUX_TPROXY \ - USE_ACCEPT4 USE_LINUX_SPLICE ASSUME_SPLICE_WORKS) + USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL ASSUME_SPLICE_WORKS) endif # Solaris 8 and above diff --git a/doc/configuration.txt b/doc/configuration.txt index 7a5903ce74..357a67e0bf 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -580,6 +580,7 @@ The following keywords are supported in the "global" section : - uid - ulimit-n - user + - set-dumpable - setenv - stats - ssl-default-bind-ciphers @@ -1028,6 +1029,25 @@ setenv the configuration file sees the new value. See also "presetenv", "resetenv", and "unsetenv". +set-dumpable + This option is better left disabled by default and enabled only upon a + developer's request. It has no impact on performance nor stability but will + try hard to re-enable core dumps that were possibly disabled by file size + limitations (ulimit -f), core size limitations (ulimit -c), or "dumpability" + of a process after changing its UID/GID (such as /proc/sys/fs/suid_dumpable + on Linux). Core dumps might still be limited by the current directory's + permissions (check what directory the file is started from), the chroot + directory's permission (it may be needed to temporarily disable the chroot + directive or to move it to a dedicated writable location), or any other + system-specific constraint. For example, some Linux flavours are notorious + for replacing the default core file with a path to an executable not even + installed on the system (check /proc/sys/kernel/core_pattern). Often, simply + writing "core", "core.%p" or "/var/log/core/core.%p" addresses the issue. + When trying to enable this option waiting for a rare issue to re-appear, it's + often a good idea to first try to obtain such a dump by issuing, for example, + "kill -11" to the haproxy process and verify that it leaves a core where + expected when dying. + ssl-default-bind-ciphers This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of cipher algorithms ("cipher suite") diff --git a/include/types/global.h b/include/types/global.h index 13831a1e02..f1db95e778 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -71,6 +71,7 @@ #define GTUNE_BUSY_POLLING (1<<11) #define GTUNE_LISTENER_MQ (1<<12) +#define GTUNE_SET_DUMPABLE (1<<13) /* Access level for a stats socket */ #define ACCESS_LVL_NONE 0 diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c index 92a089f8a6..bd8b68aaad 100644 --- a/src/cfgparse-global.c +++ b/src/cfgparse-global.c @@ -81,6 +81,14 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm) else global.tune.options |= GTUNE_BUSY_POLLING; } + else if (!strcmp(args[0], "set-dumpable")) { /* "no set-dumpable" or "set-dumpable" */ + if (alertif_too_many_args(0, file, linenum, args, &err_code)) + goto out; + if (kwm == KWM_NO) + global.tune.options &= ~GTUNE_SET_DUMPABLE; + else + global.tune.options |= GTUNE_SET_DUMPABLE; + } else if (!strcmp(args[0], "nosplice")) { if (alertif_too_many_args(0, file, linenum, args, &err_code)) goto out; diff --git a/src/haproxy.c b/src/haproxy.c index 1e5e63ea76..1b7b70c77e 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -61,6 +61,10 @@ #endif #endif +#if defined(USE_PRCTL) +#include +#endif + #ifdef DEBUG_FULL #include #endif @@ -2798,6 +2802,32 @@ int main(int argc, char **argv) exit(1); } } + + /* try our best to re-enable core dumps depending on system capabilities. + * What is addressed here : + * - remove file size limits + * - remove core size limits + * - mark the process dumpable again if it lost it due to user/group + */ + if (global.tune.options & GTUNE_SET_DUMPABLE) { + limit.rlim_cur = limit.rlim_max = RLIM_INFINITY; + +#if defined(RLIMIT_FSIZE) + if (setrlimit(RLIMIT_FSIZE, &limit) == -1) + ha_warning("[%s.main()] Failed to set the raise the maximum file size.\n", argv[0]); +#endif + +#if defined(RLIMIT_CORE) + if (setrlimit(RLIMIT_CORE, &limit) == -1) + ha_warning("[%s.main()] Failed to set the raise the core dump size.\n", argv[0]); +#endif + +#if defined(USE_PRCTL) + if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) + ha_warning("[%s.main()] Failed to set the dumpable flag, no core will be dumped.\n", argv[0]); +#endif + } + /* check ulimits */ limit.rlim_cur = limit.rlim_max = 0; getrlimit(RLIMIT_NOFILE, &limit);