]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: register containers with both the system-wide and the per-user machined instance 39145/head
authorLennart Poettering <lennart@poettering.net>
Wed, 27 Aug 2025 12:14:18 +0000 (14:14 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 7 Oct 2025 10:33:52 +0000 (12:33 +0200)
Let's make sure each container run by unpriv users is known by both
instances. Making it known by the host instance ensures it is resovlable
by nss-myhostname (and various other tools), but making it known by the
per-user instance means the user can fully manage it on their own.

This simplifies the code a bit too, i.e. we always allocate a scope
ourselves now, and just register it, instead of letting machined do that
under some circumstances. THere's little value in that and it simplifies
things for us quite a bit.

src/nspawn/nspawn-register.c
src/nspawn/nspawn-register.h
src/nspawn/nspawn.c

index 516f67c7600511cce4f99419458ce78140cfc78c..04031adcc5ab576ec5247b44407a9faf853f8590 100644 (file)
@@ -131,30 +131,25 @@ static int can_set_coredump_receive(sd_bus *bus) {
         return r >= 0;
 }
 
-static int create_or_register_machine_ex(
+static int register_machine_ex(
                 sd_bus *bus,
                 const char *machine_name,
                 const PidRef *pid,
                 const char *directory,
                 sd_id128_t uuid,
                 int local_ifindex,
-                const char *slice,
-                CustomMount *mounts,
-                unsigned n_mounts,
-                int kill_signal,
-                char **properties,
-                sd_bus_message *properties_message,
                 const char *service,
-                StartMode start_mode,
-                sd_bus_error *error,
-                bool keep_unit) {
+                sd_bus_error *error) {
 
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         int r;
 
+        assert(bus);
+        assert(machine_name);
+        assert(service);
         assert(error);
 
-        r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, keep_unit ? "RegisterMachineEx" : "CreateMachineEx");
+        r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, "RegisterMachineEx");
         if (r < 0)
                 return bus_log_create_error(r);
 
@@ -209,45 +204,6 @@ static int create_or_register_machine_ex(
         if (r < 0)
                 return bus_log_create_error(r);
 
-        if (!keep_unit) {
-                r = sd_bus_message_open_container(m, 'a', "(sv)");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                if (!isempty(slice)) {
-                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = append_controller_property(bus, m);
-                if (r < 0)
-                        return r;
-
-                r = append_machine_properties(
-                                m,
-                                mounts,
-                                n_mounts,
-                                kill_signal,
-                                start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
-                if (r < 0)
-                        return r;
-
-                if (properties_message) {
-                        r = sd_bus_message_copy(m, properties_message, true);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
-                if (r < 0)
-                        return r;
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
-        }
-
         return sd_bus_call(bus, m, 0, error, NULL);
 }
 
@@ -258,117 +214,45 @@ int register_machine(
                 const char *directory,
                 sd_id128_t uuid,
                 int local_ifindex,
-                const char *slice,
-                CustomMount *mounts,
-                unsigned n_mounts,
-                int kill_signal,
-                char **properties,
-                sd_bus_message *properties_message,
-                const char *service,
-                StartMode start_mode,
-                RegisterMachineFlags flags) {
+                const char *service) {
 
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(bus);
+        assert(machine_name);
+        assert(service);
 
-        r = create_or_register_machine_ex(
+        r = register_machine_ex(
                         bus,
                         machine_name,
                         pid,
                         directory,
                         uuid,
                         local_ifindex,
-                        slice,
-                        mounts,
-                        n_mounts,
-                        kill_signal,
-                        properties,
-                        properties_message,
                         service,
-                        start_mode,
-                        &error,
-                        FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT));
+                        &error);
         if (r >= 0)
                 return 0;
         if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
                 return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
-        sd_bus_error_free(&error);
-        if (FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT)) {
-                r = bus_call_method(
-                                bus,
-                                bus_machine_mgr,
-                                "RegisterMachineWithNetwork",
-                                &error,
-                                NULL,
-                                "sayssusai",
-                                machine_name,
-                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
-                                service,
-                                "container",
-                                pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
-                                strempty(directory),
-                                local_ifindex > 0 ? 1 : 0, local_ifindex);
-        } else {
-                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
-                r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, "CreateMachineWithNetwork");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_append(
-                                m,
-                                "sayssusai",
-                                machine_name,
-                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
-                                service,
-                                "container",
-                                pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
-                                strempty(directory),
-                                local_ifindex > 0 ? 1 : 0, local_ifindex);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                r = sd_bus_message_open_container(m, 'a', "(sv)");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                if (!isempty(slice)) {
-                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = append_controller_property(bus, m);
-                if (r < 0)
-                        return r;
-
-                r = append_machine_properties(
-                                m,
-                                mounts,
-                                n_mounts,
-                                kill_signal,
-                                start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
-                if (r < 0)
-                        return r;
 
-                if (properties_message) {
-                        r = sd_bus_message_copy(m, properties_message, true);
-                        if (r < 0)
-                                return bus_log_create_error(r);
-                }
-
-                r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
-                if (r < 0)
-                        return r;
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
+        sd_bus_error_free(&error);
 
-                r = sd_bus_call(bus, m, 0, &error, NULL);
-        }
+        r = bus_call_method(
+                        bus,
+                        bus_machine_mgr,
+                        "RegisterMachineWithNetwork",
+                        &error,
+                        NULL,
+                        "sayssusai",
+                        machine_name,
+                        SD_BUS_MESSAGE_APPEND_ID128(uuid),
+                        service,
+                        "container",
+                        pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
+                        strempty(directory),
+                        local_ifindex > 0 ? 1 : 0, local_ifindex);
         if (r < 0)
                 return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
 
index bbb0d9124e5c807dd4c6bdbac2c4aaad56b2f8d7..c81e4dac4521b20095dd9d0934b0b1c4ab4f300d 100644 (file)
@@ -4,10 +4,6 @@
 #include "forward.h"
 #include "nspawn-settings.h"
 
-typedef enum RegisterMachineFlags {
-        REGISTER_MACHINE_KEEP_UNIT   = 1 << 0,
-} RegisterMachineFlags;
-
 int register_machine(
                 sd_bus *bus,
                 const char *machine_name,
@@ -15,14 +11,7 @@ int register_machine(
                 const char *directory,
                 sd_id128_t uuid,
                 int local_ifindex,
-                const char *slice,
-                CustomMount *mounts, unsigned n_mounts,
-                int kill_signal,
-                char **properties,
-                sd_bus_message *properties_message,
-                const char *service,
-                StartMode start_mode,
-                RegisterMachineFlags flags);
+                const char *service);
 int unregister_machine(sd_bus *bus, const char *machine_name);
 
 typedef enum AllocateScopeFlags {
index f1ed036b6224da2e7bf530bf238db8caa9d25ec8..1fcd01d4bd949c87cd51b6d44fd2bcfd0a408eec 100644 (file)
@@ -5380,10 +5380,10 @@ static int run_container(
                 (void) sd_bus_set_allow_interactive_authorization(system_bus, arg_ask_password);
         }
 
-        /* Scope allocation happens on the user bus if we are unpriv, otherwise system bus. */
         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *user_bus = NULL;
         _cleanup_(sd_bus_unrefp) sd_bus *runtime_bus = NULL;
-        if (!arg_keep_unit) {
+
+        if (arg_register || !arg_keep_unit) {
                 if (arg_privileged)
                         runtime_bus = sd_bus_ref(system_bus);
                 else {
@@ -5397,7 +5397,22 @@ static int run_container(
 
                         runtime_bus = sd_bus_ref(user_bus);
                 }
+        }
 
+        /* Scope allocation happens on the user bus if we are unpriv, otherwise system bus. */
+        if (arg_keep_unit) {
+                /* If we are not supposed to allocate a unit, then let's move the process now, so that we can
+                 * register things while being in the right cgroup location already. Otherwise, let's move
+                 * the process later, once we have unit and hence cgroup. */
+                r = create_subcgroup(
+                                pid,
+                                arg_keep_unit,
+                                arg_uid_shift,
+                                userns_fd,
+                                arg_userns_mode);
+                if (r < 0)
+                        return r;
+        } else {
                 /* When a new scope is created for this container, then we'll be registered as its controller, in which
                  * case PID 1 will send us a friendly RequestStop signal, when it is asked to terminate the
                  * scope. Let's hook into that, and cleanly shut down the container, and print a friendly message. */
@@ -5416,22 +5431,8 @@ static int run_container(
                         return log_error_errno(r, "Failed to request RequestStop match: %m");
         }
 
-        if (arg_keep_unit) {
-                /* If we are not supposed to allocate a unit, then let's move the process now, so that we can
-                 * register things while being in the right cgroup location already. Otherwise, let's move
-                 * the process later, once we have unit and hence cgroup. */
-                r = create_subcgroup(
-                                pid,
-                                arg_keep_unit,
-                                arg_uid_shift,
-                                userns_fd,
-                                arg_userns_mode);
-                if (r < 0)
-                        return r;
-        }
-
         bool scope_allocated = false;
-        if (!arg_keep_unit && (!arg_register || !arg_privileged)) {
+        if (!arg_keep_unit) {
                 AllocateScopeFlags flags = ALLOCATE_SCOPE_ALLOW_PIDFD;
                 r = allocate_scope(
                                 runtime_bus,
@@ -5450,10 +5451,8 @@ static int run_container(
                 scope_allocated = true;
         }
 
-        bool registered = false;
+        bool registered_system = false, registered_runtime = false;
         if (arg_register) {
-                RegisterMachineFlags flags = 0;
-                SET_FLAG(flags, REGISTER_MACHINE_KEEP_UNIT, arg_keep_unit || !arg_privileged);
                 r = register_machine(
                                 system_bus,
                                 arg_machine,
@@ -5461,18 +5460,32 @@ static int run_container(
                                 arg_directory,
                                 arg_uuid,
                                 ifi,
-                                arg_slice,
-                                arg_custom_mounts, arg_n_custom_mounts,
-                                arg_kill_signal,
-                                arg_property,
-                                arg_property_message,
-                                arg_container_service_name,
-                                arg_start_mode,
-                                flags);
-                if (r < 0)
-                        return r;
+                                arg_container_service_name);
+                if (r < 0) {
+                        if (arg_privileged) /* if privileged the request to register definitely failed */
+                                return r;
+
+                        log_notice_errno(r, "Failed to register machine in system context, will try in user context.");
+                } else
+                        registered_system = true;
 
-                registered = true;
+                if (!arg_privileged) {
+                        r = register_machine(
+                                        runtime_bus,
+                                        arg_machine,
+                                        pid,
+                                        arg_directory,
+                                        arg_uuid,
+                                        ifi,
+                                        arg_container_service_name);
+                        if (r < 0) {
+                                if (!registered_system) /* neither registration worked: fail */
+                                        return r;
+
+                                log_notice_errno(r, "Failed to register machine in user context, but succeeded in system context, will proceed.");
+                        } else
+                                registered_runtime = true;
+                }
         }
 
         if (arg_keep_unit && (arg_slice || arg_property))
@@ -5684,8 +5697,10 @@ static int run_container(
         r = wait_for_container(pid, &container_status);
 
         /* Tell machined that we are gone. */
-        if (registered)
+        if (registered_system)
                 (void) unregister_machine(system_bus, arg_machine);
+        if (registered_runtime)
+                (void) unregister_machine(runtime_bus, arg_machine);
 
         if (r < 0)
                 /* We failed to wait for the container, or the container exited abnormally. */