summaryrefslogtreecommitdiff
path: root/vendor/github.com/projectatomic/buildah/bind
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2018-09-18 15:31:54 -0400
committerDaniel J Walsh <dwalsh@redhat.com>2018-09-18 17:20:30 -0400
commit92b28a88d8bcd5aa50352ecaff844229df1cee59 (patch)
treeb340ddc09d29ae2cf29cb83269bcb614d94a6a10 /vendor/github.com/projectatomic/buildah/bind
parentc3a0874222784e8996dbc472b9ca893a80aff451 (diff)
downloadpodman-92b28a88d8bcd5aa50352ecaff844229df1cee59.tar.gz
podman-92b28a88d8bcd5aa50352ecaff844229df1cee59.tar.bz2
podman-92b28a88d8bcd5aa50352ecaff844229df1cee59.zip
Vendor in latest containers/buildah
Switch from projectatomic/buildah to containers/buildah Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'vendor/github.com/projectatomic/buildah/bind')
-rw-r--r--vendor/github.com/projectatomic/buildah/bind/mount.go295
-rw-r--r--vendor/github.com/projectatomic/buildah/bind/mount_unsupported.go13
-rw-r--r--vendor/github.com/projectatomic/buildah/bind/util.go39
3 files changed, 0 insertions, 347 deletions
diff --git a/vendor/github.com/projectatomic/buildah/bind/mount.go b/vendor/github.com/projectatomic/buildah/bind/mount.go
deleted file mode 100644
index 695bde554..000000000
--- a/vendor/github.com/projectatomic/buildah/bind/mount.go
+++ /dev/null
@@ -1,295 +0,0 @@
-// +build linux
-
-package bind
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "syscall"
-
- "github.com/containers/storage/pkg/idtools"
- "github.com/containers/storage/pkg/mount"
- "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "github.com/projectatomic/buildah/util"
- "github.com/sirupsen/logrus"
- "golang.org/x/sys/unix"
-)
-
-// SetupIntermediateMountNamespace creates a new mount namespace and bind
-// mounts all bind-mount sources into a subdirectory of bundlePath that can
-// only be reached by the root user of the container's user namespace, except
-// for Mounts which include the NoBindOption option in their options list. The
-// NoBindOption will then merely be removed.
-func SetupIntermediateMountNamespace(spec *specs.Spec, bundlePath string) (unmountAll func() error, err error) {
- defer stripNoBindOption(spec)
-
- // We expect a root directory to be defined.
- if spec.Root == nil {
- return nil, errors.Errorf("configuration has no root filesystem?")
- }
- rootPath := spec.Root.Path
-
- // Create a new mount namespace in which to do the things we're doing.
- if err := unix.Unshare(unix.CLONE_NEWNS); err != nil {
- return nil, errors.Wrapf(err, "error creating new mount namespace for %v", spec.Process.Args)
- }
-
- // Make all of our mounts private to our namespace.
- if err := mount.MakeRPrivate("/"); err != nil {
- return nil, errors.Wrapf(err, "error making mounts private to mount namespace for %v", spec.Process.Args)
- }
-
- // Make sure the bundle directory is searchable. We created it with
- // TempDir(), so it should have started with permissions set to 0700.
- info, err := os.Stat(bundlePath)
- if err != nil {
- return nil, errors.Wrapf(err, "error checking permissions on %q", bundlePath)
- }
- if err = os.Chmod(bundlePath, info.Mode()|0111); err != nil {
- return nil, errors.Wrapf(err, "error loosening permissions on %q", bundlePath)
- }
-
- // Figure out who needs to be able to reach these bind mounts in order
- // for the container to be started.
- rootUID, rootGID, err := util.GetHostRootIDs(spec)
- if err != nil {
- return nil, err
- }
-
- // Hand back a callback that the caller can use to clean up everything
- // we're doing here.
- unmount := []string{}
- unmountAll = func() (err error) {
- for _, mountpoint := range unmount {
- // Unmount it and anything under it.
- if err2 := UnmountMountpoints(mountpoint, nil); err2 != nil {
- logrus.Warnf("pkg/bind: error unmounting %q: %v", mountpoint, err2)
- if err == nil {
- err = err2
- }
- }
- if err2 := unix.Unmount(mountpoint, unix.MNT_DETACH); err2 != nil {
- if errno, ok := err2.(syscall.Errno); !ok || errno != syscall.EINVAL {
- logrus.Warnf("pkg/bind: error detaching %q: %v", mountpoint, err2)
- if err == nil {
- err = err2
- }
- }
- }
- // Remove just the mountpoint.
- retry := 10
- remove := unix.Unlink
- err2 := remove(mountpoint)
- for err2 != nil && retry > 0 {
- if errno, ok := err2.(syscall.Errno); ok {
- switch errno {
- default:
- retry = 0
- continue
- case syscall.EISDIR:
- remove = unix.Rmdir
- err2 = remove(mountpoint)
- case syscall.EBUSY:
- if err3 := unix.Unmount(mountpoint, unix.MNT_DETACH); err3 == nil {
- err2 = remove(mountpoint)
- }
- }
- retry--
- }
- }
- if err2 != nil {
- logrus.Warnf("pkg/bind: error removing %q: %v", mountpoint, err2)
- if err == nil {
- err = err2
- }
- }
- }
- return err
- }
-
- // Create a top-level directory that the "root" user will be able to
- // access, that "root" from containers which use different mappings, or
- // other unprivileged users outside of containers, shouldn't be able to
- // access.
- mnt := filepath.Join(bundlePath, "mnt")
- if err = idtools.MkdirAndChown(mnt, 0100, idtools.IDPair{UID: int(rootUID), GID: int(rootGID)}); err != nil {
- return unmountAll, errors.Wrapf(err, "error creating %q owned by the container's root user", mnt)
- }
-
- // Make that directory private, and add it to the list of locations we
- // unmount at cleanup time.
- if err = mount.MakeRPrivate(mnt); err != nil {
- return unmountAll, errors.Wrapf(err, "error marking filesystem at %q as private", mnt)
- }
- unmount = append([]string{mnt}, unmount...)
-
- // Create a bind mount for the root filesystem and add it to the list.
- rootfs := filepath.Join(mnt, "rootfs")
- if err = os.Mkdir(rootfs, 0000); err != nil {
- return unmountAll, errors.Wrapf(err, "error creating directory %q", rootfs)
- }
- if err = unix.Mount(rootPath, rootfs, "", unix.MS_BIND|unix.MS_REC|unix.MS_PRIVATE, ""); err != nil {
- return unmountAll, errors.Wrapf(err, "error bind mounting root filesystem from %q to %q", rootPath, rootfs)
- }
- logrus.Debugf("bind mounted %q to %q", rootPath, rootfs)
- unmount = append([]string{rootfs}, unmount...)
- spec.Root.Path = rootfs
-
- // Do the same for everything we're binding in.
- mounts := make([]specs.Mount, 0, len(spec.Mounts))
- for i := range spec.Mounts {
- // If we're not using an intermediate, leave it in the list.
- if leaveBindMountAlone(spec.Mounts[i]) {
- mounts = append(mounts, spec.Mounts[i])
- continue
- }
- // Check if the source is a directory or something else.
- info, err := os.Stat(spec.Mounts[i].Source)
- if err != nil {
- if os.IsNotExist(err) {
- logrus.Warnf("couldn't find %q on host to bind mount into container", spec.Mounts[i].Source)
- continue
- }
- return unmountAll, errors.Wrapf(err, "error checking if %q is a directory", spec.Mounts[i].Source)
- }
- stage := filepath.Join(mnt, fmt.Sprintf("buildah-bind-target-%d", i))
- if info.IsDir() {
- // If the source is a directory, make one to use as the
- // mount target.
- if err = os.Mkdir(stage, 0000); err != nil {
- return unmountAll, errors.Wrapf(err, "error creating directory %q", stage)
- }
- } else {
- // If the source is not a directory, create an empty
- // file to use as the mount target.
- file, err := os.OpenFile(stage, os.O_WRONLY|os.O_CREATE, 0000)
- if err != nil {
- return unmountAll, errors.Wrapf(err, "error creating file %q", stage)
- }
- file.Close()
- }
- // Bind mount the source from wherever it is to a place where
- // we know the runtime helper will be able to get to it...
- if err = unix.Mount(spec.Mounts[i].Source, stage, "", unix.MS_BIND|unix.MS_REC|unix.MS_PRIVATE, ""); err != nil {
- return unmountAll, errors.Wrapf(err, "error bind mounting bind object from %q to %q", spec.Mounts[i].Source, stage)
- }
- logrus.Debugf("bind mounted %q to %q", spec.Mounts[i].Source, stage)
- spec.Mounts[i].Source = stage
- // ... and update the source location that we'll pass to the
- // runtime to our intermediate location.
- mounts = append(mounts, spec.Mounts[i])
- unmount = append([]string{stage}, unmount...)
- }
- spec.Mounts = mounts
-
- return unmountAll, nil
-}
-
-// Decide if the mount should not be redirected to an intermediate location first.
-func leaveBindMountAlone(mount specs.Mount) bool {
- // If we know we shouldn't do a redirection for this mount, skip it.
- if util.StringInSlice(NoBindOption, mount.Options) {
- return true
- }
- // If we're not bind mounting it in, we don't need to do anything for it.
- if mount.Type != "bind" && !util.StringInSlice("bind", mount.Options) && !util.StringInSlice("rbind", mount.Options) {
- return true
- }
- return false
-}
-
-// UnmountMountpoints unmounts the given mountpoints and anything that's hanging
-// off of them, rather aggressively. If a mountpoint also appears in the
-// mountpointsToRemove slice, the mountpoints are removed after they are
-// unmounted.
-func UnmountMountpoints(mountpoint string, mountpointsToRemove []string) error {
- mounts, err := mount.GetMounts()
- if err != nil {
- return errors.Wrapf(err, "error retrieving list of mounts")
- }
- // getChildren returns the list of mount IDs that hang off of the
- // specified ID.
- getChildren := func(id int) []int {
- var list []int
- for _, info := range mounts {
- if info.Parent == id {
- list = append(list, info.ID)
- }
- }
- return list
- }
- // getTree returns the list of mount IDs that hang off of the specified
- // ID, and off of those mount IDs, etc.
- getTree := func(id int) []int {
- mounts := []int{id}
- i := 0
- for i < len(mounts) {
- children := getChildren(mounts[i])
- mounts = append(mounts, children...)
- i++
- }
- return mounts
- }
- // getMountByID looks up the mount info with the specified ID
- getMountByID := func(id int) *mount.Info {
- for i := range mounts {
- if mounts[i].ID == id {
- return mounts[i]
- }
- }
- return nil
- }
- // getMountByPoint looks up the mount info with the specified mountpoint
- getMountByPoint := func(mountpoint string) *mount.Info {
- for i := range mounts {
- if mounts[i].Mountpoint == mountpoint {
- return mounts[i]
- }
- }
- return nil
- }
- // find the top of the tree we're unmounting
- top := getMountByPoint(mountpoint)
- if top == nil {
- return errors.Wrapf(err, "%q is not mounted", mountpoint)
- }
- // add all of the mounts that are hanging off of it
- tree := getTree(top.ID)
- // unmount each mountpoint, working from the end of the list (leaf nodes) to the top
- for i := range tree {
- var st unix.Stat_t
- id := tree[len(tree)-i-1]
- mount := getMountByID(id)
- // check if this mountpoint is mounted
- if err := unix.Lstat(mount.Mountpoint, &st); err != nil {
- return errors.Wrapf(err, "error checking if %q is mounted", mount.Mountpoint)
- }
- if mount.Major != int(unix.Major(st.Dev)) || mount.Minor != int(unix.Minor(st.Dev)) {
- logrus.Debugf("%q is apparently not really mounted, skipping", mount.Mountpoint)
- continue
- }
- // do the unmount
- if err := unix.Unmount(mount.Mountpoint, 0); err != nil {
- // if it was busy, detach it
- if errno, ok := err.(syscall.Errno); ok && errno == syscall.EBUSY {
- err = unix.Unmount(mount.Mountpoint, unix.MNT_DETACH)
- }
- if err != nil {
- // if it was invalid (not mounted), hide the error, else return it
- if errno, ok := err.(syscall.Errno); !ok || errno != syscall.EINVAL {
- logrus.Warnf("error unmounting %q: %v", mount.Mountpoint, err)
- continue
- }
- }
- }
- // if we're also supposed to remove this thing, do that, too
- if util.StringInSlice(mount.Mountpoint, mountpointsToRemove) {
- if err := os.Remove(mount.Mountpoint); err != nil {
- return errors.Wrapf(err, "error removing %q", mount.Mountpoint)
- }
- }
- }
- return nil
-}
diff --git a/vendor/github.com/projectatomic/buildah/bind/mount_unsupported.go b/vendor/github.com/projectatomic/buildah/bind/mount_unsupported.go
deleted file mode 100644
index 88ca2ca8b..000000000
--- a/vendor/github.com/projectatomic/buildah/bind/mount_unsupported.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !linux
-
-package bind
-
-import (
- "github.com/opencontainers/runtime-spec/specs-go"
-)
-
-// SetupIntermediateMountNamespace returns a no-op unmountAll() and no error.
-func SetupIntermediateMountNamespace(spec *specs.Spec, bundlePath string) (unmountAll func() error, err error) {
- stripNoBindOption(spec)
- return func() error { return nil }, nil
-}
diff --git a/vendor/github.com/projectatomic/buildah/bind/util.go b/vendor/github.com/projectatomic/buildah/bind/util.go
deleted file mode 100644
index 4408c53bb..000000000
--- a/vendor/github.com/projectatomic/buildah/bind/util.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package bind
-
-import (
- "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/projectatomic/buildah/util"
-)
-
-const (
- // NoBindOption is an option which, if present in a Mount structure's
- // options list, will cause SetupIntermediateMountNamespace to not
- // redirect it through a bind mount.
- NoBindOption = "nobuildahbind"
-)
-
-func stripNoBindOption(spec *specs.Spec) {
- for i := range spec.Mounts {
- if util.StringInSlice(NoBindOption, spec.Mounts[i].Options) {
- prunedOptions := make([]string, 0, len(spec.Mounts[i].Options))
- for _, option := range spec.Mounts[i].Options {
- if option != NoBindOption {
- prunedOptions = append(prunedOptions, option)
- }
- }
- spec.Mounts[i].Options = prunedOptions
- }
- }
-}
-
-func dedupeStringSlice(slice []string) []string {
- done := make([]string, 0, len(slice))
- m := make(map[string]struct{})
- for _, s := range slice {
- if _, present := m[s]; !present {
- m[s] = struct{}{}
- done = append(done, s)
- }
- }
- return done
-}