mount: modify func bindMount

originally, we forcefully set any bind-mount with `private` propagation
type, and it's not applied for all scenarios. e.g. we need to provide
`slave` or `shared` propagation type for bind-mounts in setting up jail
house.
Here, we add another parameter `pgtype` in func bindMount for providing
customized propagation parameters.

Fixes: #2511

Signed-off-by: Penny Zheng <penny.zheng@arm.com>
This commit is contained in:
Penny Zheng 2020-03-13 07:08:27 +00:00
parent e94cf0f135
commit 9d3022a85a
3 changed files with 18 additions and 46 deletions

View File

@ -481,7 +481,7 @@ func (c *Container) shareFiles(m Mount, idx int, hostSharedDir, guestSharedDir s
} else { } else {
// These mounts are created in the shared dir // These mounts are created in the shared dir
mountDest := filepath.Join(hostSharedDir, c.sandbox.id, filename) 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 return "", false, err
} }
// Save HostPath mount value into the mount list of the container. // Save HostPath mount value into the mount list of the container.

View File

@ -180,46 +180,6 @@ func (fc *firecracker) trace(name string) (opentracing.Span, context.Context) {
return span, ctx 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. // For firecracker this call only sets the internal structure up.
// The sandbox will be created and started through startSandbox(). // 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 { 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) src, dst)
} }
jailedLocation := filepath.Join(fc.jailerRoot, 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() fc.Logger().WithField("bindMount failed", err).Error()
return "", err return "", err
} }

View File

@ -31,6 +31,13 @@ var rootfsDir = "rootfs"
var systemMountPrefixes = []string{"/proc", "/sys"} 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 { func isSystemMount(m string) bool {
for _, p := range systemMountPrefixes { for _, p := range systemMountPrefixes {
if m == p || strings.HasPrefix(m, p+"/") { if m == p || strings.HasPrefix(m, p+"/") {
@ -260,7 +267,8 @@ const mountPerm = os.FileMode(0755)
// * evaluate all symlinks // * evaluate all symlinks
// * ensure the source exists // * ensure the source exists
// * recursively create the destination // * 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") span, _ := trace(ctx, "bindMount")
defer span.Finish() 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) 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 { if pgtype, exist := propagationTypes[pgtypes]; exist {
return fmt.Errorf("Could not make mount point %v private: %v", destination, err) 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. // 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) 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. // Mount describes a container mount.