[v1.4.2-stable] update containers/image

Note that this includes fixes for
https://access.redhat.com/security/cve/CVE-2020-1702.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2020-02-05 14:45:06 +01:00
parent d6d5c4aa02
commit 02f214ce82
10 changed files with 86 additions and 20 deletions

View File

@ -15,7 +15,7 @@ github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-rc2
github.com/containernetworking/plugins v0.7.4
github.com/containers/image v2.0.0
github.com/containers/image podman-1.4.2
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1

View File

@ -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"
@ -540,7 +540,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
}
@ -631,7 +631,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
}

View File

@ -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/none"
"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))
}

View File

@ -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/pkg/sysregistriesv2"
"github.com/containers/image/types"
@ -148,7 +149,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
}
@ -335,7 +337,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
}
@ -396,7 +398,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
}
@ -419,7 +421,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
}

View File

@ -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")
}

View File

@ -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
}

View File

@ -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/none"
"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
}

View File

@ -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/none"
"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
}

View File

@ -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
}

View File

@ -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
}