]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace-util: group userns functions together
authorMike Yuan <me@yhndnzj.com>
Sat, 11 Jan 2025 14:42:15 +0000 (15:42 +0100)
committerMike Yuan <me@yhndnzj.com>
Sat, 11 Jan 2025 14:53:14 +0000 (15:53 +0100)
src/basic/namespace-util.c
src/basic/namespace-util.h

index c7b1bcca2d32ae26ac08952d43721f404256fe0e..2ae5003459b7d7ce3b4c9f300cc7e19e27377540 100644 (file)
@@ -459,6 +459,44 @@ int detach_mount_namespace_userns(int userns_fd) {
         return detach_mount_namespace();
 }
 
+int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_range) {
+        _cleanup_free_ char *buffer = NULL;
+        const char *range, *shift;
+        int r;
+        uid_t uid_shift, uid_range = 65536;
+
+        assert(s);
+
+        range = strchr(s, ':');
+        if (range) {
+                buffer = strndup(s, range - s);
+                if (!buffer)
+                        return log_oom();
+                shift = buffer;
+
+                range++;
+                r = safe_atou32(range, &uid_range);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse UID range \"%s\": %m", range);
+        } else
+                shift = s;
+
+        r = parse_uid(shift, &uid_shift);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse UID \"%s\": %m", s);
+
+        if (!userns_shift_range_valid(uid_shift, uid_range))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "UID range cannot be empty or go beyond " UID_FMT ".", UID_INVALID);
+
+        if (ret_uid_shift)
+                *ret_uid_shift = uid_shift;
+
+        if (ret_uid_range)
+                *ret_uid_range = uid_range;
+
+        return 0;
+}
+
 int userns_acquire_empty(void) {
         _cleanup_(sigkill_waitp) pid_t pid = 0;
         _cleanup_close_ int userns_fd = -EBADF;
@@ -520,124 +558,6 @@ int userns_acquire(const char *uid_map, const char *gid_map) {
         return TAKE_FD(userns_fd);
 }
 
-int netns_acquire(void) {
-        _cleanup_(sigkill_waitp) pid_t pid = 0;
-        _cleanup_close_ int netns_fd = -EBADF;
-        int r;
-
-        /* Forks off a process in a new network namespace, acquires a network namespace fd, and then kills
-         * the process again. This way we have a netns fd that is not bound to any process. */
-
-        r = safe_fork("(sd-mknetns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_NETNS, &pid);
-        if (r < 0)
-                return log_debug_errno(r, "Failed to fork process (sd-mknetns): %m");
-        if (r == 0)
-                /* Child. We do nothing here, just freeze until somebody kills us. */
-                freeze();
-
-        r = namespace_open(pid,
-                           /* ret_pidns_fd = */ NULL,
-                           /* ret_mntns_fd = */ NULL,
-                           &netns_fd,
-                           /* ret_userns_fd = */ NULL,
-                           /* ret_root_fd = */ NULL);
-        if (r < 0)
-                return log_debug_errno(r, "Failed to open netns fd: %m");
-
-        return TAKE_FD(netns_fd);
-}
-
-int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_range) {
-        _cleanup_free_ char *buffer = NULL;
-        const char *range, *shift;
-        int r;
-        uid_t uid_shift, uid_range = 65536;
-
-        assert(s);
-
-        range = strchr(s, ':');
-        if (range) {
-                buffer = strndup(s, range - s);
-                if (!buffer)
-                        return log_oom();
-                shift = buffer;
-
-                range++;
-                r = safe_atou32(range, &uid_range);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse UID range \"%s\": %m", range);
-        } else
-                shift = s;
-
-        r = parse_uid(shift, &uid_shift);
-        if (r < 0)
-                return log_error_errno(r, "Failed to parse UID \"%s\": %m", s);
-
-        if (!userns_shift_range_valid(uid_shift, uid_range))
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "UID range cannot be empty or go beyond " UID_FMT ".", UID_INVALID);
-
-        if (ret_uid_shift)
-                *ret_uid_shift = uid_shift;
-
-        if (ret_uid_range)
-                *ret_uid_range = uid_range;
-
-        return 0;
-}
-
-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);
-
-        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);
-        if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
-                return false;
-        if (r == -ENOSPC) {
-                log_debug_errno(r, "Failed to acquire new user namespace, user.max_user_namespaces seems to be exhausted or maybe even zero, assuming ID-mapping is not supported: %m");
-                return false;
-        }
-        if (r < 0)
-                return log_debug_errno(r, "Failed to acquire new user namespace for checking if '%s' supports ID-mapping: %m", path);
-
-        dir_fd = r = RET_NERRNO(open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
-        if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
-                return false;
-        if (r < 0)
-                return log_debug_errno(r, "Failed to open '%s', cannot determine if ID-mapping is supported: %m", path);
-
-        mount_fd = r = RET_NERRNO(open_tree(dir_fd, "", AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC));
-        if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
-                return false;
-        if (r < 0)
-                return log_debug_errno(r, "Failed to open mount tree '%s', cannot determine if ID-mapping is supported: %m", path);
-
-        r = RET_NERRNO(mount_setattr(mount_fd, "", AT_EMPTY_PATH,
-                       &(struct mount_attr) {
-                                .attr_set = MOUNT_ATTR_IDMAP | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NOEXEC | MOUNT_ATTR_RDONLY | MOUNT_ATTR_NODEV,
-                                .userns_fd = userns_fd,
-                        }, sizeof(struct mount_attr)));
-        if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
-                return false;
-        if (r < 0)
-                return log_debug_errno(r, "Failed to set mount attribute to '%s', cannot determine if ID-mapping is supported: %m", path);
-
-        return true;
-}
-
 int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
         _cleanup_(close_pairp) int pfd[2] = EBADF_PAIR;
         _cleanup_(sigkill_waitp) pid_t pid = 0;
@@ -763,3 +683,84 @@ int process_is_owned_by_uid(const PidRef *pidref, uid_t uid) {
                 close_and_replace(userns_fd, parent_fd);
         }
 }
+
+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);
+
+        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);
+        if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
+                return false;
+        if (r == -ENOSPC) {
+                log_debug_errno(r, "Failed to acquire new user namespace, user.max_user_namespaces seems to be exhausted or maybe even zero, assuming ID-mapping is not supported: %m");
+                return false;
+        }
+        if (r < 0)
+                return log_debug_errno(r, "Failed to acquire new user namespace for checking if '%s' supports ID-mapping: %m", path);
+
+        dir_fd = r = RET_NERRNO(open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+        if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
+                return false;
+        if (r < 0)
+                return log_debug_errno(r, "Failed to open '%s', cannot determine if ID-mapping is supported: %m", path);
+
+        mount_fd = r = RET_NERRNO(open_tree(dir_fd, "", AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC));
+        if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
+                return false;
+        if (r < 0)
+                return log_debug_errno(r, "Failed to open mount tree '%s', cannot determine if ID-mapping is supported: %m", path);
+
+        r = RET_NERRNO(mount_setattr(mount_fd, "", AT_EMPTY_PATH,
+                       &(struct mount_attr) {
+                                .attr_set = MOUNT_ATTR_IDMAP | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NOEXEC | MOUNT_ATTR_RDONLY | MOUNT_ATTR_NODEV,
+                                .userns_fd = userns_fd,
+                        }, sizeof(struct mount_attr)));
+        if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
+                return false;
+        if (r < 0)
+                return log_debug_errno(r, "Failed to set mount attribute to '%s', cannot determine if ID-mapping is supported: %m", path);
+
+        return true;
+}
+
+int netns_acquire(void) {
+        _cleanup_(sigkill_waitp) pid_t pid = 0;
+        _cleanup_close_ int netns_fd = -EBADF;
+        int r;
+
+        /* Forks off a process in a new network namespace, acquires a network namespace fd, and then kills
+         * the process again. This way we have a netns fd that is not bound to any process. */
+
+        r = safe_fork("(sd-mknetns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_NETNS, &pid);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to fork process (sd-mknetns): %m");
+        if (r == 0)
+                /* Child. We do nothing here, just freeze until somebody kills us. */
+                freeze();
+
+        r = namespace_open(pid,
+                           /* ret_pidns_fd = */ NULL,
+                           /* ret_mntns_fd = */ NULL,
+                           &netns_fd,
+                           /* ret_userns_fd = */ NULL,
+                           /* ret_root_fd = */ NULL);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to open netns fd: %m");
+
+        return TAKE_FD(netns_fd);
+}
+
index d1ac4f6ed408e5e42237351f0f3c3147fb94309c..58347cbf885a0766a5b98007be0388e9f548bd9f 100644 (file)
@@ -83,15 +83,15 @@ static inline bool userns_shift_range_valid(uid_t shift, uid_t range) {
         return true;
 }
 
+int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_range);
+
 int userns_acquire_empty(void);
 int userns_acquire(const char *uid_map, const char *gid_map);
 
-int netns_acquire(void);
+int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
 
-int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_range);
+int process_is_owned_by_uid(const PidRef *pidref, uid_t uid);
 
 int is_idmapping_supported(const char *path);
 
-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);
+int netns_acquire(void);