aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod2
-rw-r--r--go.sum10
-rw-r--r--vendor/github.com/containerd/stargz-snapshotter/estargz/build.go44
-rw-r--r--vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go5
-rw-r--r--vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go5
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/check.go54
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go160
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go141
-rw-r--r--vendor/github.com/containers/storage/go.mod4
-rw-r--r--vendor/github.com/containers/storage/go.sum8
-rw-r--r--vendor/github.com/containers/storage/layers.go65
-rw-r--r--vendor/github.com/containers/storage/store.go10
-rw-r--r--vendor/github.com/containers/storage/utils.go8
-rw-r--r--vendor/github.com/moby/sys/mountinfo/mounted_unix.go7
-rw-r--r--vendor/modules.txt6
15 files changed, 473 insertions, 56 deletions
diff --git a/go.mod b/go.mod
index f1317118c..e41b6982d 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/containers/image/v5 v5.21.1-0.20220405081457-d1b64686e1d0
github.com/containers/ocicrypt v1.1.3
github.com/containers/psgo v1.7.2
- github.com/containers/storage v1.39.1-0.20220412073713-ea4008e14877
+ github.com/containers/storage v1.39.1-0.20220414183333-eea4e0f5f1f9
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cyphar/filepath-securejoin v0.2.3
diff --git a/go.sum b/go.sum
index 1f22ff339..66aa40eb6 100644
--- a/go.sum
+++ b/go.sum
@@ -325,8 +325,9 @@ github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sb
github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac=
github.com/containerd/stargz-snapshotter/estargz v0.11.1/go.mod h1:6VoPcf4M1wvnogWxqc4TqBWWErCS+R+ucnPZId2VbpQ=
-github.com/containerd/stargz-snapshotter/estargz v0.11.3 h1:k2kN16Px6LYuv++qFqK+JTcYqc8bEVxzGpf8/gFBL5M=
github.com/containerd/stargz-snapshotter/estargz v0.11.3/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0=
+github.com/containerd/stargz-snapshotter/estargz v0.11.4 h1:LjrYUZpyOhiSaU7hHrdR82/RBoxfGWSaC0VeSSMXqnk=
+github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@@ -379,8 +380,8 @@ github.com/containers/storage v1.38.2/go.mod h1:INP0RPLHWBxx+pTsO5uiHlDUGHDFvWZP
github.com/containers/storage v1.38.3-0.20220301151551-d06b0f81c0aa/go.mod h1:LkkL34WRi4dI4jt9Cp+ImdZi/P5i36glSHimT5CP5zM=
github.com/containers/storage v1.39.0/go.mod h1:UAD0cKLouN4BOQRgZut/nMjrh/EnTCjSNPgp4ZuGWMs=
github.com/containers/storage v1.39.1-0.20220330193934-f3200eb5a5d9/go.mod h1:IMa2AfBI+Fxxk2hQqLTGhpJX6z2pZS1/I785QJeUwUY=
-github.com/containers/storage v1.39.1-0.20220412073713-ea4008e14877 h1:V3aVdbQt9qU6tu4HHAJtro4H8+Hnv6X/hrUNba8dll0=
-github.com/containers/storage v1.39.1-0.20220412073713-ea4008e14877/go.mod h1:UuYvGSKIdmzkjHbT/PENtxLRVGQ974nyhMbYp0KP19w=
+github.com/containers/storage v1.39.1-0.20220414183333-eea4e0f5f1f9 h1:cB2AvqxpfyqyyffXtDN0txJhD0lIaZWktbSRI92WpN4=
+github.com/containers/storage v1.39.1-0.20220414183333-eea4e0f5f1f9/go.mod h1:hFiHLMgNU0r3MiUpE97hEBaEKCN8fEIuEEBXoFC9eN0=
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=
@@ -1005,8 +1006,9 @@ github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7s
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
-github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo=
github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
+github.com/moby/sys/mountinfo v0.6.1 h1:+H/KnGEAGRpTrEAqNVQ2AM3SiwMgJUt/TXj+Z8cmCIc=
+github.com/moby/sys/mountinfo v0.6.1/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go
index 9ee97fc91..0da3efe4c 100644
--- a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go
+++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go
@@ -26,10 +26,10 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
+ "context"
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"path"
"runtime"
@@ -48,6 +48,7 @@ type options struct {
prioritizedFiles []string
missedPrioritizedFiles *[]string
compression Compression
+ ctx context.Context
}
type Option func(o *options) error
@@ -104,6 +105,14 @@ func WithCompression(compression Compression) Option {
}
}
+// WithContext specifies a context that can be used for clean canceleration.
+func WithContext(ctx context.Context) Option {
+ return func(o *options) error {
+ o.ctx = ctx
+ return nil
+ }
+}
+
// Blob is an eStargz blob.
type Blob struct {
io.ReadCloser
@@ -139,12 +148,29 @@ func Build(tarBlob *io.SectionReader, opt ...Option) (_ *Blob, rErr error) {
opts.compression = newGzipCompressionWithLevel(opts.compressionLevel)
}
layerFiles := newTempFiles()
+ ctx := opts.ctx
+ if ctx == nil {
+ ctx = context.Background()
+ }
+ done := make(chan struct{})
+ defer close(done)
+ go func() {
+ select {
+ case <-done:
+ // nop
+ case <-ctx.Done():
+ layerFiles.CleanupAll()
+ }
+ }()
defer func() {
if rErr != nil {
if err := layerFiles.CleanupAll(); err != nil {
rErr = fmt.Errorf("failed to cleanup tmp files: %v: %w", err, rErr)
}
}
+ if cErr := ctx.Err(); cErr != nil {
+ rErr = fmt.Errorf("error from context %q: %w", cErr, rErr)
+ }
}()
tarBlob, err := decompressBlob(tarBlob, layerFiles)
if err != nil {
@@ -506,12 +532,13 @@ func newTempFiles() *tempFiles {
}
type tempFiles struct {
- files []*os.File
- filesMu sync.Mutex
+ files []*os.File
+ filesMu sync.Mutex
+ cleanupOnce sync.Once
}
func (tf *tempFiles) TempFile(dir, pattern string) (*os.File, error) {
- f, err := ioutil.TempFile(dir, pattern)
+ f, err := os.CreateTemp(dir, pattern)
if err != nil {
return nil, err
}
@@ -521,7 +548,14 @@ func (tf *tempFiles) TempFile(dir, pattern string) (*os.File, error) {
return f, nil
}
-func (tf *tempFiles) CleanupAll() error {
+func (tf *tempFiles) CleanupAll() (err error) {
+ tf.cleanupOnce.Do(func() {
+ err = tf.cleanupAll()
+ })
+ return
+}
+
+func (tf *tempFiles) cleanupAll() error {
tf.filesMu.Lock()
defer tf.filesMu.Unlock()
var allErr []error
diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
index 4b655c145..921e59ec6 100644
--- a/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
+++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
@@ -31,7 +31,6 @@ import (
"fmt"
"hash"
"io"
- "io/ioutil"
"os"
"path"
"sort"
@@ -579,7 +578,7 @@ func (fr *fileReader) ReadAt(p []byte, off int64) (n int, err error) {
return 0, fmt.Errorf("fileReader.ReadAt.decompressor.Reader: %v", err)
}
defer dr.Close()
- if n, err := io.CopyN(ioutil.Discard, dr, off); n != off || err != nil {
+ if n, err := io.CopyN(io.Discard, dr, off); n != off || err != nil {
return 0, fmt.Errorf("discard of %d bytes = %v, %v", off, n, err)
}
return io.ReadFull(dr, p)
@@ -933,7 +932,7 @@ func (w *Writer) appendTar(r io.Reader, lossless bool) error {
}
}
}
- remainDest := ioutil.Discard
+ remainDest := io.Discard
if lossless {
remainDest = dst // Preserve the remaining bytes in lossless mode
}
diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go
index 1de13a470..8f27dfb3e 100644
--- a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go
+++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go
@@ -31,7 +31,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"os"
"reflect"
"sort"
@@ -287,11 +286,11 @@ func isSameTarGz(t *testing.T, controller TestingController, a, b []byte) bool {
return false
}
- aFile, err := ioutil.ReadAll(aTar)
+ aFile, err := io.ReadAll(aTar)
if err != nil {
t.Fatal("failed to read tar payload of A")
}
- bFile, err := ioutil.ReadAll(bTar)
+ bFile, err := io.ReadAll(bTar)
if err != nil {
t.Fatal("failed to read tar payload of B")
}
diff --git a/vendor/github.com/containers/storage/drivers/overlay/check.go b/vendor/github.com/containers/storage/drivers/overlay/check.go
index 44b3515a8..48fb7a550 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/check.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/check.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package overlay
@@ -11,6 +12,7 @@ import (
"syscall"
"github.com/containers/storage/pkg/archive"
+ "github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/mount"
"github.com/containers/storage/pkg/system"
@@ -218,3 +220,55 @@ func doesVolatile(d string) (bool, error) {
}()
return true, nil
}
+
+// supportsIdmappedLowerLayers checks if the kernel supports mounting overlay on top of
+// a idmapped lower layer.
+func supportsIdmappedLowerLayers(home string) (bool, error) {
+ layerDir, err := ioutil.TempDir(home, "compat")
+ if err != nil {
+ return false, err
+ }
+ defer func() {
+ _ = os.RemoveAll(layerDir)
+ }()
+
+ mergedDir := filepath.Join(layerDir, "merged")
+ lowerDir := filepath.Join(layerDir, "lower")
+ lowerMappedDir := filepath.Join(layerDir, "lower-mapped")
+ upperDir := filepath.Join(layerDir, "upper")
+ workDir := filepath.Join(layerDir, "work")
+
+ _ = idtools.MkdirAs(mergedDir, 0700, 0, 0)
+ _ = idtools.MkdirAs(lowerDir, 0700, 0, 0)
+ _ = idtools.MkdirAs(lowerMappedDir, 0700, 0, 0)
+ _ = idtools.MkdirAs(upperDir, 0700, 0, 0)
+ _ = idtools.MkdirAs(workDir, 0700, 0, 0)
+
+ idmap := []idtools.IDMap{
+ {
+ ContainerID: 0,
+ HostID: 0,
+ Size: 1,
+ },
+ }
+ pid, cleanupFunc, err := createUsernsProcess(idmap, idmap)
+ if err != nil {
+ return false, err
+ }
+ defer cleanupFunc()
+
+ if err := createIDMappedMount(lowerDir, lowerMappedDir, int(pid)); err != nil {
+ return false, errors.Wrapf(err, "create mapped mount")
+ }
+ defer unix.Unmount(lowerMappedDir, unix.MNT_DETACH)
+
+ opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerMappedDir, upperDir, workDir)
+ flags := uintptr(0)
+ if err := unix.Mount("overlay", mergedDir, "overlay", flags, opts); err != nil {
+ return false, err
+ }
+ defer func() {
+ _ = unix.Unmount(mergedDir, unix.MNT_DETACH)
+ }()
+ return true, nil
+}
diff --git a/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go b/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go
new file mode 100644
index 000000000..34fdc5790
--- /dev/null
+++ b/vendor/github.com/containers/storage/drivers/overlay/idmapped_utils.go
@@ -0,0 +1,160 @@
+//go:build linux
+// +build linux
+
+package overlay
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "syscall"
+ "unsafe"
+
+ "github.com/containers/storage/pkg/idtools"
+ "github.com/pkg/errors"
+ "golang.org/x/sys/unix"
+)
+
+type attr struct {
+ attrSet uint64
+ attrClr uint64
+ propagation uint64
+ userNs uint64
+}
+
+const (
+ // _MOUNT_ATTR_IDMAP - Idmap mount to @userns_fd in struct mount_attr
+ _MOUNT_ATTR_IDMAP = 0x00100000 //nolint:golint
+
+ // _OPEN_TREE_CLONE - Clone the source path mount
+ _OPEN_TREE_CLONE = 0x00000001 //nolint:golint
+
+ // _MOVE_MOUNT_F_EMPTY_PATH - Move the path referenced by the fd
+ _MOVE_MOUNT_F_EMPTY_PATH = 0x00000004 //nolint:golint
+)
+
+// openTree is a wrapper for the open_tree syscall
+func openTree(path string, flags int) (fd int, err error) {
+ var _p0 *byte
+
+ if _p0, err = syscall.BytePtrFromString(path); err != nil {
+ return 0, err
+ }
+
+ r, _, e1 := syscall.Syscall6(uintptr(unix.SYS_OPEN_TREE), uintptr(0), uintptr(unsafe.Pointer(_p0)),
+ uintptr(flags), 0, 0, 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return int(r), nil
+}
+
+// moveMount is a wrapper for the the move_mount syscall.
+func moveMount(fdTree int, target string) (err error) {
+ var _p0, _p1 *byte
+
+ empty := ""
+
+ if _p0, err = syscall.BytePtrFromString(target); err != nil {
+ return err
+ }
+ if _p1, err = syscall.BytePtrFromString(empty); err != nil {
+ return err
+ }
+
+ flags := _MOVE_MOUNT_F_EMPTY_PATH
+
+ _, _, e1 := syscall.Syscall6(uintptr(unix.SYS_MOVE_MOUNT),
+ uintptr(fdTree), uintptr(unsafe.Pointer(_p1)),
+ 0, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// mountSetAttr is a wrapper for the mount_setattr syscall
+func mountSetAttr(dfd int, path string, flags uint, attr *attr, size uint) (err error) {
+ var _p0 *byte
+
+ if _p0, err = syscall.BytePtrFromString(path); err != nil {
+ return err
+ }
+
+ _, _, e1 := syscall.Syscall6(uintptr(unix.SYS_MOUNT_SETATTR), uintptr(dfd), uintptr(unsafe.Pointer(_p0)),
+ uintptr(flags), uintptr(unsafe.Pointer(attr)), uintptr(size), 0)
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
+
+// createIDMappedMount creates a IDMapped bind mount from SOURCE to TARGET using the user namespace
+// for the PID process.
+func createIDMappedMount(source, target string, pid int) error {
+ path := fmt.Sprintf("/proc/%d/ns/user", pid)
+ userNsFile, err := os.Open(path)
+ if err != nil {
+ return errors.Wrapf(err, "unable to get user ns file descriptor for %q", path)
+ }
+
+ var attr attr
+ attr.attrSet = _MOUNT_ATTR_IDMAP
+ attr.attrClr = 0
+ attr.propagation = 0
+ attr.userNs = uint64(userNsFile.Fd())
+
+ defer userNsFile.Close()
+
+ targetDirFd, err := openTree(source, _OPEN_TREE_CLONE|unix.AT_RECURSIVE)
+ if err != nil {
+ return err
+ }
+ defer unix.Close(targetDirFd)
+
+ if err := mountSetAttr(targetDirFd, "", unix.AT_EMPTY_PATH|unix.AT_RECURSIVE,
+ &attr, uint(unsafe.Sizeof(attr))); err != nil {
+ return err
+ }
+ if err := os.Mkdir(target, 0700); err != nil && !os.IsExist(err) {
+ return err
+ }
+ return moveMount(targetDirFd, target)
+}
+
+// createUsernsProcess forks the current process and creates a user namespace using the specified
+// mappings. It returns the pid of the new process.
+func createUsernsProcess(uidMaps []idtools.IDMap, gidMaps []idtools.IDMap) (int, func(), error) {
+ pid, _, err := syscall.Syscall6(uintptr(unix.SYS_CLONE), unix.CLONE_NEWUSER|uintptr(unix.SIGCHLD), 0, 0, 0, 0, 0)
+ if err != 0 {
+ return -1, nil, err
+ }
+ if pid == 0 {
+ _ = unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(unix.SIGKILL), 0, 0, 0)
+ // just wait for the SIGKILL
+ for {
+ syscall.Syscall6(uintptr(unix.SYS_PAUSE), 0, 0, 0, 0, 0, 0)
+ }
+ }
+ cleanupFunc := func() {
+ unix.Kill(int(pid), unix.SIGKILL)
+ _, _ = unix.Wait4(int(pid), nil, 0, nil)
+ }
+ writeMappings := func(fname string, idmap []idtools.IDMap) error {
+ mappings := ""
+ for _, m := range idmap {
+ mappings = mappings + fmt.Sprintf("%d %d %d\n", m.ContainerID, m.HostID, m.Size)
+ }
+ return ioutil.WriteFile(fmt.Sprintf("/proc/%d/%s", pid, fname), []byte(mappings), 0600)
+ }
+ if err := writeMappings("uid_map", uidMaps); err != nil {
+ cleanupFunc()
+ return -1, nil, err
+ }
+ if err := writeMappings("gid_map", gidMaps); err != nil {
+ cleanupFunc()
+ return -1, nil, err
+ }
+
+ return int(pid), cleanupFunc, nil
+}
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index a780ef5da..c911acb5c 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -39,7 +39,6 @@ import (
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
- "github.com/vbatts/tar-split/tar/storage"
"golang.org/x/sys/unix"
)
@@ -121,6 +120,8 @@ type Driver struct {
supportsVolatile *bool
usingMetacopy bool
locker *locker.Locker
+
+ supportsIDMappedMounts *bool
}
type additionalLayerStore struct {
@@ -205,6 +206,26 @@ func checkSupportVolatile(home, runhome string) (bool, error) {
return usingVolatile, nil
}
+// checkAndRecordIDMappedSupport checks and stores if the kernel supports mounting overlay on top of a
+// idmapped lower layer.
+func checkAndRecordIDMappedSupport(home, runhome string) (bool, error) {
+ feature := "idmapped-lower-dir"
+ overlayCacheResult, overlayCacheText, err := cachedFeatureCheck(runhome, feature)
+ if err == nil {
+ if overlayCacheResult {
+ logrus.Debugf("Cached value indicated that overlay is supported")
+ return true, nil
+ }
+ logrus.Debugf("Cached value indicated that overlay is not supported")
+ return false, errors.New(overlayCacheText)
+ }
+ supportsIDMappedMounts, err := supportsIdmappedLowerLayers(home)
+ if err2 := cachedFeatureRecord(runhome, feature, supportsIDMappedMounts, ""); err2 != nil {
+ return false, errors.Wrap(err2, "recording overlay idmapped mounts support status")
+ }
+ return supportsIDMappedMounts, err
+}
+
func checkAndRecordOverlaySupport(fsMagic graphdriver.FsMagic, home, runhome string) (bool, error) {
var supportsDType bool
@@ -1485,6 +1506,51 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
}
}
+ if d.supportsIDmappedMounts() && len(options.UidMaps) > 0 && len(options.GidMaps) > 0 {
+ var newAbsDir []string
+ mappedRoot := filepath.Join(d.home, id, "mapped")
+ if err := os.MkdirAll(mappedRoot, 0700); err != nil {
+ return "", err
+ }
+
+ pid, cleanupFunc, err := createUsernsProcess(options.UidMaps, options.GidMaps)
+ if err != nil {
+ return "", err
+ }
+ defer cleanupFunc()
+
+ idMappedMounts := make(map[string]string)
+
+ // rewrite the lower dirs to their idmapped mount.
+ c := 0
+ for _, absLower := range absLowers {
+ mappedMountSrc := getMappedMountRoot(absLower)
+
+ root, found := idMappedMounts[mappedMountSrc]
+ if !found {
+ root = filepath.Join(mappedRoot, fmt.Sprintf("%d", c))
+ c++
+ if err := createIDMappedMount(mappedMountSrc, root, int(pid)); err != nil {
+ return "", errors.Wrapf(err, "create mapped mount for %q on %q", mappedMountSrc, root)
+ }
+ idMappedMounts[mappedMountSrc] = root
+
+ // overlay takes a reference on the mount, so it is safe to unmount
+ // the mapped idmounts as soon as the final overlay file system is mounted.
+ defer unix.Unmount(root, unix.MNT_DETACH)
+ }
+
+ // relative path to the layer through the id mapped mount
+ rel, err := filepath.Rel(mappedMountSrc, absLower)
+ if err != nil {
+ return "", err
+ }
+
+ newAbsDir = append(newAbsDir, filepath.Join(root, rel))
+ }
+ absLowers = newAbsDir
+ }
+
var opts string
if readWrite {
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workdir)
@@ -1587,6 +1653,18 @@ func (d *Driver) Put(id string) error {
unmounted := false
+ mappedRoot := filepath.Join(d.home, id, "mapped")
+ // It should not happen, but cleanup any mapped mount if it was leaked.
+ if _, err := os.Stat(mappedRoot); err == nil {
+ mounts, err := ioutil.ReadDir(mappedRoot)
+ if err == nil {
+ // Go through all of the mapped mounts.
+ for _, m := range mounts {
+ _ = unix.Unmount(filepath.Join(mappedRoot, m.Name()), unix.MNT_DETACH)
+ }
+ }
+ }
+
if d.options.mountProgram != "" {
// Attempt to unmount the FUSE mount using either fusermount or fusermount3.
// If they fail, fallback to unix.Unmount
@@ -1664,11 +1742,24 @@ func (d *Driver) getWhiteoutFormat() archive.WhiteoutFormat {
return whiteoutFormat
}
-type fileGetNilCloser struct {
- storage.FileGetter
+type overlayFileGetter struct {
+ diffDirs []string
+}
+
+func (g *overlayFileGetter) Get(path string) (io.ReadCloser, error) {
+ for _, d := range g.diffDirs {
+ f, err := os.Open(filepath.Join(d, path))
+ if err == nil {
+ return f, nil
+ }
+ }
+ if len(g.diffDirs) > 0 {
+ return os.Open(filepath.Join(g.diffDirs[0], path))
+ }
+ return nil, fmt.Errorf("%s: %w", path, os.ErrNotExist)
}
-func (f fileGetNilCloser) Close() error {
+func (g *overlayFileGetter) Close() error {
return nil
}
@@ -1677,13 +1768,18 @@ func (d *Driver) getStagingDir() string {
}
// DiffGetter returns a FileGetCloser that can read files from the directory that
-// contains files for the layer differences. Used for direct access for tar-split.
+// contains files for the layer differences, either for this layer, or one of our
+// lowers if we're just a template directory. Used for direct access for tar-split.
func (d *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
p, err := d.getDiffPath(id)
if err != nil {
return nil, err
}
- return fileGetNilCloser{storage.NewPathFileGetter(p)}, nil
+ paths, err := d.getLowerDiffPaths(id)
+ if err != nil {
+ return nil, err
+ }
+ return &overlayFileGetter{diffDirs: append([]string{p}, paths...)}, nil
}
// CleanupStagingDirectory cleanups the staging directory.
@@ -1958,12 +2054,31 @@ func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMapp
return nil
}
+// supportsIDmappedMounts returns whether the kernel supports using idmapped mounts with
+// overlay lower layers.
+func (d *Driver) supportsIDmappedMounts() bool {
+ if d.supportsIDMappedMounts != nil {
+ return *d.supportsIDMappedMounts
+ }
+
+ supportsIDMappedMounts, err := checkAndRecordIDMappedSupport(d.home, d.runhome)
+ d.supportsIDMappedMounts = &supportsIDMappedMounts
+ if err == nil {
+ return supportsIDMappedMounts
+ }
+ logrus.Debugf("Check for idmapped mounts support %v", err)
+ return false
+}
+
// SupportsShifting tells whether the driver support shifting of the UIDs/GIDs in an userNS
func (d *Driver) SupportsShifting() bool {
if os.Getenv("_TEST_FORCE_SUPPORT_SHIFTING") == "yes-please" {
return true
}
- return d.options.mountProgram != ""
+ if d.options.mountProgram != "" {
+ return true
+ }
+ return d.supportsIDmappedMounts()
}
// dumbJoin is more or less a dumber version of filepath.Join, but one which
@@ -2132,3 +2247,15 @@ func redirectDiffIfAdditionalLayer(diffPath string) (string, error) {
}
return diffPath, nil
}
+
+// getMappedMountRoot is a heuristic that calculates the parent directory where
+// the idmapped mount should be applied.
+// It is useful to minimize the number of idmapped mounts and at the same time use
+// a common path as long as possible to reduce the length of the mount data argument.
+func getMappedMountRoot(path string) string {
+ dirName := filepath.Dir(path)
+ if filepath.Base(dirName) == linkDir {
+ return filepath.Dir(dirName)
+ }
+ return dirName
+}
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 8645bbf60..1915ea65d 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -6,7 +6,7 @@ require (
github.com/BurntSushi/toml v1.1.0
github.com/Microsoft/go-winio v0.5.2
github.com/Microsoft/hcsshim v0.9.2
- github.com/containerd/stargz-snapshotter/estargz v0.11.3
+ github.com/containerd/stargz-snapshotter/estargz v0.11.4
github.com/cyphar/filepath-securejoin v0.2.3
github.com/docker/go-units v0.4.0
github.com/google/go-intervals v0.0.2
@@ -16,7 +16,7 @@ require (
github.com/klauspost/pgzip v1.2.5
github.com/mattn/go-shellwords v1.0.12
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible
- github.com/moby/sys/mountinfo v0.6.0
+ github.com/moby/sys/mountinfo v0.6.1
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/runc v1.1.1
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index 34924ada5..cd5bf3b97 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -176,8 +176,8 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
-github.com/containerd/stargz-snapshotter/estargz v0.11.3 h1:k2kN16Px6LYuv++qFqK+JTcYqc8bEVxzGpf8/gFBL5M=
-github.com/containerd/stargz-snapshotter/estargz v0.11.3/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0=
+github.com/containerd/stargz-snapshotter/estargz v0.11.4 h1:LjrYUZpyOhiSaU7hHrdR82/RBoxfGWSaC0VeSSMXqnk=
+github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
@@ -467,8 +467,8 @@ github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQ
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
-github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo=
-github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
+github.com/moby/sys/mountinfo v0.6.1 h1:+H/KnGEAGRpTrEAqNVQ2AM3SiwMgJUt/TXj+Z8cmCIc=
+github.com/moby/sys/mountinfo v0.6.1/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index 8a5616dfc..5e9930ea7 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -725,12 +725,32 @@ func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLab
parent = parentLayer.ID
}
var parentMappings, templateIDMappings, oldMappings *idtools.IDMappings
+ var (
+ templateMetadata string
+ templateCompressedDigest digest.Digest
+ templateCompressedSize int64
+ templateUncompressedDigest digest.Digest
+ templateUncompressedSize int64
+ templateCompressionType archive.Compression
+ templateUIDs, templateGIDs []uint32
+ templateTSdata []byte
+ )
if moreOptions.TemplateLayer != "" {
+ var tserr error
templateLayer, ok := r.lookup(moreOptions.TemplateLayer)
if !ok {
return nil, -1, ErrLayerUnknown
}
+ templateMetadata = templateLayer.Metadata
templateIDMappings = idtools.NewIDMappingsFromMaps(templateLayer.UIDMap, templateLayer.GIDMap)
+ templateCompressedDigest, templateCompressedSize = templateLayer.CompressedDigest, templateLayer.CompressedSize
+ templateUncompressedDigest, templateUncompressedSize = templateLayer.UncompressedDigest, templateLayer.UncompressedSize
+ templateCompressionType = templateLayer.CompressionType
+ templateUIDs, templateGIDs = append([]uint32{}, templateLayer.UIDs...), append([]uint32{}, templateLayer.GIDs...)
+ templateTSdata, tserr = ioutil.ReadFile(r.tspath(templateLayer.ID))
+ if tserr != nil && !os.IsNotExist(tserr) {
+ return nil, -1, tserr
+ }
} else {
templateIDMappings = &idtools.IDMappings{}
}
@@ -775,17 +795,43 @@ func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLab
return nil, -1, err
}
}
+ if len(templateTSdata) > 0 {
+ if err := os.MkdirAll(filepath.Dir(r.tspath(id)), 0o700); err != nil {
+ // We don't have a record of this layer, but at least
+ // try to clean it up underneath us.
+ if err2 := r.driver.Remove(id); err2 != nil {
+ logrus.Errorf("While recovering from a failure creating in UpdateLayerIDMap, error deleting layer %#v: %v", id, err2)
+ }
+ return nil, -1, err
+ }
+ if err = ioutils.AtomicWriteFile(r.tspath(id), templateTSdata, 0o600); err != nil {
+ // We don't have a record of this layer, but at least
+ // try to clean it up underneath us.
+ if err2 := r.driver.Remove(id); err2 != nil {
+ logrus.Errorf("While recovering from a failure creating in UpdateLayerIDMap, error deleting layer %#v: %v", id, err2)
+ }
+ return nil, -1, err
+ }
+ }
if err == nil {
layer = &Layer{
- ID: id,
- Parent: parent,
- Names: names,
- MountLabel: mountLabel,
- Created: time.Now().UTC(),
- Flags: make(map[string]interface{}),
- UIDMap: copyIDMap(moreOptions.UIDMap),
- GIDMap: copyIDMap(moreOptions.GIDMap),
- BigDataNames: []string{},
+ ID: id,
+ Parent: parent,
+ Names: names,
+ MountLabel: mountLabel,
+ Metadata: templateMetadata,
+ Created: time.Now().UTC(),
+ CompressedDigest: templateCompressedDigest,
+ CompressedSize: templateCompressedSize,
+ UncompressedDigest: templateUncompressedDigest,
+ UncompressedSize: templateUncompressedSize,
+ CompressionType: templateCompressionType,
+ UIDs: templateUIDs,
+ GIDs: templateGIDs,
+ Flags: make(map[string]interface{}),
+ UIDMap: copyIDMap(moreOptions.UIDMap),
+ GIDMap: copyIDMap(moreOptions.GIDMap),
+ BigDataNames: []string{},
}
r.layers = append(r.layers, layer)
r.idindex.Add(id)
@@ -872,7 +918,6 @@ func (r *layerStore) Mounted(id string) (int, error) {
}
func (r *layerStore) Mount(id string, options drivers.MountOpts) (string, error) {
-
// check whether options include ro option
hasReadOnlyOpt := func(opts []string) bool {
for _, item := range opts {
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 6b40b68ca..30d3e8715 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -2452,6 +2452,10 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error)
}
layer := image.TopLayer
layersToRemoveMap := make(map[string]struct{})
+ layersToRemove = append(layersToRemove, image.MappedTopLayers...)
+ for _, mappedTopLayer := range image.MappedTopLayers {
+ layersToRemoveMap[mappedTopLayer] = struct{}{}
+ }
for layer != "" {
if rcstore.Exists(layer) {
break
@@ -2483,12 +2487,6 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error)
if hasChildrenNotBeingRemoved() {
break
}
- if layer == image.TopLayer {
- layersToRemove = append(layersToRemove, image.MappedTopLayers...)
- for _, mappedTopLayer := range image.MappedTopLayers {
- layersToRemoveMap[mappedTopLayer] = struct{}{}
- }
- }
layersToRemove = append(layersToRemove, layer)
layersToRemoveMap[layer] = struct{}{}
layer = parent
diff --git a/vendor/github.com/containers/storage/utils.go b/vendor/github.com/containers/storage/utils.go
index cec377f26..37d4b79b0 100644
--- a/vendor/github.com/containers/storage/utils.go
+++ b/vendor/github.com/containers/storage/utils.go
@@ -42,13 +42,14 @@ func validateMountOptions(mountOptions []string) error {
}
func applyNameOperation(oldNames []string, opParameters []string, op updateNameOperation) ([]string, error) {
- result := make([]string, 0)
+ var result []string
switch op {
case setNames:
// ignore all old names and just return new names
- return dedupeNames(opParameters), nil
+ result = opParameters
case removeNames:
// remove given names from old names
+ result = make([]string, 0, len(oldNames))
for _, name := range oldNames {
// only keep names in final result which do not intersect with input names
// basically `result = oldNames - opParameters`
@@ -62,11 +63,10 @@ func applyNameOperation(oldNames []string, opParameters []string, op updateNameO
result = append(result, name)
}
}
- return dedupeNames(result), nil
case addNames:
+ result = make([]string, 0, len(opParameters)+len(oldNames))
result = append(result, opParameters...)
result = append(result, oldNames...)
- return dedupeNames(result), nil
default:
return result, errInvalidUpdateNameOperation
}
diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
index 45ddad236..242f82cc7 100644
--- a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
+++ b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go
@@ -4,7 +4,6 @@
package mountinfo
import (
- "fmt"
"os"
"path/filepath"
@@ -33,13 +32,13 @@ func mountedByStat(path string) (bool, error) {
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)
+ return "", err
}
if realPath, err = filepath.EvalSymlinks(realPath); err != nil {
- return "", fmt.Errorf("failed to canonicalise path for %q: %w", path, err)
+ return "", err
}
if _, err := os.Stat(realPath); err != nil {
- return "", fmt.Errorf("failed to stat target of %q: %w", path, err)
+ return "", err
}
return realPath, nil
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index d6d26b561..1f878d2ef 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -69,7 +69,7 @@ github.com/containerd/containerd/log
github.com/containerd/containerd/pkg/userns
github.com/containerd/containerd/platforms
github.com/containerd/containerd/sys
-# github.com/containerd/stargz-snapshotter/estargz v0.11.3
+# github.com/containerd/stargz-snapshotter/estargz v0.11.4
github.com/containerd/stargz-snapshotter/estargz
github.com/containerd/stargz-snapshotter/estargz/errorutil
# github.com/containernetworking/cni v1.0.1
@@ -233,7 +233,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.39.1-0.20220412073713-ea4008e14877
+# github.com/containers/storage v1.39.1-0.20220414183333-eea4e0f5f1f9
## explicit
github.com/containers/storage
github.com/containers/storage/drivers
@@ -479,7 +479,7 @@ github.com/mistifyio/go-zfs
github.com/mitchellh/mapstructure
# github.com/moby/sys/mount v0.2.0
github.com/moby/sys/mount
-# github.com/moby/sys/mountinfo v0.6.0
+# github.com/moby/sys/mountinfo v0.6.1
github.com/moby/sys/mountinfo
# github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
## explicit