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.
This commit is contained in:
Willy Tarreau 2019-04-15 19:38:50 +02:00
parent 482f9a9a2f
commit 636848aa86
5 changed files with 63 additions and 3 deletions

View File

@ -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

View File

@ -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 <name> <value>
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 <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")

View File

@ -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

View File

@ -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;

View File

@ -61,6 +61,10 @@
#endif
#endif
#if defined(USE_PRCTL)
#include <sys/prctl.h>
#endif
#ifdef DEBUG_FULL
#include <assert.h>
#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);