Dump coredump to /var/log/journal/MACHINE-ID/coredump/COMM.DUMP-ID128. If can't, fallback to default behavior (dump to journal 24Mb of data). --- Makefile.am | 1 + src/journal/coredump.c | 199 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 135 insertions(+), 65 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 163e8f8..3393d8e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2644,6 +2644,7 @@ systemd_coredump_SOURCES = \ systemd_coredump_LDADD = \ libsystemd-journal-internal.la \ + libsystemd-id128-internal.la \ libsystemd-label.la \ libsystemd-shared.la diff --git a/src/journal/coredump.c b/src/journal/coredump.c index 021b4c6..17c4b6b 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -35,6 +35,7 @@ #include "macro.h" #include "mkdir.h" #include "special.h" +#include "sd-id128.h" #include "cgroup-util.h" #define COREDUMP_MAX (24*1024*1024) @@ -49,61 +50,155 @@ enum { _ARG_MAX }; -static int divert_coredump(void) { - _cleanup_fclose_ FILE *f = NULL; +static int submit_process_core(struct iovec iovec[14], int idx, + const char * comm, + const int journal) +{ + int r = EXIT_FAILURE; + + _cleanup_fclose_ FILE * corefile = NULL; + _cleanup_free_ char * corepath = NULL; + _cleanup_free_ char * corelink = NULL; + _cleanup_free_ char * t = NULL; + + if (journal) { + mkdir_p_label("/var/lib/systemd/coredump", 0755); + corelink = strdup("/var/lib/systemd/coredump/core.systemd-journald"); + corepath = strdup(corelink); + } else { + _cleanup_free_ char * c; + + char buffer[33]; + sd_id128_t coreid; + sd_id128_t machineid; + + const char *p = strrchr(comm, '/'); + if (p) + p ++; + else + p = comm; + + r = sd_id128_get_machine(&machineid); + if (r) + goto finish; + + c = sd_id128_to_string(machineid, buffer); + c = strjoin("/var/log/journal/", c, "/coredump", NULL); + if (! c) + goto finish; - log_info("Detected coredump of the journal daemon itself, diverting coredump to /var/lib/systemd/coredump/."); + r = access(c, X_OK | W_OK); + if (r) + goto finish; - mkdir_p_label("/var/lib/systemd/coredump", 0755); + r = sd_id128_randomize(&coreid); + if (r) + goto finish; + + corelink = strjoin(p, ".", sd_id128_to_string(coreid, buffer), NULL); + if (! corelink) + goto finish; - f = fopen("/var/lib/systemd/coredump/core.systemd-journald", "we"); - if (!f) { - log_error("Failed to create coredump file: %m"); - return -errno; + corepath = strjoin(c, "/", corelink, NULL); + if (! corepath) + goto finish; } - for (;;) { - uint8_t buffer[4096]; - size_t l, q; + corefile = fopen(corepath, "w"); + + if (! corefile) { + if (journal) { + log_error("Failed to create coredump file: %m"); + goto finish; + } + else { + int n; + + IOVEC_SET_STRING(iovec[idx++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); - l = fread(buffer, 1, sizeof(buffer), stdin); - if (l <= 0) { - if (ferror(f)) { - log_error("Failed to read coredump: %m"); - return -errno; + t = malloc(9 + COREDUMP_MAX); + if (!t) { + r = log_oom(); + goto finish; } - break; + memcpy(t, "COREDUMP=", 9); + + n = loop_read(STDIN_FILENO, t + 9, COREDUMP_MAX, false); + if (n < 0) { + log_error("Failed to read core dump data: %s", strerror(-n)); + r = (int) n; + goto finish; + } + + iovec[idx].iov_base = t; + iovec[idx].iov_len = 9 + n; + idx ++; + + } + } + else { + r = chmod(corepath, 0600); + if (r) { + log_debug("chmod %s: %s", corepath, strerror(errno)); + } + + for (;;) { + uint8_t buffer[4096]; + size_t l, q; + + l = fread(buffer, 1, sizeof(buffer), stdin); + if (l <= 0) { + if (ferror(corefile)) { + log_error("Failed to read coredump: %m"); + goto finish; + } + + break; + } + + q = fwrite(buffer, 1, l, corefile); + if (q != l) { + log_error("Failed to write coredump: %m"); + goto finish; + } } - q = fwrite(buffer, 1, l, f); - if (q != l) { + fflush(corefile); + + if (ferror(corefile)) { log_error("Failed to write coredump: %m"); - return -errno; } - } - fflush(f); + IOVEC_SET_STRING(iovec[idx++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b2"); - if (ferror(f)) { - log_error("Failed to write coredump: %m"); - return -errno; + t = strjoin("COREDUMP_FILE=coredump/", corelink, NULL); + if (t) + IOVEC_SET_STRING(iovec[idx ++], t); } - return 0; + r = sd_journal_sendv(iovec, idx); + if (r < 0) + log_error("Failed to send coredump: %s", strerror(-r)); + + finish: + return r; } int main(int argc, char* argv[]) { int r, j = 0; + int journal = 0; _cleanup_free_ char *p = NULL; - ssize_t n; pid_t pid; uid_t uid; gid_t gid; struct iovec iovec[14]; _cleanup_free_ char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL, *core_timestamp = NULL, *core_comm = NULL, *core_exe = NULL, *core_unit = NULL, - *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, *t = NULL; + *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, + *core_corelink = NULL; + + char * t; prctl(PR_SET_DUMPABLE, 0); @@ -126,27 +221,22 @@ int main(int argc, char* argv[]) { } if (cg_pid_get_unit(pid, &t) >= 0) { - - if (streq(t, SPECIAL_JOURNALD_SERVICE)) { - /* Make sure we don't make use of the journal, - * if it's the journal which is crashing */ - log_set_target(LOG_TARGET_KMSG); - log_open(); - - r = divert_coredump(); - goto finish; - } - core_unit = strappend("COREDUMP_UNIT=", t); } else if (cg_pid_get_user_unit(pid, &t) >= 0) core_unit = strappend("COREDUMP_USER_UNIT=", t); + journal = streq(t, SPECIAL_JOURNALD_SERVICE); + free(t); + if (core_unit) IOVEC_SET_STRING(iovec[j++], core_unit); - /* OK, now we know it's not the journal, hence make use of - * it */ - log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); + + if (journal) + log_set_target(LOG_TARGET_KMSG); + else + log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); + log_open(); r = parse_uid(argv[ARG_UID], &uid); @@ -191,7 +281,6 @@ int main(int argc, char* argv[]) { } #endif - if (get_process_exe(pid, &t) >= 0) { core_exe = strappend("COREDUMP_EXE=", t); free(t); @@ -212,7 +301,6 @@ int main(int argc, char* argv[]) { if (core_timestamp) IOVEC_SET_STRING(iovec[j++], core_timestamp); - IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); IOVEC_SET_STRING(iovec[j++], "PRIORITY=2"); core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL); @@ -232,28 +320,9 @@ int main(int argc, char* argv[]) { goto finish; } - p = malloc(9 + COREDUMP_MAX); - if (!p) { - r = log_oom(); - goto finish; - } - - memcpy(p, "COREDUMP=", 9); - - n = loop_read(STDIN_FILENO, p + 9, COREDUMP_MAX, false); - if (n < 0) { - log_error("Failed to read core dump data: %s", strerror(-n)); - r = (int) n; - goto finish; - } - - iovec[j].iov_base = p; - iovec[j].iov_len = 9 + n; - j++; - - r = sd_journal_sendv(iovec, j); + r = submit_process_core(iovec, j, argv[ARG_COMM], journal); if (r < 0) - log_error("Failed to send coredump: %s", strerror(-r)); + log_error("Failed to store coredump: %s", strerror(-r)); finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -- 1.8.1.2 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel