]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/journal/journald-server.c
core: add "invocation ID" concept to service manager
[thirdparty/systemd.git] / src / journal / journald-server.c
index 3507910919bf6656566dd5db2a12cbf838673eb8..f01cf1d93701562897f98b3e0d0a9db3e468e55d 100644 (file)
@@ -44,6 +44,7 @@
 #include "fs-util.h"
 #include "hashmap.h"
 #include "hostname-util.h"
+#include "id128-util.h"
 #include "io-util.h"
 #include "journal-authenticate.h"
 #include "journal-file.h"
@@ -56,6 +57,7 @@
 #include "journald-server.h"
 #include "journald-stream.h"
 #include "journald-syslog.h"
+#include "log.h"
 #include "missing.h"
 #include "mkdir.h"
 #include "parse-util.h"
@@ -69,7 +71,6 @@
 #include "string-table.h"
 #include "string-util.h"
 #include "user-util.h"
-#include "log.h"
 
 #define USER_JOURNALS_MAX 1024
 
@@ -675,6 +676,44 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
                 server_schedule_sync(s, priority);
 }
 
+static int get_invocation_id(const char *cgroup_root, const char *slice, const char *unit, char **ret) {
+        _cleanup_free_ char *escaped = NULL, *slice_path = NULL, *p = NULL;
+        char *copy, ids[SD_ID128_STRING_MAX];
+        int r;
+
+        /* Read the invocation ID of a unit off a unit. It's stored in the "trusted.invocation_id" extended attribute
+         * on the cgroup path. */
+
+        r = cg_slice_to_path(slice, &slice_path);
+        if (r < 0)
+                return r;
+
+        escaped = cg_escape(unit);
+        if (!escaped)
+                return -ENOMEM;
+
+        p = strjoin(cgroup_root, "/", slice_path, "/", escaped, NULL);
+        if (!p)
+                return -ENOMEM;
+
+        r = cg_get_xattr(SYSTEMD_CGROUP_CONTROLLER, p, "trusted.invocation_id", ids, 32);
+        if (r < 0)
+                return r;
+        if (r != 32)
+                return -EINVAL;
+        ids[32] = 0;
+
+        if (!id128_is_valid(ids))
+                return -EINVAL;
+
+        copy = strdup(ids);
+        if (!copy)
+                return -ENOMEM;
+
+        *ret = copy;
+        return 0;
+}
+
 static void dispatch_message_real(
                 Server *s,
                 struct iovec *iovec, unsigned n, unsigned m,
@@ -713,7 +752,7 @@ static void dispatch_message_real(
         assert(s);
         assert(iovec);
         assert(n > 0);
-        assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
+        assert(n + N_IOVEC_META_FIELDS + (object_pid > 0 ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
 
         if (ucred) {
                 realuid = ucred->uid;
@@ -771,6 +810,7 @@ static void dispatch_message_real(
 
                 r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
                 if (r >= 0) {
+                        _cleanup_free_ char *raw_unit = NULL, *raw_slice = NULL;
                         char *session = NULL;
 
                         x = strjoina("_SYSTEMD_CGROUP=", c);
@@ -790,9 +830,8 @@ static void dispatch_message_real(
                                 IOVEC_SET_STRING(iovec[n++], owner_uid);
                         }
 
-                        if (cg_path_get_unit(c, &t) >= 0) {
-                                x = strjoina("_SYSTEMD_UNIT=", t);
-                                free(t);
+                        if (cg_path_get_unit(c, &raw_unit) >= 0) {
+                                x = strjoina("_SYSTEMD_UNIT=", raw_unit);
                                 IOVEC_SET_STRING(iovec[n++], x);
                         } else if (unit_id && !session) {
                                 x = strjoina("_SYSTEMD_UNIT=", unit_id);
@@ -808,12 +847,25 @@ static void dispatch_message_real(
                                 IOVEC_SET_STRING(iovec[n++], x);
                         }
 
-                        if (cg_path_get_slice(c, &t) >= 0) {
-                                x = strjoina("_SYSTEMD_SLICE=", t);
+                        if (cg_path_get_slice(c, &raw_slice) >= 0) {
+                                x = strjoina("_SYSTEMD_SLICE=", raw_slice);
+                                IOVEC_SET_STRING(iovec[n++], x);
+                        }
+
+                        if (cg_path_get_user_slice(c, &t) >= 0) {
+                                x = strjoina("_SYSTEMD_USER_SLICE=", t);
                                 free(t);
                                 IOVEC_SET_STRING(iovec[n++], x);
                         }
 
+                        if (raw_slice && raw_unit) {
+                                if (get_invocation_id(s->cgroup_root, raw_slice, raw_unit, &t) >= 0) {
+                                        x = strjoina("_SYSTEMD_INVOCATION_ID=", t);
+                                        free(t);
+                                        IOVEC_SET_STRING(iovec[n++], x);
+                                }
+                        }
+
                         free(c);
                 } else if (unit_id) {
                         x = strjoina("_SYSTEMD_UNIT=", unit_id);
@@ -919,13 +971,25 @@ static void dispatch_message_real(
                                 IOVEC_SET_STRING(iovec[n++], x);
                         }
 
+                        if (cg_path_get_slice(c, &t) >= 0) {
+                                x = strjoina("OBJECT_SYSTEMD_SLICE=", t);
+                                free(t);
+                                IOVEC_SET_STRING(iovec[n++], x);
+                        }
+
+                        if (cg_path_get_user_slice(c, &t) >= 0) {
+                                x = strjoina("OBJECT_SYSTEMD_USER_SLICE=", t);
+                                free(t);
+                                IOVEC_SET_STRING(iovec[n++], x);
+                        }
+
                         free(c);
                 }
         }
         assert(n <= m);
 
         if (tv) {
-                sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv));
+                sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=" USEC_FMT, timeval_load(tv));
                 IOVEC_SET_STRING(iovec[n++], source_time);
         }
 
@@ -1474,7 +1538,7 @@ static int server_parse_proc_cmdline(Server *s) {
 static int server_parse_config_file(Server *s) {
         assert(s);
 
-        return config_parse_many(PKGSYSCONFDIR "/journald.conf",
+        return config_parse_many_nulstr(PKGSYSCONFDIR "/journald.conf",
                                  CONF_PATHS_NULSTR("systemd/journald.conf.d"),
                                  "Journal\0",
                                  config_item_perf_lookup, journald_gperf_lookup,
@@ -1587,7 +1651,7 @@ static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents,
         assert(s->notify_fd == fd);
 
         /* The $NOTIFY_SOCKET is writable again, now send exactly one
-         * message on it. Either it's the wtachdog event, the initial
+         * message on it. Either it's the watchdog event, the initial
          * READY=1 event or an stdout stream event. If there's nothing
          * to write anymore, turn our event source off. The next time
          * there's something to send it will be turned on again. */