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 = ""