Merge pull request from GHSA-xw73-rw38-6vjc
[24.0 backport] image/cache: Restrict cache candidates to locally built images
diff --git a/Dockerfile b/Dockerfile
index bfb64d9..463d5cf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -197,7 +197,7 @@
# When updating the binary version you may also need to update the vendor
# version to pick up bug fixes or new APIs, however, usually the Go packages
# are built from a commit from the master branch.
-ARG CONTAINERD_VERSION=v1.7.12
+ARG CONTAINERD_VERSION=v1.7.13
RUN git fetch -q --depth 1 origin "${CONTAINERD_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
FROM base AS containerd-build
@@ -280,7 +280,7 @@
# that is used. If you need to update runc, open a pull request in the containerd
# project first, and update both after that is merged. When updating RUNC_VERSION,
# consider updating runc in vendor.mod accordingly.
-ARG RUNC_VERSION=v1.1.11
+ARG RUNC_VERSION=v1.1.12
RUN git fetch -q --depth 1 origin "${RUNC_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
FROM base AS runc-build
diff --git a/Dockerfile.windows b/Dockerfile.windows
index 85067fe..ae5704d 100644
--- a/Dockerfile.windows
+++ b/Dockerfile.windows
@@ -168,7 +168,7 @@
ARG GO_VERSION=1.20.13
ARG GOTESTSUM_VERSION=v1.8.2
ARG GOWINRES_VERSION=v0.3.1
-ARG CONTAINERD_VERSION=v1.7.12
+ARG CONTAINERD_VERSION=v1.7.13
# Environment variable notes:
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
diff --git a/hack/dockerfile/install/containerd.installer b/hack/dockerfile/install/containerd.installer
index 6896181..3275d8f 100755
--- a/hack/dockerfile/install/containerd.installer
+++ b/hack/dockerfile/install/containerd.installer
@@ -15,7 +15,7 @@
# the binary version you may also need to update the vendor version to pick up
# bug fixes or new APIs, however, usually the Go packages are built from a
# commit from the master branch.
-: "${CONTAINERD_VERSION:=v1.7.12}"
+: "${CONTAINERD_VERSION:=v1.7.13}"
install_containerd() (
echo "Install containerd version $CONTAINERD_VERSION"
diff --git a/hack/dockerfile/install/runc.installer b/hack/dockerfile/install/runc.installer
index c9ddc73..f5a569e 100755
--- a/hack/dockerfile/install/runc.installer
+++ b/hack/dockerfile/install/runc.installer
@@ -9,7 +9,7 @@
# the containerd project first, and update both after that is merged.
#
# When updating RUNC_VERSION, consider updating runc in vendor.mod accordingly
-: "${RUNC_VERSION:=v1.1.11}"
+: "${RUNC_VERSION:=v1.1.12}"
install_runc() {
RUNC_BUILDTAGS="${RUNC_BUILDTAGS:-"seccomp"}"
diff --git a/hack/make.ps1 b/hack/make.ps1
index 5c9d3a9..62ecf5d 100644
--- a/hack/make.ps1
+++ b/hack/make.ps1
@@ -348,7 +348,7 @@
Function Run-IntegrationTests() {
$escRoot = [Regex]::Escape($root)
$env:DOCKER_INTEGRATION_DAEMON_DEST = $bundlesDir + "\tmp"
- $dirs = go list -test -f '{{- if ne .ForTest `"`" -}}{{- .Dir -}}{{- end -}}' .\integration\...
+ $dirs = go list -test -f '{{- if ne .ForTest "" -}}{{- .Dir -}}{{- end -}}' .\integration\...
ForEach($dir in $dirs) {
# Normalize directory name for using in the test results files.
$normDir = $dir.Trim()
diff --git a/pkg/ioutils/readers.go b/pkg/ioutils/readers.go
index de00b95..d82ae93 100644
--- a/pkg/ioutils/readers.go
+++ b/pkg/ioutils/readers.go
@@ -3,11 +3,15 @@
import (
"context"
"io"
+ "runtime/debug"
+ "sync/atomic"
// make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered
// TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged.
_ "crypto/sha256"
_ "crypto/sha512"
+
+ "github.com/sirupsen/logrus"
)
// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser
@@ -16,10 +20,15 @@
type ReadCloserWrapper struct {
io.Reader
closer func() error
+ closed atomic.Bool
}
// Close calls back the passed closer function
func (r *ReadCloserWrapper) Close() error {
+ if !r.closed.CompareAndSwap(false, true) {
+ subsequentCloseWarn("ReadCloserWrapper")
+ return nil
+ }
return r.closer()
}
@@ -87,6 +96,7 @@
cancel func()
pR *io.PipeReader // Stream to read from
pW *io.PipeWriter
+ closed atomic.Bool
}
// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the
@@ -146,6 +156,17 @@
// Close closes the wrapper its underlying reader. It will cause
// future calls to Read to return io.EOF.
func (p *cancelReadCloser) Close() error {
+ if !p.closed.CompareAndSwap(false, true) {
+ subsequentCloseWarn("cancelReadCloser")
+ return nil
+ }
p.closeWithError(io.EOF)
return nil
}
+
+func subsequentCloseWarn(name string) {
+ logrus.Error("subsequent attempt to close " + name)
+ if logrus.GetLevel() >= logrus.DebugLevel {
+ logrus.Errorf("stack trace: %s", string(debug.Stack()))
+ }
+}
diff --git a/pkg/ioutils/writers.go b/pkg/ioutils/writers.go
index 61c6794..1f50602 100644
--- a/pkg/ioutils/writers.go
+++ b/pkg/ioutils/writers.go
@@ -1,6 +1,9 @@
package ioutils // import "github.com/docker/docker/pkg/ioutils"
-import "io"
+import (
+ "io"
+ "sync/atomic"
+)
// NopWriter represents a type which write operation is nop.
type NopWriter struct{}
@@ -29,9 +32,14 @@
type writeCloserWrapper struct {
io.Writer
closer func() error
+ closed atomic.Bool
}
func (r *writeCloserWrapper) Close() error {
+ if !r.closed.CompareAndSwap(false, true) {
+ subsequentCloseWarn("WriteCloserWrapper")
+ return nil
+ }
return r.closer()
}
diff --git a/vendor.mod b/vendor.mod
index 84e1f5a..a1f8664 100644
--- a/vendor.mod
+++ b/vendor.mod
@@ -71,7 +71,7 @@
github.com/morikuni/aec v1.0.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc3
- github.com/opencontainers/runc v1.1.11
+ github.com/opencontainers/runc v1.1.12
github.com/opencontainers/runtime-spec v1.1.0-rc.2
github.com/opencontainers/selinux v1.11.0
github.com/pelletier/go-toml v1.9.5
diff --git a/vendor.sum b/vendor.sum
index 681e48c..11d3aa6 100644
--- a/vendor.sum
+++ b/vendor.sum
@@ -1147,8 +1147,8 @@
github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
-github.com/opencontainers/runc v1.1.11 h1:9LjxyVlE0BPMRP2wuQDRlHV4941Jp9rc3F0+YKimopA=
-github.com/opencontainers/runc v1.1.11/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
+github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
+github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
index 48b263a..f6e1b73 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
@@ -77,16 +77,16 @@
// TestMode is set to true by unit tests that need "fake" cgroupfs.
TestMode bool
- cgroupFd int = -1
- prepOnce sync.Once
- prepErr error
- resolveFlags uint64
+ cgroupRootHandle *os.File
+ prepOnce sync.Once
+ prepErr error
+ resolveFlags uint64
)
func prepareOpenat2() error {
prepOnce.Do(func() {
fd, err := unix.Openat2(-1, cgroupfsDir, &unix.OpenHow{
- Flags: unix.O_DIRECTORY | unix.O_PATH,
+ Flags: unix.O_DIRECTORY | unix.O_PATH | unix.O_CLOEXEC,
})
if err != nil {
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
@@ -97,15 +97,16 @@
}
return
}
+ file := os.NewFile(uintptr(fd), cgroupfsDir)
+
var st unix.Statfs_t
- if err = unix.Fstatfs(fd, &st); err != nil {
+ if err := unix.Fstatfs(int(file.Fd()), &st); err != nil {
prepErr = &os.PathError{Op: "statfs", Path: cgroupfsDir, Err: err}
logrus.Warnf("falling back to securejoin: %s", prepErr)
return
}
- cgroupFd = fd
-
+ cgroupRootHandle = file
resolveFlags = unix.RESOLVE_BENEATH | unix.RESOLVE_NO_MAGICLINKS
if st.Type == unix.CGROUP2_SUPER_MAGIC {
// cgroupv2 has a single mountpoint and no "cpu,cpuacct" symlinks
@@ -132,7 +133,7 @@
return openFallback(path, flags, mode)
}
- fd, err := unix.Openat2(cgroupFd, relPath,
+ fd, err := unix.Openat2(int(cgroupRootHandle.Fd()), relPath,
&unix.OpenHow{
Resolve: resolveFlags,
Flags: uint64(flags) | unix.O_CLOEXEC,
@@ -140,20 +141,20 @@
})
if err != nil {
err = &os.PathError{Op: "openat2", Path: path, Err: err}
- // Check if cgroupFd is still opened to cgroupfsDir
+ // Check if cgroupRootHandle is still opened to cgroupfsDir
// (happens when this package is incorrectly used
// across the chroot/pivot_root/mntns boundary, or
// when /sys/fs/cgroup is remounted).
//
// TODO: if such usage will ever be common, amend this
- // to reopen cgroupFd and retry openat2.
- fdStr := strconv.Itoa(cgroupFd)
+ // to reopen cgroupRootHandle and retry openat2.
+ fdStr := strconv.Itoa(int(cgroupRootHandle.Fd()))
fdDest, _ := os.Readlink("/proc/self/fd/" + fdStr)
if fdDest != cgroupfsDir {
- // Wrap the error so it is clear that cgroupFd
+ // Wrap the error so it is clear that cgroupRootHandle
// is opened to an unexpected/wrong directory.
- err = fmt.Errorf("cgroupFd %s unexpectedly opened to %s != %s: %w",
- fdStr, fdDest, cgroupfsDir, err)
+ err = fmt.Errorf("cgroupRootHandle %d unexpectedly opened to %s != %s: %w",
+ cgroupRootHandle.Fd(), fdDest, cgroupfsDir, err)
}
return nil, err
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
index 220d0b4..bf3237a 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
@@ -7,6 +7,7 @@
"fmt"
"os"
"strconv"
+ _ "unsafe" // for go:linkname
"golang.org/x/sys/unix"
)
@@ -23,9 +24,11 @@
return nil
}
-// CloseExecFrom applies O_CLOEXEC to all file descriptors currently open for
-// the process (except for those below the given fd value).
-func CloseExecFrom(minFd int) error {
+type fdFunc func(fd int)
+
+// fdRangeFrom calls the passed fdFunc for each file descriptor that is open in
+// the current process.
+func fdRangeFrom(minFd int, fn fdFunc) error {
fdDir, err := os.Open("/proc/self/fd")
if err != nil {
return err
@@ -50,15 +53,60 @@
if fd < minFd {
continue
}
- // Intentionally ignore errors from unix.CloseOnExec -- the cases where
- // this might fail are basically file descriptors that have already
- // been closed (including and especially the one that was created when
- // os.ReadDir did the "opendir" syscall).
- unix.CloseOnExec(fd)
+ // Ignore the file descriptor we used for readdir, as it will be closed
+ // when we return.
+ if uintptr(fd) == fdDir.Fd() {
+ continue
+ }
+ // Run the closure.
+ fn(fd)
}
return nil
}
+// CloseExecFrom sets the O_CLOEXEC flag on all file descriptors greater or
+// equal to minFd in the current process.
+func CloseExecFrom(minFd int) error {
+ return fdRangeFrom(minFd, unix.CloseOnExec)
+}
+
+//go:linkname runtime_IsPollDescriptor internal/poll.IsPollDescriptor
+
+// In order to make sure we do not close the internal epoll descriptors the Go
+// runtime uses, we need to ensure that we skip descriptors that match
+// "internal/poll".IsPollDescriptor. Yes, this is a Go runtime internal thing,
+// unfortunately there's no other way to be sure we're only keeping the file
+// descriptors the Go runtime needs. Hopefully nothing blows up doing this...
+func runtime_IsPollDescriptor(fd uintptr) bool //nolint:revive
+
+// UnsafeCloseFrom closes all file descriptors greater or equal to minFd in the
+// current process, except for those critical to Go's runtime (such as the
+// netpoll management descriptors).
+//
+// NOTE: That this function is incredibly dangerous to use in most Go code, as
+// closing file descriptors from underneath *os.File handles can lead to very
+// bad behaviour (the closed file descriptor can be re-used and then any
+// *os.File operations would apply to the wrong file). This function is only
+// intended to be called from the last stage of runc init.
+func UnsafeCloseFrom(minFd int) error {
+ // We must not close some file descriptors.
+ return fdRangeFrom(minFd, func(fd int) {
+ if runtime_IsPollDescriptor(uintptr(fd)) {
+ // These are the Go runtimes internal netpoll file descriptors.
+ // These file descriptors are operated on deep in the Go scheduler,
+ // and closing those files from underneath Go can result in panics.
+ // There is no issue with keeping them because they are not
+ // executable and are not useful to an attacker anyway. Also we
+ // don't have any choice.
+ return
+ }
+ // There's nothing we can do about errors from close(2), and the
+ // only likely error to be seen is EBADF which indicates the fd was
+ // already closed (in which case, we got what we wanted).
+ _ = unix.Close(fd)
+ })
+}
+
// NewSockPair returns a new unix socket pair
func NewSockPair(name string) (parent *os.File, child *os.File, err error) {
fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index bf5933a..dd3fb54 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -837,7 +837,7 @@
github.com/opencontainers/image-spec/identity
github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1
-# github.com/opencontainers/runc v1.1.11
+# github.com/opencontainers/runc v1.1.12
## explicit; go 1.17
github.com/opencontainers/runc/libcontainer/cgroups
github.com/opencontainers/runc/libcontainer/configs