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 <dongsu@kinvolk.io>
  • Loading branch information
Dongsu Park committed Jun 11, 2018
1 parent dd56ece commit da16461
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 @@ -110,6 +110,15 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
return newSystemErrorWithCause(err, "jailing process inside rootfs")
}

// 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 newSystemErrorWithCause(err, "reopening /dev/null inside container")
Expand Down Expand Up @@ -608,6 +617,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 unix.Mount("", parentMount, "", 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 da16461

Please sign in to comment.