]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: Enable specifying root as the mount target directory.
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 6 Dec 2019 21:45:14 +0000 (22:45 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 12 Dec 2019 19:15:03 +0000 (20:15 +0100)
Fixes #3847.

src/nspawn/nspawn-mount.c
src/nspawn/nspawn-mount.h
src/nspawn/nspawn.c

index 6407503c4c9116c9cd1196d8b616fc7f47044d69..8225cf473a56e66a0b4d56e7c4789b4a533cd6b7 100644 (file)
@@ -222,8 +222,6 @@ int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only)
 
         if (!path_is_absolute(destination))
                 return -EINVAL;
-        if (empty_or_root(destination))
-                return -EINVAL;
 
         m = custom_mount_add(l, n, CUSTOM_MOUNT_BIND);
         if (!m)
@@ -262,8 +260,6 @@ int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s) {
 
         if (!path_is_absolute(path))
                 return -EINVAL;
-        if (empty_or_root(path))
-                return -EINVAL;
 
         m = custom_mount_add(l, n, CUSTOM_MOUNT_TMPFS);
         if (!m)
@@ -323,9 +319,6 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl
                         return -EINVAL;
         }
 
-        if (empty_or_root(destination))
-                return -EINVAL;
-
         m = custom_mount_add(l, n, CUSTOM_MOUNT_OVERLAY);
         if (!m)
                 return -ENOMEM;
@@ -923,7 +916,7 @@ int mount_custom(
                 CustomMount *mounts, size_t n,
                 bool userns, uid_t uid_shift, uid_t uid_range,
                 const char *selinux_apifs_context,
-                bool in_userns) {
+                MountSettingsMask mount_settings) {
 
         size_t i;
         int r;
@@ -933,7 +926,13 @@ int mount_custom(
         for (i = 0; i < n; i++) {
                 CustomMount *m = mounts + i;
 
-                if (m->in_userns != in_userns)
+                if ((mount_settings & MOUNT_IN_USERNS) != m->in_userns)
+                        continue;
+
+                if (mount_settings & MOUNT_ROOT_ONLY && !path_equal(m->destination, "/"))
+                        continue;
+
+                if (mount_settings & MOUNT_NON_ROOT_ONLY && path_equal(m->destination, "/"))
                         continue;
 
                 switch (m->type) {
index ff6990c7344c21f997a578f0054af00635f96505..08d3e68f291eb9e6ba7e1e5bbd4738ba9a058633 100644 (file)
@@ -14,6 +14,8 @@ typedef enum MountSettingsMask {
         MOUNT_APPLY_APIVFS_NETNS = 1 << 4, /* if set, /proc/sys/net will be mounted read-write.
                                                Works only if MOUNT_APPLY_APIVFS_RO is also set. */
         MOUNT_APPLY_TMPFS_TMP    = 1 << 5, /* if set, /tmp will be mounted as tmpfs */
+        MOUNT_ROOT_ONLY          = 1 << 6, /* if set, only root mounts are mounted */
+        MOUNT_NON_ROOT_ONLY      = 1 << 7, /* if set, only non-root mounts are mounted */
 } MountSettingsMask;
 
 typedef enum CustomMountType {
@@ -52,7 +54,7 @@ int inaccessible_mount_parse(CustomMount **l, size_t *n, const char *s);
 int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, const char *selinux_apifs_context);
 int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
 
-int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool in_userns);
+int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, MountSettingsMask mount_settings);
 
 int setup_volatile_mode(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
 
index 9fac32621964d3a9e42edcc0d8fa926d5cd19e55..31a9a6d11f55254608499ffab9532206f2cee8b0 100644 (file)
@@ -2979,7 +2979,7 @@ static int inner_child(
                         0,
                         0,
                         arg_selinux_apifs_context,
-                        true);
+                        MOUNT_NON_ROOT_ONLY | MOUNT_IN_USERNS);
         if (r < 0)
                 return r;
 
@@ -3371,6 +3371,18 @@ static int outer_child(
         if (r < 0)
                 return r;
 
+        r = mount_custom(
+                        directory,
+                        arg_custom_mounts,
+                        arg_n_custom_mounts,
+                        arg_userns_mode != USER_NAMESPACE_NO,
+                        arg_uid_shift,
+                        arg_uid_range,
+                        arg_selinux_apifs_context,
+                        MOUNT_ROOT_ONLY);
+        if (r < 0)
+                return r;
+
         if (dissected_image) {
                 /* Now we know the uid shift, let's now mount everything else that might be in the image. */
                 r = dissected_image_mount(dissected_image, directory, arg_uid_shift,
@@ -3401,7 +3413,12 @@ static int outer_child(
          * inside the container that create a new mount namespace.
          * See https://github.com/systemd/systemd/issues/3860
          * Further submounts (such as /dev) done after this will inherit the
-         * shared propagation mode. */
+         * shared propagation mode.
+         *
+         * IMPORTANT: Do not overmount the root directory anymore from now on to
+         * enable moving the root directory mount to root later on.
+         * https://github.com/systemd/systemd/issues/3847#issuecomment-562735251
+         */
         r = mount_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL);
         if (r < 0)
                 return r;
@@ -3474,7 +3491,7 @@ static int outer_child(
                         arg_uid_shift,
                         arg_uid_range,
                         arg_selinux_apifs_context,
-                        false);
+                        MOUNT_NON_ROOT_ONLY);
         if (r < 0)
                 return r;