]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
MountAPIVFS: always mount a tmpfs on /run
authorLuca Boccassi <luca.boccassi@microsoft.com>
Fri, 18 Dec 2020 16:16:46 +0000 (16:16 +0000)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Mon, 18 Jan 2021 17:24:05 +0000 (17:24 +0000)
We need a writable /run for most operations, but in case a read-only
RootImage (or similar) is used, by default there's no additional
tmpfs mount on /run. Change this behaviour and document it.

NEWS
man/systemd.exec.xml
src/core/namespace.c

diff --git a/NEWS b/NEWS
index bdac561bc0b58e34be54a1de2409ff9a5d4d920a..c7ee3dbb40e1c21c7970987d0e1f1797be468a91 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,15 @@
 systemd System and Service Manager
 
+CHANGES WITH 248:
+
+        * The MountAPIVFS= service file setting now additionally mounts a tmpfs
+          on /run/ if it is not already a mount point. A writable /run/ has always
+          been a requirement for a functioning system, but this was not
+          guaranteed when using a read-only image.
+          Users can always specify BindPaths= or InaccessiblePaths= as overrides,
+          and they will take precedence. If the host's root mount point is used,
+          there is no change in behaviour.
+
 CHANGES WITH 247:
 
         * KERNEL API INCOMPATIBILITY: Linux 4.14 introduced two new uevents
index 7328f9b96590999a9db26639c4ccf621e5a2296d..568839e0d9e3f77187ff7be25f4da2f9a519483d 100644 (file)
         <term><varname>MountAPIVFS=</varname></term>
 
         <listitem><para>Takes a boolean argument. If on, a private mount namespace for the unit's processes is created
-        and the API file systems <filename>/proc/</filename>, <filename>/sys/</filename>, and <filename>/dev/</filename>
-        are mounted inside of it, unless they are already mounted. Note that this option has no effect unless used in
-        conjunction with <varname>RootDirectory=</varname>/<varname>RootImage=</varname> as these three mounts are
+        and the API file systems <filename>/proc/</filename>, <filename>/sys/</filename>, <filename>/dev/</filename> and
+        <filename>/run/</filename> (as an empty <literal>tmpfs</literal>) are mounted inside of it, unless they are
+        already mounted. Note that this option has no effect unless used in conjunction with
+        <varname>RootDirectory=</varname>/<varname>RootImage=</varname> as these four mounts are
         generally mounted in the host anyway, and unless the root directory is changed, the private mount namespace
-        will be a 1:1 copy of the host's, and include these three mounts. Note that the <filename>/dev/</filename> file
+        will be a 1:1 copy of the host's, and include these four mounts. Note that the <filename>/dev/</filename> file
         system of the host is bind mounted if this option is used without <varname>PrivateDevices=</varname>. To run
         the service with a private, minimal version of <filename>/dev/</filename>, combine this option with
         <varname>PrivateDevices=</varname>.</para>
index e32336a7ff0c44ab9cf0256d6c62ebc0ca5ba3ea..73a8fa73a4dcea19e4c97f2c4eff5f30c22af2ec 100644 (file)
@@ -51,6 +51,7 @@ typedef enum MountMode {
         EMPTY_DIR,
         SYSFS,
         PROCFS,
+        RUN,
         READONLY,
         READWRITE,
         TMPFS,
@@ -76,12 +77,13 @@ typedef struct MountEntry {
         LIST_HEAD(MountOptions, image_options);
 } MountEntry;
 
-/* If MountAPIVFS= is used, let's mount /sys and /proc into the it, but only as a fallback if the user hasn't mounted
+/* If MountAPIVFS= is used, let's mount /sys, /proc, /dev and /run into the it, but only as a fallback if the user hasn't mounted
  * something there already. These mounts are hence overridden by any other explicitly configured mounts. */
 static const MountEntry apivfs_table[] = {
         { "/proc",               PROCFS,       false },
         { "/dev",                BIND_DEV,     false },
         { "/sys",                SYSFS,        false },
+        { "/run",                RUN,          false, .options_const = "mode=755" TMPFS_LIMITS_RUN, .flags = MS_NOSUID|MS_NODEV|MS_STRICTATIME },
 };
 
 /* ProtectKernelTunables= option and the related filesystem APIs */
@@ -945,6 +947,20 @@ static int mount_tmpfs(const MountEntry *m) {
         return 1;
 }
 
+static int mount_run(const MountEntry *m) {
+        int r;
+
+        assert(m);
+
+        r = path_is_mount_point(mount_entry_path(m), NULL, 0);
+        if (r < 0 && r != -ENOENT)
+                return log_debug_errno(r, "Unable to determine whether /run is already mounted: %m");
+        if (r > 0) /* make this a NOP if /run is already a mount point */
+                return 0;
+
+        return mount_tmpfs(m);
+}
+
 static int mount_images(const MountEntry *m) {
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
@@ -1170,6 +1186,9 @@ static int apply_mount(
         case PROCFS:
                 return mount_procfs(m, ns_info);
 
+        case RUN:
+                return mount_run(m);
+
         case MOUNT_IMAGES:
                 return mount_images(m);