diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index 322cba4cf3..b24901c082 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -524,8 +524,8 @@ int userns_acquire_empty(void) { return pidref_namespace_open_by_type(&pid, NAMESPACE_USER); } -int userns_acquire(const char *uid_map, const char *gid_map) { - char path[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1]; +int userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny) { + char path[STRLEN("/proc//setgroups") + DECIMAL_STR_MAX(pid_t) + 1]; _cleanup_(pidref_done_sigkill_wait) PidRef pid = PIDREF_NULL; int r; @@ -546,6 +546,13 @@ int userns_acquire(const char *uid_map, const char *gid_map) { if (r < 0) return log_debug_errno(r, "Failed to write UID map: %m"); + if (setgroups_deny) { + xsprintf(path, "/proc/" PID_FMT "/setgroups", pid.pid); + r = write_string_file(path, "deny", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_debug_errno(r, "Failed to write setgroups file: %m"); + } + xsprintf(path, "/proc/" PID_FMT "/gid_map", pid.pid); r = write_string_file(path, gid_map, WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) @@ -713,7 +720,7 @@ int is_idmapping_supported(const char *path) { if (r < 0) return r; - userns_fd = r = userns_acquire(uid_map, gid_map); + userns_fd = r = userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true); 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 3d40a515e7..74fd8a96d4 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -86,7 +86,7 @@ static inline bool userns_shift_range_valid(uid_t shift, uid_t range) { 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 userns_acquire(const char *uid_map, const char *gid_map, bool setgroups_deny); 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); diff --git a/src/core/namespace.c b/src/core/namespace.c index e801b6ea60..0943e0818f 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1917,7 +1917,7 @@ static int apply_one_mount( return log_oom(); } - userns_fd = userns_acquire(uid_map, gid_map); + userns_fd = userns_acquire(uid_map, gid_map, /* setgroups_deny= */ true); if (userns_fd < 0) return log_error_errno(userns_fd, "Failed to allocate user namespace: %m"); diff --git a/src/home/homework-mount.c b/src/home/homework-mount.c index 085ba09e81..52115d86be 100644 --- a/src/home/homework-mount.c +++ b/src/home/homework-mount.c @@ -232,7 +232,7 @@ static int make_home_userns(uid_t stored_uid, uid_t exposed_uid) { log_debug("Creating userns with mapping:\n%s", text); - userns_fd = userns_acquire(text, text); /* same uid + gid mapping */ + userns_fd = userns_acquire(text, text, /* setgroups_deny= */ true); /* same uid + gid mapping */ if (userns_fd < 0) return log_error_errno(userns_fd, "Failed to allocate user namespace: %m"); diff --git a/src/mountfsd/mountwork.c b/src/mountfsd/mountwork.c index eaf72893aa..41c1d65391 100644 --- a/src/mountfsd/mountwork.c +++ b/src/mountfsd/mountwork.c @@ -860,7 +860,7 @@ static int vl_method_mount_directory( if (r < 0) return r; - _cleanup_close_ int idmap_userns_fd = userns_acquire(new_uid_map, new_uid_map); + _cleanup_close_ int idmap_userns_fd = userns_acquire(new_uid_map, new_uid_map, /* setgroups_deny= */ true); if (idmap_userns_fd < 0) return log_debug_errno(idmap_userns_fd, "Failed to acquire user namespace for id mapping: %m"); diff --git a/src/nsresourced/test-userns-restrict.c b/src/nsresourced/test-userns-restrict.c index d6df02428e..59ca1cabbb 100644 --- a/src/nsresourced/test-userns-restrict.c +++ b/src/nsresourced/test-userns-restrict.c @@ -78,7 +78,7 @@ static int run(int argc, char *argv[]) { host_tmpfs = make_tmpfs_fsmount(); assert_se(host_tmpfs >= 0); - userns_fd = userns_acquire("0 0 1", "0 0 1"); + userns_fd = userns_acquire("0 0 1", "0 0 1", /* setgroups_deny= */ true); if (userns_fd < 0) return log_error_errno(userns_fd, "Failed to make user namespace: %m"); diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 97ff6d0764..d7471bc78d 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -1442,7 +1442,7 @@ int make_userns(uid_t uid_shift, } /* We always assign the same UID and GID ranges */ - userns_fd = userns_acquire(line, line); + userns_fd = userns_acquire(line, line, /* setgroups_deny= */ true); if (userns_fd < 0) return log_debug_errno(userns_fd, "Failed to acquire new userns: %m"); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index cae65a14b1..52049efdb8 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -258,7 +258,7 @@ TEST(namespace_is_init) { TEST(userns_get_base_uid) { _cleanup_close_ int fd = -EBADF; - fd = userns_acquire("0 1 1", "0 2 1"); + fd = userns_acquire("0 1 1", "0 2 1", /* setgroups_deny= */ true); if (ERRNO_IS_NEG_NOT_SUPPORTED(fd)) return (void) log_tests_skipped("userns is not supported"); if (ERRNO_IS_NEG_PRIVILEGE(fd))