]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace-util: introduce userns_enter_and_pin() helper
authorMike Yuan <me@yhndnzj.com>
Wed, 8 Jan 2025 11:43:05 +0000 (12:43 +0100)
committerMike Yuan <me@yhndnzj.com>
Sat, 11 Jan 2025 14:53:14 +0000 (15:53 +0100)
which generalizes forking a process into userns and freeze()

Addresses https://github.com/systemd/systemd/pull/35833/files#r1905508153

src/basic/namespace-util.c
src/basic/namespace-util.h
src/basic/uid-range.c

index 2ae5003459b7d7ce3b4c9f300cc7e19e27377540..6ece5108dfb37fa13140fd20d1fc9b3c5a9829ce 100644 (file)
@@ -558,7 +558,7 @@ int userns_acquire(const char *uid_map, const char *gid_map) {
         return TAKE_FD(userns_fd);
 }
 
-int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
+int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) {
         _cleanup_(close_pairp) int pfd[2] = EBADF_PAIR;
         _cleanup_(sigkill_waitp) pid_t pid = 0;
         ssize_t n;
@@ -566,12 +566,13 @@ int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
         int r;
 
         assert(userns_fd >= 0);
+        assert(ret_pid);
 
         if (pipe2(pfd, O_CLOEXEC) < 0)
                 return -errno;
 
         r = safe_fork_full(
-                        "(sd-baseuns)",
+                        "(sd-pinuserns)",
                         /* stdio_fds= */ NULL,
                         (int[]) { pfd[1], userns_fd }, 2,
                         FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
@@ -608,6 +609,20 @@ int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
         assert(n == 1);
         assert(x == 'x');
 
+        *ret_pid = TAKE_PID(pid);
+        return 0;
+}
+
+int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
+        _cleanup_(sigkill_waitp) pid_t pid = 0;
+        int r;
+
+        assert(userns_fd >= 0);
+
+        r = userns_enter_and_pin(userns_fd, &pid);
+        if (r < 0)
+                return r;
+
         uid_t uid;
         r = uid_map_search_root(pid, "uid_map", &uid);
         if (r < 0)
@@ -630,13 +645,13 @@ int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
 }
 
 int process_is_owned_by_uid(const PidRef *pidref, uid_t uid) {
-        assert(uid_is_valid(uid));
-
         int r;
 
         /* Checks if the specified process either is owned directly by the specified user, or if it is inside
          * a user namespace owned by it. */
 
+        assert(uid_is_valid(uid));
+
         uid_t process_uid;
         r = pidref_get_uid(pidref, &process_uid);
         if (r < 0)
index 58347cbf885a0766a5b98007be0388e9f548bd9f..49e2de3bb3c65a670d82e97b12c5da434c5899a3 100644 (file)
@@ -87,6 +87,7 @@ int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_r
 
 int userns_acquire_empty(void);
 int userns_acquire(const char *uid_map, const char *gid_map);
+int userns_enter_and_pin(int userns_fd, pid_t *ret_pid);
 
 int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
 
index 687ddacc5791ff02864074250fc15e101951a26e..cbae1bbf78a0fecc04e174b56944f780032810d6 100644 (file)
@@ -9,6 +9,7 @@
 #include "fd-util.h"
 #include "format-util.h"
 #include "macro.h"
+#include "namespace-util.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "sort-util.h"
@@ -264,10 +265,7 @@ int uid_range_load_userns(const char *path, UIDRangeUsernsMode mode, UIDRange **
 }
 
 int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange **ret) {
-        _cleanup_(close_pairp) int pfd[2] = EBADF_PAIR;
         _cleanup_(sigkill_waitp) pid_t pid = 0;
-        ssize_t n;
-        char x;
         int r;
 
         assert(userns_fd >= 0);
@@ -275,46 +273,9 @@ int uid_range_load_userns_by_fd(int userns_fd, UIDRangeUsernsMode mode, UIDRange
         assert(mode < _UID_RANGE_USERNS_MODE_MAX);
         assert(ret);
 
-        if (pipe2(pfd, O_CLOEXEC) < 0)
-                return -errno;
-
-        r = safe_fork_full(
-                        "(sd-mkuserns)",
-                        /* stdio_fds= */ NULL,
-                        (int[]) { pfd[1], userns_fd }, 2,
-                        FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL,
-                        &pid);
+        r = userns_enter_and_pin(userns_fd, &pid);
         if (r < 0)
                 return r;
-        if (r == 0) {
-                /* Child. */
-
-                if (setns(userns_fd, CLONE_NEWUSER) < 0) {
-                        log_debug_errno(errno, "Failed to join userns: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
-                userns_fd = safe_close(userns_fd);
-
-                n = write(pfd[1], &(const char) { 'x' }, 1);
-                if (n < 0) {
-                        log_debug_errno(errno, "Failed to write to fifo: %m");
-                        _exit(EXIT_FAILURE);
-                }
-                assert(n == 1);
-
-                freeze();
-        }
-
-        pfd[1] = safe_close(pfd[1]);
-
-        n = read(pfd[0], &x, 1);
-        if (n < 0)
-                return -errno;
-        if (n == 0)
-                return -EPROTO;
-        assert(n == 1);
-        assert(x == 'x');
 
         const char *p = procfs_file_alloca(
                         pid,