]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #5373 from poettering/coredump-timestamp-fixes
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 17 Feb 2017 20:23:52 +0000 (15:23 -0500)
committerGitHub <noreply@github.com>
Fri, 17 Feb 2017 20:23:52 +0000 (15:23 -0500)
various coredump fixes

1  2 
src/coredump/coredump.c

diff --combined src/coredump/coredump.c
index d76d49a679efed4d9e73735ba82da6b2a3af37f6,838396b0c2a3ebb56b3c42e5180c2dac49b423bf..0fa830c33ee2babc77534467e7226d453858c455
@@@ -54,6 -54,7 +54,7 @@@
  #include "mkdir.h"
  #include "parse-util.h"
  #include "process-util.h"
+ #include "signal-util.h"
  #include "socket-util.h"
  #include "special.h"
  #include "stacktrace.h"
@@@ -186,6 -187,7 +187,7 @@@ static int fix_xattr(int fd, const cha
                  [CONTEXT_GID] = "user.coredump.gid",
                  [CONTEXT_SIGNAL] = "user.coredump.signal",
                  [CONTEXT_TIMESTAMP] = "user.coredump.timestamp",
+                 [CONTEXT_RLIMIT] = "user.coredump.rlimit",
                  [CONTEXT_COMM] = "user.coredump.comm",
                  [CONTEXT_EXE] = "user.coredump.exe",
          };
@@@ -352,7 -354,7 +354,7 @@@ static int save_external_coredump
          if (fd < 0)
                  return log_error_errno(fd, "Failed to create temporary file for coredump %s: %m", fn);
  
 -        r = copy_bytes(input_fd, fd, max_size, false);
 +        r = copy_bytes(input_fd, fd, max_size, 0);
          if (r < 0) {
                  log_error_errno(r, "Cannot store coredump of %s (%s): %m", context[CONTEXT_PID], context[CONTEXT_COMM]);
                  goto fail;
@@@ -820,7 -822,7 +822,7 @@@ static void map_context_fields(const st
  static int process_socket(int fd) {
          _cleanup_close_ int coredump_fd = -1;
          struct iovec *iovec = NULL;
-         size_t n_iovec = 0, n_allocated = 0, i;
+         size_t n_iovec = 0, n_allocated = 0, i, k;
          const char *context[_CONTEXT_MAX] = {};
          int r;
  
          assert(context[CONTEXT_COMM]);
          assert(coredump_fd >= 0);
  
+         /* Small quirk: the journal fields contain the timestamp padded with six zeroes, so that the kernel-supplied 1s
+          * granularity timestamps becomes 1µs granularity, i.e. the granularity systemd usually operates in. Since we
+          * are reconstructing the original kernel context, we chop this off again, here. */
+         k = strlen(context[CONTEXT_TIMESTAMP]);
+         if (k > 6)
+                 context[CONTEXT_TIMESTAMP] = strndupa(context[CONTEXT_TIMESTAMP], k - 6);
          r = submit_coredump(context, iovec, n_allocated, n_iovec, coredump_fd);
  
  finish:
@@@ -1044,21 -1053,23 +1053,23 @@@ static char* set_iovec_field_free(struc
          return x;
  }
  
- static int gather_pid_metadata(
+ static int gather_pid_metadata_and_process_special_crash(
                  const char *context[_CONTEXT_MAX],
                  char **comm_fallback,
                  char **comm_ret,
                  struct iovec *iovec, size_t *n_iovec) {
-         /* We need 25 empty slots in iovec!
-          * Note that if we fail on oom later on, we do not roll-back changes to the iovec
-          * structure. (It remains valid, with the first n_iovec fields initialized.) */
+         /* We need 26 empty slots in iovec!
+          *
+          * Note that if we fail on oom later on, we do not roll-back changes to the iovec structure. (It remains valid,
+          * with the first n_iovec fields initialized.) */
  
          _cleanup_free_ char *exe = NULL, *comm = NULL;
          uid_t owner_uid;
          pid_t pid;
          char *t;
          const char *p;
-         int r;
+         int r, signo;
  
          r = parse_pid(context[CONTEXT_PID], &pid);
          if (r < 0)
                   * are unlikely to work then. */
                  if (STR_IN_SET(t, SPECIAL_JOURNALD_SERVICE, SPECIAL_INIT_SCOPE)) {
                          free(t);
-                         return process_special_crash(context, STDIN_FILENO);
+                         r = process_special_crash(context, STDIN_FILENO);
+                         if (r < 0)
+                                 return r;
+                         return 1; /* > 0 means: we have already processed it, because it's a special crash */
                  }
  
                  set_iovec_field_free(iovec, n_iovec, "COREDUMP_UNIT=", t);
          if (t)
                  IOVEC_SET_STRING(iovec[(*n_iovec)++], t);
  
+         if (safe_atoi(context[CONTEXT_SIGNAL], &signo) >= 0 && SIGNAL_VALID(signo))
+                 set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
          if (comm_ret) {
                  *comm_ret = comm;
                  comm = NULL;
          }
  
-         return 0;
+         return 0; /* == 0 means: we successfully acquired all metadata */
  }
  
  static int process_kernel(int argc, char* argv[]) {
  
          const char *context[_CONTEXT_MAX];
-         struct iovec iovec[27];
+         struct iovec iovec[28];
          size_t i, n_iovec, n_to_free = 0;
          int r;
  
          context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1];
          context[CONTEXT_RLIMIT]    = argv[CONTEXT_RLIMIT + 1];
  
-         r = gather_pid_metadata(context, argv + CONTEXT_COMM + 1, NULL, iovec, &n_to_free);
+         r = gather_pid_metadata_and_process_special_crash(context, argv + CONTEXT_COMM + 1, NULL, iovec, &n_to_free);
          if (r < 0)
                  goto finish;
+         if (r > 0) {
+                 /* This was a special crash, and has already been processed. */
+                 r = 0;
+                 goto finish;
+         }
          n_iovec = n_to_free;
  
          IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR);
@@@ -1262,17 -1286,22 +1286,22 @@@ static int process_backtrace(int argc, 
          context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 2];
          context[CONTEXT_RLIMIT]    = argv[CONTEXT_RLIMIT + 2];
  
-         n_allocated = 32; /* 25 metadata, 2 static, +unknown input, rounded up */
+         n_allocated = 33; /* 25 metadata, 2 static, +unknown input, rounded up */
          iovec = new(struct iovec, n_allocated);
          if (!iovec)
                  return log_oom();
  
-         r = gather_pid_metadata(context, argv + CONTEXT_COMM + 2, &comm, iovec, &n_to_free);
+         r = gather_pid_metadata_and_process_special_crash(context, argv + CONTEXT_COMM + 2, &comm, iovec, &n_to_free);
          if (r < 0)
                  goto finish;
+         if (r > 0) {
+                 /* This was a special crash, and has already been processed. */
+                 r = 0;
+                 goto finish;
+         }
          n_iovec = n_to_free;
  
-         while (true) {
+         for (;;) {
                  r = journal_importer_process_data(&importer);
                  if (r < 0) {
                          log_error_errno(r, "Failed to parse journal entry on stdin: %m");