]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
machined: skip leader ownership check for user scope
authorDaan De Meyer <daan@amutable.com>
Sat, 4 Apr 2026 18:00:13 +0000 (18:00 +0000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 6 Apr 2026 15:13:40 +0000 (17:13 +0200)
When registering a machine, machined verifies that the leader process
is owned by the calling user via process_is_owned_by_uid(). This
check fails for user scope machined when the leader is inside a user
namespace: after the leader calls setns(CLONE_NEWUSER), it becomes
non-dumpable, and the subsequent ptrace_may_access() check in the
kernel denies access to the process's user namespace, since the
calling user lacks CAP_SYS_PTRACE in the mm's user namespace (the
host namespace), even though the user owns the child user namespace.

Skip this check when running in user scope. For system scope, the
check is important because multiple users share the same machined
instance, so one user must not be able to claim another user's process
as a machine leader. For user scope this is unnecessary: the varlink
socket lives under $XDG_RUNTIME_DIR (mode 0700), so only the owning
user can connect, and the user machined instance can only perform
operations bounded by that user's own privileges. Registering a
foreign PID does not escalate capabilities.

src/machine/machine-varlink.c

index dfc7020fc95839f980a4ad9606a371b2ebbb7d2a..07a860f6c16ca71912acc675ab8b33029dc58306 100644 (file)
@@ -192,8 +192,10 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
         if (r < 0)
                 return r;
 
-        /* Ensure an unprivileged user cannot claim any process they don't control as their own machine */
-        if (machine->uid != 0) {
+        /* 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) {
                 r = process_is_owned_by_uid(&machine->leader, machine->uid);
                 if (r < 0)
                         return r;