Skip to content

Commit

Permalink
master: Improve "core not dumped" error messages with Linux
Browse files Browse the repository at this point in the history
Recommend setting /proc/fs/suid_dumpable to 2 and
/proc/sys/kernel/core_pattern to absolute path, if they already aren't.
  • Loading branch information
sirainen authored and cmouse committed Mar 6, 2018
1 parent 9fd384e commit 9225b51
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/master/common.h
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions src/master/main.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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));
}

Expand Down
63 changes: 63 additions & 0 deletions src/master/service-process.c
Expand Up @@ -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)");
Expand All @@ -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 "
Expand Down

0 comments on commit 9225b51

Please sign in to comment.