From 3ebb4467fdfa5dd3ef7d46d592be06a0ba179807 Mon Sep 17 00:00:00 2001 From: xiadanni Date: Fri, 4 Jun 2021 12:46:21 +0800 Subject: [PATCH] runc:add mount destination validation(fix CVE-2021-30465) Signed-off-by: xiadanni (cherry picked from commit e026adfb26b4d945e631369d5359720d1d097056) --- ...-destination-validation-fix-CVE-2021.patch | 1344 +++++++++++++++++ runc-openeuler.spec | 8 +- series.conf | 1 + 3 files changed, 1352 insertions(+), 1 deletion(-) create mode 100644 patch/0126-runc-add-mount-destination-validation-fix-CVE-2021.patch diff --git a/patch/0126-runc-add-mount-destination-validation-fix-CVE-2021.patch b/patch/0126-runc-add-mount-destination-validation-fix-CVE-2021.patch new file mode 100644 index 0000000..5649b87 --- /dev/null +++ b/patch/0126-runc-add-mount-destination-validation-fix-CVE-2021.patch @@ -0,0 +1,1344 @@ +From d0b1d58edca28b6e4264abb1645fa8f7e56fc03e Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Thu, 3 Jun 2021 19:58:55 +0800 +Subject: [PATCH] rootfs:add mount destination validation(fix CVE-2021-30465) + +Conflict:NA +Reference:https://github.com/opencontainers/runc/commit/0ca91f44f1664da834bc61115a849b56d22f595f + +Signed-off-by: xiadanni +--- + libcontainer/init_linux.go | 1 + + libcontainer/rootfs_linux.go | 38 ++- + libcontainer/utils/utils.go | 69 +++++ + .../cyphar/filepath-securejoin/.travis.yml | 19 ++ + .../cyphar/filepath-securejoin/LICENSE | 28 ++ + .../cyphar/filepath-securejoin/README.md | 65 ++++ + .../cyphar/filepath-securejoin/VERSION | 1 + + .../cyphar/filepath-securejoin/join.go | 134 ++++++++ + .../cyphar/filepath-securejoin/vendor.conf | 1 + + .../cyphar/filepath-securejoin/vfs.go | 41 +++ + vendor/github.com/pkg/errors/.gitignore | 24 ++ + vendor/github.com/pkg/errors/.travis.yml | 10 + + vendor/github.com/pkg/errors/LICENSE | 23 ++ + vendor/github.com/pkg/errors/Makefile | 44 +++ + vendor/github.com/pkg/errors/README.md | 59 ++++ + vendor/github.com/pkg/errors/appveyor.yml | 32 ++ + vendor/github.com/pkg/errors/errors.go | 288 ++++++++++++++++++ + vendor/github.com/pkg/errors/go113.go | 38 +++ + vendor/github.com/pkg/errors/stack.go | 177 +++++++++++ + 19 files changed, 1080 insertions(+), 12 deletions(-) + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/.travis.yml + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/LICENSE + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/README.md + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/VERSION + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/join.go + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/vendor.conf + create mode 100644 vendor/github.com/cyphar/filepath-securejoin/vfs.go + create mode 100644 vendor/github.com/pkg/errors/.gitignore + create mode 100644 vendor/github.com/pkg/errors/.travis.yml + create mode 100644 vendor/github.com/pkg/errors/LICENSE + create mode 100644 vendor/github.com/pkg/errors/Makefile + create mode 100644 vendor/github.com/pkg/errors/README.md + create mode 100644 vendor/github.com/pkg/errors/appveyor.yml + create mode 100644 vendor/github.com/pkg/errors/errors.go + create mode 100644 vendor/github.com/pkg/errors/go113.go + create mode 100644 vendor/github.com/pkg/errors/stack.go + +diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go +index 73505ef9..ee632b4c 100644 +--- a/libcontainer/init_linux.go ++++ b/libcontainer/init_linux.go +@@ -71,6 +71,7 @@ func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, stateDi + if err := json.NewDecoder(pipe).Decode(&config); err != nil { + return nil, err + } ++ utils.ConfigRootfs = config.Config.Rootfs + if err := populateProcessEnvironment(config.Env); err != nil { + return nil, err + } +diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go +index 4c184822..908e9d53 100644 +--- a/libcontainer/rootfs_linux.go ++++ b/libcontainer/rootfs_linux.go +@@ -14,6 +14,7 @@ import ( + "syscall" + "time" + ++ securejoin "github.com/cyphar/filepath-securejoin" + "github.com/docker/docker/pkg/mount" + "github.com/docker/docker/pkg/symlink" + "github.com/mrunalp/fileutils" +@@ -161,9 +162,13 @@ func mountCmd(cmd configs.Command) error { + func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { + var ( + dest = m.Destination ++ err error + ) + if !strings.HasPrefix(dest, rootfs) { +- dest = filepath.Join(rootfs, dest) ++ dest, err = securejoin.SecureJoin(rootfs, m.Destination) ++ if err != nil { ++ return err ++ } + } + + switch m.Device { +@@ -216,7 +221,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { + } + return errMsg + } +- if err := syscall.Mount(tmpDir, dest, "", syscall.MS_MOVE, ""); err != nil { ++ if err := libcontainerUtils.Mount(tmpDir, dest, "", syscall.MS_MOVE, ""); err != nil { + errMsg := fmt.Errorf("tmpcopyup: failed to move mount %s to %s: %v", tmpDir, dest, err) + if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil { + return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg) +@@ -494,12 +499,15 @@ func bindMountDeviceNode(dest string, node *configs.Device) error { + if f != nil { + f.Close() + } +- return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "") ++ return libcontainerUtils.Mount(node.Path, dest, "bind", syscall.MS_BIND, "") + } + + // Creates the device node in the rootfs of the container. + func createDeviceNode(rootfs string, node *configs.Device, bind bool) error { +- dest := filepath.Join(rootfs, node.Path) ++ dest, err := securejoin.SecureJoin(rootfs, node.Path) ++ if err != nil { ++ return err ++ } + if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + return err + } +@@ -815,14 +823,16 @@ func writeSystemProperty(key, value string) error { + func remount(m *configs.Mount, rootfs string) error { + var ( + dest = m.Destination ++ err error + ) + if !strings.HasPrefix(dest, rootfs) { +- dest = filepath.Join(rootfs, dest) +- } +- if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil { +- return err ++ dest, err = securejoin.SecureJoin(rootfs, dest) ++ if err != nil { ++ return err ++ } + } +- return nil ++ ++ return libcontainerUtils.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), "") + } + + // Do the mount operation followed by additional mounts required to take care +@@ -832,6 +842,7 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { + dest = m.Destination + data = label.FormatMountLabel(m.Data, mountLabel) + flags = m.Flags ++ err error + ) + if libcontainerUtils.CleanPath(dest) == "/dev" { + flags &= ^syscall.MS_RDONLY +@@ -839,15 +850,18 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { + + copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP + if !(copyUp || strings.HasPrefix(dest, rootfs)) { +- dest = filepath.Join(rootfs, dest) ++ dest, err = securejoin.SecureJoin(rootfs, dest) ++ if err != nil { ++ return err ++ } + } + +- if err := syscall.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil { ++ if err = libcontainerUtils.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil { + return err + } + + for _, pflag := range m.PropagationFlags { +- if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil { ++ if err := libcontainerUtils.Mount("", dest, "", uintptr(pflag), ""); err != nil { + return err + } + } +diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go +index 2b35b9a7..bdd13d49 100644 +--- a/libcontainer/utils/utils.go ++++ b/libcontainer/utils/utils.go +@@ -4,18 +4,25 @@ import ( + "crypto/rand" + "encoding/hex" + "encoding/json" ++ "fmt" + "io" + "os" + "path/filepath" ++ "strconv" + "strings" + "syscall" + "unsafe" ++ ++ securejoin "github.com/cyphar/filepath-securejoin" ++ "golang.org/x/sys/unix" + ) + + const ( + exitSignalOffset = 128 + ) + ++var ConfigRootfs string ++ + // GenerateRandomName returns a new name joined with a prefix. This size + // specified is used to truncate the randomly generated value + func GenerateRandomName(prefix string, size int) (string, error) { +@@ -124,3 +131,65 @@ func Annotations(labels []string) (bundle string, userAnnotations map[string]str + func GetIntSize() int { + return int(unsafe.Sizeof(1)) + } ++ ++func Mount(source, target, fstype string, flags uintptr, data string) error { ++ if ConfigRootfs == "" { ++ panic("rootfs is not inited from config.json") ++ } ++ return WithProcfd(ConfigRootfs, target, func(procfd string) error { ++ return syscall.Mount(source, procfd, fstype, flags, data) ++ }) ++} ++ ++// stripRoot returns the passed path, stripping the root path if it was ++// (lexicially) inside it. Note that both passed paths will always be treated ++// as absolute, and the returned path will also always be absolute. In ++// addition, the paths are cleaned before stripping the root. ++func stripRoot(root, path string) string { ++ // Make the paths clean and absolute. ++ root, path = CleanPath("/"+root), CleanPath("/"+path) ++ switch { ++ case path == root: ++ path = "/" ++ case root == "/": ++ // do nothing ++ case strings.HasPrefix(path, root+"/"): ++ path = strings.TrimPrefix(path, root+"/") ++ default: ++ panic("invalid path to mount, path not begin with rootfs") ++ } ++ return CleanPath("/" + path) ++} ++ ++// WithProcfd runs the passed closure with a procfd path (/proc/self/fd/...) ++// corresponding to the unsafePath resolved within the root. Before passing the ++// fd, this path is verified to have been inside the root -- so operating on it ++// through the passed fdpath should be safe. Do not access this path through ++// the original path strings, and do not attempt to use the pathname outside of ++// the passed closure (the file handle will be freed once the closure returns). ++func WithProcfd(root, unsafePath string, fn func(procfd string) error) error { ++ // Remove the root then forcefully resolve inside the root. ++ unsafePath = stripRoot(root, unsafePath) ++ path, err := securejoin.SecureJoin(root, unsafePath) ++ if err != nil { ++ return fmt.Errorf("resolving path inside rootfs failed: %v", err) ++ } ++ ++ // Open the target path. ++ fh, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC, 0) ++ if err != nil { ++ return fmt.Errorf("open o_path procfd: %w", err) ++ } ++ defer fh.Close() ++ ++ // Double-check the path is the one we expected. ++ procfd := "/proc/self/fd/" + strconv.Itoa(int(fh.Fd())) ++ if realpath, err := os.Readlink(procfd); err != nil { ++ return fmt.Errorf("procfd verification failed: %w", err) ++ } else if realpath != path { ++ return fmt.Errorf("possibly malicious path detected -- refusing to operate on %s", realpath) ++ } ++ ++ // Run the closure. ++ return fn(procfd) ++} +diff --git a/vendor/github.com/cyphar/filepath-securejoin/.travis.yml b/vendor/github.com/cyphar/filepath-securejoin/.travis.yml +new file mode 100644 +index 00000000..3938f383 +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/.travis.yml +@@ -0,0 +1,19 @@ ++# Copyright (C) 2017 SUSE LLC. All rights reserved. ++# Use of this source code is governed by a BSD-style ++# license that can be found in the LICENSE file. ++ ++language: go ++go: ++ - 1.7.x ++ - 1.8.x ++ - tip ++ ++os: ++ - linux ++ - osx ++ ++script: ++ - go test -cover -v ./... ++ ++notifications: ++ email: false +diff --git a/vendor/github.com/cyphar/filepath-securejoin/LICENSE b/vendor/github.com/cyphar/filepath-securejoin/LICENSE +new file mode 100644 +index 00000000..bec842f2 +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/LICENSE +@@ -0,0 +1,28 @@ ++Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. ++Copyright (C) 2017 SUSE LLC. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are ++met: ++ ++ * Redistributions of source code must retain the above copyright ++notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above ++copyright notice, this list of conditions and the following disclaimer ++in the documentation and/or other materials provided with the ++distribution. ++ * Neither the name of Google Inc. nor the names of its ++contributors may be used to endorse or promote products derived from ++this software without specific prior written permission. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +diff --git a/vendor/github.com/cyphar/filepath-securejoin/README.md b/vendor/github.com/cyphar/filepath-securejoin/README.md +new file mode 100644 +index 00000000..49b2baa9 +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/README.md +@@ -0,0 +1,65 @@ ++## `filepath-securejoin` ## ++ ++[![Build Status](https://travis-ci.org/cyphar/filepath-securejoin.svg?branch=master)](https://travis-ci.org/cyphar/filepath-securejoin) ++ ++An implementation of `SecureJoin`, a [candidate for inclusion in the Go ++standard library][go#20126]. The purpose of this function is to be a "secure" ++alternative to `filepath.Join`, and in particular it provides certain ++guarantees that are not provided by `filepath.Join`. ++ ++This is the function prototype: ++ ++```go ++func SecureJoin(root, unsafePath string) (string, error) ++``` ++ ++This library **guarantees** the following: ++ ++* If no error is set, the resulting string **must** be a child path of ++ `SecureJoin` and will not contain any symlink path components (they will all ++ be expanded). ++ ++* When expanding symlinks, all symlink path components **must** be resolved ++ relative to the provided root. In particular, this can be considered a ++ userspace implementation of how `chroot(2)` operates on file paths. Note that ++ these symlinks will **not** be expanded lexically (`filepath.Clean` is not ++ called on the input before processing). ++ ++* Non-existant path components are unaffected by `SecureJoin` (similar to ++ `filepath.EvalSymlinks`'s semantics). ++ ++* The returned path will always be `filepath.Clean`ed and thus not contain any ++ `..` components. ++ ++A (trivial) implementation of this function on GNU/Linux systems could be done ++with the following (note that this requires root privileges and is far more ++opaque than the implementation in this library, and also requires that ++`readlink` is inside the `root` path): ++ ++```go ++package securejoin ++ ++import ( ++ "os/exec" ++ "path/filepath" ++) ++ ++func SecureJoin(root, unsafePath string) (string, error) { ++ unsafePath = string(filepath.Separator) + unsafePath ++ cmd := exec.Command("chroot", root, ++ "readlink", "--canonicalize-missing", "--no-newline", unsafePath) ++ output, err := cmd.CombinedOutput() ++ if err != nil { ++ return "", err ++ } ++ expanded := string(output) ++ return filepath.Join(root, expanded), nil ++} ++``` ++ ++[go#20126]: https://github.com/golang/go/issues/20126 ++ ++### License ### ++ ++The license of this project is the same as Go, which is a BSD 3-clause license ++available in the `LICENSE` file. +diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION +new file mode 100644 +index 00000000..ee1372d3 +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION +@@ -0,0 +1 @@ ++0.2.2 +diff --git a/vendor/github.com/cyphar/filepath-securejoin/join.go b/vendor/github.com/cyphar/filepath-securejoin/join.go +new file mode 100644 +index 00000000..c4ca3d71 +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/join.go +@@ -0,0 +1,134 @@ ++// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. ++// Copyright (C) 2017 SUSE LLC. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package securejoin is an implementation of the hopefully-soon-to-be-included ++// SecureJoin helper that is meant to be part of the "path/filepath" package. ++// The purpose of this project is to provide a PoC implementation to make the ++// SecureJoin proposal (https://github.com/golang/go/issues/20126) more ++// tangible. ++package securejoin ++ ++import ( ++ "bytes" ++ "os" ++ "path/filepath" ++ "strings" ++ "syscall" ++ ++ "github.com/pkg/errors" ++) ++ ++// ErrSymlinkLoop is returned by SecureJoinVFS when too many symlinks have been ++// evaluated in attempting to securely join the two given paths. ++var ErrSymlinkLoop = errors.Wrap(syscall.ELOOP, "secure join") ++ ++// IsNotExist tells you if err is an error that implies that either the path ++// accessed does not exist (or path components don't exist). This is ++// effectively a more broad version of os.IsNotExist. ++func IsNotExist(err error) bool { ++ // If it's a bone-fide ENOENT just bail. ++ if os.IsNotExist(errors.Cause(err)) { ++ return true ++ } ++ ++ // Check that it's not actually an ENOTDIR, which in some cases is a more ++ // convoluted case of ENOENT (usually involving weird paths). ++ var errno error ++ switch err := errors.Cause(err).(type) { ++ case *os.PathError: ++ errno = err.Err ++ case *os.LinkError: ++ errno = err.Err ++ case *os.SyscallError: ++ errno = err.Err ++ } ++ return errno == syscall.ENOTDIR || errno == syscall.ENOENT ++} ++ ++// SecureJoinVFS joins the two given path components (similar to Join) except ++// that the returned path is guaranteed to be scoped inside the provided root ++// path (when evaluated). Any symbolic links in the path are evaluated with the ++// given root treated as the root of the filesystem, similar to a chroot. The ++// filesystem state is evaluated through the given VFS interface (if nil, the ++// standard os.* family of functions are used). ++// ++// Note that the guarantees provided by this function only apply if the path ++// components in the returned string are not modified (in other words are not ++// replaced with symlinks on the filesystem) after this function has returned. ++// Such a symlink race is necessarily out-of-scope of SecureJoin. ++func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { ++ // Use the os.* VFS implementation if none was specified. ++ if vfs == nil { ++ vfs = osVFS{} ++ } ++ ++ var path bytes.Buffer ++ n := 0 ++ for unsafePath != "" { ++ if n > 255 { ++ return "", ErrSymlinkLoop ++ } ++ ++ // Next path component, p. ++ i := strings.IndexRune(unsafePath, filepath.Separator) ++ var p string ++ if i == -1 { ++ p, unsafePath = unsafePath, "" ++ } else { ++ p, unsafePath = unsafePath[:i], unsafePath[i+1:] ++ } ++ ++ // Create a cleaned path, using the lexical semantics of /../a, to ++ // create a "scoped" path component which can safely be joined to fullP ++ // for evaluation. At this point, path.String() doesn't contain any ++ // symlink components. ++ cleanP := filepath.Clean(string(filepath.Separator) + path.String() + p) ++ if cleanP == string(filepath.Separator) { ++ path.Reset() ++ continue ++ } ++ fullP := filepath.Clean(root + cleanP) ++ ++ // Figure out whether the path is a symlink. ++ fi, err := vfs.Lstat(fullP) ++ if err != nil && !IsNotExist(err) { ++ return "", err ++ } ++ // Treat non-existent path components the same as non-symlinks (we ++ // can't do any better here). ++ if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 { ++ path.WriteString(p) ++ path.WriteRune(filepath.Separator) ++ continue ++ } ++ ++ // Only increment when we actually dereference a link. ++ n++ ++ ++ // It's a symlink, expand it by prepending it to the yet-unparsed path. ++ dest, err := vfs.Readlink(fullP) ++ if err != nil { ++ return "", err ++ } ++ // Absolute symlinks reset any work we've already done. ++ if filepath.IsAbs(dest) { ++ path.Reset() ++ } ++ unsafePath = dest + string(filepath.Separator) + unsafePath ++ } ++ ++ // We have to clean path.String() here because it may contain '..' ++ // components that are entirely lexical, but would be misleading otherwise. ++ // And finally do a final clean to ensure that root is also lexically ++ // clean. ++ fullP := filepath.Clean(string(filepath.Separator) + path.String()) ++ return filepath.Clean(root + fullP), nil ++} ++ ++// SecureJoin is a wrapper around SecureJoinVFS that just uses the os.* library ++// of functions as the VFS. If in doubt, use this function over SecureJoinVFS. ++func SecureJoin(root, unsafePath string) (string, error) { ++ return SecureJoinVFS(root, unsafePath, nil) ++} +diff --git a/vendor/github.com/cyphar/filepath-securejoin/vendor.conf b/vendor/github.com/cyphar/filepath-securejoin/vendor.conf +new file mode 100644 +index 00000000..66bb574b +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/vendor.conf +@@ -0,0 +1 @@ ++github.com/pkg/errors v0.8.0 +diff --git a/vendor/github.com/cyphar/filepath-securejoin/vfs.go b/vendor/github.com/cyphar/filepath-securejoin/vfs.go +new file mode 100644 +index 00000000..a82a5eae +--- /dev/null ++++ b/vendor/github.com/cyphar/filepath-securejoin/vfs.go +@@ -0,0 +1,41 @@ ++// Copyright (C) 2017 SUSE LLC. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package securejoin ++ ++import "os" ++ ++// In future this should be moved into a separate package, because now there ++// are several projects (umoci and go-mtree) that are using this sort of ++// interface. ++ ++// VFS is the minimal interface necessary to use SecureJoinVFS. A nil VFS is ++// equivalent to using the standard os.* family of functions. This is mainly ++// used for the purposes of mock testing, but also can be used to otherwise use ++// SecureJoin with VFS-like system. ++type VFS interface { ++ // Lstat returns a FileInfo describing the named file. If the file is a ++ // symbolic link, the returned FileInfo describes the symbolic link. Lstat ++ // makes no attempt to follow the link. These semantics are identical to ++ // os.Lstat. ++ Lstat(name string) (os.FileInfo, error) ++ ++ // Readlink returns the destination of the named symbolic link. These ++ // semantics are identical to os.Readlink. ++ Readlink(name string) (string, error) ++} ++ ++// osVFS is the "nil" VFS, in that it just passes everything through to the os ++// module. ++type osVFS struct{} ++ ++// Lstat returns a FileInfo describing the named file. If the file is a ++// symbolic link, the returned FileInfo describes the symbolic link. Lstat ++// makes no attempt to follow the link. These semantics are identical to ++// os.Lstat. ++func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } ++ ++// Readlink returns the destination of the named symbolic link. These ++// semantics are identical to os.Readlink. ++func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) } +diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore +new file mode 100644 +index 00000000..daf913b1 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/.gitignore +@@ -0,0 +1,24 @@ ++# Compiled Object files, Static and Dynamic libs (Shared Objects) ++*.o ++*.a ++*.so ++ ++# Folders ++_obj ++_test ++ ++# Architecture specific extensions/prefixes ++*.[568vq] ++[568vq].out ++ ++*.cgo1.go ++*.cgo2.c ++_cgo_defun.c ++_cgo_gotypes.go ++_cgo_export.* ++ ++_testmain.go ++ ++*.exe ++*.test ++*.prof +diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml +new file mode 100644 +index 00000000..9159de03 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/.travis.yml +@@ -0,0 +1,10 @@ ++language: go ++go_import_path: github.com/pkg/errors ++go: ++ - 1.11.x ++ - 1.12.x ++ - 1.13.x ++ - tip ++ ++script: ++ - make check +diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE +new file mode 100644 +index 00000000..835ba3e7 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/LICENSE +@@ -0,0 +1,23 @@ ++Copyright (c) 2015, Dave Cheney ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ ++* Redistributions of source code must retain the above copyright notice, this ++ list of conditions and the following disclaimer. ++ ++* Redistributions in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ++FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile +new file mode 100644 +index 00000000..ce9d7cde +--- /dev/null ++++ b/vendor/github.com/pkg/errors/Makefile +@@ -0,0 +1,44 @@ ++PKGS := github.com/pkg/errors ++SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) ++GO := go ++ ++check: test vet gofmt misspell unconvert staticcheck ineffassign unparam ++ ++test: ++ $(GO) test $(PKGS) ++ ++vet: | test ++ $(GO) vet $(PKGS) ++ ++staticcheck: ++ $(GO) get honnef.co/go/tools/cmd/staticcheck ++ staticcheck -checks all $(PKGS) ++ ++misspell: ++ $(GO) get github.com/client9/misspell/cmd/misspell ++ misspell \ ++ -locale GB \ ++ -error \ ++ *.md *.go ++ ++unconvert: ++ $(GO) get github.com/mdempsky/unconvert ++ unconvert -v $(PKGS) ++ ++ineffassign: ++ $(GO) get github.com/gordonklaus/ineffassign ++ find $(SRCDIRS) -name '*.go' | xargs ineffassign ++ ++pedantic: check errcheck ++ ++unparam: ++ $(GO) get mvdan.cc/unparam ++ unparam ./... ++ ++errcheck: ++ $(GO) get github.com/kisielk/errcheck ++ errcheck $(PKGS) ++ ++gofmt: ++ @echo Checking code is gofmted ++ @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" +diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md +new file mode 100644 +index 00000000..54dfdcb1 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/README.md +@@ -0,0 +1,59 @@ ++# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) ++ ++Package errors provides simple error handling primitives. ++ ++`go get github.com/pkg/errors` ++ ++The traditional error handling idiom in Go is roughly akin to ++```go ++if err != nil { ++ return err ++} ++``` ++which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. ++ ++## Adding context to an error ++ ++The errors.Wrap function returns a new error that adds context to the original error. For example ++```go ++_, err := ioutil.ReadAll(r) ++if err != nil { ++ return errors.Wrap(err, "read failed") ++} ++``` ++## Retrieving the cause of an error ++ ++Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. ++```go ++type causer interface { ++ Cause() error ++} ++``` ++`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: ++```go ++switch err := errors.Cause(err).(type) { ++case *MyError: ++ // handle specifically ++default: ++ // unknown error ++} ++``` ++ ++[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). ++ ++## Roadmap ++ ++With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: ++ ++- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) ++- 1.0. Final release. ++ ++## Contributing ++ ++Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. ++ ++Before sending a PR, please discuss your change by raising an issue. ++ ++## License ++ ++BSD-2-Clause +diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml +new file mode 100644 +index 00000000..a932eade +--- /dev/null ++++ b/vendor/github.com/pkg/errors/appveyor.yml +@@ -0,0 +1,32 @@ ++version: build-{build}.{branch} ++ ++clone_folder: C:\gopath\src\github.com\pkg\errors ++shallow_clone: true # for startup speed ++ ++environment: ++ GOPATH: C:\gopath ++ ++platform: ++ - x64 ++ ++# http://www.appveyor.com/docs/installed-software ++install: ++ # some helpful output for debugging builds ++ - go version ++ - go env ++ # pre-installed MinGW at C:\MinGW is 32bit only ++ # but MSYS2 at C:\msys64 has mingw64 ++ - set PATH=C:\msys64\mingw64\bin;%PATH% ++ - gcc --version ++ - g++ --version ++ ++build_script: ++ - go install -v ./... ++ ++test_script: ++ - set PATH=C:\gopath\bin;%PATH% ++ - go test -v ./... ++ ++#artifacts: ++# - path: '%GOPATH%\bin\*.exe' ++deploy: off +diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go +new file mode 100644 +index 00000000..161aea25 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/errors.go +@@ -0,0 +1,288 @@ ++// Package errors provides simple error handling primitives. ++// ++// The traditional error handling idiom in Go is roughly akin to ++// ++// if err != nil { ++// return err ++// } ++// ++// which when applied recursively up the call stack results in error reports ++// without context or debugging information. The errors package allows ++// programmers to add context to the failure path in their code in a way ++// that does not destroy the original value of the error. ++// ++// Adding context to an error ++// ++// The errors.Wrap function returns a new error that adds context to the ++// original error by recording a stack trace at the point Wrap is called, ++// together with the supplied message. For example ++// ++// _, err := ioutil.ReadAll(r) ++// if err != nil { ++// return errors.Wrap(err, "read failed") ++// } ++// ++// If additional control is required, the errors.WithStack and ++// errors.WithMessage functions destructure errors.Wrap into its component ++// operations: annotating an error with a stack trace and with a message, ++// respectively. ++// ++// Retrieving the cause of an error ++// ++// Using errors.Wrap constructs a stack of errors, adding context to the ++// preceding error. Depending on the nature of the error it may be necessary ++// to reverse the operation of errors.Wrap to retrieve the original error ++// for inspection. Any error value which implements this interface ++// ++// type causer interface { ++// Cause() error ++// } ++// ++// can be inspected by errors.Cause. errors.Cause will recursively retrieve ++// the topmost error that does not implement causer, which is assumed to be ++// the original cause. For example: ++// ++// switch err := errors.Cause(err).(type) { ++// case *MyError: ++// // handle specifically ++// default: ++// // unknown error ++// } ++// ++// Although the causer interface is not exported by this package, it is ++// considered a part of its stable public interface. ++// ++// Formatted printing of errors ++// ++// All error values returned from this package implement fmt.Formatter and can ++// be formatted by the fmt package. The following verbs are supported: ++// ++// %s print the error. If the error has a Cause it will be ++// printed recursively. ++// %v see %s ++// %+v extended format. Each Frame of the error's StackTrace will ++// be printed in detail. ++// ++// Retrieving the stack trace of an error or wrapper ++// ++// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are ++// invoked. This information can be retrieved with the following interface: ++// ++// type stackTracer interface { ++// StackTrace() errors.StackTrace ++// } ++// ++// The returned errors.StackTrace type is defined as ++// ++// type StackTrace []Frame ++// ++// The Frame type represents a call site in the stack trace. Frame supports ++// the fmt.Formatter interface that can be used for printing information about ++// the stack trace of this error. For example: ++// ++// if err, ok := err.(stackTracer); ok { ++// for _, f := range err.StackTrace() { ++// fmt.Printf("%+s:%d\n", f, f) ++// } ++// } ++// ++// Although the stackTracer interface is not exported by this package, it is ++// considered a part of its stable public interface. ++// ++// See the documentation for Frame.Format for more details. ++package errors ++ ++import ( ++ "fmt" ++ "io" ++) ++ ++// New returns an error with the supplied message. ++// New also records the stack trace at the point it was called. ++func New(message string) error { ++ return &fundamental{ ++ msg: message, ++ stack: callers(), ++ } ++} ++ ++// Errorf formats according to a format specifier and returns the string ++// as a value that satisfies error. ++// Errorf also records the stack trace at the point it was called. ++func Errorf(format string, args ...interface{}) error { ++ return &fundamental{ ++ msg: fmt.Sprintf(format, args...), ++ stack: callers(), ++ } ++} ++ ++// fundamental is an error that has a message and a stack, but no caller. ++type fundamental struct { ++ msg string ++ *stack ++} ++ ++func (f *fundamental) Error() string { return f.msg } ++ ++func (f *fundamental) Format(s fmt.State, verb rune) { ++ switch verb { ++ case 'v': ++ if s.Flag('+') { ++ io.WriteString(s, f.msg) ++ f.stack.Format(s, verb) ++ return ++ } ++ fallthrough ++ case 's': ++ io.WriteString(s, f.msg) ++ case 'q': ++ fmt.Fprintf(s, "%q", f.msg) ++ } ++} ++ ++// WithStack annotates err with a stack trace at the point WithStack was called. ++// If err is nil, WithStack returns nil. ++func WithStack(err error) error { ++ if err == nil { ++ return nil ++ } ++ return &withStack{ ++ err, ++ callers(), ++ } ++} ++ ++type withStack struct { ++ error ++ *stack ++} ++ ++func (w *withStack) Cause() error { return w.error } ++ ++// Unwrap provides compatibility for Go 1.13 error chains. ++func (w *withStack) Unwrap() error { return w.error } ++ ++func (w *withStack) Format(s fmt.State, verb rune) { ++ switch verb { ++ case 'v': ++ if s.Flag('+') { ++ fmt.Fprintf(s, "%+v", w.Cause()) ++ w.stack.Format(s, verb) ++ return ++ } ++ fallthrough ++ case 's': ++ io.WriteString(s, w.Error()) ++ case 'q': ++ fmt.Fprintf(s, "%q", w.Error()) ++ } ++} ++ ++// Wrap returns an error annotating err with a stack trace ++// at the point Wrap is called, and the supplied message. ++// If err is nil, Wrap returns nil. ++func Wrap(err error, message string) error { ++ if err == nil { ++ return nil ++ } ++ err = &withMessage{ ++ cause: err, ++ msg: message, ++ } ++ return &withStack{ ++ err, ++ callers(), ++ } ++} ++ ++// Wrapf returns an error annotating err with a stack trace ++// at the point Wrapf is called, and the format specifier. ++// If err is nil, Wrapf returns nil. ++func Wrapf(err error, format string, args ...interface{}) error { ++ if err == nil { ++ return nil ++ } ++ err = &withMessage{ ++ cause: err, ++ msg: fmt.Sprintf(format, args...), ++ } ++ return &withStack{ ++ err, ++ callers(), ++ } ++} ++ ++// WithMessage annotates err with a new message. ++// If err is nil, WithMessage returns nil. ++func WithMessage(err error, message string) error { ++ if err == nil { ++ return nil ++ } ++ return &withMessage{ ++ cause: err, ++ msg: message, ++ } ++} ++ ++// WithMessagef annotates err with the format specifier. ++// If err is nil, WithMessagef returns nil. ++func WithMessagef(err error, format string, args ...interface{}) error { ++ if err == nil { ++ return nil ++ } ++ return &withMessage{ ++ cause: err, ++ msg: fmt.Sprintf(format, args...), ++ } ++} ++ ++type withMessage struct { ++ cause error ++ msg string ++} ++ ++func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } ++func (w *withMessage) Cause() error { return w.cause } ++ ++// Unwrap provides compatibility for Go 1.13 error chains. ++func (w *withMessage) Unwrap() error { return w.cause } ++ ++func (w *withMessage) Format(s fmt.State, verb rune) { ++ switch verb { ++ case 'v': ++ if s.Flag('+') { ++ fmt.Fprintf(s, "%+v\n", w.Cause()) ++ io.WriteString(s, w.msg) ++ return ++ } ++ fallthrough ++ case 's', 'q': ++ io.WriteString(s, w.Error()) ++ } ++} ++ ++// Cause returns the underlying cause of the error, if possible. ++// An error value has a cause if it implements the following ++// interface: ++// ++// type causer interface { ++// Cause() error ++// } ++// ++// If the error does not implement Cause, the original error will ++// be returned. If the error is nil, nil will be returned without further ++// investigation. ++func Cause(err error) error { ++ type causer interface { ++ Cause() error ++ } ++ ++ for err != nil { ++ cause, ok := err.(causer) ++ if !ok { ++ break ++ } ++ err = cause.Cause() ++ } ++ return err ++} +diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go +new file mode 100644 +index 00000000..be0d10d0 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/go113.go +@@ -0,0 +1,38 @@ ++// +build go1.13 ++ ++package errors ++ ++import ( ++ stderrors "errors" ++) ++ ++// Is reports whether any error in err's chain matches target. ++// ++// The chain consists of err itself followed by the sequence of errors obtained by ++// repeatedly calling Unwrap. ++// ++// An error is considered to match a target if it is equal to that target or if ++// it implements a method Is(error) bool such that Is(target) returns true. ++func Is(err, target error) bool { return stderrors.Is(err, target) } ++ ++// As finds the first error in err's chain that matches target, and if so, sets ++// target to that error value and returns true. ++// ++// The chain consists of err itself followed by the sequence of errors obtained by ++// repeatedly calling Unwrap. ++// ++// An error matches target if the error's concrete value is assignable to the value ++// pointed to by target, or if the error has a method As(interface{}) bool such that ++// As(target) returns true. In the latter case, the As method is responsible for ++// setting target. ++// ++// As will panic if target is not a non-nil pointer to either a type that implements ++// error, or to any interface type. As returns false if err is nil. ++func As(err error, target interface{}) bool { return stderrors.As(err, target) } ++ ++// Unwrap returns the result of calling the Unwrap method on err, if err's ++// type contains an Unwrap method returning error. ++// Otherwise, Unwrap returns nil. ++func Unwrap(err error) error { ++ return stderrors.Unwrap(err) ++} +diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go +new file mode 100644 +index 00000000..779a8348 +--- /dev/null ++++ b/vendor/github.com/pkg/errors/stack.go +@@ -0,0 +1,177 @@ ++package errors ++ ++import ( ++ "fmt" ++ "io" ++ "path" ++ "runtime" ++ "strconv" ++ "strings" ++) ++ ++// Frame represents a program counter inside a stack frame. ++// For historical reasons if Frame is interpreted as a uintptr ++// its value represents the program counter + 1. ++type Frame uintptr ++ ++// pc returns the program counter for this frame; ++// multiple frames may have the same PC value. ++func (f Frame) pc() uintptr { return uintptr(f) - 1 } ++ ++// file returns the full path to the file that contains the ++// function for this Frame's pc. ++func (f Frame) file() string { ++ fn := runtime.FuncForPC(f.pc()) ++ if fn == nil { ++ return "unknown" ++ } ++ file, _ := fn.FileLine(f.pc()) ++ return file ++} ++ ++// line returns the line number of source code of the ++// function for this Frame's pc. ++func (f Frame) line() int { ++ fn := runtime.FuncForPC(f.pc()) ++ if fn == nil { ++ return 0 ++ } ++ _, line := fn.FileLine(f.pc()) ++ return line ++} ++ ++// name returns the name of this function, if known. ++func (f Frame) name() string { ++ fn := runtime.FuncForPC(f.pc()) ++ if fn == nil { ++ return "unknown" ++ } ++ return fn.Name() ++} ++ ++// Format formats the frame according to the fmt.Formatter interface. ++// ++// %s source file ++// %d source line ++// %n function name ++// %v equivalent to %s:%d ++// ++// Format accepts flags that alter the printing of some verbs, as follows: ++// ++// %+s function name and path of source file relative to the compile time ++// GOPATH separated by \n\t (\n\t) ++// %+v equivalent to %+s:%d ++func (f Frame) Format(s fmt.State, verb rune) { ++ switch verb { ++ case 's': ++ switch { ++ case s.Flag('+'): ++ io.WriteString(s, f.name()) ++ io.WriteString(s, "\n\t") ++ io.WriteString(s, f.file()) ++ default: ++ io.WriteString(s, path.Base(f.file())) ++ } ++ case 'd': ++ io.WriteString(s, strconv.Itoa(f.line())) ++ case 'n': ++ io.WriteString(s, funcname(f.name())) ++ case 'v': ++ f.Format(s, 's') ++ io.WriteString(s, ":") ++ f.Format(s, 'd') ++ } ++} ++ ++// MarshalText formats a stacktrace Frame as a text string. The output is the ++// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. ++func (f Frame) MarshalText() ([]byte, error) { ++ name := f.name() ++ if name == "unknown" { ++ return []byte(name), nil ++ } ++ return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil ++} ++ ++// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). ++type StackTrace []Frame ++ ++// Format formats the stack of Frames according to the fmt.Formatter interface. ++// ++// %s lists source files for each Frame in the stack ++// %v lists the source file and line number for each Frame in the stack ++// ++// Format accepts flags that alter the printing of some verbs, as follows: ++// ++// %+v Prints filename, function, and line number for each Frame in the stack. ++func (st StackTrace) Format(s fmt.State, verb rune) { ++ switch verb { ++ case 'v': ++ switch { ++ case s.Flag('+'): ++ for _, f := range st { ++ io.WriteString(s, "\n") ++ f.Format(s, verb) ++ } ++ case s.Flag('#'): ++ fmt.Fprintf(s, "%#v", []Frame(st)) ++ default: ++ st.formatSlice(s, verb) ++ } ++ case 's': ++ st.formatSlice(s, verb) ++ } ++} ++ ++// formatSlice will format this StackTrace into the given buffer as a slice of ++// Frame, only valid when called with '%s' or '%v'. ++func (st StackTrace) formatSlice(s fmt.State, verb rune) { ++ io.WriteString(s, "[") ++ for i, f := range st { ++ if i > 0 { ++ io.WriteString(s, " ") ++ } ++ f.Format(s, verb) ++ } ++ io.WriteString(s, "]") ++} ++ ++// stack represents a stack of program counters. ++type stack []uintptr ++ ++func (s *stack) Format(st fmt.State, verb rune) { ++ switch verb { ++ case 'v': ++ switch { ++ case st.Flag('+'): ++ for _, pc := range *s { ++ f := Frame(pc) ++ fmt.Fprintf(st, "\n%+v", f) ++ } ++ } ++ } ++} ++ ++func (s *stack) StackTrace() StackTrace { ++ f := make([]Frame, len(*s)) ++ for i := 0; i < len(f); i++ { ++ f[i] = Frame((*s)[i]) ++ } ++ return f ++} ++ ++func callers() *stack { ++ const depth = 32 ++ var pcs [depth]uintptr ++ n := runtime.Callers(3, pcs[:]) ++ var st stack = pcs[0:n] ++ return &st ++} ++ ++// funcname removes the path prefix component of a function's name reported by func.Name(). ++func funcname(name string) string { ++ i := strings.LastIndex(name, "/") ++ name = name[i+1:] ++ i = strings.Index(name, ".") ++ return name[i+1:] ++} +-- +2.27.0 + diff --git a/runc-openeuler.spec b/runc-openeuler.spec index 8a74111..cc4e23b 100644 --- a/runc-openeuler.spec +++ b/runc-openeuler.spec @@ -2,7 +2,7 @@ Name: docker-runc Version: 1.0.0.rc3 -Release: 200 +Release: 201 Summary: runc is a CLI tool for spawning and running containers according to the OCI specification. License: ASL 2.0 @@ -40,6 +40,12 @@ install -p -m 755 runc $RPM_BUILD_ROOT/%{_bindir}/runc %{_bindir}/runc %changelog +* Thu Jun 03 2021 xiadanni - 1.0.0.rc3-201 +- Type:CVE +- CVE:CVE-2021-30465 +- SUG:NA +- DESC:add mount destination validation(fix CVE-2021-30465) + * Wed Feb 9 2021 xiadanni - 1.0.0.rc3-200 - Type:bugfix - ID:NA diff --git a/series.conf b/series.conf index be43304..8b9c027 100644 --- a/series.conf +++ b/series.conf @@ -119,3 +119,4 @@ 0120-runc-fix-permission-denied.patch 0121-runc-add-cpu-and-memory-info-when-print-cgroup-info.patch 0124-runc-fix-freezing-race.patch +0126-runc-add-mount-destination-validation-fix-CVE-2021.patch -- Gitee