summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-02-08 22:08:49 +0100
committerLennart Poettering <lennart@poettering.net>2016-02-10 16:08:32 +0100
commitbdfd7b2c63cac944a3aa1fc0fafd19f41789e208 (patch)
tree7a89a715e0d6d2dd4b91d97d354e54d4447f893e
parent3c171f0b1ec3ce1b98777cca7330727b9ebfd17d (diff)
downloadsystemd-bdfd7b2c63cac944a3aa1fc0fafd19f41789e208.tar.gz
coredump: honour RLIMIT_CORE when saving/processing coredumps
With this change processing/saving of coredumps takes the RLIMIT_CORE resource limit of the crashing process into account, given the user control whether specific processes shall core dump or not, and how large to make the core dump. Note that this effectively disables core-dumping for now, as RLIMIT_CORE defaults to 0 (i.e. is disabled) for all system processes.
-rw-r--r--src/coredump/coredump.c32
-rw-r--r--sysctl.d/50-coredump.conf.in2
2 files changed, 26 insertions, 8 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 9dec6521f1..9e056436ea 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -64,12 +64,10 @@
/* The maximum size up to which we process coredumps */
#define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU))
-/* The maximum size up to which we leave the coredump around on
- * disk */
+/* The maximum size up to which we leave the coredump around on disk */
#define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX
-/* The maximum size up to which we store the coredump in the
- * journal */
+/* The maximum size up to which we store the coredump in the journal */
#define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU))
/* Make sure to not make this larger than the maximum journal entry
@@ -84,6 +82,7 @@ enum {
CONTEXT_GID,
CONTEXT_SIGNAL,
CONTEXT_TIMESTAMP,
+ CONTEXT_RLIMIT,
CONTEXT_COMM,
CONTEXT_EXE,
_CONTEXT_MAX
@@ -305,6 +304,7 @@ static int save_external_coredump(
_cleanup_free_ char *fn = NULL, *tmp = NULL;
_cleanup_close_ int fd = -1;
+ uint64_t rlimit, max_size;
struct stat st;
uid_t uid;
int r;
@@ -319,6 +319,18 @@ static int save_external_coredump(
if (r < 0)
return log_error_errno(r, "Failed to parse UID: %m");
+ r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resource limit: %s", context[CONTEXT_RLIMIT]);
+ if (rlimit <= 0) {
+ /* Is coredumping disabled? Then don't bother saving/processing the coredump */
+ log_info("Core Dumping has been disabled for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]);
+ return -EBADSLT;
+ }
+
+ /* Never store more than the process configured, or than we actually shall keep or process */
+ max_size = MIN(rlimit, MAX(arg_process_size_max, arg_external_size_max));
+
r = make_filename(context, &fn);
if (r < 0)
return log_error_errno(r, "Failed to determine coredump file name: %m");
@@ -333,7 +345,7 @@ static int save_external_coredump(
if (fd < 0)
return log_error_errno(errno, "Failed to create coredump file %s: %m", tmp);
- r = copy_bytes(input_fd, fd, arg_process_size_max, false);
+ r = copy_bytes(input_fd, fd, max_size, false);
if (r == -EFBIG) {
log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]);
goto fail;
@@ -668,6 +680,7 @@ static void map_context_fields(const struct iovec *iovec, const char *context[])
[CONTEXT_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
[CONTEXT_COMM] = "COREDUMP_COMM=",
[CONTEXT_EXE] = "COREDUMP_EXE=",
+ [CONTEXT_RLIMIT] = "COREDUMP_RLIMIT=",
};
unsigned i;
@@ -793,6 +806,7 @@ static int process_socket(int fd) {
assert(context[CONTEXT_GID]);
assert(context[CONTEXT_SIGNAL]);
assert(context[CONTEXT_TIMESTAMP]);
+ assert(context[CONTEXT_RLIMIT]);
assert(context[CONTEXT_COMM]);
assert(coredump_fd >= 0);
@@ -875,7 +889,7 @@ static int process_kernel(int argc, char* argv[]) {
*core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
*core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL,
*core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL,
- *core_user_unit = NULL, *core_slice = NULL, *core_timestamp = NULL;
+ *core_user_unit = NULL, *core_slice = NULL, *core_timestamp = NULL, *core_rlimit = NULL;
/* The larger ones we allocate on the heap */
_cleanup_free_ char
@@ -884,7 +898,7 @@ static int process_kernel(int argc, char* argv[]) {
_cleanup_free_ char *exe = NULL, *comm = NULL;
const char *context[_CONTEXT_MAX];
- struct iovec iovec[24];
+ struct iovec iovec[25];
size_t n_iovec = 0;
uid_t owner_uid;
const char *p;
@@ -918,6 +932,7 @@ static int process_kernel(int argc, char* argv[]) {
context[CONTEXT_GID] = argv[CONTEXT_GID + 1];
context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 1];
context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1];
+ context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1];
context[CONTEXT_COMM] = comm;
context[CONTEXT_EXE] = exe;
@@ -957,6 +972,9 @@ static int process_kernel(int argc, char* argv[]) {
core_signal = strjoina("COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]);
IOVEC_SET_STRING(iovec[n_iovec++], core_signal);
+ core_rlimit = strjoina("COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]);
+ IOVEC_SET_STRING(iovec[n_iovec++], core_rlimit);
+
if (sd_pid_get_session(pid, &t) >= 0) {
core_session = strjoina("COREDUMP_SESSION=", t);
free(t);
diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in
index 5e04c821b6..5a25de4512 100644
--- a/sysctl.d/50-coredump.conf.in
+++ b/sysctl.d/50-coredump.conf.in
@@ -9,4 +9,4 @@
# and systemd-coredump(8) and core(5) for the explanation of the
# setting below.
-kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %e
+kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %e