From: Lennart Poettering Date: Mon, 10 Mar 2025 10:30:11 +0000 (+0100) Subject: namespace-util: introduce userns_acquire_self_root() X-Git-Tag: v258-rc1~1062^2~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=783b40bd73aafa5993a64f7a795f2f91def3c487;p=thirdparty%2Fsystemd.git namespace-util: introduce userns_acquire_self_root() 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). --- diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index b24901c0820..a026ae7d059 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -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) { diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index 74fd8a96d48..0c227e5adf0 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -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);