Skip to content

Commit ec170d8

Browse files
committed
fix(libcontainer): preserve rootfs slave propagation
When rootfsPropagation is set to rslave, prepareRoot() was forcing the rootfs parent mount to MS_PRIVATE before bind-mounting and pivoting into the rootfs. That breaks the slave relationship needed for HostToContainer propagation, so later unmount/remount events on host mountpoints under the rootfs are not reflected inside the running container. Fix this by keeping the rootfs parent mount as MS_SLAVE for slave-like rootfs propagation settings, while leaving the final root propagation remount in place. Signed-off-by: sean <xujihui1985@gmail.com>
1 parent 506a568 commit ec170d8

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

libcontainer/rootfs_linux.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ func prepareRootfs(pipe *syncSocket, iConfig *initConfig) (err error) {
241241
// to the current root ("/"), and not to the old rootfs before it becomes "/". Applying the
242242
// flag in prepareRoot would affect the host mount namespace if the container's
243243
// root mount is shared.
244-
// MS_PRIVATE is skipped as rootfsParentMountPrivate() is already called.
245-
if config.RootPropagation != 0 && config.RootPropagation&unix.MS_PRIVATE == 0 {
244+
// MS_PRIVATE or MS_SLAVE is skipped as rootfsParentMountPropagation() is already called.
245+
if config.RootPropagation != 0 && config.RootPropagation&(unix.MS_PRIVATE|unix.MS_SLAVE) == 0 {
246246
if err := mount("", "/", "", uintptr(config.RootPropagation), ""); err != nil {
247247
return fmt.Errorf("unable to apply root propagation flags: %w", err)
248248
}
@@ -1061,19 +1061,27 @@ func mknodDevice(destDir *os.File, destName string, node *devices.Device) error
10611061
return nil
10621062
}
10631063

1064-
// rootfsParentMountPrivate ensures rootfs parent mount is private.
1064+
func rootfsParentMountPropagationFlags(rootPropagation int) uintptr {
1065+
if rootPropagation&unix.MS_SLAVE != 0 {
1066+
return unix.MS_SLAVE
1067+
}
1068+
return unix.MS_PRIVATE
1069+
}
1070+
1071+
// rootfsParentMountPropagation ensures rootfs parent mount is not shared.
10651072
// This is needed for two reasons:
10661073
// - pivot_root() will fail if parent mount is shared;
1067-
// - when we bind mount rootfs, if its parent is not private, the new mount
1074+
// - when we bind mount rootfs, if its parent is (r)shared, the new mount
10681075
// will propagate (leak!) to parent namespace and we don't want that.
1069-
func rootfsParentMountPrivate(path string) error {
1076+
func rootfsParentMountPropagation(path string, rootPropagation int) error {
10701077
var err error
1078+
flags := rootfsParentMountPropagationFlags(rootPropagation)
10711079
// Assuming path is absolute and clean (this is checked in
10721080
// libcontainer/validate). Any error other than EINVAL means we failed,
10731081
// and EINVAL means this is not a mount point, so traverse up until we
10741082
// find one.
10751083
for {
1076-
err = unix.Mount("", path, "", unix.MS_PRIVATE, "")
1084+
err = unix.Mount("", path, "", flags, "")
10771085
if err == nil {
10781086
return nil
10791087
}
@@ -1083,9 +1091,9 @@ func rootfsParentMountPrivate(path string) error {
10831091
path = filepath.Dir(path)
10841092
}
10851093
return &mountError{
1086-
op: "remount-private",
1094+
op: "remount-propagation",
10871095
target: path,
1088-
flags: unix.MS_PRIVATE,
1096+
flags: flags,
10891097
err: err,
10901098
}
10911099
}
@@ -1099,7 +1107,7 @@ func prepareRoot(config *configs.Config) error {
10991107
return err
11001108
}
11011109

1102-
if err := rootfsParentMountPrivate(config.Rootfs); err != nil {
1110+
if err := rootfsParentMountPropagation(config.Rootfs, config.RootPropagation); err != nil {
11031111
return err
11041112
}
11051113

0 commit comments

Comments
 (0)