]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/machine/machine.c
Merge pull request #31899 from yuwata/sd-journal-add-match
[thirdparty/systemd.git] / src / machine / machine.c
index c08a645814d00f53cd91c0f0f4252c40cb773a26..309bffa3c8075bbe0b0ccd5aa2008cf7cd7dedf5 100644 (file)
@@ -9,6 +9,7 @@
 #include "alloc-util.h"
 #include "bus-error.h"
 #include "bus-locator.h"
+#include "bus-unit-util.h"
 #include "bus-util.h"
 #include "env-file.h"
 #include "errno-util.h"
@@ -17,6 +18,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
+#include "fs-util.h"
 #include "hashmap.h"
 #include "machine-dbus.h"
 #include "machine.h"
@@ -30,6 +32,7 @@
 #include "string-table.h"
 #include "terminal-util.h"
 #include "tmpfile-util.h"
+#include "uid-range.h"
 #include "unit-name.h"
 #include "user-util.h"
 
@@ -48,10 +51,14 @@ int machine_new(Manager *manager, MachineClass class, const char *name, Machine
          * means as much as "we don't know yet", and that we'll figure
          * it out later when loading the state file. */
 
-        m = new0(Machine, 1);
+        m = new(Machine, 1);
         if (!m)
                 return -ENOMEM;
 
+        *m = (Machine) {
+                .leader = PIDREF_NULL,
+        };
+
         m->name = strdup(name);
         if (!m->name)
                 return -ENOMEM;
@@ -93,8 +100,10 @@ Machine* machine_free(Machine *m) {
         if (m->manager->host_machine == m)
                 m->manager->host_machine = NULL;
 
-        if (m->leader > 0)
-                (void) hashmap_remove_value(m->manager->machine_leaders, PID_TO_PTR(m->leader), m);
+        if (pidref_is_set(&m->leader)) {
+                (void) hashmap_remove_value(m->manager->machine_leaders, PID_TO_PTR(m->leader.pid), m);
+                pidref_done(&m->leader);
+        }
 
         sd_bus_message_unref(m->create_message);
 
@@ -107,7 +116,7 @@ Machine* machine_free(Machine *m) {
 }
 
 int machine_save(Machine *m) {
-        _cleanup_free_ char *temp_path = NULL;
+        _cleanup_(unlink_and_freep) char *temp_path = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
@@ -174,8 +183,8 @@ int machine_save(Machine *m) {
         if (!sd_id128_is_null(m->id))
                 fprintf(f, "ID=" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->id));
 
-        if (m->leader != 0)
-                fprintf(f, "LEADER="PID_FMT"\n", m->leader);
+        if (pidref_is_set(&m->leader))
+                fprintf(f, "LEADER="PID_FMT"\n", m->leader.pid);
 
         if (m->class != _MACHINE_CLASS_INVALID)
                 fprintf(f, "CLASS=%s\n", machine_class_to_string(m->class));
@@ -211,6 +220,8 @@ int machine_save(Machine *m) {
                 goto fail;
         }
 
+        temp_path = mfree(temp_path);
+
         if (m->unit) {
                 char *sl;
 
@@ -226,9 +237,6 @@ int machine_save(Machine *m) {
 fail:
         (void) unlink(m->state_file);
 
-        if (temp_path)
-                (void) unlink(temp_path);
-
         return log_error_errno(r, "Failed to save machine data %s: %m", m->state_file);
 }
 
@@ -272,10 +280,14 @@ int machine_load(Machine *m) {
                 return log_error_errno(r, "Failed to read %s: %m", m->state_file);
 
         if (id)
-                sd_id128_from_string(id, &m->id);
+                (void) sd_id128_from_string(id, &m->id);
 
-        if (leader)
-                parse_pid(leader, &m->leader);
+        if (leader) {
+                pidref_done(&m->leader);
+                r = pidref_set_pidstr(&m->leader, leader);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to set leader PID to '%s', ignoring: %m", leader);
+        }
 
         if (class) {
                 MachineClass c;
@@ -337,7 +349,7 @@ static int machine_start_scope(
         int r;
 
         assert(machine);
-        assert(machine->leader > 0);
+        assert(pidref_is_set(&machine->leader));
         assert(!machine->unit);
 
         escaped = unit_name_escape(machine->name);
@@ -373,8 +385,11 @@ static int machine_start_scope(
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
-                                  "PIDs", "au", 1, machine->leader,
+        r = bus_append_scope_pidref(m, &machine->leader, /* allow_pidfd = */ true);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
                                   "Delegate", "b", 1,
                                   "CollectMode", "s", "inactive-or-failed",
                                   "AddRef", "b", 1,
@@ -440,7 +455,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
         if (m->started)
                 return 0;
 
-        r = hashmap_put(m->manager->machine_leaders, PID_TO_PTR(m->leader), m);
+        r = hashmap_put(m->manager->machine_leaders, PID_TO_PTR(m->leader.pid), m);
         if (r < 0)
                 return r;
 
@@ -452,11 +467,11 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
         log_struct(LOG_INFO,
                    "MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR,
                    "NAME=%s", m->name,
-                   "LEADER="PID_FMT, m->leader,
+                   "LEADER="PID_FMT, m->leader.pid,
                    LOG_MESSAGE("New machine %s.", m->name));
 
         if (!dual_timestamp_is_set(&m->timestamp))
-                dual_timestamp_get(&m->timestamp);
+                dual_timestamp_now(&m->timestamp);
 
         m->started = true;
 
@@ -503,7 +518,7 @@ int machine_finalize(Machine *m) {
                 log_struct(LOG_INFO,
                            "MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR,
                            "NAME=%s", m->name,
-                           "LEADER="PID_FMT, m->leader,
+                           "LEADER="PID_FMT, m->leader.pid,
                            LOG_MESSAGE("Machine %s terminated.", m->name));
 
                 m->stopping = true; /* The machine is supposed to be going away. Don't try to kill it. */
@@ -573,7 +588,7 @@ int machine_kill(Machine *m, KillWho who, int signo) {
                 return -ESRCH;
 
         if (who == KILL_LEADER) /* If we shall simply kill the leader, do so directly */
-                return RET_NERRNO(kill(m->leader, signo));
+                return pidref_kill(&m->leader, signo);
 
         /* Otherwise, make PID 1 do it for us, for the entire cgroup */
         return manager_kill_unit(m->manager, m->unit, signo, NULL);
@@ -585,14 +600,13 @@ int machine_openpt(Machine *m, int flags, char **ret_slave) {
         switch (m->class) {
 
         case MACHINE_HOST:
-
                 return openpt_allocate(flags, ret_slave);
 
         case MACHINE_CONTAINER:
-                if (m->leader <= 0)
+                if (!pidref_is_set(&m->leader))
                         return -EINVAL;
 
-                return openpt_allocate_in_namespace(m->leader, flags, ret_slave);
+                return openpt_allocate_in_namespace(m->leader.pid, flags, ret_slave);
 
         default:
                 return -EOPNOTSUPP;
@@ -608,10 +622,10 @@ int machine_open_terminal(Machine *m, const char *path, int mode) {
                 return open_terminal(path, mode);
 
         case MACHINE_CONTAINER:
-                if (m->leader <= 0)
+                if (!pidref_is_set(&m->leader))
                         return -EINVAL;
 
-                return open_terminal_in_namespace(m->leader, path, mode);
+                return open_terminal_in_namespace(m->leader.pid, path, mode);
 
         default:
                 return -EOPNOTSUPP;
@@ -645,7 +659,7 @@ int machine_get_uid_shift(Machine *m, uid_t *ret) {
         uid_t uid_base, uid_shift, uid_range;
         gid_t gid_base, gid_shift, gid_range;
         _cleanup_fclose_ FILE *f = NULL;
-        int k, r;
+        int r;
 
         assert(m);
         assert(ret);
@@ -664,7 +678,7 @@ int machine_get_uid_shift(Machine *m, uid_t *ret) {
         if (m->class != MACHINE_CONTAINER)
                 return -EOPNOTSUPP;
 
-        xsprintf(p, "/proc/" PID_FMT "/uid_map", m->leader);
+        xsprintf(p, "/proc/" PID_FMT "/uid_map", m->leader.pid);
         f = fopen(p, "re");
         if (!f) {
                 if (errno == ENOENT) {
@@ -677,14 +691,9 @@ int machine_get_uid_shift(Machine *m, uid_t *ret) {
         }
 
         /* Read the first line. There's at least one. */
-        errno = 0;
-        k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range);
-        if (k != 3) {
-                if (ferror(f))
-                        return errno_or_else(EIO);
-
-                return -EBADMSG;
-        }
+        r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+        if (r < 0)
+                return r;
 
         /* Not a mapping starting at 0? Then it's a complex mapping we can't expose here. */
         if (uid_base != 0)
@@ -702,20 +711,19 @@ int machine_get_uid_shift(Machine *m, uid_t *ret) {
 
         fclose(f);
 
-        xsprintf(p, "/proc/" PID_FMT "/gid_map", m->leader);
+        xsprintf(p, "/proc/" PID_FMT "/gid_map", m->leader.pid);
         f = fopen(p, "re");
         if (!f)
                 return -errno;
 
         /* Read the first line. There's at least one. */
         errno = 0;
-        k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT "\n", &gid_base, &gid_shift, &gid_range);
-        if (k != 3) {
-                if (ferror(f))
-                        return errno_or_else(EIO);
-
+        r = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT "\n", &gid_base, &gid_shift, &gid_range);
+        if (r == EOF)
+                return errno_or_else(ENOMSG);
+        assert(r >= 0);
+        if (r != 3)
                 return -EBADMSG;
-        }
 
         /* If there's more than one line, then we don't support this file. */
         r = safe_fgetc(f, NULL);
@@ -744,6 +752,7 @@ static int machine_owns_uid_internal(
 
         _cleanup_fclose_ FILE *f = NULL;
         const char *p;
+        int r;
 
         /* This is a generic implementation for both uids and gids, under the assumptions they have the same types and semantics. */
         assert_cc(sizeof(uid_t) == sizeof(gid_t));
@@ -756,7 +765,7 @@ static int machine_owns_uid_internal(
         if (machine->class != MACHINE_CONTAINER)
                 goto negative;
 
-        p = procfs_file_alloca(machine->leader, map_file);
+        p = procfs_file_alloca(machine->leader.pid, map_file);
         f = fopen(p, "re");
         if (!f) {
                 log_debug_errno(errno, "Failed to open %s, ignoring.", p);
@@ -765,18 +774,12 @@ static int machine_owns_uid_internal(
 
         for (;;) {
                 uid_t uid_base, uid_shift, uid_range, converted;
-                int k;
 
-                errno = 0;
-                k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
-                if (k < 0 && feof(f))
+                r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+                if (r == -ENOMSG)
                         break;
-                if (k != 3) {
-                        if (ferror(f))
-                                return errno_or_else(EIO);
-
-                        return -EIO;
-                }
+                if (r < 0)
+                        return r;
 
                 /* The private user namespace is disabled, ignoring. */
                 if (uid_shift == 0)
@@ -818,6 +821,7 @@ static int machine_translate_uid_internal(
 
         _cleanup_fclose_ FILE *f = NULL;
         const char *p;
+        int r;
 
         /* This is a generic implementation for both uids and gids, under the assumptions they have the same types and semantics. */
         assert_cc(sizeof(uid_t) == sizeof(gid_t));
@@ -830,25 +834,19 @@ static int machine_translate_uid_internal(
 
         /* Translates a machine UID into a host UID */
 
-        p = procfs_file_alloca(machine->leader, map_file);
+        p = procfs_file_alloca(machine->leader.pid, map_file);
         f = fopen(p, "re");
         if (!f)
                 return -errno;
 
         for (;;) {
                 uid_t uid_base, uid_shift, uid_range, converted;
-                int k;
 
-                errno = 0;
-                k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
-                if (k < 0 && feof(f))
+                r = uid_map_read_one(f, &uid_base, &uid_shift, &uid_range);
+                if (r == -ENOMSG)
                         break;
-                if (k != 3) {
-                        if (ferror(f))
-                                return errno_or_else(EIO);
-
-                        return -EIO;
-                }
+                if (r < 0)
+                        return r;
 
                 if (uid < uid_base || uid >= uid_base + uid_range)
                         continue;
@@ -859,6 +857,7 @@ static int machine_translate_uid_internal(
 
                 if (ret_host_uid)
                         *ret_host_uid = converted;
+
                 return 0;
         }