Merge pull request #29297 from vieux/plugins_cherry-picks

Make `docker pull` detect plugin content and error out.
diff --git a/api/client/image/pull.go b/api/client/image/pull.go
index e5968db..159156f 100644
--- a/api/client/image/pull.go
+++ b/api/client/image/pull.go
@@ -77,9 +77,13 @@
 
 	if client.IsTrusted() && !registryRef.HasDigest() {
 		// Check if tag is digest
-		return dockerCli.TrustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege)
+		err = dockerCli.TrustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege)
+	} else {
+		err = dockerCli.ImagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, opts.all)
+	}
+	if err != nil {
+		return err
 	}
 
-	return dockerCli.ImagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, opts.all)
-
+	return nil
 }
diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go
index c78e221..5a786fb 100644
--- a/distribution/pull_v2.go
+++ b/distribution/pull_v2.go
@@ -9,6 +9,7 @@
 	"net/url"
 	"os"
 	"runtime"
+	"strings"
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution"
@@ -32,7 +33,11 @@
 	"golang.org/x/net/context"
 )
 
-var errRootFSMismatch = errors.New("layers from manifest don't match image configuration")
+var (
+	errRootFSMismatch  = errors.New("layers from manifest don't match image configuration")
+	errMediaTypePlugin = errors.New("target is a plugin")
+	errRootFSInvalid   = errors.New("invalid rootfs in image configuration")
+)
 
 // ImageConfigPullError is an error pulling the image config blob
 // (only applies to schema2).
@@ -356,6 +361,12 @@
 		return false, fmt.Errorf("image manifest does not exist for tag or digest %q", tagOrDigest)
 	}
 
+	if m, ok := manifest.(*schema2.DeserializedManifest); ok {
+		if strings.HasPrefix(m.Manifest.Config.MediaType, "application/vnd.docker.plugin") {
+			return false, errMediaTypePlugin
+		}
+	}
+
 	// If manSvc.Get succeeded, we can be confident that the registry on
 	// the other side speaks the v2 protocol.
 	p.confirmedV2 = true
@@ -583,6 +594,10 @@
 		}
 	}
 
+	if unmarshalledConfig.RootFS == nil {
+		return "", "", errRootFSInvalid
+	}
+
 	// The DiffIDs returned in rootFS MUST match those in the config.
 	// Otherwise the image config could be referencing layers that aren't
 	// included in the manifest.
diff --git a/plugin/distribution/pull.go b/plugin/distribution/pull.go
index b8b3ebb..1bae8d4 100644
--- a/plugin/distribution/pull.go
+++ b/plugin/distribution/pull.go
@@ -143,8 +143,7 @@
 		logrus.Debugf("pull.go: error in json.Unmarshal(): %v", err)
 		return nil, err
 	}
-	if m.Config.MediaType != MediaTypeConfig &&
-		m.Config.MediaType != "application/vnd.docker.plugin.image.v0+json" {
+	if m.Config.MediaType != MediaTypeConfig {
 		return nil, ErrUnsupportedMediaType
 	}