From: Michal Sekletar Date: Fri, 7 Feb 2025 19:18:49 +0000 (+0100) Subject: basic/namespace-util: obtain uid and gid before unsharing user namespace X-Git-Tag: v258-rc1~866 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8b5e3be88eeb1bdba50c87cb24d9e6b31e825f38;p=thirdparty%2Fsystemd.git basic/namespace-util: obtain uid and gid before unsharing user namespace Getting user and group after unsharing user namespace is too late because without any mapping, i.e. just after unshare(), we are mapped to nobody. --- diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index a026ae7d059..e110001716a 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -412,6 +412,8 @@ int detach_mount_namespace(void) { } int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid) { + uid_t from_uid; + gid_t from_gid; int r; /* Tried detach_mount_namespace() first. If that doesn't work due to permissions, opens up an @@ -439,11 +441,14 @@ int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid) { if (r != -EPERM) return r; + from_uid = getuid(); + from_gid = getgid(); + if (unshare(CLONE_NEWUSER) < 0) return log_debug_errno(errno, "Failed to acquire user namespace: %m"); r = write_string_filef("/proc/self/uid_map", 0, - UID_FMT " " UID_FMT " 1\n", target_uid, getuid()); + UID_FMT " " UID_FMT " 1\n", target_uid, from_uid); if (r < 0) return log_debug_errno(r, "Failed to write uid map: %m"); @@ -452,7 +457,7 @@ int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid) { return log_debug_errno(r, "Failed to write setgroups file: %m"); r = write_string_filef("/proc/self/gid_map", 0, - GID_FMT " " GID_FMT " 1\n", target_gid, getgid()); + GID_FMT " " GID_FMT " 1\n", target_gid, from_gid); if (r < 0) return log_debug_errno(r, "Failed to write gid map: %m"); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index 52049efdb88..9d30b08c5e1 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -414,6 +414,32 @@ TEST(namespace_get_leader) { } } +TEST(detach_mount_namespace_harder) { + _cleanup_(pidref_done) PidRef pid = PIDREF_NULL; + _cleanup_close_pair_ int p[2] = EBADF_PAIR; + char x = 0; + int r; + + ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC)); + + ASSERT_OK(r = pidref_safe_fork("(child)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pid)); + if (r == 0) { + p[0] = safe_close(p[0]); + + ASSERT_OK(detach_mount_namespace_harder(0, 0)); + + ASSERT_OK_EQ_ERRNO(write(p[1], &(const char[]) { 'x' }, 1), 1); + freeze(); + } + + p[1] = safe_close(p[1]); + ASSERT_OK_EQ_ERRNO(read(p[0], &x, 1), 1); + ASSERT_EQ(x, 'x'); + + ASSERT_OK_POSITIVE(pidref_in_same_namespace(NULL, &pid, NAMESPACE_USER)); + ASSERT_OK_ZERO(pidref_in_same_namespace(NULL, &pid, NAMESPACE_MOUNT)); +} + static int intro(void) { if (!have_namespaces()) return log_tests_skipped("Don't have namespace support or lacking privileges");