diff --git a/virtcontainers/container.go b/virtcontainers/container.go index a5ff44a557..780a4370e2 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -481,7 +481,7 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s } else { // These mounts are created in the shared dir mountDest := filepath.Join(hostSharedDir, c.sandbox.id, filename) - if err := bindMount(c.ctx, m.Source, mountDest, false); err != nil { + if err := bindMount(c.ctx, m.Source, mountDest, false, "private"); err != nil { return "", false, err } // Save HostPath mount value into the mount list of the container. diff --git a/virtcontainers/fc.go b/virtcontainers/fc.go index 653eae1824..3ebb00c839 100644 --- a/virtcontainers/fc.go +++ b/virtcontainers/fc.go @@ -180,46 +180,6 @@ func (fc *firecracker) trace(name string) (opentracing.Span, context.Context) { return span, ctx } -// bindMount bind mounts a source in to a destination. This will -// do some bookkeeping: -// * evaluate all symlinks -// * ensure the source exists -// * recursively create the destination -func (fc *firecracker) bindMount(ctx context.Context, source, destination string, readonly bool) error { - span, _ := trace(ctx, "bindMount") - defer span.Finish() - - if source == "" { - return fmt.Errorf("source must be specified") - } - if destination == "" { - return fmt.Errorf("destination must be specified") - } - - absSource, err := filepath.EvalSymlinks(source) - if err != nil { - return fmt.Errorf("Could not resolve symlink for source %v", source) - } - - if err := ensureDestinationExists(absSource, destination); err != nil { - return fmt.Errorf("Could not create destination mount point %v: %v", destination, err) - } - - fc.Logger().WithFields(logrus.Fields{"src": absSource, "dst": destination}).Debug("Bind mounting resource") - - if err := syscall.Mount(absSource, destination, "bind", syscall.MS_BIND|syscall.MS_SLAVE, ""); err != nil { - return fmt.Errorf("Could not bind mount %v to %v: %v", absSource, destination, err) - } - - // For readonly bind mounts, we need to remount with the readonly flag. - // This is needed as only very recent versions of libmount/util-linux support "bind,ro" - if readonly { - return syscall.Mount(absSource, destination, "bind", uintptr(syscall.MS_BIND|syscall.MS_SLAVE|syscall.MS_REMOUNT|syscall.MS_RDONLY), "") - } - - return nil -} - // For firecracker this call only sets the internal structure up. // The sandbox will be created and started through startSandbox(). func (fc *firecracker) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, stateful bool) error { @@ -543,7 +503,7 @@ func (fc *firecracker) fcJailResource(src, dst string) (string, error) { src, dst) } jailedLocation := filepath.Join(fc.jailerRoot, dst) - if err := fc.bindMount(context.Background(), src, jailedLocation, false); err != nil { + if err := bindMount(context.Background(), src, jailedLocation, false, "slave"); err != nil { fc.Logger().WithField("bindMount failed", err).Error() return "", err } diff --git a/virtcontainers/mount.go b/virtcontainers/mount.go index 9987a9b177..93951ac4fd 100644 --- a/virtcontainers/mount.go +++ b/virtcontainers/mount.go @@ -31,6 +31,13 @@ var rootfsDir = "rootfs" var systemMountPrefixes = []string{"/proc", "/sys"} +var propagationTypes = map[string]uintptr{ + "shared": syscall.MS_SHARED, + "private": syscall.MS_PRIVATE, + "slave": syscall.MS_SLAVE, + "ubind": syscall.MS_UNBINDABLE, +} + func isSystemMount(m string) bool { for _, p := range systemMountPrefixes { if m == p || strings.HasPrefix(m, p+"/") { @@ -260,7 +267,8 @@ const mountPerm = os.FileMode(0755) // * evaluate all symlinks // * ensure the source exists // * recursively create the destination -func bindMount(ctx context.Context, source, destination string, readonly bool) error { +// pgtypes stands for propagation types, which are shared, private, slave, and ubind. +func bindMount(ctx context.Context, source, destination string, readonly bool, pgtypes string) error { span, _ := trace(ctx, "bindMount") defer span.Finish() @@ -284,8 +292,12 @@ func bindMount(ctx context.Context, source, destination string, readonly bool) e return fmt.Errorf("Could not bind mount %v to %v: %v", absSource, destination, err) } - if err := syscall.Mount("none", destination, "", syscall.MS_PRIVATE, ""); err != nil { - return fmt.Errorf("Could not make mount point %v private: %v", destination, err) + if pgtype, exist := propagationTypes[pgtypes]; exist { + if err := syscall.Mount("none", destination, "", pgtype, ""); err != nil { + return fmt.Errorf("Could not make mount point %v %s: %v", destination, pgtypes, err) + } + } else { + return fmt.Errorf("Wrong propagation type %s", pgtypes) } // For readonly bind mounts, we need to remount with the readonly flag. @@ -305,7 +317,7 @@ func bindMountContainerRootfs(ctx context.Context, sharedDir, sandboxID, cID, cR rootfsDest := filepath.Join(sharedDir, sandboxID, cID, rootfsDir) - return bindMount(ctx, cRootFs, rootfsDest, readonly) + return bindMount(ctx, cRootFs, rootfsDest, readonly, "private") } // Mount describes a container mount.