From 75f8173247e7e5c50e1121c5330acf6f165a910d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Mar 2023 18:28:37 +0100 Subject: [PATCH 1/2] nspawn: disconnect mounts propagation from host on our container dir @brauner noticed that in invoked containers the root directory is set to still receive mounts from the host. We should disable that, and guarantee we live in our own world, because that's what an (nspawn-style) container *is* after all: a whole new world. This hence mounts the container subtree to MS_PRIVATE after getting the root dir in place. Note that this will later be set to MS_SHARED again. The MS_PRIVATE disconnects mounts from the host, the MS_SHARED then establishes a new peer group for mount propagation events, so that payload service managers (such as systemd) can take benefit of propagation further down the tree. --- src/nspawn/nspawn.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index db9e3b12c7..13d744870d 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3758,6 +3758,19 @@ static int outer_child( directory = "/run/systemd/nspawn-root"; } + /* Make sure we always have a mount that we can move to root later on. */ + r = make_mount_point(directory); + if (r < 0) + return r; + + /* So the whole tree is now MS_SLAVE, i.e. we'll still receive mount/umount events from the host + * mount namespace. For the directory we are going to run our container let's turn this off, so that + * we'll live in our own little world from now on, and propagation from the host may only happen via + * the mount tunnel dir, or not at all. */ + r = mount_follow_verbose(LOG_ERR, NULL, directory, NULL, MS_PRIVATE|MS_REC, NULL); + if (r < 0) + return r; + r = setup_pivot_root( directory, arg_pivot_root_new, @@ -3815,11 +3828,6 @@ static int outer_child( if (r < 0) return r; - /* Make sure we always have a mount that we can move to root later on. */ - r = make_mount_point(directory); - if (r < 0) - return r; - if (arg_userns_mode != USER_NAMESPACE_NO && IN_SET(arg_userns_ownership, USER_NAMESPACE_OWNERSHIP_MAP, USER_NAMESPACE_OWNERSHIP_AUTO) && arg_uid_shift != 0) { From 56339a10db0c701a298f51e0d6cb02901b366ffa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Mar 2023 19:01:39 +0100 Subject: [PATCH 2/2] nspawn: disable propagation for selected host API bind mounts We bind mount two selected inodes from the host into our container. Let's turn off propagation for that, since we just want those inodes, nothing else. With this change "grep master: /proc/self/mountinfo" should list only the mount propagation "tunnel" dir, and nothing else anymore. --- src/nspawn/nspawn-mount.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index ee00362b54..ea54b23e08 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -598,6 +598,8 @@ int mount_all(const char *dest, MOUNT_FATAL }, /* If /etc/os-release doesn't exist use the version in /usr/lib as fallback */ { NULL, "/run/host/os-release", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL }, + { NULL, "/run/host/os-release", NULL, NULL, MS_PRIVATE, + MOUNT_FATAL }, /* Turn off propagation (we only want that for the mount propagation tunnel dir) */ { NULL, "/run/host", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL|MOUNT_IN_USERNS }, #if HAVE_SELINUX @@ -605,6 +607,8 @@ int mount_all(const char *dest, MOUNT_MKDIR }, /* Bind mount first (mkdir/chown the mount point in case /sys/ is mounted as minimal skeleton tmpfs) */ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, 0 }, /* Then, make it r/o (don't mkdir/chown the mount point here, the previous entry already did that) */ + { NULL, "/sys/fs/selinux", NULL, NULL, MS_PRIVATE, + 0 }, /* Turn off propagation (we only want that for the mount propagation tunnel dir) */ #endif };