From 6d7d0e7d39efab93c5e21d812feee706e6264296 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 12 Nov 2020 06:17:50 -0500 Subject: [PATCH] Bump github.com/containers/storage from 1.23.5 to 1.23.9 Bumps [github.com/containers/storage](https://github.com/containers/storage) from 1.23.5 to 1.23.9. - [Release notes](https://github.com/containers/storage/releases) - [Changelog](https://github.com/containers/storage/blob/master/docs/containers-storage-changes.md) - [Commits](containers/storage@v1.23.5...v1.23.9) Signed-off-by: dependabot-preview[bot] Signed-off-by: Daniel J Walsh --- go.mod | 2 +- go.sum | 7 + .../github.com/containers/storage/.cirrus.yml | 11 +- .../github.com/containers/storage/.gitignore | 1 + vendor/github.com/containers/storage/VERSION | 2 +- .../containers/storage/drivers/btrfs/btrfs.go | 2 +- .../containers/storage/drivers/chown_unix.go | 12 +- .../storage/drivers/copy/copy_linux.go | 5 +- .../storage/drivers/devmapper/deviceset.go | 96 +++++++------ .../storage/drivers/devmapper/driver.go | 32 ++++- .../storage/drivers/overlay/overlay.go | 37 +++-- .../containers/storage/drivers/zfs/zfs.go | 2 +- vendor/github.com/containers/storage/go.mod | 10 +- vendor/github.com/containers/storage/go.sum | 11 +- .../github.com/containers/storage/layers.go | 5 +- .../containers/storage/pkg/archive/archive.go | 69 ++++----- .../storage/pkg/archive/changes_linux.go | 13 +- .../storage/pkg/devicemapper/devmapper_log.go | 2 +- .../storage/pkg/fileutils/fileutils.go | 2 +- .../storage/pkg/homedir/homedir_linux.go | 96 ------------- .../storage/pkg/homedir/homedir_others.go | 2 +- .../storage/pkg/homedir/homedir_unix.go | 100 +++++++++++-- .../containers/storage/pkg/idtools/idtools.go | 2 +- .../containers/storage/pkg/idtools/parser.go | 14 +- .../containers/storage/pkg/mount/mount.go | 2 +- .../containers/storage/pkg/mount/mountinfo.go | 12 +- .../containers/storage/pkg/system/chmod.go | 17 +++ .../containers/storage/pkg/system/lchown.go | 20 +++ .../storage/pkg/system/xattrs_linux.go | 15 +- .../containers/storage/storage.conf | 2 +- vendor/github.com/containers/storage/store.go | 53 +++---- .../github.com/containers/storage/userns.go | 121 +++++++--------- vendor/github.com/containers/storage/utils.go | 50 +++---- .../klauspost/compress/zstd/README.md | 4 +- .../compress/zstd/encoder_options.go | 13 +- vendor/github.com/moby/sys/mountinfo/doc.go | 44 ++++++ vendor/github.com/moby/sys/mountinfo/go.mod | 2 + vendor/github.com/moby/sys/mountinfo/go.sum | 2 + .../moby/sys/mountinfo/mounted_linux.go | 58 ++++++++ .../moby/sys/mountinfo/mounted_unix.go | 66 +++++++++ .../moby/sys/mountinfo/mountinfo.go | 42 +++--- ...{mountinfo_freebsd.go => mountinfo_bsd.go} | 16 ++- .../moby/sys/mountinfo/mountinfo_filters.go | 26 ++-- .../moby/sys/mountinfo/mountinfo_linux.go | 134 +++++++++++++----- .../sys/mountinfo/mountinfo_unsupported.go | 11 +- .../moby/sys/mountinfo/mountinfo_windows.go | 6 +- vendor/modules.txt | 6 +- 47 files changed, 782 insertions(+), 475 deletions(-) delete mode 100644 vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go create mode 100644 vendor/github.com/containers/storage/pkg/system/chmod.go create mode 100644 vendor/github.com/containers/storage/pkg/system/lchown.go create mode 100644 vendor/github.com/moby/sys/mountinfo/doc.go create mode 100644 vendor/github.com/moby/sys/mountinfo/go.sum create mode 100644 vendor/github.com/moby/sys/mountinfo/mounted_linux.go create mode 100644 vendor/github.com/moby/sys/mountinfo/mounted_unix.go rename vendor/github.com/moby/sys/mountinfo/{mountinfo_freebsd.go => mountinfo_bsd.go} (73%) diff --git a/go.mod b/go.mod index 63c4e3bd..f09ad78e 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/containers/common v0.26.0 github.com/containers/image/v5 v5.6.0 github.com/containers/ocicrypt v1.0.3 - github.com/containers/storage v1.23.5 + github.com/containers/storage v1.23.9 github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f github.com/dsnet/compress v0.0.1 // indirect github.com/go-check/check v0.0.0-20180628173108-788fd7840127 diff --git a/go.sum b/go.sum index 0345540d..686c2b59 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6Gz github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g= github.com/containers/storage v1.23.5 h1:He9I6y1vRVXYoQg4v2Q9HFAcX4dI3V5MCCrjeBcjkCY= github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM= +github.com/containers/storage v1.23.9 h1:qbgnTp76pLSyW3vYwY5GH4vk5cHYVXFJ+CsUEBp9TMw= +github.com/containers/storage v1.23.9/go.mod h1:3b2ktpB6pw53SEeIoFfO0sQfP9+IoJJKPq5iJk74gxE= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -199,6 +201,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.0 h1:wJbzvpYMVGG9iTI9VxpnNZfd4DzMPoCWze3GgSqz8yg= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= +github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -234,6 +238,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/sys/mountinfo v0.1.3 h1:KIrhRO14+AkwKvG/g2yIpNMOUVZ02xNhOw8KY1WsLOI= github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= +github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -485,6 +491,7 @@ golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1 h1:sIky/MyNRSHTrdxfsiUSS4WIA golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed h1:WBkVNH1zd9jg/dK4HCM4lNANnmd12EHC9z+LmcCG4ns= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml index 6ba46ebb..539bfeab 100644 --- a/vendor/github.com/containers/storage/.cirrus.yml +++ b/vendor/github.com/containers/storage/.cirrus.yml @@ -17,14 +17,15 @@ env: #### #### Cache-image names to test with (double-quotes around names are critical) ### - FEDORA_NAME: "fedora-32" - PRIOR_FEDORA_NAME: "fedora-31" - UBUNTU_NAME: "ubuntu-20" - PRIOR_UBUNTU_NAME: "ubuntu-19" + FEDORA_NAME: "fedora" + PRIOR_FEDORA_NAME: "prior-fedora" + UBUNTU_NAME: "ubuntu" + PRIOR_UBUNTU_NAME: "prior-ubuntu" # GCE project where images live IMAGE_PROJECT: "libpod-218412" - _BUILT_IMAGE_SUFFIX: "libpod-6508632441356288" + # VM Image built in containers/automation_images + _BUILT_IMAGE_SUFFIX: "c4948709391728640" FEDORA_CACHE_IMAGE_NAME: "${FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "${PRIOR_FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "${UBUNTU_NAME}-${_BUILT_IMAGE_SUFFIX}" diff --git a/vendor/github.com/containers/storage/.gitignore b/vendor/github.com/containers/storage/.gitignore index 64b9a98b..99b40fbd 100644 --- a/vendor/github.com/containers/storage/.gitignore +++ b/vendor/github.com/containers/storage/.gitignore @@ -9,6 +9,7 @@ *.test .*.swp .DS_Store +.idea* # a .bashrc may be added to customize the build environment .bashrc .gopath/ diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index ca8ec414..63f23d2a 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.23.5 +1.23.9 diff --git a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go index be4362dc..e71ad69e 100644 --- a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go +++ b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go @@ -422,7 +422,7 @@ func subvolLimitQgroup(path string, size uint64) error { // subvolQgroupStatus performs a BTRFS_IOC_TREE_SEARCH on the root path // with search key of BTRFS_QGROUP_STATUS_KEY. -// In case qgroup is enabled, the retuned key type will match BTRFS_QGROUP_STATUS_KEY. +// In case qgroup is enabled, the returned key type will match BTRFS_QGROUP_STATUS_KEY. // For more details please see https://github.com/kdave/btrfs-progs/blob/v4.9/qgroup.c#L1035 func subvolQgroupStatus(path string) error { dir, err := openDir(path) diff --git a/vendor/github.com/containers/storage/drivers/chown_unix.go b/vendor/github.com/containers/storage/drivers/chown_unix.go index 3a3978b7..7c2a73f6 100644 --- a/vendor/github.com/containers/storage/drivers/chown_unix.go +++ b/vendor/github.com/containers/storage/drivers/chown_unix.go @@ -50,22 +50,22 @@ func platformLChown(path string, info os.FileInfo, toHost, toContainer *idtools. if uid != int(st.Uid) || gid != int(st.Gid) { cap, err := system.Lgetxattr(path, "security.capability") if err != nil && err != system.ErrNotSupportedPlatform { - return fmt.Errorf("%s: Lgetxattr(%q): %v", os.Args[0], path, err) + return fmt.Errorf("%s: %v", os.Args[0], err) } // Make the change. - if err := syscall.Lchown(path, uid, gid); err != nil { - return fmt.Errorf("%s: chown(%q): %v", os.Args[0], path, err) + if err := system.Lchown(path, uid, gid); err != nil { + return fmt.Errorf("%s: %v", os.Args[0], err) } // Restore the SUID and SGID bits if they were originally set. if (info.Mode()&os.ModeSymlink == 0) && info.Mode()&(os.ModeSetuid|os.ModeSetgid) != 0 { - if err := os.Chmod(path, info.Mode()); err != nil { - return fmt.Errorf("%s: chmod(%q): %v", os.Args[0], path, err) + if err := system.Chmod(path, info.Mode()); err != nil { + return fmt.Errorf("%s: %v", os.Args[0], err) } } if cap != nil { if err := system.Lsetxattr(path, "security.capability", cap, 0); err != nil { - return fmt.Errorf("%s: Lsetxattr(%q): %v", os.Args[0], path, err) + return fmt.Errorf("%s: %v", os.Args[0], err) } } diff --git a/vendor/github.com/containers/storage/drivers/copy/copy_linux.go b/vendor/github.com/containers/storage/drivers/copy/copy_linux.go index 1e380a5a..5147b01d 100644 --- a/vendor/github.com/containers/storage/drivers/copy/copy_linux.go +++ b/vendor/github.com/containers/storage/drivers/copy/copy_linux.go @@ -12,6 +12,7 @@ package copy import "C" import ( "container/list" + "errors" "fmt" "io" "os" @@ -98,7 +99,7 @@ func legacyCopy(srcFile io.Reader, dstFile io.Writer) error { func copyXattr(srcPath, dstPath, attr string) error { data, err := system.Lgetxattr(srcPath, attr) - if err != nil && err != unix.EOPNOTSUPP { + if err != nil && !errors.Is(err, unix.EOPNOTSUPP) { return err } if data != nil { @@ -269,7 +270,7 @@ func doCopyXattrs(srcPath, dstPath string) error { } xattrs, err := system.Llistxattr(srcPath) - if err != nil && err != unix.EOPNOTSUPP { + if err != nil && !errors.Is(err, unix.EOPNOTSUPP) { return err } diff --git a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go index cba3d05e..775dc168 100644 --- a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go +++ b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go @@ -1213,7 +1213,11 @@ func (devices *DeviceSet) growFS(info *devInfo) error { return errors.Wrapf(err, "Failed to mount; dmesg: %s", string(dmesg.Dmesg(256))) } - defer unix.Unmount(fsMountPoint, unix.MNT_DETACH) + defer func() { + if err := mount.Unmount(fsMountPoint); err != nil { + logrus.Warnf("devmapper.growFS cleanup error: %v", err) + } + }() switch devices.BaseDeviceFilesystem { case ext4: @@ -2257,6 +2261,38 @@ func (devices *DeviceSet) cancelDeferredRemoval(info *devInfo) error { return err } +func (devices *DeviceSet) unmountAndDeactivateAll(dir string) { + files, err := ioutil.ReadDir(dir) + if err != nil { + logrus.Warnf("devmapper: unmountAndDeactivate: %s", err) + return + } + + for _, d := range files { + if !d.IsDir() { + continue + } + + name := d.Name() + fullname := path.Join(dir, name) + + // We use MNT_DETACH here in case it is still busy in some running + // container. This means it'll go away from the global scope directly, + // and the device will be released when that container dies. + if err := mount.Unmount(fullname); err != nil { + logrus.Warnf("devmapper.Shutdown error: %s", err) + } + + if devInfo, err := devices.lookupDevice(name); err != nil { + logrus.Debugf("devmapper: Shutdown lookup device %s, error: %s", name, err) + } else { + if err := devices.deactivateDevice(devInfo); err != nil { + logrus.Debugf("devmapper: Shutdown deactivate %s, error: %s", devInfo.Hash, err) + } + } + } +} + // Shutdown shuts down the device by unmounting the root. func (devices *DeviceSet) Shutdown(home string) error { logrus.Debugf("devmapper: [deviceset %s] Shutdown()", devices.devicePrefix) @@ -2278,45 +2314,7 @@ func (devices *DeviceSet) Shutdown(home string) error { // will be killed and we will not get a chance to save deviceset // metadata. Hence save this early before trying to deactivate devices. devices.saveDeviceSetMetaData() - - // ignore the error since it's just a best effort to not try to unmount something that's mounted - mounts, _ := mount.GetMounts() - mounted := make(map[string]bool, len(mounts)) - for _, mnt := range mounts { - mounted[mnt.Mountpoint] = true - } - - if err := filepath.Walk(path.Join(home, "mnt"), func(p string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - return nil - } - - if mounted[p] { - // We use MNT_DETACH here in case it is still busy in some running - // container. This means it'll go away from the global scope directly, - // and the device will be released when that container dies. - if err := unix.Unmount(p, unix.MNT_DETACH); err != nil { - logrus.Debugf("devmapper: Shutdown unmounting %s, error: %s", p, err) - } - } - - if devInfo, err := devices.lookupDevice(path.Base(p)); err != nil { - logrus.Debugf("devmapper: Shutdown lookup device %s, error: %s", path.Base(p), err) - } else { - if err := devices.deactivateDevice(devInfo); err != nil { - logrus.Debugf("devmapper: Shutdown deactivate %s , error: %s", devInfo.Hash, err) - } - } - - return nil - }); err != nil && !os.IsNotExist(err) { - devices.Unlock() - return err - } - + devices.unmountAndDeactivateAll(path.Join(home, "mnt")) devices.Unlock() info, _ := devices.lookupDeviceWithLock("") @@ -2420,7 +2418,9 @@ func (devices *DeviceSet) MountDevice(hash, path string, moptions graphdriver.Mo if fstype == xfs && devices.xfsNospaceRetries != "" { if err := devices.xfsSetNospaceRetries(info); err != nil { - unix.Unmount(path, unix.MNT_DETACH) + if err := mount.Unmount(path); err != nil { + logrus.Warnf("devmapper.MountDevice cleanup error: %v", err) + } devices.deactivateDevice(info) return err } @@ -2446,11 +2446,23 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { defer devices.Unlock() logrus.Debugf("devmapper: Unmount(%s)", mountPath) - if err := unix.Unmount(mountPath, unix.MNT_DETACH); err != nil { + if err := mount.Unmount(mountPath); err != nil { return err } logrus.Debug("devmapper: Unmount done") + // Remove the mountpoint here. Removing the mountpoint (in newer kernels) + // will cause all other instances of this mount in other mount namespaces + // to be killed (this is an anti-DoS measure that is necessary for things + // like devicemapper). This is necessary to avoid cases where a libdm mount + // that is present in another namespace will cause subsequent RemoveDevice + // operations to fail. We ignore any errors here because this may fail on + // older kernels which don't have + // torvalds/linux@8ed936b5671bfb33d89bc60bdcc7cf0470ba52fe applied. + if err := os.Remove(mountPath); err != nil { + logrus.Debugf("devmapper: error doing a remove on unmounted device %s: %v", mountPath, err) + } + return devices.deactivateDevice(info) } diff --git a/vendor/github.com/containers/storage/drivers/devmapper/driver.go b/vendor/github.com/containers/storage/drivers/devmapper/driver.go index 0afa6c84..4149979a 100644 --- a/vendor/github.com/containers/storage/drivers/devmapper/driver.go +++ b/vendor/github.com/containers/storage/drivers/devmapper/driver.go @@ -14,9 +14,9 @@ import ( "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/locker" "github.com/containers/storage/pkg/mount" - "github.com/containers/storage/pkg/system" units "github.com/docker/go-units" "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" ) func init() { @@ -116,11 +116,13 @@ func (d *Driver) Metadata(id string) (map[string]string, error) { func (d *Driver) Cleanup() error { err := d.DeviceSet.Shutdown(d.home) - if err2 := mount.Unmount(d.home); err == nil { - err = err2 + umountErr := mount.Unmount(d.home) + // in case we have two errors, prefer the one from Shutdown() + if err != nil { + return err } - return err + return umountErr } // CreateFromTemplate creates a layer with the same contents and parent as another layer. @@ -148,7 +150,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { return nil } -// Remove removes a device with a given id, unmounts the filesystem. +// Remove removes a device with a given id, unmounts the filesystem, and removes the mount point. func (d *Driver) Remove(id string) error { d.locker.Lock(id) defer d.locker.Unlock(id) @@ -163,7 +165,21 @@ func (d *Driver) Remove(id string) error { if err := d.DeviceSet.DeleteDevice(id, false); err != nil { return fmt.Errorf("failed to remove device %s: %v", id, err) } - return system.EnsureRemoveAll(path.Join(d.home, "mnt", id)) + + // Most probably the mount point is already removed on Put() + // (see DeviceSet.UnmountDevice()), but just in case it was not + // let's try to remove it here as well, ignoring errors as + // an older kernel can return EBUSY if e.g. the mount was leaked + // to other mount namespaces. A failure to remove the container's + // mount point is not important and should not be treated + // as a failure to remove the container. + mp := path.Join(d.home, "mnt", id) + err := unix.Rmdir(mp) + if err != nil && !os.IsNotExist(err) { + logrus.WithField("storage-driver", "devicemapper").Warnf("unable to remove mount point %q: %s", mp, err) + } + + return nil } // Get mounts a device with given id into the root filesystem @@ -226,10 +242,12 @@ func (d *Driver) Put(id string) error { if count := d.ctr.Decrement(mp); count > 0 { return nil } + err := d.DeviceSet.UnmountDevice(id, mp) if err != nil { - logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err) + logrus.Errorf("devmapper: Error unmounting device %s: %v", id, err) } + return err } diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 1de771bb..a7cfeadc 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -42,6 +42,8 @@ var ( untar = chrootarchive.UntarUncompressed ) +const defaultPerms = os.FileMode(0555) + // This backend uses the overlay union filesystem for containers // with diff directories for each layer. @@ -75,7 +77,7 @@ const ( maxDepth = 128 // idLength represents the number of random characters - // which can be used to create the unique link identifer + // which can be used to create the unique link identifier // for every layer. If this value is too long then the // page size limit for the mount command may be exceeded. // The idLength should be selected such that following equation @@ -219,7 +221,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) return nil, errors.Wrap(err, "error recording metacopy-being-used status") } } else { - logrus.Warnf("overlay test mount did not indicate whether or not metacopy is being used: %v", err) + logrus.Infof("overlay test mount did not indicate whether or not metacopy is being used: %v", err) return nil, err } } @@ -280,7 +282,7 @@ func parseOptions(options []string) (*overlayOptions, error) { trimkey = strings.TrimPrefix(trimkey, ".") switch trimkey { case "override_kernel_check": - logrus.Warnf("overlay: override_kernel_check option was specified, but is no longer necessary") + logrus.Debugf("overlay: override_kernel_check option was specified, but is no longer necessary") case "mountopt": o.mountOptions = val case "size": @@ -444,14 +446,14 @@ func (d *Driver) useNaiveDiff() bool { logrus.Debugf("cached value indicated that native-diff is usable") } else { logrus.Debugf("cached value indicated that native-diff is not being used") - logrus.Warn(nativeDiffCacheText) + logrus.Info(nativeDiffCacheText) } useNaiveDiffOnly = !nativeDiffCacheResult return } if err := doesSupportNativeDiff(d.home, d.options.mountOptions); err != nil { nativeDiffCacheText = fmt.Sprintf("Not using native diff for overlay, this may cause degraded performance for building images: %v", err) - logrus.Warn(nativeDiffCacheText) + logrus.Info(nativeDiffCacheText) useNaiveDiffOnly = true } cachedFeatureRecord(d.runhome, feature, !useNaiveDiffOnly, nativeDiffCacheText) @@ -571,15 +573,17 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr if err := idtools.MkdirAllAs(path.Dir(dir), 0700, rootUID, rootGID); err != nil { return err } + perms := defaultPerms if parent != "" { st, err := system.Stat(d.dir(parent)) if err != nil { return err } + perms = os.FileMode(st.Mode()) rootUID = int(st.UID()) rootGID = int(st.GID()) } - if err := idtools.MkdirAs(dir, 0700, rootUID, rootGID); err != nil { + if err := idtools.MkdirAs(dir, perms, rootUID, rootGID); err != nil { return err } @@ -604,7 +608,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr } } - if err := idtools.MkdirAs(path.Join(dir, "diff"), 0755, rootUID, rootGID); err != nil { + if err := idtools.MkdirAs(path.Join(dir, "diff"), perms, rootUID, rootGID); err != nil { return err } @@ -847,7 +851,11 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO return "", err } diffN := 1 - _, err = os.Stat(filepath.Join(dir, nameWithSuffix("diff", diffN))) + perms := defaultPerms + st, err := os.Stat(filepath.Join(dir, nameWithSuffix("diff", diffN))) + if err == nil { + perms = os.FileMode(st.Mode()) + } for err == nil { absLowers = append(absLowers, filepath.Join(dir, nameWithSuffix("diff", diffN))) relLowers = append(relLowers, dumbJoin(string(link), "..", nameWithSuffix("diff", diffN))) @@ -908,7 +916,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO return "", err } diffDir := path.Join(dir, "diff") - if err := idtools.MkdirAllAs(diffDir, 0755, rootUID, rootGID); err != nil { + if err := idtools.MkdirAllAs(diffDir, perms, rootUID, rootGID); err != nil { return "", err } @@ -1241,11 +1249,16 @@ func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMapp // Rotate the diff directories. i := 0 - _, err = os.Stat(nameWithSuffix(diffDir, i)) + perms := defaultPerms + st, err := os.Stat(nameWithSuffix(diffDir, i)) + if err == nil { + perms = os.FileMode(st.Mode()) + } for err == nil { i++ _, err = os.Stat(nameWithSuffix(diffDir, i)) } + for i > 0 { err = os.Rename(nameWithSuffix(diffDir, i-1), nameWithSuffix(diffDir, i)) if err != nil { @@ -1258,13 +1271,13 @@ func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMapp // to the old upper layer in the index. workDir := filepath.Join(dir, "work") if err := os.RemoveAll(workDir); err == nil { - if err := idtools.MkdirAs(workDir, 0755, rootUID, rootGID); err != nil { + if err := idtools.MkdirAs(workDir, defaultPerms, rootUID, rootGID); err != nil { return err } } // Re-create the directory that we're going to use as the upper layer. - if err := idtools.MkdirAs(diffDir, 0755, rootUID, rootGID); err != nil { + if err := idtools.MkdirAs(diffDir, perms, rootUID, rootGID); err != nil { return err } return nil diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs.go b/vendor/github.com/containers/storage/drivers/zfs/zfs.go index 3e850d13..4e7290ef 100644 --- a/vendor/github.com/containers/storage/drivers/zfs/zfs.go +++ b/vendor/github.com/containers/storage/drivers/zfs/zfs.go @@ -160,7 +160,7 @@ func lookupZfsDataset(rootdir string) (string, error) { continue // may fail on fuse file systems } - if stat.Dev == wantedDev && m.Fstype == "zfs" { + if stat.Dev == wantedDev && m.FSType == "zfs" { return m.Source, nil } } diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod index 39db6664..9d5a2b42 100644 --- a/vendor/github.com/containers/storage/go.mod +++ b/vendor/github.com/containers/storage/go.mod @@ -1,4 +1,4 @@ -go 1.15 +go 1.14 module github.com/containers/storage @@ -8,23 +8,23 @@ require ( github.com/Microsoft/hcsshim v0.8.9 github.com/docker/go-units v0.4.0 github.com/hashicorp/go-multierror v1.1.0 - github.com/klauspost/compress v1.11.0 + github.com/klauspost/compress v1.11.2 github.com/klauspost/pgzip v1.2.5 github.com/mattn/go-shellwords v1.0.10 github.com/mistifyio/go-zfs v2.1.1+incompatible - github.com/moby/sys/mountinfo v0.1.3 + github.com/moby/sys/mountinfo v0.4.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/runc v1.0.0-rc91 github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 github.com/opencontainers/selinux v1.6.0 github.com/pkg/errors v0.9.1 github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7 - github.com/sirupsen/logrus v1.6.0 + github.com/sirupsen/logrus v1.7.0 github.com/stretchr/testify v1.6.1 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 github.com/tchap/go-patricia v2.3.0+incompatible github.com/vbatts/tar-split v0.11.1 golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 - golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 + golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 gotest.tools v2.2.0+incompatible ) diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum index d1fb711b..681f77cb 100644 --- a/vendor/github.com/containers/storage/go.sum +++ b/vendor/github.com/containers/storage/go.sum @@ -62,8 +62,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.0 h1:wJbzvpYMVGG9iTI9VxpnNZfd4DzMPoCWze3GgSqz8yg= -github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ= +github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -80,6 +80,8 @@ github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJd github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/moby/sys/mountinfo v0.1.3 h1:KIrhRO14+AkwKvG/g2yIpNMOUVZ02xNhOw8KY1WsLOI= github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o= +github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM= github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -113,6 +115,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -163,12 +167,15 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index 52577299..72f00b8d 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -907,11 +907,11 @@ func (r *layerStore) ParentOwners(id string) (uids, gids []int, err error) { for dir := filepath.Dir(layer.MountPoint); dir != "" && dir != string(os.PathSeparator); dir = filepath.Dir(dir) { st, err := system.Stat(dir) if err != nil { - return nil, nil, errors.Wrapf(err, "error reading ownership of directory %q", dir) + return nil, nil, errors.Wrap(err, "read directory ownership") } lst, err := system.Lstat(dir) if err != nil { - return nil, nil, errors.Wrapf(err, "error reading ownership of directory-in-case-it's-a-symlink %q", dir) + return nil, nil, err } fsuid := int(st.UID()) fsgid := int(st.GID()) @@ -1329,6 +1329,7 @@ func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error if err != nil { return -1, err } + defer uncompressed.Close() uncompressedDigest := digest.Canonical.Digester() uncompressedCounter := ioutils.NewWriteCounter(uncompressedDigest.Hash()) uidLog := make(map[uint32]struct{}) diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go index ac0f5f33..345da290 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive.go @@ -139,6 +139,7 @@ func IsArchivePath(path string) bool { if err != nil { return false } + defer rdr.Close() r := tar.NewReader(rdr) _, err = r.Next() return err == nil @@ -398,7 +399,7 @@ func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { } for _, xattr := range []string{"security.capability", "security.ima"} { capability, err := system.Lgetxattr(path, xattr) - if err != nil && err != system.EOPNOTSUPP && err != system.ErrNotSupportedPlatform { + if err != nil && !errors.Is(err, system.EOPNOTSUPP) && err != system.ErrNotSupportedPlatform { return errors.Wrapf(err, "failed to read %q attribute from %q", xattr, path) } if capability != nil { @@ -411,17 +412,17 @@ func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { // ReadUserXattrToTarHeader reads user.* xattr from filesystem to a tar header func ReadUserXattrToTarHeader(path string, hdr *tar.Header) error { xattrs, err := system.Llistxattr(path) - if err != nil && err != system.EOPNOTSUPP && err != system.ErrNotSupportedPlatform { + if err != nil && !errors.Is(err, system.EOPNOTSUPP) && err != system.ErrNotSupportedPlatform { return err } for _, key := range xattrs { if strings.HasPrefix(key, "user.") { value, err := system.Lgetxattr(path, key) - if err == system.E2BIG { - logrus.Errorf("archive: Skipping xattr for file %s since value is too big: %s", path, key) - continue - } if err != nil { + if errors.Is(err, system.E2BIG) { + logrus.Errorf("archive: Skipping xattr for file %s since value is too big: %s", path, key) + continue + } return err } if hdr.Xattrs == nil { @@ -694,29 +695,6 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L } } - var errors []string - for key, value := range hdr.Xattrs { - if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil { - if err == syscall.ENOTSUP || (err == syscall.EPERM && inUserns) { - // We ignore errors here because not all graphdrivers support - // xattrs *cough* old versions of AUFS *cough*. However only - // ENOTSUP should be emitted in that case, otherwise we still - // bail. We also ignore EPERM errors if we are running in a - // user namespace. - errors = append(errors, err.Error()) - continue - } - return err - } - - } - - if len(errors) > 0 { - logrus.WithFields(logrus.Fields{ - "errors": errors, - }).Warn("ignored xattrs in archive: underlying filesystem doesn't support them") - } - // There is no LChmod, so ignore mode for symlink. Also, this // must happen after chown, as that can modify the file mode if err := handleLChmod(hdr, path, hdrInfo); err != nil { @@ -746,6 +724,30 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L return err } } + + var errs []string + for key, value := range hdr.Xattrs { + if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil { + if errors.Is(err, syscall.ENOTSUP) || (inUserns && errors.Is(err, syscall.EPERM)) { + // We ignore errors here because not all graphdrivers support + // xattrs *cough* old versions of AUFS *cough*. However only + // ENOTSUP should be emitted in that case, otherwise we still + // bail. We also ignore EPERM errors if we are running in a + // user namespace. + errs = append(errs, err.Error()) + continue + } + return err + } + + } + + if len(errs) > 0 { + logrus.WithFields(logrus.Fields{ + "errors": errs, + }).Warn("ignored xattrs in archive: underlying filesystem doesn't support them") + } + return nil } @@ -1247,10 +1249,11 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { }() options := &TarOptions{ - UIDMaps: archiver.UntarIDMappings.UIDs(), - GIDMaps: archiver.UntarIDMappings.GIDs(), - ChownOpts: archiver.ChownOpts, - InUserNS: rsystem.RunningInUserNS(), + UIDMaps: archiver.UntarIDMappings.UIDs(), + GIDMaps: archiver.UntarIDMappings.GIDs(), + ChownOpts: archiver.ChownOpts, + InUserNS: rsystem.RunningInUserNS(), + NoOverwriteDirNonDir: true, } err = archiver.Untar(r, filepath.Dir(dst), options) if err != nil { diff --git a/vendor/github.com/containers/storage/pkg/archive/changes_linux.go b/vendor/github.com/containers/storage/pkg/archive/changes_linux.go index ecfa45d7..da86e0c0 100644 --- a/vendor/github.com/containers/storage/pkg/archive/changes_linux.go +++ b/vendor/github.com/containers/storage/pkg/archive/changes_linux.go @@ -2,6 +2,7 @@ package archive import ( "bytes" + "errors" "fmt" "os" "path/filepath" @@ -86,21 +87,21 @@ func walkchunk(path string, fi os.FileInfo, dir string, root *FileInfo) error { } info.stat = stat info.capability, err = system.Lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access - if err != nil && err != system.EOPNOTSUPP { + if err != nil && !errors.Is(err, system.EOPNOTSUPP) { return err } xattrs, err := system.Llistxattr(cpath) - if err != nil && err != system.EOPNOTSUPP { + if err != nil && !errors.Is(err, system.EOPNOTSUPP) { return err } for _, key := range xattrs { if strings.HasPrefix(key, "user.") { value, err := system.Lgetxattr(cpath, key) - if err == system.E2BIG { - logrus.Errorf("archive: Skipping xattr for file %s since value is too big: %s", cpath, key) - continue - } if err != nil { + if errors.Is(err, system.E2BIG) { + logrus.Errorf("archive: Skipping xattr for file %s since value is too big: %s", cpath, key) + continue + } return err } if info.xattrs == nil { diff --git a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go index b540281f..082fb1ba 100644 --- a/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go +++ b/vendor/github.com/containers/storage/pkg/devicemapper/devmapper_log.go @@ -12,7 +12,7 @@ import ( ) // DevmapperLogger defines methods required to register as a callback for -// logging events recieved from devicemapper. Note that devicemapper will send +// logging events received from devicemapper. Note that devicemapper will send // *all* logs regardless to callbacks (including debug logs) so it's // recommended to not spam the console with the outputs. type DevmapperLogger interface { diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go index e5faf9aa..b3998fb3 100644 --- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go +++ b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go @@ -13,7 +13,7 @@ import ( "github.com/sirupsen/logrus" ) -// PatternMatcher allows checking paths agaist a list of patterns +// PatternMatcher allows checking paths against a list of patterns type PatternMatcher struct { patterns []*Pattern exclusions bool diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go deleted file mode 100644 index d28ba9d6..00000000 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_linux.go +++ /dev/null @@ -1,96 +0,0 @@ -package homedir - -// Copyright 2013-2018 Docker, Inc. -// NOTE: this package has originally been copied from github.com/docker/docker. - -import ( - "errors" - "os" - "path/filepath" - "strings" -) - -// GetRuntimeDir returns XDG_RUNTIME_DIR. -// XDG_RUNTIME_DIR is typically configured via pam_systemd. -// GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set. -// -// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html -func GetRuntimeDir() (string, error) { - if xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR"); xdgRuntimeDir != "" { - return xdgRuntimeDir, nil - } - return "", errors.New("could not get XDG_RUNTIME_DIR") -} - -// StickRuntimeDirContents sets the sticky bit on files that are under -// XDG_RUNTIME_DIR, so that the files won't be periodically removed by the system. -// -// StickyRuntimeDir returns slice of sticked files. -// StickyRuntimeDir returns nil error if XDG_RUNTIME_DIR is not set. -// -// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html -func StickRuntimeDirContents(files []string) ([]string, error) { - runtimeDir, err := GetRuntimeDir() - if err != nil { - // ignore error if runtimeDir is empty - return nil, nil - } - runtimeDir, err = filepath.Abs(runtimeDir) - if err != nil { - return nil, err - } - var sticked []string - for _, f := range files { - f, err = filepath.Abs(f) - if err != nil { - return sticked, err - } - if strings.HasPrefix(f, runtimeDir+"/") { - if err = stick(f); err != nil { - return sticked, err - } - sticked = append(sticked, f) - } - } - return sticked, nil -} - -func stick(f string) error { - st, err := os.Stat(f) - if err != nil { - return err - } - m := st.Mode() - m |= os.ModeSticky - return os.Chmod(f, m) -} - -// GetDataHome returns XDG_DATA_HOME. -// GetDataHome returns $HOME/.local/share and nil error if XDG_DATA_HOME is not set. -// -// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html -func GetDataHome() (string, error) { - if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" { - return xdgDataHome, nil - } - home := os.Getenv("HOME") - if home == "" { - return "", errors.New("could not get either XDG_DATA_HOME or HOME") - } - return filepath.Join(home, ".local", "share"), nil -} - -// GetConfigHome returns XDG_CONFIG_HOME. -// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set. -// -// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html -func GetConfigHome() (string, error) { - if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" { - return xdgConfigHome, nil - } - home := os.Getenv("HOME") - if home == "" { - return "", errors.New("could not get either XDG_CONFIG_HOME or HOME") - } - return filepath.Join(home, ".config"), nil -} diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go index f7bcfb87..4f778c85 100644 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go +++ b/vendor/github.com/containers/storage/pkg/homedir/homedir_others.go @@ -1,4 +1,4 @@ -// +build !linux +// +build !linux,!darwin package homedir diff --git a/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go b/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go index dcadb7e8..0274d037 100644 --- a/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go +++ b/vendor/github.com/containers/storage/pkg/homedir/homedir_unix.go @@ -6,8 +6,12 @@ package homedir // NOTE: this package has originally been copied from github.com/docker/docker. import ( + "errors" "os" - "os/user" + "path/filepath" + "strings" + + "github.com/containers/storage/pkg/unshare" ) // Key returns the env var name for the user's home dir based on @@ -25,13 +29,8 @@ func Key() string { // // If needing to do nss lookups, do not disable cgo or set osusergo. func Get() string { - home := os.Getenv(Key()) - if home == "" { - if u, err := user.Current(); err == nil { - return u.HomeDir - } - } - return home + homedir, _ := unshare.HomeDir() + return homedir } // GetShortcutString returns the string that is shortcut to user's home directory @@ -39,3 +38,88 @@ func Get() string { func GetShortcutString() string { return "~" } + +// GetRuntimeDir returns XDG_RUNTIME_DIR. +// XDG_RUNTIME_DIR is typically configured via pam_systemd. +// GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set. +// +// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html +func GetRuntimeDir() (string, error) { + if xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR"); xdgRuntimeDir != "" { + return xdgRuntimeDir, nil + } + return "", errors.New("could not get XDG_RUNTIME_DIR") +} + +// StickRuntimeDirContents sets the sticky bit on files that are under +// XDG_RUNTIME_DIR, so that the files won't be periodically removed by the system. +// +// StickyRuntimeDir returns slice of sticked files. +// StickyRuntimeDir returns nil error if XDG_RUNTIME_DIR is not set. +// +// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html +func StickRuntimeDirContents(files []string) ([]string, error) { + runtimeDir, err := GetRuntimeDir() + if err != nil { + // ignore error if runtimeDir is empty + return nil, nil + } + runtimeDir, err = filepath.Abs(runtimeDir) + if err != nil { + return nil, err + } + var sticked []string + for _, f := range files { + f, err = filepath.Abs(f) + if err != nil { + return sticked, err + } + if strings.HasPrefix(f, runtimeDir+"/") { + if err = stick(f); err != nil { + return sticked, err + } + sticked = append(sticked, f) + } + } + return sticked, nil +} + +func stick(f string) error { + st, err := os.Stat(f) + if err != nil { + return err + } + m := st.Mode() + m |= os.ModeSticky + return os.Chmod(f, m) +} + +// GetDataHome returns XDG_DATA_HOME. +// GetDataHome returns $HOME/.local/share and nil error if XDG_DATA_HOME is not set. +// +// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html +func GetDataHome() (string, error) { + if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" { + return xdgDataHome, nil + } + home := Get() + if home == "" { + return "", errors.New("could not get either XDG_DATA_HOME or HOME") + } + return filepath.Join(home, ".local", "share"), nil +} + +// GetConfigHome returns XDG_CONFIG_HOME. +// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set. +// +// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html +func GetConfigHome() (string, error) { + if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" { + return xdgConfigHome, nil + } + home := Get() + if home == "" { + return "", errors.New("could not get either XDG_CONFIG_HOME or HOME") + } + return filepath.Join(home, ".config"), nil +} diff --git a/vendor/github.com/containers/storage/pkg/idtools/idtools.go b/vendor/github.com/containers/storage/pkg/idtools/idtools.go index 5105720b..0958c0c5 100644 --- a/vendor/github.com/containers/storage/pkg/idtools/idtools.go +++ b/vendor/github.com/containers/storage/pkg/idtools/idtools.go @@ -291,7 +291,7 @@ func parseSubidFile(path, username string) (ranges, error) { func checkChownErr(err error, name string, uid, gid int) error { if e, ok := err.(*os.PathError); ok && e.Err == syscall.EINVAL { - return errors.Wrapf(err, "there might not be enough IDs available in the namespace (requested %d:%d for %s)", uid, gid, name) + return errors.Wrapf(err, "potentially insufficient UIDs or GIDs available in user namespace (requested %d:%d for %s): Check /etc/subuid and /etc/subgid", uid, gid, name) } return err } diff --git a/vendor/github.com/containers/storage/pkg/idtools/parser.go b/vendor/github.com/containers/storage/pkg/idtools/parser.go index 86f98f16..1c819a1f 100644 --- a/vendor/github.com/containers/storage/pkg/idtools/parser.go +++ b/vendor/github.com/containers/storage/pkg/idtools/parser.go @@ -8,13 +8,6 @@ import ( "strings" ) -func nonDigitsToWhitespace(r rune) rune { - if !strings.ContainsRune("0123456789", r) { - return ' ' - } - return r -} - func parseTriple(spec []string) (container, host, size uint32, err error) { cid, err := strconv.ParseUint(spec[0], 10, 32) if err != nil { @@ -33,9 +26,12 @@ func parseTriple(spec []string) (container, host, size uint32, err error) { // ParseIDMap parses idmap triples from string. func ParseIDMap(mapSpec []string, mapSetting string) (idmap []IDMap, err error) { - stdErr := fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting) + stdErr := fmt.Errorf("error initializing ID mappings: %s setting is malformed expected [\"uint32:uint32:uint32\"]: %q", mapSetting, mapSpec) for _, idMapSpec := range mapSpec { - idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec)) + if idMapSpec == "" { + continue + } + idSpec := strings.Split(idMapSpec, ":") if len(idSpec)%3 != 0 { return nil, stdErr } diff --git a/vendor/github.com/containers/storage/pkg/mount/mount.go b/vendor/github.com/containers/storage/pkg/mount/mount.go index 8273ab5a..cd4bacd6 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mount.go +++ b/vendor/github.com/containers/storage/pkg/mount/mount.go @@ -90,7 +90,7 @@ func RecursiveUnmount(target string) error { if err := Unmount(m.Mountpoint); err != nil && i == len(mounts)-1 { return err // Ignore errors for submounts and continue trying to unmount others - // The final unmount should fail if there ane any submounts remaining + // The final unmount should fail if there are any submounts remaining } } return nil diff --git a/vendor/github.com/containers/storage/pkg/mount/mountinfo.go b/vendor/github.com/containers/storage/pkg/mount/mountinfo.go index efc6c406..bb2da474 100644 --- a/vendor/github.com/containers/storage/pkg/mount/mountinfo.go +++ b/vendor/github.com/containers/storage/pkg/mount/mountinfo.go @@ -1,21 +1,13 @@ package mount import ( - "github.com/containers/storage/pkg/fileutils" "github.com/moby/sys/mountinfo" ) type Info = mountinfo.Info +var Mounted = mountinfo.Mounted + func GetMounts() ([]*Info, error) { return mountinfo.GetMounts(nil) } - -// Mounted determines if a specified mountpoint has been mounted. -func Mounted(mountpoint string) (bool, error) { - mountpoint, err := fileutils.ReadSymlinkedPath(mountpoint) - if err != nil { - return false, err - } - return mountinfo.Mounted(mountpoint) -} diff --git a/vendor/github.com/containers/storage/pkg/system/chmod.go b/vendor/github.com/containers/storage/pkg/system/chmod.go new file mode 100644 index 00000000..a01d8abf --- /dev/null +++ b/vendor/github.com/containers/storage/pkg/system/chmod.go @@ -0,0 +1,17 @@ +package system + +import ( + "errors" + "os" + "syscall" +) + +func Chmod(name string, mode os.FileMode) error { + err := os.Chmod(name, mode) + + for err != nil && errors.Is(err, syscall.EINTR) { + err = os.Chmod(name, mode) + } + + return err +} diff --git a/vendor/github.com/containers/storage/pkg/system/lchown.go b/vendor/github.com/containers/storage/pkg/system/lchown.go new file mode 100644 index 00000000..eb2d8b46 --- /dev/null +++ b/vendor/github.com/containers/storage/pkg/system/lchown.go @@ -0,0 +1,20 @@ +package system + +import ( + "os" + "syscall" +) + +func Lchown(name string, uid, gid int) error { + err := syscall.Lchown(name, uid, gid) + + for err == syscall.EINTR { + err = syscall.Lchown(name, uid, gid) + } + + if err != nil { + return &os.PathError{Op: "lchown", Path: name, Err: err} + } + + return nil +} diff --git a/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go b/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go index e94bb5d5..10355848 100644 --- a/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go +++ b/vendor/github.com/containers/storage/pkg/system/xattrs_linux.go @@ -2,6 +2,7 @@ package system import ( "bytes" + "os" "golang.org/x/sys/unix" ) @@ -26,7 +27,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) { // Buffer too small, use zero-sized buffer to get the actual size sz, errno = unix.Lgetxattr(path, attr, []byte{}) if errno != nil { - return nil, errno + return nil, &os.PathError{Op: "lgetxattr", Path: path, Err: errno} } dest = make([]byte, sz) sz, errno = unix.Lgetxattr(path, attr, dest) @@ -36,7 +37,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) { case errno == unix.ENODATA: return nil, nil case errno != nil: - return nil, errno + return nil, &os.PathError{Op: "lgetxattr", Path: path, Err: errno} } return dest[:sz], nil @@ -45,7 +46,11 @@ func Lgetxattr(path string, attr string) ([]byte, error) { // Lsetxattr sets the value of the extended attribute identified by attr // and associated with the given path in the file system. func Lsetxattr(path string, attr string, data []byte, flags int) error { - return unix.Lsetxattr(path, attr, data, flags) + if err := unix.Lsetxattr(path, attr, data, flags); err != nil { + return &os.PathError{Op: "lsetxattr", Path: path, Err: err} + } + + return nil } // Llistxattr lists extended attributes associated with the given path @@ -58,14 +63,14 @@ func Llistxattr(path string) ([]string, error) { // Buffer too small, use zero-sized buffer to get the actual size sz, errno = unix.Llistxattr(path, []byte{}) if errno != nil { - return nil, errno + return nil, &os.PathError{Op: "llistxattr", Path: path, Err: errno} } dest = make([]byte, sz) sz, errno = unix.Llistxattr(path, dest) } if errno != nil { - return nil, errno + return nil, &os.PathError{Op: "llistxattr", Path: path, Err: errno} } var attrs []string diff --git a/vendor/github.com/containers/storage/storage.conf b/vendor/github.com/containers/storage/storage.conf index a8ec9d98..64e02f32 100644 --- a/vendor/github.com/containers/storage/storage.conf +++ b/vendor/github.com/containers/storage/storage.conf @@ -47,7 +47,7 @@ additionalimagestores = [ # remap-group = "containers" # Root-auto-userns-user is a user name which can be used to look up one or more UID/GID -# ranges in the /etc/subuid and /etc/subgid file. These ranges will be partioned +# ranges in the /etc/subuid and /etc/subgid file. These ranges will be partitioned # to containers configured to create automatically a user namespace. Containers # configured to automatically create a user namespace can still overlap with containers # having an explicit mapping set. diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index 2a34c84c..6b51b405 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -613,14 +613,14 @@ func GetStore(options StoreOptions) (Store, error) { if options.GraphRoot != "" { dir, err := filepath.Abs(options.GraphRoot) if err != nil { - return nil, errors.Wrapf(err, "error deriving an absolute path from %q", options.GraphRoot) + return nil, err } options.GraphRoot = dir } if options.RunRoot != "" { dir, err := filepath.Abs(options.RunRoot) if err != nil { - return nil, errors.Wrapf(err, "error deriving an absolute path from %q", options.RunRoot) + return nil, err } options.RunRoot = dir } @@ -2677,21 +2677,16 @@ func (s *store) MountImage(id string, mountOpts []string, mountLabel string) (st } func (s *store) Mount(id, mountLabel string) (string, error) { - container, err := s.Container(id) - var ( - uidMap, gidMap []idtools.IDMap - mountOpts []string - ) - if err == nil { - uidMap, gidMap = container.UIDMap, container.GIDMap - id = container.LayerID - mountOpts = container.MountOpts() - } options := drivers.MountOpts{ MountLabel: mountLabel, - UidMaps: uidMap, - GidMaps: gidMap, - Options: mountOpts, + } + // check if `id` is a container, then grab the LayerID, uidmap and gidmap, along with + // otherwise we assume the id is a LayerID and attempt to mount it. + if container, err := s.Container(id); err == nil { + id = container.LayerID + options.UidMaps = container.UIDMap + options.GidMaps = container.GIDMap + options.Options = container.MountOpts() } return s.mount(id, options) } @@ -3460,7 +3455,10 @@ func copyStringInterfaceMap(m map[string]interface{}) map[string]interface{} { } // defaultConfigFile path to the system wide storage.conf file -var defaultConfigFile = "/etc/containers/storage.conf" +var ( + defaultConfigFile = "/etc/containers/storage.conf" + defaultConfigFileSet = false +) // AutoUserNsMinSize is the minimum size for automatically created user namespaces const AutoUserNsMinSize = 1024 @@ -3475,21 +3473,24 @@ const RootAutoUserNsUser = "containers" // SetDefaultConfigFilePath sets the default configuration to the specified path func SetDefaultConfigFilePath(path string) { defaultConfigFile = path + defaultConfigFileSet = true + reloadConfigurationFileIfNeeded(defaultConfigFile, &defaultStoreOptions) } // DefaultConfigFile returns the path to the storage config file used func DefaultConfigFile(rootless bool) (string, error) { - if rootless { - if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" { - return filepath.Join(configHome, "containers/storage.conf"), nil - } - home := homedir.Get() - if home == "" { - return "", errors.New("cannot determine user's homedir") - } - return filepath.Join(home, ".config/containers/storage.conf"), nil + if defaultConfigFileSet || !rootless { + return defaultConfigFile, nil } - return defaultConfigFile, nil + + if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" { + return filepath.Join(configHome, "containers/storage.conf"), nil + } + home := homedir.Get() + if home == "" { + return "", errors.New("cannot determine user's homedir") + } + return filepath.Join(home, ".config/containers/storage.conf"), nil } // TOML-friendly explicit tables used for conversions. diff --git a/vendor/github.com/containers/storage/userns.go b/vendor/github.com/containers/storage/userns.go index 5ba8cc41..49ec544a 100644 --- a/vendor/github.com/containers/storage/userns.go +++ b/vendor/github.com/containers/storage/userns.go @@ -221,94 +221,71 @@ outer: return size, nil } +func minInt(a, b int) int { + if a < b { + return a + } + return b +} + +func maxInt(a, b int) int { + if a < b { + return b + } + return a +} + // subtractHostIDs return the subtraction of the range USED from AVAIL. The range is specified // by [HostID, HostID+Size). // ContainerID is ignored. func subtractHostIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap { - switch { - case used.HostID <= avail.HostID && used.HostID+used.Size >= avail.HostID+avail.Size: - return nil - case used.HostID <= avail.HostID && used.HostID+used.Size > avail.HostID && used.HostID+used.Size < avail.HostID+avail.Size: - newContainerID := avail.ContainerID + used.Size - newHostID := used.HostID + used.Size - r := idtools.IDMap{ - ContainerID: newContainerID, - HostID: newHostID, - Size: avail.Size + avail.HostID - newHostID, - } - return []idtools.IDMap{r} - case used.HostID > avail.HostID && used.HostID < avail.HostID+avail.Size && used.HostID+used.Size >= avail.HostID+avail.Size: - r := idtools.IDMap{ + var out []idtools.IDMap + availEnd := avail.HostID + avail.Size + usedEnd := used.HostID + used.Size + // Intersection of [avail.HostID, availEnd) and (-inf, used.HostID) is [avail.HostID, newEnd). + if newEnd := minInt(availEnd, used.HostID); newEnd > avail.HostID { + out = append(out, idtools.IDMap{ ContainerID: avail.ContainerID, HostID: avail.HostID, - Size: used.HostID - avail.HostID, - } - return []idtools.IDMap{r} - case used.HostID > avail.HostID && used.HostID < avail.HostID+avail.Size && used.HostID+used.Size < avail.HostID+avail.Size: - r1 := idtools.IDMap{ - ContainerID: avail.ContainerID, - HostID: avail.HostID, - Size: used.HostID - avail.HostID, - } - r2 := idtools.IDMap{ - ContainerID: used.ContainerID + used.Size, - HostID: avail.HostID + (used.HostID - avail.HostID), - Size: avail.HostID + avail.Size - used.HostID - used.Size, - } - return []idtools.IDMap{r1, r2} - default: - r := idtools.IDMap{ - ContainerID: 0, - HostID: avail.HostID, - Size: avail.Size, - } - return []idtools.IDMap{r} + Size: newEnd - avail.HostID, + }) } + // Intersection of [avail.HostID, availEnd) and [usedEnd, +inf) is [newStart, availEnd). + if newStart := maxInt(avail.HostID, usedEnd); newStart < availEnd { + out = append(out, idtools.IDMap{ + ContainerID: newStart + avail.ContainerID - avail.HostID, + HostID: newStart, + Size: availEnd - newStart, + }) + } + return out } // subtractContainerIDs return the subtraction of the range USED from AVAIL. The range is specified // by [ContainerID, ContainerID+Size). // HostID is ignored. func subtractContainerIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap { - switch { - case used.ContainerID <= avail.ContainerID && used.ContainerID+used.Size >= avail.ContainerID+avail.Size: - return nil - case used.ContainerID <= avail.ContainerID && used.ContainerID+used.Size > avail.ContainerID && used.ContainerID+used.Size < avail.ContainerID+avail.Size: - newContainerID := used.ContainerID + used.Size - newHostID := avail.HostID + used.Size - r := idtools.IDMap{ - ContainerID: newContainerID, - HostID: newHostID, - Size: avail.Size + avail.ContainerID - newContainerID, - } - return []idtools.IDMap{r} - case used.ContainerID > avail.ContainerID && used.ContainerID < avail.ContainerID+avail.Size && used.ContainerID+used.Size >= avail.ContainerID+avail.Size: - r := idtools.IDMap{ + var out []idtools.IDMap + availEnd := avail.ContainerID + avail.Size + usedEnd := used.ContainerID + used.Size + // Intersection of [avail.ContainerID, availEnd) and (-inf, used.ContainerID) is + // [avail.ContainerID, newEnd). + if newEnd := minInt(availEnd, used.ContainerID); newEnd > avail.ContainerID { + out = append(out, idtools.IDMap{ ContainerID: avail.ContainerID, HostID: avail.HostID, - Size: used.ContainerID - avail.ContainerID, - } - return []idtools.IDMap{r} - case used.ContainerID > avail.ContainerID && used.ContainerID < avail.ContainerID+avail.Size && used.ContainerID+used.Size < avail.ContainerID+avail.Size: - r1 := idtools.IDMap{ - ContainerID: avail.ContainerID, - HostID: avail.HostID, - Size: used.ContainerID - avail.ContainerID, - } - r2 := idtools.IDMap{ - ContainerID: used.ContainerID + used.Size, - HostID: avail.HostID + (used.ContainerID - avail.ContainerID), - Size: avail.ContainerID + avail.Size - used.ContainerID - used.Size, - } - return []idtools.IDMap{r1, r2} - default: - r := idtools.IDMap{ - ContainerID: avail.ContainerID, - HostID: avail.HostID, - Size: avail.Size, - } - return []idtools.IDMap{r} + Size: newEnd - avail.ContainerID, + }) } + // Intersection of [avail.ContainerID, availEnd) and [usedEnd, +inf) is [newStart, availEnd). + if newStart := maxInt(avail.ContainerID, usedEnd); newStart < availEnd { + out = append(out, idtools.IDMap{ + ContainerID: newStart, + HostID: newStart + avail.HostID - avail.ContainerID, + Size: availEnd - newStart, + }) + } + return out } // subtractAll subtracts all usedIDs from the available IDs. diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go index b22263fe..bd6c4feb 100644 --- a/vendor/github.com/containers/storage/utils.go +++ b/vendor/github.com/containers/storage/utils.go @@ -76,7 +76,7 @@ func GetRootlessRuntimeDir(rootlessUID int) (string, error) { } path = filepath.Join(path, "containers") if err := os.MkdirAll(path, 0700); err != nil { - return "", errors.Wrapf(err, "unable to make rootless runtime dir %s", path) + return "", errors.Wrapf(err, "unable to make rootless runtime") } return path, nil } @@ -154,7 +154,7 @@ func getRootlessRuntimeDirIsolated(env rootlessRuntimeDirEnvironment) (string, e } resolvedHomeDir, err := filepath.EvalSymlinks(homeDir) if err != nil { - return "", errors.Wrapf(err, "cannot resolve %s", homeDir) + return "", err } return filepath.Join(resolvedHomeDir, "rundir"), nil } @@ -190,7 +190,7 @@ func getRootlessDirInfo(rootlessUID int) (string, string, error) { // on CoreOS /home is a symlink to /var/home, so resolve any symlink. resolvedHome, err := filepath.EvalSymlinks(home) if err != nil { - return "", "", errors.Wrapf(err, "cannot resolve %s", home) + return "", "", err } dataDir = filepath.Join(resolvedHome, ".local", "share") @@ -206,11 +206,10 @@ func getRootlessStorageOpts(rootlessUID int, systemOpts StoreOptions) (StoreOpti return opts, err } opts.RunRoot = rootlessRuntime - opts.GraphRoot = filepath.Join(dataDir, "containers", "storage") if systemOpts.RootlessStoragePath != "" { - opts.RootlessStoragePath = systemOpts.RootlessStoragePath + opts.GraphRoot = systemOpts.RootlessStoragePath } else { - opts.RootlessStoragePath = opts.GraphRoot + opts.GraphRoot = filepath.Join(dataDir, "containers", "storage") } if path, err := exec.LookPath("fuse-overlayfs"); err == nil { opts.GraphDriverName = "overlay" @@ -259,13 +258,28 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str } _, err = os.Stat(storageConf) if err != nil && !os.IsNotExist(err) { - return storageOpts, errors.Wrapf(err, "cannot stat %s", storageConf) + return storageOpts, err } - if err == nil { + if err == nil && !defaultConfigFileSet { defaultRootlessRunRoot = storageOpts.RunRoot defaultRootlessGraphRoot = storageOpts.GraphRoot storageOpts = StoreOptions{} reloadConfigurationFileIfNeeded(storageConf, &storageOpts) + if rootless && rootlessUID != 0 { + // If the file did not specify a graphroot or runroot, + // set sane defaults so we don't try and use root-owned + // directories + if storageOpts.RunRoot == "" { + storageOpts.RunRoot = defaultRootlessRunRoot + } + if storageOpts.GraphRoot == "" { + if storageOpts.RootlessStoragePath != "" { + storageOpts.GraphRoot = storageOpts.RootlessStoragePath + } else { + storageOpts.GraphRoot = defaultRootlessGraphRoot + } + } + } } if storageOpts.RunRoot != "" { runRoot, err := expandEnvPath(storageOpts.RunRoot, rootlessUID) @@ -282,26 +296,6 @@ func defaultStoreOptionsIsolated(rootless bool, rootlessUID int, storageConf str storageOpts.GraphRoot = graphRoot } - if rootless && rootlessUID != 0 { - if err == nil { - // If the file did not specify a graphroot or runroot, - // set sane defaults so we don't try and use root-owned - // directories - if storageOpts.RunRoot == "" { - storageOpts.RunRoot = defaultRootlessRunRoot - } - if storageOpts.GraphRoot == "" { - storageOpts.GraphRoot = defaultRootlessGraphRoot - } - if storageOpts.RootlessStoragePath != "" { - rootlessStoragePath, err := expandEnvPath(storageOpts.RootlessStoragePath, rootlessUID) - if err != nil { - return storageOpts, err - } - storageOpts.GraphRoot = rootlessStoragePath - } - } - } return storageOpts, nil } diff --git a/vendor/github.com/klauspost/compress/zstd/README.md b/vendor/github.com/klauspost/compress/zstd/README.md index ea3e5108..07f7285f 100644 --- a/vendor/github.com/klauspost/compress/zstd/README.md +++ b/vendor/github.com/klauspost/compress/zstd/README.md @@ -251,14 +251,14 @@ For streaming use a simple setup could look like this: import "github.com/klauspost/compress/zstd" func Decompress(in io.Reader, out io.Writer) error { - d, err := zstd.NewReader(input) + d, err := zstd.NewReader(in) if err != nil { return err } defer d.Close() // Copy content... - _, err := io.Copy(out, d) + _, err = io.Copy(out, d) return err } ``` diff --git a/vendor/github.com/klauspost/compress/zstd/encoder_options.go b/vendor/github.com/klauspost/compress/zstd/encoder_options.go index 57920616..1209915b 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder_options.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder_options.go @@ -30,12 +30,13 @@ type encoderOptions struct { func (o *encoderOptions) setDefault() { *o = encoderOptions{ // use less ram: true for now, but may change. - concurrent: runtime.GOMAXPROCS(0), - crc: true, - single: nil, - blockSize: 1 << 16, - windowSize: 8 << 20, - level: SpeedDefault, + concurrent: runtime.GOMAXPROCS(0), + crc: true, + single: nil, + blockSize: 1 << 16, + windowSize: 8 << 20, + level: SpeedDefault, + allLitEntropy: true, } } diff --git a/vendor/github.com/moby/sys/mountinfo/doc.go b/vendor/github.com/moby/sys/mountinfo/doc.go new file mode 100644 index 00000000..b80e05ef --- /dev/null +++ b/vendor/github.com/moby/sys/mountinfo/doc.go @@ -0,0 +1,44 @@ +// Package mountinfo provides a set of functions to retrieve information about OS mounts. +// +// Currently it supports Linux. For historical reasons, there is also some support for FreeBSD and OpenBSD, +// and a shallow implementation for Windows, but in general this is Linux-only package, so +// the rest of the document only applies to Linux, unless explicitly specified otherwise. +// +// In Linux, information about mounts seen by the current process is available from +// /proc/self/mountinfo. Note that due to mount namespaces, different processes can +// see different mounts. A per-process mountinfo table is available from /proc//mountinfo, +// where is a numerical process identifier. +// +// In general, /proc is not a very efficient interface, and mountinfo is not an exception. +// For example, there is no way to get information about a specific mount point (i.e. it +// is all-or-nothing). This package tries to hide the /proc ineffectiveness by using +// parse filters while reading mountinfo. A filter can skip some entries, or stop +// processing the rest of the file once the needed information is found. +// +// For mountinfo filters that accept path as an argument, the path must be absolute, +// having all symlinks resolved, and being cleaned (i.e. no extra slashes or dots). +// One way to achieve all of the above is to employ filepath.Abs followed by +// filepath.EvalSymlinks (the latter calls filepath.Clean on the result so +// there is no need to explicitly call filepath.Clean). +// +// NOTE that in many cases there is no need to consult mountinfo at all. Here are some +// of the cases where mountinfo should not be parsed: +// +// 1. Before performing a mount. Usually, this is not needed, but if required (say to +// prevent over-mounts), to check whether a directory is mounted, call os.Lstat +// on it and its parent directory, and compare their st.Sys().(*syscall.Stat_t).Dev +// fields -- if they differ, then the directory is the mount point. NOTE this does +// not work for bind mounts. Optionally, the filesystem type can also be checked +// by calling unix.Statfs and checking the Type field (i.e. filesystem type). +// +// 2. After performing a mount. If there is no error returned, the mount succeeded; +// checking the mount table for a new mount is redundant and expensive. +// +// 3. Before performing an unmount. It is more efficient to do an unmount and ignore +// a specific error (EINVAL) which tells the directory is not mounted. +// +// 4. After performing an unmount. If there is no error returned, the unmount succeeded. +// +// 5. To find the mount point root of a specific directory. You can perform os.Stat() +// on the directory and traverse up until the Dev field of a parent directory differs. +package mountinfo diff --git a/vendor/github.com/moby/sys/mountinfo/go.mod b/vendor/github.com/moby/sys/mountinfo/go.mod index 10d9a15a..9749ea96 100644 --- a/vendor/github.com/moby/sys/mountinfo/go.mod +++ b/vendor/github.com/moby/sys/mountinfo/go.mod @@ -1,3 +1,5 @@ module github.com/moby/sys/mountinfo go 1.14 + +require golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 diff --git a/vendor/github.com/moby/sys/mountinfo/go.sum b/vendor/github.com/moby/sys/mountinfo/go.sum new file mode 100644 index 00000000..2a5be7ea --- /dev/null +++ b/vendor/github.com/moby/sys/mountinfo/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_linux.go b/vendor/github.com/moby/sys/mountinfo/mounted_linux.go new file mode 100644 index 00000000..bc9f6b2a --- /dev/null +++ b/vendor/github.com/moby/sys/mountinfo/mounted_linux.go @@ -0,0 +1,58 @@ +package mountinfo + +import ( + "os" + "path/filepath" + + "golang.org/x/sys/unix" +) + +// mountedByOpenat2 is a method of detecting a mount that works for all kinds +// of mounts (incl. bind mounts), but requires a recent (v5.6+) linux kernel. +func mountedByOpenat2(path string) (bool, error) { + dir, last := filepath.Split(path) + + dirfd, err := unix.Openat2(unix.AT_FDCWD, dir, &unix.OpenHow{ + Flags: unix.O_PATH | unix.O_CLOEXEC, + }) + if err != nil { + if err == unix.ENOENT { // not a mount + return false, nil + } + return false, &os.PathError{Op: "openat2", Path: dir, Err: err} + } + fd, err := unix.Openat2(dirfd, last, &unix.OpenHow{ + Flags: unix.O_PATH | unix.O_CLOEXEC | unix.O_NOFOLLOW, + Resolve: unix.RESOLVE_NO_XDEV, + }) + _ = unix.Close(dirfd) + switch err { + case nil: // definitely not a mount + _ = unix.Close(fd) + return false, nil + case unix.EXDEV: // definitely a mount + return true, nil + case unix.ENOENT: // not a mount + return false, nil + } + // not sure + return false, &os.PathError{Op: "openat2", Path: path, Err: err} +} + +func mounted(path string) (bool, error) { + // Try a fast path, using openat2() with RESOLVE_NO_XDEV. + mounted, err := mountedByOpenat2(path) + if err == nil { + return mounted, nil + } + // Another fast path: compare st.st_dev fields. + mounted, err = mountedByStat(path) + // This does not work for bind mounts, so false negative + // is possible, therefore only trust if return is true. + if mounted && err == nil { + return mounted, nil + } + + // Fallback to parsing mountinfo + return mountedByMountinfo(path) +} diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go new file mode 100644 index 00000000..efb03978 --- /dev/null +++ b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go @@ -0,0 +1,66 @@ +// +build linux freebsd,cgo openbsd,cgo + +package mountinfo + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "golang.org/x/sys/unix" +) + +func mountedByStat(path string) (bool, error) { + var st unix.Stat_t + + if err := unix.Lstat(path, &st); err != nil { + if err == unix.ENOENT { + // Treat ENOENT as "not mounted". + return false, nil + } + return false, &os.PathError{Op: "stat", Path: path, Err: err} + } + dev := st.Dev + parent := filepath.Dir(path) + if err := unix.Lstat(parent, &st); err != nil { + return false, &os.PathError{Op: "stat", Path: parent, Err: err} + } + if dev != st.Dev { + // Device differs from that of parent, + // so definitely a mount point. + return true, nil + } + // NB: this does not detect bind mounts on Linux. + return false, nil +} + +func normalizePath(path string) (realPath string, err error) { + if realPath, err = filepath.Abs(path); err != nil { + return "", fmt.Errorf("unable to get absolute path for %q: %w", path, err) + } + if realPath, err = filepath.EvalSymlinks(realPath); err != nil { + return "", fmt.Errorf("failed to canonicalise path for %q: %w", path, err) + } + if _, err := os.Stat(realPath); err != nil { + return "", fmt.Errorf("failed to stat target of %q: %w", path, err) + } + return realPath, nil +} + +func mountedByMountinfo(path string) (bool, error) { + path, err := normalizePath(path) + if err != nil { + if errors.Is(err, unix.ENOENT) { + // treat ENOENT as "not mounted" + return false, nil + } + return false, err + } + entries, err := GetMounts(SingleEntryFilter(path)) + if err != nil { + return false, err + } + + return len(entries) > 0, nil +} diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo.go b/vendor/github.com/moby/sys/mountinfo/mountinfo.go index 136b1416..fe828c8f 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo.go @@ -1,6 +1,8 @@ package mountinfo -import "io" +import ( + "os" +) // GetMounts retrieves a list of mounts for the current running process, // with an optional filter applied (use nil for no filter). @@ -8,23 +10,17 @@ func GetMounts(f FilterFunc) ([]*Info, error) { return parseMountTable(f) } -// GetMountsFromReader retrieves a list of mounts from the -// reader provided, with an optional filter applied (use nil -// for no filter). This can be useful in tests or benchmarks -// that provide a fake mountinfo data. -func GetMountsFromReader(reader io.Reader, f FilterFunc) ([]*Info, error) { - return parseInfoFile(reader, f) -} - -// Mounted determines if a specified mountpoint has been mounted. -// On Linux it looks at /proc/self/mountinfo. -func Mounted(mountpoint string) (bool, error) { - entries, err := GetMounts(SingleEntryFilter(mountpoint)) - if err != nil { - return false, err +// Mounted determines if a specified path is a mount point. +// +// The argument must be an absolute path, with all symlinks resolved, and clean. +// One way to ensure it is to process the path using filepath.Abs followed by +// filepath.EvalSymlinks before calling this function. +func Mounted(path string) (bool, error) { + // root is always mounted + if path == string(os.PathSeparator) { + return true, nil } - - return len(entries) > 0, nil + return mounted(path) } // Info reveals information about a particular mounted filesystem. This @@ -50,18 +46,18 @@ type Info struct { // Mountpoint indicates the mount point relative to the process's root. Mountpoint string - // Opts represents mount-specific options. - Opts string + // Options represents mount-specific options. + Options string // Optional represents optional fields. Optional string - // Fstype indicates the type of filesystem, such as EXT3. - Fstype string + // FSType indicates the type of filesystem, such as EXT3. + FSType string // Source indicates filesystem specific information or "none". Source string - // VfsOpts represents per super block options. - VfsOpts string + // VFSOptions represents per super block options. + VFSOptions string } diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go similarity index 73% rename from vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go rename to vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go index a7dbb1b4..b1c12d02 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsd.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go @@ -1,3 +1,5 @@ +// +build freebsd,cgo openbsd,cgo + package mountinfo /* @@ -33,7 +35,7 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) { var mountinfo Info var skip, stop bool mountinfo.Mountpoint = C.GoString(&entry.f_mntonname[0]) - mountinfo.Fstype = C.GoString(&entry.f_fstypename[0]) + mountinfo.FSType = C.GoString(&entry.f_fstypename[0]) mountinfo.Source = C.GoString(&entry.f_mntfromname[0]) if filter != nil { @@ -51,3 +53,15 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) { } return out, nil } + +func mounted(path string) (bool, error) { + // Fast path: compare st.st_dev fields. + // This should always work for FreeBSD and OpenBSD. + mounted, err := mountedByStat(path) + if err == nil { + return mounted, nil + } + + // Fallback to parsing mountinfo + return mountedByMountinfo(path) +} diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go index 79502646..5869b2ce 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go @@ -6,16 +6,16 @@ import "strings" // used to filter out mountinfo entries we're not interested in, // and/or stop further processing if we found what we wanted. // -// It takes a pointer to the Info struct (not fully populated, -// currently only Mountpoint, Fstype, Source, and (on Linux) -// VfsOpts are filled in), and returns two booleans: +// It takes a pointer to the Info struct (fully populated with all available +// fields on the GOOS platform), and returns two booleans: // -// - skip: true if the entry should be skipped -// - stop: true if parsing should be stopped after the entry +// skip: true if the entry should be skipped; +// +// stop: true if parsing should be stopped after the entry. type FilterFunc func(*Info) (skip, stop bool) // PrefixFilter discards all entries whose mount points -// do not start with a specific prefix +// do not start with a specific prefix. func PrefixFilter(prefix string) FilterFunc { return func(m *Info) (bool, bool) { skip := !strings.HasPrefix(m.Mountpoint, prefix) @@ -23,7 +23,7 @@ func PrefixFilter(prefix string) FilterFunc { } } -// SingleEntryFilter looks for a specific entry +// SingleEntryFilter looks for a specific entry. func SingleEntryFilter(mp string) FilterFunc { return func(m *Info) (bool, bool) { if m.Mountpoint == mp { @@ -36,8 +36,8 @@ func SingleEntryFilter(mp string) FilterFunc { // ParentsFilter returns all entries whose mount points // can be parents of a path specified, discarding others. // -// For example, given `/var/lib/docker/something`, entries -// like `/var/lib/docker`, `/var` and `/` are returned. +// For example, given /var/lib/docker/something, entries +// like /var/lib/docker, /var and / are returned. func ParentsFilter(path string) FilterFunc { return func(m *Info) (bool, bool) { skip := !strings.HasPrefix(path, m.Mountpoint) @@ -45,12 +45,12 @@ func ParentsFilter(path string) FilterFunc { } } -// FstypeFilter returns all entries that match provided fstype(s). -func FstypeFilter(fstype ...string) FilterFunc { +// FSTypeFilter returns all entries that match provided fstype(s). +func FSTypeFilter(fstype ...string) FilterFunc { return func(m *Info) (bool, bool) { for _, t := range fstype { - if m.Fstype == t { - return false, false // don't skeep, keep going + if m.FSType == t { + return false, false // don't skip, keep going } } return true, false // skip, keep going diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go index 2d630c8d..e591c836 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go @@ -1,5 +1,3 @@ -// +build go1.13 - package mountinfo import ( @@ -11,14 +9,18 @@ import ( "strings" ) -func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) { +// GetMountsFromReader retrieves a list of mounts from the +// reader provided, with an optional filter applied (use nil +// for no filter). This can be useful in tests or benchmarks +// that provide a fake mountinfo data. +// +// This function is Linux-specific. +func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) { s := bufio.NewScanner(r) out := []*Info{} - var err error for s.Scan() { - if err = s.Err(); err != nil { - return nil, err - } + var err error + /* See http://man7.org/linux/man-pages/man5/proc.5.html @@ -70,26 +72,19 @@ func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) { p := &Info{} - // Fill in the fields that a filter might check - p.Mountpoint, err = strconv.Unquote(`"` + fields[4] + `"`) + p.Mountpoint, err = unescape(fields[4]) if err != nil { - return nil, fmt.Errorf("Parsing '%s' failed: unable to unquote mount point field: %w", fields[4], err) + return nil, fmt.Errorf("Parsing '%s' failed: mount point: %w", fields[4], err) } - p.Fstype = fields[sepIdx+1] - p.Source = fields[sepIdx+2] - p.VfsOpts = fields[sepIdx+3] - - // Run a filter soon so we can skip parsing/adding entries - // the caller is not interested in - var skip, stop bool - if filter != nil { - skip, stop = filter(p) - if skip { - continue - } + p.FSType, err = unescape(fields[sepIdx+1]) + if err != nil { + return nil, fmt.Errorf("Parsing '%s' failed: fstype: %w", fields[sepIdx+1], err) } - - // Fill in the rest of the fields + p.Source, err = unescape(fields[sepIdx+2]) + if err != nil { + return nil, fmt.Errorf("Parsing '%s' failed: source: %w", fields[sepIdx+2], err) + } + p.VFSOptions = fields[sepIdx+3] // ignore any numbers parsing errors, as there should not be any p.ID, _ = strconv.Atoi(fields[0]) @@ -101,12 +96,12 @@ func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) { p.Major, _ = strconv.Atoi(mm[0]) p.Minor, _ = strconv.Atoi(mm[1]) - p.Root, err = strconv.Unquote(`"` + fields[3] + `"`) + p.Root, err = unescape(fields[3]) if err != nil { - return nil, fmt.Errorf("Parsing '%s' failed: unable to unquote root field: %w", fields[3], err) + return nil, fmt.Errorf("Parsing '%s' failed: root: %w", fields[3], err) } - p.Opts = fields[5] + p.Options = fields[5] // zero or more optional fields switch { @@ -118,11 +113,23 @@ func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) { p.Optional = strings.Join(fields[6:sepIdx-1], " ") } + // Run the filter after parsing all of the fields. + var skip, stop bool + if filter != nil { + skip, stop = filter(p) + if skip { + continue + } + } + out = append(out, p) if stop { break } } + if err := s.Err(); err != nil { + return nil, err + } return out, nil } @@ -135,12 +142,17 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) { } defer f.Close() - return parseInfoFile(f, filter) + return GetMountsFromReader(f, filter) } -// PidMountInfo collects the mounts for a specific process ID. If the process -// ID is unknown, it is better to use `GetMounts` which will inspect -// "/proc/self/mountinfo" instead. +// PidMountInfo retrieves the list of mounts from a given process' mount +// namespace. Unless there is a need to get mounts from a mount namespace +// different from that of a calling process, use GetMounts. +// +// This function is Linux-specific. +// +// Deprecated: this will be removed before v1; use GetMountsFromReader with +// opened /proc//mountinfo as an argument instead. func PidMountInfo(pid int) ([]*Info, error) { f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid)) if err != nil { @@ -148,5 +160,63 @@ func PidMountInfo(pid int) ([]*Info, error) { } defer f.Close() - return parseInfoFile(f, nil) + return GetMountsFromReader(f, nil) +} + +// A few specific characters in mountinfo path entries (root and mountpoint) +// are escaped using a backslash followed by a character's ascii code in octal. +// +// space -- as \040 +// tab (aka \t) -- as \011 +// newline (aka \n) -- as \012 +// backslash (aka \\) -- as \134 +// +// This function converts path from mountinfo back, i.e. it unescapes the above sequences. +func unescape(path string) (string, error) { + // try to avoid copying + if strings.IndexByte(path, '\\') == -1 { + return path, nil + } + + // The following code is UTF-8 transparent as it only looks for some + // specific characters (backslash and 0..7) with values < utf8.RuneSelf, + // and everything else is passed through as is. + buf := make([]byte, len(path)) + bufLen := 0 + for i := 0; i < len(path); i++ { + if path[i] != '\\' { + buf[bufLen] = path[i] + bufLen++ + continue + } + s := path[i:] + if len(s) < 4 { + // too short + return "", fmt.Errorf("bad escape sequence %q: too short", s) + } + c := s[1] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7': + v := c - '0' + for j := 2; j < 4; j++ { // one digit already; two more + if s[j] < '0' || s[j] > '7' { + return "", fmt.Errorf("bad escape sequence %q: not a digit", s[:3]) + } + x := s[j] - '0' + v = (v << 3) | x + } + if v > 255 { + return "", fmt.Errorf("bad escape sequence %q: out of range" + s[:3]) + } + buf[bufLen] = v + bufLen++ + i += 3 + continue + default: + return "", fmt.Errorf("bad escape sequence %q: not a digit" + s[:3]) + + } + } + + return string(buf[:bufLen]), nil } diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go index dc186921..d33ebca0 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go @@ -1,17 +1,18 @@ -// +build !windows,!linux,!freebsd freebsd,!cgo +// +build !windows,!linux,!freebsd,!openbsd freebsd,!cgo openbsd,!cgo package mountinfo import ( "fmt" - "io" "runtime" ) +var errNotImplemented = fmt.Errorf("not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) + func parseMountTable(_ FilterFunc) ([]*Info, error) { - return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) + return nil, errNotImplemented } -func parseInfoFile(_ io.Reader, f FilterFunc) ([]*Info, error) { - return parseMountTable(f) +func mounted(path string) (bool, error) { + return false, errNotImplemented } diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go index 69ffdc52..13fad165 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_windows.go @@ -1,12 +1,10 @@ package mountinfo -import "io" - func parseMountTable(_ FilterFunc) ([]*Info, error) { // Do NOT return an error! return nil, nil } -func parseInfoFile(_ io.Reader, f FilterFunc) ([]*Info, error) { - return parseMountTable(f) +func mounted(_ string) (bool, error) { + return false, nil } diff --git a/vendor/modules.txt b/vendor/modules.txt index b56ecb69..27d92a4a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -94,7 +94,7 @@ github.com/containers/ocicrypt/keywrap/pgp github.com/containers/ocicrypt/keywrap/pkcs7 github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/utils -# github.com/containers/storage v1.23.5 +# github.com/containers/storage v1.23.9 github.com/containers/storage github.com/containers/storage/drivers github.com/containers/storage/drivers/aufs @@ -206,7 +206,7 @@ github.com/hashicorp/golang-lru/simplelru github.com/imdario/mergo # github.com/inconshreveable/mousetrap v1.0.0 github.com/inconshreveable/mousetrap -# github.com/klauspost/compress v1.11.0 +# github.com/klauspost/compress v1.11.2 github.com/klauspost/compress/flate github.com/klauspost/compress/fse github.com/klauspost/compress/huff0 @@ -227,7 +227,7 @@ github.com/mattn/go-shellwords github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/mistifyio/go-zfs v2.1.1+incompatible github.com/mistifyio/go-zfs -# github.com/moby/sys/mountinfo v0.1.3 +# github.com/moby/sys/mountinfo v0.4.0 github.com/moby/sys/mountinfo # github.com/mtrmac/gpgme v0.1.2 github.com/mtrmac/gpgme