]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/nspawn/nspawn-register.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / nspawn / nspawn-register.c
index e5b76a0c5db265e15d4ba46da69d98e0e3800d1d..9d5895351584b9bb2e7768676c05fc064f059159 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
 #include "strv.h"
 #include "util.h"
 
+static int append_machine_properties(
+                sd_bus_message *m,
+                CustomMount *mounts,
+                unsigned n_mounts,
+                int kill_signal,
+                char **properties) {
+
+        unsigned j;
+        int r;
+
+        assert(m);
+
+        r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in
+         * sync regardless if we are run with or without the --keep-unit switch. */
+        r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
+                                  /* Allow the container to
+                                   * access and create the API
+                                   * device nodes, so that
+                                   * PrivateDevices= in the
+                                   * container can work
+                                   * fine */
+                                  "/dev/net/tun", "rwm",
+                                  /* Allow the container
+                                   * access to ptys. However,
+                                   * do not permit the
+                                   * container to ever create
+                                   * these device nodes. */
+                                  "char-pts", "rw");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        for (j = 0; j < n_mounts; j++) {
+                CustomMount *cm = mounts + j;
+
+                if (cm->type != CUSTOM_MOUNT_BIND)
+                        continue;
+
+                r = is_device_node(cm->source);
+                if (r == -ENOENT) {
+                        /* The bind source might only appear as the image is put together, hence don't complain */
+                        log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
+                        continue;
+                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to stat %s: %m", cm->source);
+
+                if (r) {
+                        r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
+                                                  cm->source, cm->read_only ? "r" : "rw");
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to append message arguments: %m");
+                }
+        }
+
+        if (kill_signal != 0) {
+                r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
+        return 0;
+}
+
 int register_machine(
                 const char *machine_name,
                 pid_t pid,
@@ -68,8 +140,6 @@ int register_machine(
                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
         } else {
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-                char **i;
-                unsigned j;
 
                 r = sd_bus_message_new_method_call(
                                 bus,
@@ -104,64 +174,18 @@ int register_machine(
                                 return bus_log_create_error(r);
                 }
 
-                r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
+                r = append_machine_properties(
+                                m,
+                                mounts,
+                                n_mounts,
+                                kill_signal,
+                                properties);
                 if (r < 0)
-                        return bus_log_create_error(r);
+                        return r;
 
-                /* If you make changes here, also make sure to update
-                 * systemd-nspawn@.service, to keep the device
-                 * policies in sync regardless if we are run with or
-                 * without the --keep-unit switch. */
-                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
-                                          /* Allow the container to
-                                           * access and create the API
-                                           * device nodes, so that
-                                           * PrivateDevices= in the
-                                           * container can work
-                                           * fine */
-                                          "/dev/net/tun", "rwm",
-                                          /* Allow the container
-                                           * access to ptys. However,
-                                           * do not permit the
-                                           * container to ever create
-                                           * these device nodes. */
-                                          "char-pts", "rw");
+                r = bus_append_unit_property_assignment_many(m, properties);
                 if (r < 0)
-                        return bus_log_create_error(r);
-
-                for (j = 0; j < n_mounts; j++) {
-                        CustomMount *cm = mounts + j;
-
-                        if (cm->type != CUSTOM_MOUNT_BIND)
-                                continue;
-
-                        r = is_device_node(cm->source);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to stat %s: %m", cm->source);
-
-                        if (r) {
-                                r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
-                                        cm->source, cm->read_only ? "r" : "rw");
-                                if (r < 0)
-                                        return log_error_errno(r, "Failed to append message arguments: %m");
-                        }
-                }
-
-                if (kill_signal != 0) {
-                        r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
-                        r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                STRV_FOREACH(i, properties) {
-                        r = bus_append_unit_property_assignment(m, *i);
-                        if (r < 0)
-                                return r;
-                }
+                        return r;
 
                 r = sd_bus_message_close_container(m);
                 if (r < 0)
@@ -227,3 +251,104 @@ int terminate_machine(pid_t pid) {
 
         return 0;
 }
+
+int allocate_scope(
+                const char *machine_name,
+                pid_t pid,
+                const char *slice,
+                CustomMount *mounts,
+                unsigned n_mounts,
+                int kill_signal,
+                char **properties) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
+        _cleanup_free_ char *scope = NULL;
+        const char *description, *object;
+        int r;
+
+        r = sd_bus_default_system(&bus);
+        if (r < 0)
+                return log_error_errno(r, "Failed to open system bus: %m");
+
+        r = bus_wait_for_jobs_new(bus, &w);
+        if (r < 0)
+                return log_error_errno(r, "Could not watch job: %m");
+
+        r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope);
+        if (r < 0)
+                return log_error_errno(r, "Failed to mangle scope name: %m");
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        &m,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "StartTransientUnit");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_append(m, "ss", scope, "fail");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* Properties */
+        r = sd_bus_message_open_container(m, 'a', "(sv)");
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        description = strjoina("Container ", machine_name);
+
+        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
+                                  "PIDs", "au", 1, pid,
+                                  "Description", "s", description,
+                                  "Delegate", "b", 1,
+                                  "Slice", "s", isempty(slice) ? "machine.slice" : slice);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = append_machine_properties(
+                        m,
+                        mounts,
+                        n_mounts,
+                        kill_signal,
+                        properties);
+        if (r < 0)
+                return r;
+
+        r = bus_append_unit_property_assignment_many(m, properties);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_close_container(m);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        /* No auxiliary units */
+        r = sd_bus_message_append(
+                        m,
+                        "a(sa(sv))",
+                        0);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_call(bus, m, 0, &error, &reply);
+        if (r < 0) {
+                log_error("Failed to allocate scope: %s", bus_error_message(&error, r));
+                return r;
+        }
+
+        r = sd_bus_message_read(reply, "o", &object);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = bus_wait_for_jobs_one(w, object, false);
+        if (r < 0)
+                return r;
+
+        return 0;
+}