Fixes #3847.
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)
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)
return -EINVAL;
}
- if (empty_or_root(destination))
- return -EINVAL;
-
m = custom_mount_add(l, n, CUSTOM_MOUNT_OVERLAY);
if (!m)
return -ENOMEM;
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;
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) {
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 {
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);
0,
0,
arg_selinux_apifs_context,
- true);
+ MOUNT_NON_ROOT_ONLY | MOUNT_IN_USERNS);
if (r < 0)
return r;
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,
* 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;
arg_uid_shift,
arg_uid_range,
arg_selinux_apifs_context,
- false);
+ MOUNT_NON_ROOT_ONLY);
if (r < 0)
return r;