[systemd-devel] [PATCH 3/6] Optionally save core dumps as plain files

Oleksii Shevchuk alxchk at gmail.com
Mon Feb 11 15:14:40 PST 2013


Save core dumps to /var/log/journal/MACHINE-ID/coredump/COMM.CORE-ID.
If no access rights or directory not present, save core to journal.

When saving to file, use journal message id
fc2e22bc6ee647b6b90729ab34a250b2 instead of
fc2e22bc6ee647b6b90729ab34a250b1, and use field COREDUMP_FILE to
store relative path to core file.
---
 Makefile.am            |   1 +
 src/core/manager.c     |   1 +
 src/journal/coredump.c | 214 ++++++++++++++++++++++++++++++++++---------------
 3 files changed, 150 insertions(+), 66 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 2cec04a..af9e903 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2663,6 +2663,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/core/manager.c b/src/core/manager.c
index af77598..dd74237 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -51,6 +51,7 @@
 #include "hashmap.h"
 #include "macro.h"
 #include "strv.h"
+#include "env-util.h"
 #include "log.h"
 #include "util.h"
 #include "mkdir.h"
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index 021b4c6..680b26c 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,170 @@ enum {
         _ARG_MAX
 };
 
-static int divert_coredump(void) {
-        _cleanup_fclose_ FILE *f = NULL;
+static int submit_process_core(struct iovec iovec[15], 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");
+                if (! corelink) {
+                        r = log_oom();
+                        goto finish;
+                }
+
+                corepath = strdup(corelink);
+                if (! corepath) {
+                        r = log_oom();
+                        goto finish;
+                }
+        } 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 journal;
+
+                c = sd_id128_to_string(machineid, buffer);
+                c = strjoin("/var/log/journal/", c, "/coredump", NULL);
+                if (! c)
+                        goto journal;
+
+                r = access(c, X_OK | W_OK);
+                if (r)
+                        goto journal;
+
+                r = sd_id128_randomize(&coreid);
+                if (r)
+                        goto journal;
+
+                corelink = strjoin(p, ".", sd_id128_to_string(coreid, buffer), NULL);
+                if (! corelink)
+                        goto journal;
+
+                corepath = strjoin(c, "/", corelink, NULL);
+                if (! corepath)
+                        goto journal;
+        }
+
+        corefile = fopen(corepath, "w");
+
+journal:
+        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");
 
-        log_info("Detected coredump of the journal daemon itself, diverting coredump to /var/lib/systemd/coredump/.");
+                        t = malloc(9 + COREDUMP_MAX);
+                        if (!t) {
+                                r = log_oom();
+                                goto finish;
+                        }
+
+                        memcpy(t, "COREDUMP=", 9);
 
-        mkdir_p_label("/var/lib/systemd/coredump", 0755);
+                        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;
+                        }
 
-        f = fopen("/var/lib/systemd/coredump/core.systemd-journald", "we");
-        if (!f) {
-                log_error("Failed to create coredump file: %m");
-                return -errno;
+                        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;
 
-        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;
+                                }
 
-                l = fread(buffer, 1, sizeof(buffer), stdin);
-                if (l <= 0) {
-                        if (ferror(f)) {
-                                log_error("Failed to read coredump: %m");
-                                return -errno;
+                                break;
                         }
 
-                        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 (journal) {
+                        log_error("Detected coredump of the journal daemon itself, coredump diverted to /var/lib/systemd/coredump/");
+                        r = EXIT_SUCCESS;
+                        goto finish;
+                }
 
-        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];
+        struct iovec iovec[15];
         _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 +236,20 @@ 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);
+                journal = streq(t, SPECIAL_JOURNALD_SERVICE);
         } else if (cg_pid_get_user_unit(pid, &t) >= 0)
                 core_unit = strappend("COREDUMP_USER_UNIT=", t);
+        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 +294,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 +314,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 +333,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



More information about the systemd-devel mailing list