]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: init: add a "set-dumpable" global directive to enable core dumps
authorWilly Tarreau <w@1wt.eu>
Mon, 15 Apr 2019 17:38:50 +0000 (19:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 16 Apr 2019 12:31:23 +0000 (14:31 +0200)
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.

Makefile
doc/configuration.txt
include/types/global.h
src/cfgparse-global.c
src/haproxy.c

index 0c62ca849b04534586ffbddc69edf534abca4e8a..35772be90dc8692fa53a2569ad0c4bff2b6ffa37 100644 (file)
--- 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
index 7a5903ce7430c2316c29155f1be7229e4a95de0d..357a67e0bfaf1ce6045b3f164fe1c30833252bd3 100644 (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")
index 13831a1e02e9bb0856d32180fc434b6abca264fe..f1db95e778074c0f26f5ef576889afa0af915e83 100644 (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
index 92a089f8a678940e0ab87dec4b01dda6f7e1d06c..bd8b68aaad791ed354fcc3f38d2b76f308f62777 100644 (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;
index 1e5e63ea7632c6b9e5acd4912ec09e6698b65931..1b7b70c77e09b73329d8c1daf851e77aa9556fae 100644 (file)
 #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);