chiark / gitweb /
coredump: also escape spaces in comm fields when formatting file names
[elogind.git] / src / journal / coredump.c
index a396491a4bc11e45bb8bee28f12064e957e76679..287e0ed7fdd065bd30053ae196ea1084858d3f2c 100644 (file)
@@ -24,7 +24,7 @@
 #include <stdio.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
-#include <attr/xattr.h>
+#include <sys/xattr.h>
 
 #include <systemd/sd-journal.h>
 #include <systemd/sd-login.h>
@@ -38,6 +38,7 @@
 #include "journald-native.h"
 #include "conf-parser.h"
 #include "copy.h"
+#include "stacktrace.h"
 
 #ifdef HAVE_ACL
 #include <sys/acl.h>
@@ -158,39 +159,34 @@ static int fix_acl(int fd, uid_t uid) {
 }
 
 static int fix_xattr(int fd, char *argv[]) {
+
+        static const char * const xattrs[_ARG_MAX] = {
+                [ARG_PID] = "user.coredump.pid",
+                [ARG_UID] = "user.coredump.uid",
+                [ARG_GID] = "user.coredump.gid",
+                [ARG_SIGNAL] = "user.coredump.signal",
+                [ARG_TIMESTAMP] = "user.coredump.timestamp",
+                [ARG_COMM] = "user.coredump.comm",
+        };
+
         int r = 0;
+        unsigned i;
 
         /* Attach some metadate to coredumps via extended
          * attributes. Just because we can. */
 
-        if (!isempty(argv[ARG_PID]))
-                if (fsetxattr(fd, "user.coredump.pid", argv[ARG_PID], strlen(argv[ARG_PID]), XATTR_CREATE) < 0)
-                        r = -errno;
+        for (i = 0; i < _ARG_MAX; i++) {
+                if (isempty(argv[i]))
+                        continue;
 
-        if (!isempty(argv[ARG_UID]))
-                if (fsetxattr(fd, "user.coredump.uid", argv[ARG_UID], strlen(argv[ARG_UID]), XATTR_CREATE) < 0)
-                        r = -errno;
-
-        if (!isempty(argv[ARG_GID]))
-                if (fsetxattr(fd, "user.coredump.gid", argv[ARG_GID], strlen(argv[ARG_GID]), XATTR_CREATE) < 0)
-                        r = -errno;
-
-        if (!isempty(argv[ARG_SIGNAL]))
-                if (fsetxattr(fd, "user.coredump.signal", argv[ARG_SIGNAL], strlen(argv[ARG_SIGNAL]), XATTR_CREATE) < 0)
-                        r = -errno;
-
-        if (!isempty(argv[ARG_TIMESTAMP]))
-                if (fsetxattr(fd, "user.coredump.timestamp", argv[ARG_TIMESTAMP], strlen(argv[ARG_TIMESTAMP]), XATTR_CREATE) < 0)
-                        r = -errno;
-
-        if (!isempty(argv[ARG_COMM]))
-                if (fsetxattr(fd, "user.coredump.comm", argv[ARG_COMM], strlen(argv[ARG_COMM]), XATTR_CREATE) < 0)
+                if (fsetxattr(fd, xattrs[i], argv[i], strlen(argv[i]), XATTR_CREATE) < 0)
                         r = -errno;
+        }
 
         return r;
 }
 
-#define filename_escape(s) xescape((s), "./")
+#define filename_escape(s) xescape((s), "./ ")
 
 static int save_external_coredump(char **argv, uid_t uid, char **ret_filename, int *ret_fd, off_t *ret_size) {
         _cleanup_free_ char *p = NULL, *t = NULL, *c = NULL, *fn = NULL, *tmp = NULL;
@@ -290,6 +286,7 @@ static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_s
         _cleanup_free_ char *field = NULL;
         ssize_t n;
 
+        assert(fd >= 0);
         assert(ret);
         assert(ret_size);
 
@@ -346,16 +343,17 @@ int main(int argc, char* argv[]) {
         _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, *coredump_data = NULL,
-                *coredump_filename = NULL;
+                *coredump_filename = NULL, *core_slice = NULL, *core_cgroup = NULL, *core_owner_uid = NULL,
+                *exe = NULL;
 
         _cleanup_close_ int coredump_fd = -1;
 
-        struct iovec iovec[14];
+        struct iovec iovec[17];
         off_t coredump_size;
         int r, j = 0;
-        pid_t pid;
-        uid_t uid;
+        uid_t uid, owner_uid;
         gid_t gid;
+        pid_t pid;
         char *t;
 
         /* Make sure we never enter a loop */
@@ -365,7 +363,6 @@ int main(int argc, char* argv[]) {
          * crashed and it might be journald which we'd rather not log
          * to then. */
         log_set_target(LOG_TARGET_KMSG);
-        log_set_max_level(LOG_DEBUG);
         log_open();
 
         if (argc != _ARG_MAX) {
@@ -459,10 +456,23 @@ int main(int argc, char* argv[]) {
                         IOVEC_SET_STRING(iovec[j++], core_session);
         }
 
-        if (get_process_exe(pid, &t) >= 0) {
-                core_exe = strappend("COREDUMP_EXE=", t);
+        if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
+                asprintf(&core_owner_uid, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid);
+
+                if (core_owner_uid)
+                        IOVEC_SET_STRING(iovec[j++], core_owner_uid);
+        }
+
+        if (sd_pid_get_slice(pid, &t) >= 0) {
+                core_slice = strappend("COREDUMP_SLICE=", t);
                 free(t);
 
+                if (core_slice)
+                        IOVEC_SET_STRING(iovec[j++], core_slice);
+        }
+
+        if (get_process_exe(pid, &exe) >= 0) {
+                core_exe = strappend("COREDUMP_EXE=", exe);
                 if (core_exe)
                         IOVEC_SET_STRING(iovec[j++], core_exe);
         }
@@ -475,6 +485,14 @@ int main(int argc, char* argv[]) {
                         IOVEC_SET_STRING(iovec[j++], core_cmdline);
         }
 
+        if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) {
+                core_cgroup = strappend("COREDUMP_CGROUP=", t);
+                free(t);
+
+                if (core_cgroup)
+                        IOVEC_SET_STRING(iovec[j++], core_cgroup);
+        }
+
         core_timestamp = strjoin("COREDUMP_TIMESTAMP=", argv[ARG_TIMESTAMP], "000000", NULL);
         if (core_timestamp)
                 IOVEC_SET_STRING(iovec[j++], core_timestamp);
@@ -482,17 +500,15 @@ int main(int argc, char* argv[]) {
         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);
-        if (core_message)
-                IOVEC_SET_STRING(iovec[j++], core_message);
-
         /* Always stream the coredump to disk, if that's possible */
         r = save_external_coredump(argv, uid, &coredump_filename, &coredump_fd, &coredump_size);
         if (r < 0)
                 goto finish;
 
         /* If we don't want to keep the coredump on disk, remove it
-         * now, as later on we will lack the privileges for it. */
+         * now, as later on we will lack the privileges for
+         * it. However, we keep the fd to it, so that we can still
+         * process it and log it. */
         r = maybe_remove_external_coredump(coredump_filename, coredump_size);
         if (r < 0)
                 goto finish;
@@ -509,6 +525,24 @@ int main(int argc, char* argv[]) {
                 goto finish;
         }
 
+#ifdef HAVE_ELFUTILS
+        /* Try to get a strack trace if we can */
+        if (coredump_size <= arg_process_size_max) {
+                _cleanup_free_ char *stacktrace = NULL;
+
+                r = coredump_make_stack_trace(coredump_fd, exe, &stacktrace);
+                if (r >= 0)
+                        core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") of user ", argv[ARG_UID], " dumped core.\n\n", stacktrace, NULL);
+                else
+                        log_warning("Failed to generate stack trace: %s", strerror(-r));
+        }
+
+        if (!core_message)
+#endif
+        core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") of user ", argv[ARG_UID], " dumped core.", NULL);
+        if (core_message)
+                IOVEC_SET_STRING(iovec[j++], core_message);
+
         /* Optionally store the entire coredump in the journal */
         if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) &&
             coredump_size <= (off_t) arg_journal_size_max) {