]> 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)
committerLuca Boccassi <luca.boccassi@gmail.com>
Sat, 17 May 2025 11:43:20 +0000 (12:43 +0100)
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.

(cherry picked from commit 8b5e3be88eeb1bdba50c87cb24d9e6b31e825f38)

The chunk in test-namespace that used pidref_in_same_namespace() was dropped.

(cherry picked from commit 071e18561043e9fed12171cf795973ef1866d373)

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

index 5b4e43f9210ef90f488950a61edd71611fb34419..6b6053369ec436c706eebdce655335e102459fa8 100644 (file)
@@ -223,6 +223,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
@@ -250,11 +252,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");
 
@@ -263,7 +268,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 2a684ce0960aaf73ad949d10b5bfe4ad184b33dd..5e3f3981f931294b227139a73fe406695ed12f80 100644 (file)
@@ -205,6 +205,29 @@ TEST(protect_kernel_logs) {
         assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS);
 }
 
+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');
+}
+
 static int intro(void) {
         if (!have_namespaces())
                 return log_tests_skipped("Don't have namespace support");