Merge pull request #43004 from AkihiroSuda/cherrypick-42152
[20.10 backport] info: unset cgroup-related fields when CgroupDriver == none
diff --git a/cmd/dockerd/service_windows.go b/cmd/dockerd/service_windows.go
index 92d2462..2d7c3b7 100644
--- a/cmd/dockerd/service_windows.go
+++ b/cmd/dockerd/service_windows.go
@@ -372,7 +372,7 @@
func initPanicFile(path string) error {
var err error
- panicFile, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0)
+ panicFile, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o200)
if err != nil {
return err
}
diff --git a/distribution/manifest.go b/distribution/manifest.go
index a97373b..3b5a18b 100644
--- a/distribution/manifest.go
+++ b/distribution/manifest.go
@@ -3,6 +3,7 @@
import (
"context"
"encoding/json"
+ "fmt"
"io"
"io/ioutil"
@@ -11,7 +12,9 @@
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/remotes"
"github.com/docker/distribution"
+ "github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/schema1"
+ "github.com/docker/distribution/manifest/schema2"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@@ -166,8 +169,10 @@
func detectManifestBlobMediaType(dt []byte) (string, error) {
var mfst struct {
MediaType string `json:"mediaType"`
- Config json.RawMessage `json:"config"` // schema2 Manifest
- FSLayers json.RawMessage `json:"fsLayers"` // schema1 Manifest
+ Manifests json.RawMessage `json:"manifests"` // oci index, manifest list
+ Config json.RawMessage `json:"config"` // schema2 Manifest
+ Layers json.RawMessage `json:"layers"` // schema2 Manifest
+ FSLayers json.RawMessage `json:"fsLayers"` // schema1 Manifest
}
if err := json.Unmarshal(dt, &mfst); err != nil {
@@ -178,18 +183,40 @@
// Docker types should generally have a media type set.
// OCI (golang) types do not have a `mediaType` defined, and it is optional in the spec.
//
- // `distrubtion.UnmarshalManifest`, which is used to unmarshal this for real, checks these media type values.
+ // `distribution.UnmarshalManifest`, which is used to unmarshal this for real, checks these media type values.
// If the specified media type does not match it will error, and in some cases (docker media types) it is required.
// So pretty much if we don't have a media type we can fall back to OCI.
// This does have a special fallback for schema1 manifests just because it is easy to detect.
- switch {
- case mfst.MediaType != "":
+ switch mfst.MediaType {
+ case schema2.MediaTypeManifest, specs.MediaTypeImageManifest:
+ if mfst.Manifests != nil || mfst.FSLayers != nil {
+ return "", fmt.Errorf(`media-type: %q should not have "manifests" or "fsLayers"`, mfst.MediaType)
+ }
return mfst.MediaType, nil
- case mfst.FSLayers != nil:
- return schema1.MediaTypeManifest, nil
- case mfst.Config != nil:
- return specs.MediaTypeImageManifest, nil
+ case manifestlist.MediaTypeManifestList, specs.MediaTypeImageIndex:
+ if mfst.Config != nil || mfst.Layers != nil || mfst.FSLayers != nil {
+ return "", fmt.Errorf(`media-type: %q should not have "config", "layers", or "fsLayers"`, mfst.MediaType)
+ }
+ return mfst.MediaType, nil
+ case schema1.MediaTypeManifest:
+ if mfst.Manifests != nil || mfst.Layers != nil {
+ return "", fmt.Errorf(`media-type: %q should not have "manifests" or "layers"`, mfst.MediaType)
+ }
+ return mfst.MediaType, nil
default:
+ if mfst.MediaType != "" {
+ return mfst.MediaType, nil
+ }
+ }
+ switch {
+ case mfst.FSLayers != nil && mfst.Manifests == nil && mfst.Layers == nil && mfst.Config == nil:
+ return schema1.MediaTypeManifest, nil
+ case mfst.Config != nil && mfst.Manifests == nil && mfst.FSLayers == nil,
+ mfst.Layers != nil && mfst.Manifests == nil && mfst.FSLayers == nil:
+ return specs.MediaTypeImageManifest, nil
+ case mfst.Config == nil && mfst.Layers == nil && mfst.FSLayers == nil:
+ // fallback to index
return specs.MediaTypeImageIndex, nil
}
+ return "", errors.New("media-type: cannot determine")
}
diff --git a/distribution/manifest_test.go b/distribution/manifest_test.go
index 0976a71..578f8cc 100644
--- a/distribution/manifest_test.go
+++ b/distribution/manifest_test.go
@@ -14,8 +14,10 @@
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/remotes"
"github.com/docker/distribution"
+ "github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/ocischema"
"github.com/docker/distribution/manifest/schema1"
+ "github.com/docker/distribution/manifest/schema2"
"github.com/google/go-cmp/cmp/cmpopts"
digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -349,3 +351,73 @@
}
}
+
+func TestDetectManifestBlobMediaTypeInvalid(t *testing.T) {
+ type testCase struct {
+ json []byte
+ expected string
+ }
+ cases := map[string]testCase{
+ "schema 1 mediaType with manifests": {
+ []byte(`{"mediaType": "` + schema1.MediaTypeManifest + `","manifests":[]}`),
+ `media-type: "application/vnd.docker.distribution.manifest.v1+json" should not have "manifests" or "layers"`,
+ },
+ "schema 1 mediaType with layers": {
+ []byte(`{"mediaType": "` + schema1.MediaTypeManifest + `","layers":[]}`),
+ `media-type: "application/vnd.docker.distribution.manifest.v1+json" should not have "manifests" or "layers"`,
+ },
+ "schema 2 mediaType with manifests": {
+ []byte(`{"mediaType": "` + schema2.MediaTypeManifest + `","manifests":[]}`),
+ `media-type: "application/vnd.docker.distribution.manifest.v2+json" should not have "manifests" or "fsLayers"`,
+ },
+ "schema 2 mediaType with fsLayers": {
+ []byte(`{"mediaType": "` + schema2.MediaTypeManifest + `","fsLayers":[]}`),
+ `media-type: "application/vnd.docker.distribution.manifest.v2+json" should not have "manifests" or "fsLayers"`,
+ },
+ "oci manifest mediaType with manifests": {
+ []byte(`{"mediaType": "` + specs.MediaTypeImageManifest + `","manifests":[]}`),
+ `media-type: "application/vnd.oci.image.manifest.v1+json" should not have "manifests" or "fsLayers"`,
+ },
+ "manifest list mediaType with fsLayers": {
+ []byte(`{"mediaType": "` + manifestlist.MediaTypeManifestList + `","fsLayers":[]}`),
+ `media-type: "application/vnd.docker.distribution.manifest.list.v2+json" should not have "config", "layers", or "fsLayers"`,
+ },
+ "index mediaType with layers": {
+ []byte(`{"mediaType": "` + specs.MediaTypeImageIndex + `","layers":[]}`),
+ `media-type: "application/vnd.oci.image.index.v1+json" should not have "config", "layers", or "fsLayers"`,
+ },
+ "index mediaType with config": {
+ []byte(`{"mediaType": "` + specs.MediaTypeImageIndex + `","config":{}}`),
+ `media-type: "application/vnd.oci.image.index.v1+json" should not have "config", "layers", or "fsLayers"`,
+ },
+ "config and manifests": {
+ []byte(`{"config":{}, "manifests":[]}`),
+ `media-type: cannot determine`,
+ },
+ "layers and manifests": {
+ []byte(`{"layers":[], "manifests":[]}`),
+ `media-type: cannot determine`,
+ },
+ "layers and fsLayers": {
+ []byte(`{"layers":[], "fsLayers":[]}`),
+ `media-type: cannot determine`,
+ },
+ "fsLayers and manifests": {
+ []byte(`{"fsLayers":[], "manifests":[]}`),
+ `media-type: cannot determine`,
+ },
+ "config and fsLayers": {
+ []byte(`{"config":{}, "fsLayers":[]}`),
+ `media-type: cannot determine`,
+ },
+ }
+
+ for name, tc := range cases {
+ t.Run(name, func(t *testing.T) {
+ mt, err := detectManifestBlobMediaType(tc.json)
+ assert.Error(t, err, tc.expected)
+ assert.Equal(t, mt, "")
+ })
+ }
+
+}
diff --git a/hack/dockerfile/install/containerd.installer b/hack/dockerfile/install/containerd.installer
index 92547b6..e6f5b23 100755
--- a/hack/dockerfile/install/containerd.installer
+++ b/hack/dockerfile/install/containerd.installer
@@ -4,7 +4,7 @@
# containerd is also pinned in vendor.conf. When updating the binary
# version you may also need to update the vendor version to pick up bug
# fixes or new APIs.
-: "${CONTAINERD_COMMIT:=5b46e404f6b9f661a205e28d59c982d3634148f8}" # v1.4.11
+: "${CONTAINERD_COMMIT:=7b11cfaabd73bb80907dd23182b9347b4245eb5d}" # v1.4.12
install_containerd() (
echo "Install containerd version $CONTAINERD_COMMIT"
diff --git a/integration/build/build_userns_linux_test.go b/integration/build/build_userns_linux_test.go
index 5c0bd54..b826943 100644
--- a/integration/build/build_userns_linux_test.go
+++ b/integration/build/build_userns_linux_test.go
@@ -41,6 +41,7 @@
dUserRemap.Start(t, "--userns-remap", "default")
ctx := context.Background()
clientUserRemap := dUserRemap.NewClientT(t)
+ defer clientUserRemap.Close()
err = load.FrozenImagesLinux(clientUserRemap, "debian:bullseye")
assert.NilError(t, err)
@@ -49,6 +50,7 @@
defer func() {
if dUserRemapRunning {
dUserRemap.Stop(t)
+ dUserRemap.Cleanup(t)
}
}()
@@ -89,12 +91,17 @@
dNoUserRemap := daemon.New(t)
dNoUserRemap.Start(t)
- defer dNoUserRemap.Stop(t)
+ defer func() {
+ dNoUserRemap.Stop(t)
+ dNoUserRemap.Cleanup(t)
+ }()
clientNoUserRemap := dNoUserRemap.NewClientT(t)
+ defer clientNoUserRemap.Close()
tarFile, err := os.Open(tmp + "/image.tar")
assert.NilError(t, err, "failed to open image tar file")
+ defer tarFile.Close()
tarReader := bufio.NewReader(tarFile)
loadResp, err := clientNoUserRemap.ImageLoad(ctx, tarReader, false)
@@ -112,6 +119,7 @@
ShowStdout: true,
})
assert.NilError(t, err)
+ defer logReader.Close()
actualStdout := new(bytes.Buffer)
actualStderr := ioutil.Discard
diff --git a/integration/plugin/common/plugin_test.go b/integration/plugin/common/plugin_test.go
index a5568cc..21add8f 100644
--- a/integration/plugin/common/plugin_test.go
+++ b/integration/plugin/common/plugin_test.go
@@ -276,11 +276,7 @@
assert.NilError(t, err)
defer rdr.Close()
- type manifest struct {
- MediaType string
- v1.Manifest
- }
- var m manifest
+ var m v1.Manifest
assert.NilError(t, json.NewDecoder(rdr).Decode(&m))
assert.Check(t, cmp.Equal(m.MediaType, images.MediaTypeDockerSchema2Manifest))
assert.Check(t, cmp.Len(m.Layers, 1))
diff --git a/testutil/daemon/daemon.go b/testutil/daemon/daemon.go
index 52882e4..ebaad1c 100644
--- a/testutil/daemon/daemon.go
+++ b/testutil/daemon/daemon.go
@@ -281,6 +281,7 @@
t.Helper()
cleanupMount(t, d)
cleanupRaftDir(t, d)
+ cleanupDaemonStorage(t, d)
cleanupNetworkNamespace(t, d)
}
@@ -822,3 +823,36 @@
}
}
}
+
+// cleanupDaemonStorage removes the daemon's storage directory.
+//
+// Note that we don't delete the whole directory, as some files (e.g. daemon
+// logs) are collected for inclusion in the "bundles" that are stored as Jenkins
+// artifacts.
+//
+// We currently do not include container logs in the bundles, so this also
+// removes the "containers" sub-directory.
+func cleanupDaemonStorage(t testing.TB, d *Daemon) {
+ t.Helper()
+ dirs := []string{
+ "builder",
+ "buildkit",
+ "containers",
+ "image",
+ "network",
+ "plugins",
+ "tmp",
+ "trust",
+ "volumes",
+ // note: this assumes storage-driver name matches the subdirectory,
+ // which is currently true, but not guaranteed.
+ d.storageDriver,
+ }
+
+ for _, p := range dirs {
+ dir := filepath.Join(d.Root, p)
+ if err := os.RemoveAll(dir); err != nil {
+ t.Logf("[%s] error removing %v: %v", d.id, dir, err)
+ }
+ }
+}
diff --git a/vendor.conf b/vendor.conf
index a88f05b..dbf3e99 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -33,7 +33,7 @@
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
# buildkit
-github.com/moby/buildkit 244e8cde639f71a05a1a2e0670bd88e0206ce55c # v0.8.3-3-g244e8cde
+github.com/moby/buildkit bc07b2b81b1c6a62d29981ac564b16a15ce2bfa7 # v0.8.3-4-gbc07b2b8
github.com/tonistiigi/fsutil 0834f99b7b85462efb69b4f571a4fa3ca7da5ac9
github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
@@ -76,7 +76,7 @@
go.etcd.io/bbolt 232d8fc87f50244f9c808f4745759e08a304c029 # v1.3.5
# get graph and distribution packages
-github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
+github.com/docker/distribution 58f99e93b767ebacbf8e62a9074844712d31a177 https://github.com/samuelkarp/docker-distribution.git
github.com/vbatts/tar-split 620714a4c508c880ac1bdda9c8370a2b19af1a55 # v0.11.1
github.com/opencontainers/go-digest ea51bea511f75cfa3ef6098cc253c5c3609b037a # v1.0.0
@@ -92,7 +92,7 @@
# packages but should be newer or equal.
github.com/opencontainers/runc ff819c7e9184c13b7c2607fe6c30ae19403a7aff # v1.0.0-rc92
github.com/opencontainers/runtime-spec 4d89ac9fbff6c455f46a5bb59c6b1bb7184a5e43 # v1.0.3-0.20200728170252-4d89ac9fbff6
-github.com/opencontainers/image-spec d60099175f88c47cd379c4738d158884749ed235 # v1.0.1
+github.com/opencontainers/image-spec 67d2d5658fe0476ab9bf414cec164077ebff3920 # v1.0.2
github.com/cyphar/filepath-securejoin a261ee33d7a517f054effbf451841abaafe3e0fd # v0.2.2
# go-systemd v17 is required by github.com/coreos/pkg/capnslog/journald_formatter.go
@@ -130,7 +130,7 @@
google.golang.org/genproto 3f1135a288c9a07e340ae8ba4cc6c7065a3160e8
# containerd
-github.com/containerd/containerd 0edc412565dcc6e3d6125ff9e4b009ad4b89c638 # master (v1.5.0-dev)
+github.com/containerd/containerd e048c115a3a89caf63941d363858e207c28bccd6 https://github.com/moby/containerd.git # master (v1.5.0-dev) + patch for CVE-2021-41190
github.com/containerd/fifo 0724c46b320cf96bb172a0550c19a4b1fca4dacb
github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
github.com/containerd/cgroups 0b889c03f102012f1d93a97ddd3ef71cd6f4f510
@@ -151,7 +151,7 @@
golang.org/x/crypto c1f2f97bffc9c53fc40a1a28a5b460094c0050d9
golang.org/x/time 555d28b269f0569763d25dbe1a237ae74c6bcc82
github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad
-github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 git://github.com/tonistiigi/go-immutable-radix.git
+github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 https://github.com/tonistiigi/go-immutable-radix.git
github.com/hashicorp/golang-lru 7f827b33c0f158ec5dfbba01bb0b14a4541fd81d # v0.5.3
github.com/coreos/pkg 3ac0863d7acf3bc44daf49afef8919af12f704ef # v3
code.cloudfoundry.org/clock 02e53af36e6c978af692887ed449b74026d76fec # v1.0.0
diff --git a/vendor/github.com/containerd/containerd/images/image.go b/vendor/github.com/containerd/containerd/images/image.go
index 1868ee8..2e42ca0 100644
--- a/vendor/github.com/containerd/containerd/images/image.go
+++ b/vendor/github.com/containerd/containerd/images/image.go
@@ -19,6 +19,7 @@
import (
"context"
"encoding/json"
+ "fmt"
"sort"
"time"
@@ -154,6 +155,10 @@
return nil, err
}
+ if err := validateMediaType(p, desc.MediaType); err != nil {
+ return nil, errors.Wrapf(err, "manifest: invalid desc %s", desc.Digest)
+ }
+
var manifest ocispec.Manifest
if err := json.Unmarshal(p, &manifest); err != nil {
return nil, err
@@ -194,6 +199,10 @@
return nil, err
}
+ if err := validateMediaType(p, desc.MediaType); err != nil {
+ return nil, errors.Wrapf(err, "manifest: invalid desc %s", desc.Digest)
+ }
+
var idx ocispec.Index
if err := json.Unmarshal(p, &idx); err != nil {
return nil, err
@@ -336,6 +345,10 @@
return nil, err
}
+ if err := validateMediaType(p, desc.MediaType); err != nil {
+ return nil, errors.Wrapf(err, "children: invalid desc %s", desc.Digest)
+ }
+
// TODO(stevvooe): We just assume oci manifest, for now. There may be
// subtle differences from the docker version.
var manifest ocispec.Manifest
@@ -351,6 +364,10 @@
return nil, err
}
+ if err := validateMediaType(p, desc.MediaType); err != nil {
+ return nil, errors.Wrapf(err, "children: invalid desc %s", desc.Digest)
+ }
+
var index ocispec.Index
if err := json.Unmarshal(p, &index); err != nil {
return nil, err
@@ -368,6 +385,44 @@
return descs, nil
}
+// unknownDocument represents a manifest, manifest list, or index that has not
+// yet been validated.
+type unknownDocument struct {
+ MediaType string `json:"mediaType,omitempty"`
+ Config json.RawMessage `json:"config,omitempty"`
+ Layers json.RawMessage `json:"layers,omitempty"`
+ Manifests json.RawMessage `json:"manifests,omitempty"`
+ FSLayers json.RawMessage `json:"fsLayers,omitempty"` // schema 1
+}
+
+// validateMediaType returns an error if the byte slice is invalid JSON or if
+// the media type identifies the blob as one format but it contains elements of
+// another format.
+func validateMediaType(b []byte, mt string) error {
+ var doc unknownDocument
+ if err := json.Unmarshal(b, &doc); err != nil {
+ return err
+ }
+ if len(doc.FSLayers) != 0 {
+ return fmt.Errorf("media-type: schema 1 not supported")
+ }
+ switch mt {
+ case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
+ if len(doc.Manifests) != 0 ||
+ doc.MediaType == MediaTypeDockerSchema2ManifestList ||
+ doc.MediaType == ocispec.MediaTypeImageIndex {
+ return fmt.Errorf("media-type: expected manifest but found index (%s)", mt)
+ }
+ case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
+ if len(doc.Config) != 0 || len(doc.Layers) != 0 ||
+ doc.MediaType == MediaTypeDockerSchema2Manifest ||
+ doc.MediaType == ocispec.MediaTypeImageManifest {
+ return fmt.Errorf("media-type: expected index but found manifest (%s)", mt)
+ }
+ }
+ return nil
+}
+
// RootFS returns the unpacked diffids that make up and images rootfs.
//
// These are used to verify that a set of layers unpacked to the expected
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
index 8314c01..f15a9ac 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
@@ -256,6 +256,9 @@
if err := json.Unmarshal(b, &m); err != nil {
return err
}
+ if len(m.Manifests) != 0 || len(m.Layers) != 0 {
+ return errors.New("converter: expected schema1 document but found extra keys")
+ }
c.pulledManifest = &m
return nil
@@ -472,8 +475,10 @@
}
type manifest struct {
- FSLayers []fsLayer `json:"fsLayers"`
- History []history `json:"history"`
+ FSLayers []fsLayer `json:"fsLayers"`
+ History []history `json:"history"`
+ Layers json.RawMessage `json:"layers,omitempty"` // OCI manifest
+ Manifests json.RawMessage `json:"manifests,omitempty"` // OCI index
}
type v1History struct {
diff --git a/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go b/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go
index 54c8f3c..09b3609 100644
--- a/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go
+++ b/vendor/github.com/docker/distribution/manifest/manifestlist/manifestlist.go
@@ -54,6 +54,9 @@
}
imageIndexFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
+ if err := validateIndex(b); err != nil {
+ return nil, distribution.Descriptor{}, err
+ }
m := new(DeserializedManifestList)
err := m.UnmarshalJSON(b)
if err != nil {
@@ -214,3 +217,23 @@
return mediaType, m.canonical, nil
}
+
+// unknownDocument represents a manifest, manifest list, or index that has not
+// yet been validated
+type unknownDocument struct {
+ Config interface{} `json:"config,omitempty"`
+ Layers interface{} `json:"layers,omitempty"`
+}
+
+// validateIndex returns an error if the byte slice is invalid JSON or if it
+// contains fields that belong to a manifest
+func validateIndex(b []byte) error {
+ var doc unknownDocument
+ if err := json.Unmarshal(b, &doc); err != nil {
+ return err
+ }
+ if doc.Config != nil || doc.Layers != nil {
+ return errors.New("index: expected index but found manifest")
+ }
+ return nil
+}
diff --git a/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go b/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go
index b8c4bab..910a64a 100644
--- a/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go
+++ b/vendor/github.com/docker/distribution/manifest/ocischema/manifest.go
@@ -22,6 +22,9 @@
func init() {
ocischemaFunc := func(b []byte) (distribution.Manifest, distribution.Descriptor, error) {
+ if err := validateManifest(b); err != nil {
+ return nil, distribution.Descriptor{}, err
+ }
m := new(DeserializedManifest)
err := m.UnmarshalJSON(b)
if err != nil {
@@ -122,3 +125,22 @@
func (m DeserializedManifest) Payload() (string, []byte, error) {
return v1.MediaTypeImageManifest, m.canonical, nil
}
+
+// unknownDocument represents a manifest, manifest list, or index that has not
+// yet been validated
+type unknownDocument struct {
+ Manifests interface{} `json:"manifests,omitempty"`
+}
+
+// validateManifest returns an error if the byte slice is invalid JSON or if it
+// contains fields that belong to a index
+func validateManifest(b []byte) error {
+ var doc unknownDocument
+ if err := json.Unmarshal(b, &doc); err != nil {
+ return err
+ }
+ if doc.Manifests != nil {
+ return errors.New("ocimanifest: expected manifest but found index")
+ }
+ return nil
+}
diff --git a/vendor/github.com/moby/buildkit/util/imageutil/config.go b/vendor/github.com/moby/buildkit/util/imageutil/config.go
index 0be5870..a93c8cc 100644
--- a/vendor/github.com/moby/buildkit/util/imageutil/config.go
+++ b/vendor/github.com/moby/buildkit/util/imageutil/config.go
@@ -183,19 +183,39 @@
func DetectManifestBlobMediaType(dt []byte) (string, error) {
var mfst struct {
- MediaType string `json:"mediaType"`
+ MediaType *string `json:"mediaType"`
Config json.RawMessage `json:"config"`
+ Manifests json.RawMessage `json:"manifests"`
+ Layers json.RawMessage `json:"layers"`
}
if err := json.Unmarshal(dt, &mfst); err != nil {
return "", err
}
- if mfst.MediaType != "" {
- return mfst.MediaType, nil
+ mt := images.MediaTypeDockerSchema2ManifestList
+
+ if mfst.Config != nil || mfst.Layers != nil {
+ mt = images.MediaTypeDockerSchema2Manifest
+
+ if mfst.Manifests != nil {
+ return "", errors.Errorf("invalid ambiguous manifest and manifest list")
+ }
}
- if mfst.Config != nil {
- return images.MediaTypeDockerSchema2Manifest, nil
+
+ if mfst.MediaType != nil {
+ switch *mfst.MediaType {
+ case images.MediaTypeDockerSchema2ManifestList, specs.MediaTypeImageIndex:
+ if mt != images.MediaTypeDockerSchema2ManifestList {
+ return "", errors.Errorf("mediaType in manifest does not match manifest contents")
+ }
+ mt = *mfst.MediaType
+ case images.MediaTypeDockerSchema2Manifest, specs.MediaTypeImageManifest:
+ if mt != images.MediaTypeDockerSchema2Manifest {
+ return "", errors.Errorf("mediaType in manifest does not match manifest contents")
+ }
+ mt = *mfst.MediaType
+ }
}
- return images.MediaTypeDockerSchema2ManifestList, nil
+ return mt, nil
}
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
index 4e6c4b2..82da6c6 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
@@ -21,6 +21,9 @@
type Index struct {
specs.Versioned
+ // MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
+ MediaType string `json:"mediaType,omitempty"`
+
// Manifests references platform specific manifests.
Manifests []Descriptor `json:"manifests"`
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
index 7ff32c4..d72d15c 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
@@ -20,6 +20,9 @@
type Manifest struct {
specs.Versioned
+ // MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
+ MediaType string `json:"mediaType,omitempty"`
+
// Config references a configuration object for a container, by digest.
// The referenced configuration object is a JSON blob that the runtime uses to set up the container.
Config Descriptor `json:"config"`
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
index 5d493df..0d9543f 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
@@ -22,7 +22,7 @@
// VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 0
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 1
+ VersionPatch = 2
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = ""