diff options
author | Christian Brauner <brauner@kernel.org> | 2022-12-05 18:34:00 +0100 |
---|---|---|
committer | Christian Brauner (Microsoft) <brauner@kernel.org> | 2022-12-05 18:35:02 +0100 |
commit | e79581ddfefd5d565bb3b497f1e6adae688c8810 (patch) | |
tree | 294bd69bad1256e9446702956861dfe209651656 /src/nspawn/nspawn.c | |
parent | nspawn: mount temporary visible procfs and sysfs instance (diff) | |
download | systemd-e79581ddfefd5d565bb3b497f1e6adae688c8810.tar.xz systemd-e79581ddfefd5d565bb3b497f1e6adae688c8810.zip |
nspawn: split mount tunnel setup
Before we supported pivot_root() nspawn used to make the rootfs shared
before setting up the mount tunnel. So it was safe for it to just turn
it into a dependent mount during setup.
However, we cannot do this anymore because of the requirements
pivot_root() has. After the pivot_root() we will make the rootfs shared
recursively. If we turned the mount tunnel into dependent mount before
mount_switch_root() this will have the consequence that it becomes a
shared mount within the same peer group as the rootfs. So no mounts will
propagate into the container from the host anymore.
To fix this we split setting up the mount tunnel and making it active
into two steps. Setting up the mount tunnel is performed before
mount_switch_root() and activating it afterwards. Note that this works
because turning a shared mount into a shared mount is a nop. IOW, no new
peer group will be allocated.
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Diffstat (limited to '')
-rw-r--r-- | src/nspawn/nspawn.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 392336dfa5..0d025804fa 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -114,6 +114,7 @@ /* The notify socket inside the container it can use to talk to nspawn using the sd_notify(3) protocol */ #define NSPAWN_NOTIFY_SOCKET_PATH "/run/host/notify" +#define NSPAWN_MOUNT_TUNNEL "/run/host/incoming" #define EXIT_FORCE_RESTART 133 @@ -2776,7 +2777,7 @@ static int reset_audit_loginuid(void) { return 0; } -static int setup_propagate(const char *root) { +static int mount_tunnel_dig(const char *root) { const char *p, *q; int r; @@ -2789,11 +2790,11 @@ static int setup_propagate(const char *root) { if (r < 0) return log_error_errno(r, "Failed to create /run/host: %m"); - r = userns_mkdir(root, "/run/host/incoming", 0600, 0, 0); + r = userns_mkdir(root, NSPAWN_MOUNT_TUNNEL, 0600, 0, 0); if (r < 0) - return log_error_errno(r, "Failed to create /run/host/incoming: %m"); + return log_error_errno(r, "Failed to create "NSPAWN_MOUNT_TUNNEL": %m"); - q = prefix_roota(root, "/run/host/incoming"); + q = prefix_roota(root, NSPAWN_MOUNT_TUNNEL); r = mount_nofollow_verbose(LOG_ERR, p, q, NULL, MS_BIND, NULL); if (r < 0) return r; @@ -2802,8 +2803,17 @@ static int setup_propagate(const char *root) { if (r < 0) return r; - /* machined will MS_MOVE into that directory, and that's only supported for non-shared mounts. */ - return mount_nofollow_verbose(LOG_ERR, NULL, q, NULL, MS_SLAVE, NULL); + return 0; +} + +static int mount_tunnel_open(void) { + int r; + + r = mount_follow_verbose(LOG_ERR, NULL, NSPAWN_MOUNT_TUNNEL, NULL, MS_SLAVE, NULL); + if (r < 0) + return r; + + return 0; } static int setup_machine_id(const char *directory) { @@ -3906,7 +3916,7 @@ static int outer_child( if (r < 0) return r; - r = setup_propagate(directory); + r = mount_tunnel_dig(directory); if (r < 0) return r; @@ -3983,6 +3993,13 @@ static int outer_child( if (r < 0) return log_error_errno(r, "Failed to move root directory: %m"); + /* We finished setting up the rootfs which is a shared mount. The mount tunnel needs to be a + * dependent mount otherwise we can't MS_MOVE mounts that were propagated from the host into + * the container. */ + r = mount_tunnel_open(); + if (r < 0) + return r; + if (arg_userns_mode != USER_NAMESPACE_NO) { /* In order to mount procfs and sysfs in an unprivileged container the kernel * requires that a fully visible instance is already present in the target mount |