]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace-util: introduce userns_acquire_self_root()
authorLennart Poettering <lennart@poettering.net>
Mon, 10 Mar 2025 10:30:11 +0000 (11:30 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 17 Mar 2025 15:03:18 +0000 (16:03 +0100)
This is a simple helper for creating a userns that just maps the
callers user to UID 0 in the namespace. This can be acquired unpriv,
which makes it useful for various purposes, for example for the logic in
is_idmapping_supported(), hence port it over.

(is_idmapping_supported() used a different mapping before, with the
nobody users, but there's no real reason for that, and we'll use
userns_acquire_self_root() elsewhere soon, where the root mapping is
important).

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

index b24901c0820fc9c7af0a70e93268873272bd0d1b..a026ae7d05977a4b9d812e66ea253904ca320f90 100644 (file)
@@ -561,6 +561,21 @@ int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny
         return pidref_namespace_open_by_type(&pid, NAMESPACE_USER);
 }
 
+int userns_acquire_self_root(void) {
+
+        /* Returns a user namespace with only our own uid/gid mapped to root, and everything else unmapped.
+         *
+         * Note: this can be acquired unprivileged! */
+
+        _cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
+        if (asprintf(&uid_map, "0 " UID_FMT " 1", getuid()) < 0)
+                return -ENOMEM;
+        if (asprintf(&gid_map, "0 " GID_FMT " 1", getgid()) < 0)
+                return -ENOMEM;
+
+        return userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
+}
+
 int userns_enter_and_pin(int userns_fd, pid_t *ret_pid) {
         _cleanup_close_pair_ int pfd[2] = EBADF_PAIR;
         _cleanup_(sigkill_waitp) pid_t pid = 0;
@@ -704,7 +719,6 @@ int process_is_owned_by_uid(const PidRef *pidref, uid_t uid) {
 
 int is_idmapping_supported(const char *path) {
         _cleanup_close_ int mount_fd = -EBADF, userns_fd = -EBADF, dir_fd = -EBADF;
-        _cleanup_free_ char *uid_map = NULL, *gid_map = NULL;
         int r;
 
         assert(path);
@@ -712,15 +726,7 @@ int is_idmapping_supported(const char *path) {
         if (!mount_new_api_supported())
                 return false;
 
-        r = strextendf(&uid_map, UID_FMT " " UID_FMT " " UID_FMT "\n", UID_NOBODY, UID_NOBODY, 1u);
-        if (r < 0)
-                return r;
-
-        r = strextendf(&gid_map, GID_FMT " " GID_FMT " " GID_FMT "\n", GID_NOBODY, GID_NOBODY, 1u);
-        if (r < 0)
-                return r;
-
-        userns_fd = r = userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true);
+        userns_fd = r = userns_acquire_self_root();
         if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
                 return false;
         if (r == -ENOSPC) {
index 74fd8a96d4889381bb7019006295a86db85a7f90..0c227e5adf0182731f0f6176f4ee6c07780d42bc 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, bool setgroups_deny);
+int userns_acquire_self_root(void);
 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);