]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machine: never ever allow non-root-owned host machine
authorMike Yuan <me@yhndnzj.com>
Thu, 26 Mar 2026 11:16:36 +0000 (12:16 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 27 Mar 2026 10:47:42 +0000 (11:47 +0100)
We really should lock this down _hard_, as evidenced by recent
security fallouts.

src/machine/machine-dbus.c
src/machine/machine-varlink.c

index d567cd6d503f75ec108deb1952982182a7ebffca..2dab827d41c5166a47475d4de31a1e50f81e539d 100644 (file)
@@ -366,14 +366,15 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
                 return r;
         user = isempty(user) ? "root" : user;
 
-        /* Ensure only root can shell into the root namespace, unless it's specifically the host machine,
-         * which is owned by uid 0 anyway and cannot be self-registered. This is to avoid unprivileged
-         * users registering a process they own in the root user namespace, and then shelling in as root
-         * or another user. Note that the shell operation is privileged and requires 'auth_admin', so we
-         * do not need to check the caller's uid, as that will be checked by polkit, and if they machine's
-         * and the caller's do not match, authorization will be required. It's only the case where the
-         * caller owns the machine that will be shortcut and needs to be checked here. */
-        if (m->manager->runtime_scope != RUNTIME_SCOPE_USER && m->uid != 0 && m->class != MACHINE_HOST) {
+        /* Ensure only root can shell into the root namespace. This is to avoid unprivileged users registering
+         * a process they own in the root user namespace, and then shelling in as root or another user. Note that
+         * the shell operation is privileged and requires 'auth_admin', so we do not need to check the caller's uid,
+         * as that will be checked by polkit, and if the machine's and the caller's do not match, authorization
+         * will be required. It's only the case where the caller owns the machine that will be shortcut and needs
+         * to be checked here. */
+        if (m->manager->runtime_scope != RUNTIME_SCOPE_USER && m->uid != 0) {
+                assert(m->class != MACHINE_HOST);
+
                 r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &m->leader, NAMESPACE_USER);
                 if (r < 0)
                         return log_debug_errno(
index 40e9136b2705f6945dcdfeaedd6c9c3e924cbac9..dfc7020fc95839f980a4ad9606a371b2ebbb7d2a 100644 (file)
@@ -555,14 +555,15 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
                 return r;
 
         if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
-                /* Ensure only root can shell into the root namespace, unless it's specifically the host machine,
-                 * which is owned by uid 0 anyway and cannot be self-registered. This is to avoid unprivileged
-                 * users registering a process they own in the root user namespace, and then shelling in as root
+                /* Ensure only root can shell into the root namespace. This is to avoid unprivileged users
+                 * registering a process they own in the root user namespace, and then shelling in as root
                  * or another user. Note that the shell operation is privileged and requires 'auth_admin', so we
-                 * do not need to check the caller's uid, as that will be checked by polkit, and if they machine's
+                 * do not need to check the caller's uid, as that will be checked by polkit, and if the machine's
                  * and the caller's do not match, authorization will be required. It's only the case where the
                  * caller owns the machine that will be shortcut and needs to be checked here. */
-                if (machine->uid != 0 && machine->class != MACHINE_HOST) {
+                if (machine->uid != 0) {
+                        assert(machine->class != MACHINE_HOST);
+
                         r = pidref_in_same_namespace(&PIDREF_MAKE_FROM_PID(1), &machine->leader, NAMESPACE_USER);
                         if (r < 0)
                                 return log_debug_errno(