]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/namespace: clean up append_private_tmp() a bit 39790/head
authorMike Yuan <me@yhndnzj.com>
Tue, 24 Feb 2026 18:40:14 +0000 (19:40 +0100)
committerMike Yuan <me@yhndnzj.com>
Wed, 25 Feb 2026 11:38:12 +0000 (12:38 +0100)
With the previous changes the modes for /tmp/ and /var/tmp/
may come in arbitrary directions, i.e. we may downgrade one
and upgrade another. Hence let's refactor the setup logic
a bit so they're truly independent.

src/core/namespace.c

index 54504564aba9959a56cf6476530b59c466ba3597..9727d725eb7dfe4cb5c021460fba7ae6f231fd16 100644 (file)
@@ -751,59 +751,71 @@ static int append_tmpfs_mounts(MountList *ml, const TemporaryFileSystem *tmpfs,
         return 0;
 }
 
-static int append_private_tmp(MountList *ml, const NamespaceParameters *p) {
-        MountEntry *me;
+static int append_private_tmp_one(
+                MountList *ml,
+                PrivateTmp mode,
+                const char *path,
+                const char *connected_source) {
 
         assert(ml);
-        assert(p);
-        assert(p->private_tmp >= 0 && p->private_tmp < _PRIVATE_TMP_MAX);
-        assert(p->private_var_tmp >= 0 && p->private_var_tmp < _PRIVATE_TMP_MAX);
+        assert(mode >= 0 && mode < _PRIVATE_TMP_MAX);
+        assert(path);
 
-        if (p->tmp_dir) {
-                assert(p->private_tmp == PRIVATE_TMP_CONNECTED);
+        if (mode == PRIVATE_TMP_NO)
+                return 0;
 
-                me = mount_list_extend(ml);
-                if (!me)
-                        return log_oom_debug();
-                *me = (MountEntry) {
-                        .path_const = "/tmp/",
-                        .mode = MOUNT_PRIVATE_TMP,
-                        .read_only = streq(p->tmp_dir, RUN_SYSTEMD_EMPTY),
-                        .source_const = p->tmp_dir,
-                };
-        }
+        if (mode == PRIVATE_TMP_CONNECTED && !connected_source)
+                /* Do nothing if the private tmp dir was suppressed as it would be made inaccessible anyways
+                 * (see exec_shared_runtime_make()). */
+                return 0;
 
-        if (p->var_tmp_dir) {
-                assert(p->private_var_tmp == PRIVATE_TMP_CONNECTED);
+        MountEntry *me = mount_list_extend(ml);
+        if (!me)
+                return log_oom_debug();
 
-                me = mount_list_extend(ml);
-                if (!me)
-                        return log_oom_debug();
+        if (mode == PRIVATE_TMP_CONNECTED)
                 *me = (MountEntry) {
-                        .path_const = "/var/tmp/",
+                        .path_const = path,
                         .mode = MOUNT_PRIVATE_TMP,
-                        .read_only = streq(p->var_tmp_dir, RUN_SYSTEMD_EMPTY),
-                        .source_const = p->var_tmp_dir,
+                        .read_only = streq(connected_source, RUN_SYSTEMD_EMPTY),
+                        .source_const = connected_source,
                 };
-        }
-
-        if (p->private_tmp != PRIVATE_TMP_DISCONNECTED)
-                return 0;
-
-        if (p->private_var_tmp == PRIVATE_TMP_NO) {
-                me = mount_list_extend(ml);
-                if (!me)
-                        return log_oom_debug();
+        else
                 *me = (MountEntry) {
-                        .path_const = "/tmp/",
+                        .path_const = path,
                         .mode = MOUNT_PRIVATE_TMPFS,
                         .options_const = "mode=0700" NESTED_TMPFS_LIMITS,
                         .flags = MS_NODEV|MS_STRICTATIME,
                 };
 
+        return 0;
+}
+
+static int append_private_tmp(MountList *ml, const NamespaceParameters *p) {
+        int r;
+
+        assert(ml);
+        assert(p);
+        assert(p->private_tmp >= 0 && p->private_tmp < _PRIVATE_TMP_MAX);
+        assert(p->private_var_tmp >= 0 && p->private_var_tmp < _PRIVATE_TMP_MAX);
+
+        if (p->private_tmp != PRIVATE_TMP_DISCONNECTED || p->private_var_tmp != PRIVATE_TMP_DISCONNECTED) {
+                r = append_private_tmp_one(ml, p->private_tmp, "/tmp/", p->tmp_dir);
+                if (r < 0)
+                        return r;
+
+                r = append_private_tmp_one(ml, p->private_var_tmp, "/var/tmp/", p->var_tmp_dir);
+                if (r < 0)
+                        return r;
+
                 return 0;
         }
 
+        /* Fully disconnected private tmp: we mount a single tmpfs instance with two subdirs which are
+         * bind mounted to /tmp/ and /var/tmp/. */
+
+        MountEntry *me;
+
         _cleanup_free_ char *tmpfs_dir = NULL, *tmp_dir = NULL, *var_tmp_dir = NULL;
         tmpfs_dir = path_join(p->private_namespace_dir, "unit-private-tmp");
         tmp_dir = path_join(tmpfs_dir, "tmp");