]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machined: allow privileged users to register other users machines 39042/head
authorLuca Boccassi <luca.boccassi@gmail.com>
Fri, 19 Sep 2025 23:49:42 +0000 (00:49 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Thu, 25 Jun 2026 09:39:11 +0000 (10:39 +0100)
If a user is authenticated by polkit as admin then it should be
able to manage any resource on the system.

Follow-up for 119d332d9c2cf1974b235c8d9e4e3ad821cf436a

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

index 7c4c05865b818eeae66d395d60f74885c5c6f333..a73f81b6f722520b2399aac1e71937439be41634 100644 (file)
@@ -126,6 +126,7 @@ static int machine_cid(const char *name, sd_json_variant *variant, sd_json_dispa
 int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
         Manager *manager = ASSERT_PTR(userdata);
         _cleanup_(machine_freep) Machine *machine = NULL;
+        bool sender_is_admin = false;
         int r;
 
         static const sd_json_dispatch_field dispatch_table[] = {
@@ -160,13 +161,16 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
                 return sd_varlink_error_invalid_parameter_name(link, "class");
 
         if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
-                r = varlink_verify_polkit_async(
+                r = varlink_verify_polkit_async_full(
                                 link,
                                 manager->system_bus,
                                 machine->allocate_unit ? "org.freedesktop.machine1.create-machine" : "org.freedesktop.machine1.register-machine",
                                 (const char**) STRV_MAKE("name", machine->name,
                                                          "class", machine_class_to_string(machine->class)),
-                                &manager->polkit_registry);
+                                /* good_user= */ UID_INVALID,
+                                /* flags= */ 0,
+                                &manager->polkit_registry,
+                                &sender_is_admin);
                 if (r <= 0)
                         return r;
         }
@@ -196,7 +200,7 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
         /* In system scope, ensure an unprivileged user cannot claim any process they don't
          * control as their own machine. In user scope the varlink socket is already
          * protected by $XDG_RUNTIME_DIR permissions. */
-        if (manager->runtime_scope != RUNTIME_SCOPE_USER && machine->uid != 0) {
+        if (manager->runtime_scope != RUNTIME_SCOPE_USER && machine->uid != 0 && !sender_is_admin) {
                 r = process_is_owned_by_uid(&machine->leader, machine->uid);
                 if (r < 0)
                         return r;
index f5315b9763083e0b4fb20589fdb61c4e88494f94..3591bbca2e5655cf46b5abf205e1b420e9b90a4e 100644 (file)
@@ -279,12 +279,33 @@ static int machine_add_from_params(
         /* Ensure an unprivileged user cannot claim any process they don't control as their own machine */
         switch (manager->runtime_scope) {
 
-        case RUNTIME_SCOPE_SYSTEM:
-                /* In system mode root may register anything */
-                if (uid == 0)
+        case RUNTIME_SCOPE_SYSTEM: {
+                const char *details[] = {
+                        "name",  name,
+                        "class", machine_class_to_string(c),
+                        NULL
+                };
+                bool sender_is_admin = false;
+
+                r = bus_verify_polkit_async_full(
+                                message,
+                                polkit_action,
+                                details,
+                                /* good_user= */ UID_INVALID,
+                                /* flags= */ 0,
+                                &manager->polkit_registry,
+                                &sender_is_admin,
+                                error);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return 0; /* Will call us back */
+
+                /* In system mode root/admin may register anything */
+                if (uid == 0 || sender_is_admin)
                         break;
 
-                /* And non-root may only register things if they own the userns */
+                /* And non-root/admin may only register things if they own the userns */
                 r = process_is_owned_by_uid(leader_pidref, uid);
                 if (r < 0)
                         return r;
@@ -292,7 +313,8 @@ static int machine_add_from_params(
                         break;
 
                 /* Nothing else may */
-                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only root may register machines for other users");
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only privileged users may register machines for other users");
+        }
 
         case RUNTIME_SCOPE_USER:
                 /* In user mode the user owning our instance may register anything. */
@@ -306,23 +328,6 @@ static int machine_add_from_params(
                 assert_not_reached();
         }
 
-        if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
-                const char *details[] = {
-                        "name",  name,
-                        "class", machine_class_to_string(c),
-                        NULL
-                };
-
-                r = bus_verify_polkit_async(
-                                message,
-                                polkit_action,
-                                details,
-                                &manager->polkit_registry,
-                                error);
-                if (r <= 0)
-                        return r; /* 0 means Polkit will call us back, see method_create_machine() */
-        }
-
         r = manager_add_machine(manager, name, &m);
         if (r < 0)
                 return r;