]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/namespace-util: obtain uid and gid before unsharing user namespace
authorMichal Sekletar <msekleta@redhat.com>
Fri, 7 Feb 2025 19:18:49 +0000 (20:18 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 8 Apr 2025 18:06:05 +0000 (03:06 +0900)
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.

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

index a026ae7d05977a4b9d812e66ea253904ca320f90..e110001716a0bef4a828dd4acd51e6376f2e4e1b 100644 (file)
@@ -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");
 
index 52049efdb88f375f84b14a10eb721f826be3dc04..9d30b08c5e140792a32d00d7c66116c1dca82fc0 100644 (file)
@@ -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");