diff --git a/vendor.conf b/vendor.conf index ff7fccc0ea..9ded457896 100644 --- a/vendor.conf +++ b/vendor.conf @@ -11,7 +11,7 @@ github.com/containerd/cgroups 58556f5ad8448d99a6f7bea69ea4bdb7747cfeb0 github.com/containerd/continuity master github.com/containernetworking/cni v0.7.0-alpha1 github.com/containernetworking/plugins 1562a1e60ed101aacc5e08ed9dbeba8e9f3d4ec1 -github.com/containers/image 93bced01015eb94bec4821df1876314be8197680 +github.com/containers/image podman-1.0 github.com/containers/storage backport_symlinks https://github.com/mheon/storage.git github.com/containers/psgo dc0bc9fac5b715034c4310ed4d795b3182360842 github.com/coreos/go-systemd v14 diff --git a/vendor/github.com/containers/image/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go index 43eb22ba22..3d4bac668a 100644 --- a/vendor/github.com/containers/image/docker/docker_client.go +++ b/vendor/github.com/containers/image/docker/docker_client.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "os" @@ -17,6 +16,7 @@ import ( "time" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/pkg/docker/config" "github.com/containers/image/pkg/sysregistriesv2" "github.com/containers/image/pkg/tlsclientconfig" @@ -546,7 +546,7 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge, default: return nil, errors.Errorf("unexpected http code: %d (%s), URL: %s", res.StatusCode, http.StatusText(res.StatusCode), authReq.URL) } - tokenBlob, err := ioutil.ReadAll(res.Body) + tokenBlob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize) if err != nil { return nil, err } @@ -632,7 +632,8 @@ func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerRe if res.StatusCode != http.StatusOK { return nil, errors.Wrapf(client.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name()) } - body, err := ioutil.ReadAll(res.Body) + + body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureListBodySize) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/image/docker/docker_image_dest.go b/vendor/github.com/containers/image/docker/docker_image_dest.go index 38500dd0e3..acd44b45c9 100644 --- a/vendor/github.com/containers/image/docker/docker_image_dest.go +++ b/vendor/github.com/containers/image/docker/docker_image_dest.go @@ -15,6 +15,7 @@ import ( "strings" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/manifest" "github.com/containers/image/pkg/blobinfocache" "github.com/containers/image/types" @@ -590,7 +591,7 @@ sigExists: } defer res.Body.Close() if res.StatusCode != http.StatusCreated { - body, err := ioutil.ReadAll(res.Body) + body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxErrorBodySize) if err == nil { logrus.Debugf("Error body %s", string(body)) } diff --git a/vendor/github.com/containers/image/docker/docker_image_src.go b/vendor/github.com/containers/image/docker/docker_image_src.go index 8367792bf0..517630e46b 100644 --- a/vendor/github.com/containers/image/docker/docker_image_src.go +++ b/vendor/github.com/containers/image/docker/docker_image_src.go @@ -12,6 +12,7 @@ import ( "strconv" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/manifest" "github.com/containers/image/types" "github.com/docker/distribution/registry/client" @@ -97,7 +98,8 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin if res.StatusCode != http.StatusOK { return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.ref.ref.Name()) } - manblob, err := ioutil.ReadAll(res.Body) + + manblob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxManifestBodySize) if err != nil { return nil, "", err } @@ -284,7 +286,7 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) ( } else if res.StatusCode != http.StatusOK { return nil, false, errors.Errorf("Error reading signature from %s: status %d (%s)", url.String(), res.StatusCode, http.StatusText(res.StatusCode)) } - sig, err := ioutil.ReadAll(res.Body) + sig, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureBodySize) if err != nil { return nil, false, err } @@ -345,7 +347,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere return err } defer get.Body.Close() - manifestBody, err := ioutil.ReadAll(get.Body) + manifestBody, err := iolimits.ReadAtMost(get.Body, iolimits.MaxManifestBodySize) if err != nil { return err } @@ -368,7 +370,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere } defer delete.Body.Close() - body, err := ioutil.ReadAll(delete.Body) + body, err := iolimits.ReadAtMost(delete.Body, iolimits.MaxErrorBodySize) if err != nil { return err } diff --git a/vendor/github.com/containers/image/docker/tarfile/dest.go b/vendor/github.com/containers/image/docker/tarfile/dest.go index 5f30eddbc7..3557b0f9e0 100644 --- a/vendor/github.com/containers/image/docker/tarfile/dest.go +++ b/vendor/github.com/containers/image/docker/tarfile/dest.go @@ -13,6 +13,7 @@ import ( "time" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/internal/tmpdir" "github.com/containers/image/manifest" "github.com/containers/image/types" @@ -135,7 +136,7 @@ func (d *Destination) PutBlob(ctx context.Context, stream io.Reader, inputInfo t } if isConfig { - buf, err := ioutil.ReadAll(stream) + buf, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize) if err != nil { return types.BlobInfo{}, errors.Wrap(err, "Error reading Config file stream") } diff --git a/vendor/github.com/containers/image/docker/tarfile/src.go b/vendor/github.com/containers/image/docker/tarfile/src.go index 03735f8a4f..6e0f3570f8 100644 --- a/vendor/github.com/containers/image/docker/tarfile/src.go +++ b/vendor/github.com/containers/image/docker/tarfile/src.go @@ -12,6 +12,7 @@ import ( "sync" "github.com/containers/image/internal/tmpdir" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/manifest" "github.com/containers/image/pkg/compression" "github.com/containers/image/types" @@ -187,13 +188,13 @@ func findTarComponent(inputFile io.Reader, path string) (*tar.Reader, *tar.Heade } // readTarComponent returns full contents of componentPath. -func (s *Source) readTarComponent(path string) ([]byte, error) { +func (s *Source) readTarComponent(path string, limit int) ([]byte, error) { file, err := s.openTarComponent(path) if err != nil { return nil, errors.Wrapf(err, "Error loading tar component %s", path) } defer file.Close() - bytes, err := ioutil.ReadAll(file) + bytes, err := iolimits.ReadAtMost(file, limit) if err != nil { return nil, err } @@ -217,7 +218,7 @@ func (s *Source) ensureCachedDataIsPresent() error { } // Read and parse config. - configBytes, err := s.readTarComponent(tarManifest[0].Config) + configBytes, err := s.readTarComponent(tarManifest[0].Config, iolimits.MaxConfigBodySize) if err != nil { s.cacheDataResult = err return @@ -247,7 +248,7 @@ func (s *Source) ensureCachedDataIsPresent() error { // loadTarManifest loads and decodes the manifest.json. func (s *Source) loadTarManifest() ([]ManifestItem, error) { // FIXME? Do we need to deal with the legacy format? - bytes, err := s.readTarComponent(manifestFileName) + bytes, err := s.readTarComponent(manifestFileName, iolimits.MaxTarFileManifestSize) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/image/image/docker_schema2.go b/vendor/github.com/containers/image/image/docker_schema2.go index cee60f824c..0d35e3de57 100644 --- a/vendor/github.com/containers/image/image/docker_schema2.go +++ b/vendor/github.com/containers/image/image/docker_schema2.go @@ -6,10 +6,10 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "io/ioutil" "strings" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/manifest" "github.com/containers/image/pkg/blobinfocache" "github.com/containers/image/types" @@ -101,7 +101,7 @@ func (m *manifestSchema2) ConfigBlob(ctx context.Context) ([]byte, error) { return nil, err } defer stream.Close() - blob, err := ioutil.ReadAll(stream) + blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/image/image/oci.go b/vendor/github.com/containers/image/image/oci.go index 6fe2a9a327..85d5717265 100644 --- a/vendor/github.com/containers/image/image/oci.go +++ b/vendor/github.com/containers/image/image/oci.go @@ -3,9 +3,9 @@ package image import ( "context" "encoding/json" - "io/ioutil" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/manifest" "github.com/containers/image/pkg/blobinfocache" "github.com/containers/image/types" @@ -66,7 +66,7 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) { return nil, err } defer stream.Close() - blob, err := ioutil.ReadAll(stream) + blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/image/internal/iolimits/iolimits.go b/vendor/github.com/containers/image/internal/iolimits/iolimits.go new file mode 100644 index 0000000000..3fed1995cb --- /dev/null +++ b/vendor/github.com/containers/image/internal/iolimits/iolimits.go @@ -0,0 +1,60 @@ +package iolimits + +import ( + "io" + "io/ioutil" + + "github.com/pkg/errors" +) + +// All constants below are intended to be used as limits for `ReadAtMost`. The +// immediate use-case for limiting the size of in-memory copied data is to +// protect against OOM DOS attacks as described inCVE-2020-1702. Instead of +// copying data until running out of memory, we error out after hitting the +// specified limit. +const ( + // megaByte denotes one megabyte and is intended to be used as a limit in + // `ReadAtMost`. + megaByte = 1 << 20 + // MaxManifestBodySize is the maximum allowed size of a manifest. The limit + // of 4 MB aligns with the one of a Docker registry: + // https://github.com/docker/distribution/blob/a8371794149d1d95f1e846744b05c87f2f825e5a/registry/handlers/manifests.go#L30 + MaxManifestBodySize = 4 * megaByte + // MaxAuthTokenBodySize is the maximum allowed size of an auth token. + // The limit of 1 MB is considered to be greatly sufficient. + MaxAuthTokenBodySize = megaByte + // MaxSignatureListBodySize is the maximum allowed size of a signature list. + // The limit of 4 MB is considered to be greatly sufficient. + MaxSignatureListBodySize = 4 * megaByte + // MaxSignatureBodySize is the maximum allowed size of a signature. + // The limit of 4 MB is considered to be greatly sufficient. + MaxSignatureBodySize = 4 * megaByte + // MaxErrorBodySize is the maximum allowed size of an error-response body. + // The limit of 1 MB is considered to be greatly sufficient. + MaxErrorBodySize = megaByte + // MaxConfigBodySize is the maximum allowed size of a config blob. + // The limit of 4 MB is considered to be greatly sufficient. + MaxConfigBodySize = 4 * megaByte + // MaxOpenShiftStatusBody is the maximum allowed size of an OpenShift status body. + // The limit of 4 MB is considered to be greatly sufficient. + MaxOpenShiftStatusBody = 4 * megaByte + // MaxTarFileManifestSize is the maximum allowed size of a (docker save)-like manifest (which may contain multiple images) + // The limit of 1 MB is considered to be greatly sufficient. + MaxTarFileManifestSize = megaByte +) + +// ReadAtMost reads from reader and errors out if the specified limit (in bytes) is exceeded. +func ReadAtMost(reader io.Reader, limit int) ([]byte, error) { + limitedReader := io.LimitReader(reader, int64(limit+1)) + + res, err := ioutil.ReadAll(limitedReader) + if err != nil { + return nil, err + } + + if len(res) > limit { + return nil, errors.Errorf("exceeded maximum allowed size of %d bytes", limit) + } + + return res, nil +} diff --git a/vendor/github.com/containers/image/openshift/openshift.go b/vendor/github.com/containers/image/openshift/openshift.go index 814c3eea1d..78c8ae4db7 100644 --- a/vendor/github.com/containers/image/openshift/openshift.go +++ b/vendor/github.com/containers/image/openshift/openshift.go @@ -7,13 +7,13 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" "github.com/containers/image/docker" "github.com/containers/image/docker/reference" + "github.com/containers/image/internal/iolimits" "github.com/containers/image/manifest" "github.com/containers/image/types" "github.com/containers/image/version" @@ -102,7 +102,7 @@ func (c *openshiftClient) doRequest(ctx context.Context, method, path string, re return nil, err } defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) + body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxOpenShiftStatusBody) if err != nil { return nil, err }