Skip to content

Commit

Permalink
libcontainer: fix a bug when setting shared rootfs propagation mode
Browse files Browse the repository at this point in the history
So far when the input mount flags contain `MS_SHARED`, the flag has
not been applied to the container rootfs. That's because we call
`rootfsParentMountPrivate()` after applying the original mount flags.
As a result, the original flags are overwritten. Though it's also true
that we actually need to mount the container rootfs with `MS_PRIVATE`,
to avoid failure from `pivot_root()` in the Linux kernel.

Thus if the mount flags contain `MS_SHARED`, we need a special case
handling. First do `pivotRoot()` (or `msMoveRoot`, `chroot`) with the
rootfs with a mount flag `MS_PRIVATE`. Then after `pivotRoot()`, again
mount the rootfs with `MS_SHARED`.

With this fix, `validation/linux_rootfs_propagation.t` of runtime-tools
works well with the shared mode finally.

Fixes #1755

Signed-off-by: Dongsu Park <dpark@linux.microsoft.com>
  • Loading branch information
dongsupark committed Jul 28, 2023
1 parent a5777e8 commit 4ba925f
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions libcontainer/rootfs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig, mountFds mountFds) (
return fmt.Errorf("error jailing process inside rootfs: %w", err)
}

// mount with MS_SHARED flag does not work well with pivotRoot, because
// of the checks in the Linux kernel. So we need to first pivotRoot with
// a private rootfs, and after that make it shared.
if config.RootPropagation&unix.MS_SHARED != 0 {
if err := rootfsParentMountShared(config.Rootfs); err != nil {
return err
}
}

if setupDev {
if err := reOpenDevNull(); err != nil {
return fmt.Errorf("error reopening /dev/null inside container: %w", err)
Expand Down Expand Up @@ -834,6 +843,31 @@ func rootfsParentMountPrivate(rootfs string) error {
return nil
}

// Make parent mount shared if it was not shared
func rootfsParentMountShared(rootfs string) error {
sharedMount := false

parentMount, optionalOpts, err := getParentMount(rootfs)
if err != nil {
return err
}

optsSplit := strings.Split(optionalOpts, " ")
for _, opt := range optsSplit {
if strings.HasPrefix(opt, "shared:") {
sharedMount = true
break
}
}

// Make parent mount SHARED if it was not shared.
if !sharedMount {
return mount("", parentMount, "", uintptr(unix.MS_SHARED), "")
}

return nil
}

func prepareRoot(config *configs.Config) error {
flag := unix.MS_SLAVE | unix.MS_REC
if config.RootPropagation != 0 {
Expand Down

0 comments on commit 4ba925f

Please sign in to comment.