From: Timo Sirainen Date: Thu, 1 Mar 2018 16:38:43 +0000 (+0200) Subject: master: Improve "core not dumped" error messages with Linux X-Git-Tag: 2.3.1~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f6b8fa45ae8872c295ba142eb464c43f42c88967;p=thirdparty%2Fdovecot%2Fcore.git master: Improve "core not dumped" error messages with Linux Recommend setting /proc/fs/suid_dumpable to 2 and /proc/sys/kernel/core_pattern to absolute path, if they already aren't. --- diff --git a/src/master/common.h b/src/master/common.h index 6f228a5f01..36bda94d71 100644 --- a/src/master/common.h +++ b/src/master/common.h @@ -5,9 +5,14 @@ #include "master-interface.h" #include "master-settings.h" +#define LINUX_PROC_FS_SUID_DUMPABLE "/proc/sys/fs/suid_dumpable" +#define LINUX_PROC_SYS_KERNEL_CORE_PATTERN "/proc/sys/kernel/core_pattern" + extern uid_t master_uid; extern gid_t master_gid; extern bool core_dumps_disabled; +extern bool have_proc_fs_suid_dumpable; +extern bool have_proc_sys_kernel_core_pattern; extern const char *ssl_manual_key_password; extern int global_master_dead_pipe_fd[2]; extern struct service_list *services; diff --git a/src/master/main.c b/src/master/main.c index 6968b02fa0..a29926fdf8 100644 --- a/src/master/main.c +++ b/src/master/main.c @@ -46,6 +46,8 @@ struct master_delayed_error { uid_t master_uid; gid_t master_gid; bool core_dumps_disabled; +bool have_proc_fs_suid_dumpable; +bool have_proc_sys_kernel_core_pattern; const char *ssl_manual_key_password; int global_master_dead_pipe_fd[2]; struct service_list *services; @@ -471,6 +473,7 @@ static void main_log_startup(char **protocols) #define STARTUP_STRING PACKAGE_NAME" v"DOVECOT_VERSION_FULL" starting up" string_t *str = t_str_new(128); rlim_t core_limit; + struct stat st; str_append(str, STARTUP_STRING); if (protocols[0] == NULL) @@ -484,6 +487,10 @@ static void main_log_startup(char **protocols) core_limit == 0; if (core_dumps_disabled) str_append(str, " (core dumps disabled)"); + if (stat(LINUX_PROC_FS_SUID_DUMPABLE, &st) == 0) + have_proc_fs_suid_dumpable = TRUE; + if (stat(LINUX_PROC_SYS_KERNEL_CORE_PATTERN, &st) == 0) + have_proc_sys_kernel_core_pattern = TRUE; i_info("%s", str_c(str)); } diff --git a/src/master/service-process.c b/src/master/service-process.c index 9fa8449028..968084bec3 100644 --- a/src/master/service-process.c +++ b/src/master/service-process.c @@ -444,12 +444,57 @@ get_exit_status_message(struct service *service, enum fatal_exit_status status) return NULL; } +static bool linux_proc_fs_suid_is_dumpable(unsigned int *value_r) +{ + int fd = open(LINUX_PROC_FS_SUID_DUMPABLE, O_RDONLY); + if (fd == -1) { + /* we already checked that it exists - shouldn't get here */ + i_error("open(%s) failed: %m", LINUX_PROC_FS_SUID_DUMPABLE); + have_proc_fs_suid_dumpable = FALSE; + return FALSE; + } + char buf[10]; + ssize_t ret = read(fd, buf, sizeof(buf)-1); + if (ret < 0) { + i_error("read(%s) failed: %m", LINUX_PROC_FS_SUID_DUMPABLE); + have_proc_fs_suid_dumpable = FALSE; + *value_r = 0; + } else { + buf[ret] = '\0'; + if (str_to_uint(buf, value_r) < 0) + *value_r = 0; + } + i_close_fd(&fd); + return *value_r != 0; +} + +static bool linux_is_absolute_core_pattern(void) +{ + int fd = open(LINUX_PROC_SYS_KERNEL_CORE_PATTERN, O_RDONLY); + if (fd == -1) { + /* we already checked that it exists - shouldn't get here */ + i_error("open(%s) failed: %m", LINUX_PROC_SYS_KERNEL_CORE_PATTERN); + have_proc_sys_kernel_core_pattern = FALSE; + return FALSE; + } + char buf[10]; + ssize_t ret = read(fd, buf, sizeof(buf)-1); + if (ret < 0) { + i_error("read(%s) failed: %m", LINUX_PROC_SYS_KERNEL_CORE_PATTERN); + have_proc_sys_kernel_core_pattern = FALSE; + buf[0] = '\0'; + } + i_close_fd(&fd); + return buf[0] == '/' || buf[0] == '|'; +} + static void log_coredump(struct service *service, string_t *str, int status) { #define CORE_DUMP_URL "https://dovecot.org/bugreport.html#coredumps" #ifdef WCOREDUMP int signum = WTERMSIG(status); + unsigned int dumpable; if (WCOREDUMP(status) != 0) { str_append(str, " (core dumped)"); @@ -466,6 +511,24 @@ log_coredump(struct service *service, string_t *str, int status) } str_append(str, " (core not dumped - "CORE_DUMP_URL); + /* If we're running on Linux, the best way to get core dumps is to set + fs.suid_dumpable=2 and sys.kernel.core_pattern to be an absolute + path. */ + if (!have_proc_fs_suid_dumpable) + ; + else if (!linux_proc_fs_suid_is_dumpable(&dumpable)) { + str_printfa(str, " - set %s to 2)", LINUX_PROC_FS_SUID_DUMPABLE); + return; + } else if (dumpable == 2 && have_proc_sys_kernel_core_pattern && + !linux_is_absolute_core_pattern()) { + str_printfa(str, " - set %s to absolute path)", + LINUX_PROC_SYS_KERNEL_CORE_PATTERN); + return; + } else if (dumpable == 1 || have_proc_sys_kernel_core_pattern) { + str_append(str, " - core wasn't writable?)"); + return; + } + #ifndef HAVE_PR_SET_DUMPABLE if (!service->set->drop_priv_before_exec && service->uid != 0) { str_printfa(str, " - set service %s "