Merge pull request #41622 from bboehmke/ipv6_nat

IPv6 iptables config option
diff --git a/Jenkinsfile b/Jenkinsfile
index c2b17b1..ec5c651 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -214,14 +214,6 @@
                                 '''
                             }
                         }
-                        stage("Build e2e image") {
-                            steps {
-                                sh '''
-                                echo "Building e2e image"
-                                docker build --build-arg DOCKER_GITCOMMIT=${GIT_COMMIT} -t moby-e2e-test -f Dockerfile.e2e .
-                                '''
-                            }
-                        }
                     }
 
                     post {
diff --git a/api/types/mount/mount.go b/api/types/mount/mount.go
index ab4446b..443b8d0 100644
--- a/api/types/mount/mount.go
+++ b/api/types/mount/mount.go
@@ -113,7 +113,7 @@
 	// TODO(stevvooe): There are several more tmpfs flags, specified in the
 	// daemon, that are accepted. Only the most basic are added for now.
 	//
-	// From docker/docker/pkg/mount/flags.go:
+	// From https://github.com/moby/sys/blob/mount/v0.1.1/mount/flags.go#L47-L56
 	//
 	// var validFlags = map[string]bool{
 	// 	"":          true,
diff --git a/builder/builder-next/adapters/containerimage/pull.go b/builder/builder-next/adapters/containerimage/pull.go
index 65ee7a3..733a337 100644
--- a/builder/builder-next/adapters/containerimage/pull.go
+++ b/builder/builder-next/adapters/containerimage/pull.go
@@ -9,7 +9,6 @@
 	"path"
 	"runtime"
 	"sync"
-	"sync/atomic"
 	"time"
 
 	"github.com/containerd/containerd/content"
@@ -31,6 +30,7 @@
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/source"
 	"github.com/moby/buildkit/util/flightcontrol"
 	"github.com/moby/buildkit/util/imageutil"
@@ -59,18 +59,12 @@
 // Source is the source implementation for accessing container images
 type Source struct {
 	SourceOpt
-	g             flightcontrol.Group
-	resolverCache *resolverCache
+	g flightcontrol.Group
 }
 
 // NewSource creates a new image source
 func NewSource(opt SourceOpt) (*Source, error) {
-	is := &Source{
-		SourceOpt:     opt,
-		resolverCache: newResolverCache(),
-	}
-
-	return is, nil
+	return &Source{SourceOpt: opt}, nil
 }
 
 // ID returns image scheme identifier
@@ -78,16 +72,6 @@
 	return source.DockerImageScheme
 }
 
-func (is *Source) getResolver(hosts docker.RegistryHosts, ref string, sm *session.Manager, g session.Group) remotes.Resolver {
-	if res := is.resolverCache.Get(ref, g); res != nil {
-		return res
-	}
-	auth := resolver.NewSessionAuthenticator(sm, g)
-	r := resolver.New(hosts, auth)
-	r = is.resolverCache.Add(ref, auth, r, g)
-	return r
-}
-
 func (is *Source) resolveLocal(refStr string) (*image.Image, error) {
 	ref, err := distreference.ParseNormalizedNamed(refStr)
 	if err != nil {
@@ -109,8 +93,15 @@
 		dgst digest.Digest
 		dt   []byte
 	}
-	res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) {
-		dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(is.RegistryHosts, ref, sm, g), is.ContentStore, nil, platform)
+	p := platforms.DefaultSpec()
+	if platform != nil {
+		p = *platform
+	}
+	// key is used to synchronize resolutions that can happen in parallel when doing multi-stage.
+	key := "getconfig::" + ref + "::" + platforms.Format(p)
+	res, err := is.g.Do(ctx, key, func(ctx context.Context) (interface{}, error) {
+		res := resolver.DefaultPool.GetResolver(is.RegistryHosts, ref, "pull", sm, g)
+		dgst, dt, err := imageutil.Config(ctx, ref, res, is.ContentStore, nil, platform)
 		if err != nil {
 			return nil, err
 		}
@@ -168,7 +159,7 @@
 }
 
 // Resolve returns access to pulling for an identifier
-func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager) (source.SourceInstance, error) {
+func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, vtx solver.Vertex) (source.SourceInstance, error) {
 	imageIdentifier, ok := id.(*source.ImageIdentifier)
 	if !ok {
 		return nil, errors.Errorf("invalid image identifier %v", id)
@@ -191,29 +182,20 @@
 
 type puller struct {
 	is               *Source
-	resolveOnce      sync.Once
 	resolveLocalOnce sync.Once
 	src              *source.ImageIdentifier
 	desc             ocispec.Descriptor
 	ref              string
-	resolveErr       error
-	resolverInstance remotes.Resolver
-	resolverOnce     sync.Once
 	config           []byte
 	platform         ocispec.Platform
 	sm               *session.Manager
 }
 
 func (p *puller) resolver(g session.Group) remotes.Resolver {
-	p.resolverOnce.Do(func() {
-		if p.resolverInstance == nil {
-			p.resolverInstance = p.is.getResolver(p.is.RegistryHosts, p.src.Reference.String(), p.sm, g)
-		}
-	})
-	return p.resolverInstance
+	return resolver.DefaultPool.GetResolver(p.is.RegistryHosts, p.src.Reference.String(), "pull", p.sm, g)
 }
 
-func (p *puller) mainManifestKey(dgst digest.Digest, platform ocispec.Platform) (digest.Digest, error) {
+func (p *puller) mainManifestKey(platform ocispec.Platform) (digest.Digest, error) {
 	dt, err := json.Marshal(struct {
 		Digest  digest.Digest
 		OS      string
@@ -271,22 +253,23 @@
 }
 
 func (p *puller) resolve(ctx context.Context, g session.Group) error {
-	p.resolveOnce.Do(func() {
+	// key is used to synchronize resolutions that can happen in parallel when doing multi-stage.
+	key := "resolve::" + p.ref + "::" + platforms.Format(p.platform)
+	_, err := p.is.g.Do(ctx, key, func(ctx context.Context) (_ interface{}, err error) {
 		resolveProgressDone := oneOffProgress(ctx, "resolve "+p.src.Reference.String())
+		defer func() {
+			resolveProgressDone(err)
+		}()
 
 		ref, err := distreference.ParseNormalizedNamed(p.src.Reference.String())
 		if err != nil {
-			p.resolveErr = err
-			_ = resolveProgressDone(err)
-			return
+			return nil, err
 		}
 
 		if p.desc.Digest == "" && p.config == nil {
 			origRef, desc, err := p.resolver(g).Resolve(ctx, ref.String())
 			if err != nil {
-				p.resolveErr = err
-				_ = resolveProgressDone(err)
-				return
+				return nil, err
 			}
 
 			p.desc = desc
@@ -301,65 +284,61 @@
 		if p.config == nil && p.desc.MediaType != images.MediaTypeDockerSchema1Manifest {
 			ref, err := distreference.WithDigest(ref, p.desc.Digest)
 			if err != nil {
-				p.resolveErr = err
-				_ = resolveProgressDone(err)
-				return
+				return nil, err
 			}
 			_, dt, err := p.is.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{Platform: &p.platform, ResolveMode: resolveModeToString(p.src.ResolveMode)}, p.sm, g)
 			if err != nil {
-				p.resolveErr = err
-				_ = resolveProgressDone(err)
-				return
+				return nil, err
 			}
 
 			p.config = dt
 		}
-		_ = resolveProgressDone(nil)
+		return nil, nil
 	})
-	return p.resolveErr
+	return err
 }
 
-func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (string, bool, error) {
+func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (string, solver.CacheOpts, bool, error) {
 	p.resolveLocal()
 
 	if p.desc.Digest != "" && index == 0 {
-		dgst, err := p.mainManifestKey(p.desc.Digest, p.platform)
+		dgst, err := p.mainManifestKey(p.platform)
 		if err != nil {
-			return "", false, err
+			return "", nil, false, err
 		}
-		return dgst.String(), false, nil
+		return dgst.String(), nil, false, nil
 	}
 
 	if p.config != nil {
 		k := cacheKeyFromConfig(p.config).String()
 		if k == "" {
-			return digest.FromBytes(p.config).String(), true, nil
+			return digest.FromBytes(p.config).String(), nil, true, nil
 		}
-		return k, true, nil
+		return k, nil, true, nil
 	}
 
 	if err := p.resolve(ctx, g); err != nil {
-		return "", false, err
+		return "", nil, false, err
 	}
 
 	if p.desc.Digest != "" && index == 0 {
-		dgst, err := p.mainManifestKey(p.desc.Digest, p.platform)
+		dgst, err := p.mainManifestKey(p.platform)
 		if err != nil {
-			return "", false, err
+			return "", nil, false, err
 		}
-		return dgst.String(), false, nil
+		return dgst.String(), nil, false, nil
 	}
 
 	k := cacheKeyFromConfig(p.config).String()
 	if k == "" {
-		dgst, err := p.mainManifestKey(p.desc.Digest, p.platform)
+		dgst, err := p.mainManifestKey(p.platform)
 		if err != nil {
-			return "", false, err
+			return "", nil, false, err
 		}
-		return dgst.String(), true, nil
+		return dgst.String(), nil, true, nil
 	}
 
-	return k, true, nil
+	return k, nil, true, nil
 }
 
 func (p *puller) getRef(ctx context.Context, diffIDs []layer.DiffID, opts ...cache.RefOption) (cache.ImmutableRef, error) {
@@ -426,10 +405,6 @@
 	}
 
 	platform := platforms.Only(p.platform)
-	// workaround for GCR bug that requires a request to manifest endpoint for authentication to work.
-	// if current resolver has not used manifests do a dummy request.
-	// in most cases resolver should be cached and extra request is not needed.
-	ensureManifestRequested(ctx, p.resolver(g), p.ref)
 
 	var (
 		schema1Converter *schema1.Converter
@@ -845,97 +820,6 @@
 	return ""
 }
 
-type resolverCache struct {
-	mu sync.Mutex
-	m  map[string]cachedResolver
-}
-
-type cachedResolver struct {
-	counter int64 // needs to be 64bit aligned for 32bit systems
-	timeout time.Time
-	remotes.Resolver
-	auth *resolver.SessionAuthenticator
-}
-
-func (cr *cachedResolver) Resolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error) {
-	atomic.AddInt64(&cr.counter, 1)
-	return cr.Resolver.Resolve(ctx, ref)
-}
-
-func (r *resolverCache) Add(ref string, auth *resolver.SessionAuthenticator, resolver remotes.Resolver, g session.Group) *cachedResolver {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	ref = r.repo(ref)
-
-	cr, ok := r.m[ref]
-	cr.timeout = time.Now().Add(time.Minute)
-	if ok {
-		cr.auth.AddSession(g)
-		return &cr
-	}
-
-	cr.Resolver = resolver
-	cr.auth = auth
-	r.m[ref] = cr
-	return &cr
-}
-
-func (r *resolverCache) repo(refStr string) string {
-	ref, err := distreference.ParseNormalizedNamed(refStr)
-	if err != nil {
-		return refStr
-	}
-	return ref.Name()
-}
-
-func (r *resolverCache) Get(ref string, g session.Group) *cachedResolver {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	ref = r.repo(ref)
-
-	cr, ok := r.m[ref]
-	if ok {
-		cr.auth.AddSession(g)
-		return &cr
-	}
-	return nil
-}
-
-func (r *resolverCache) clean(now time.Time) {
-	r.mu.Lock()
-	for k, cr := range r.m {
-		if now.After(cr.timeout) {
-			delete(r.m, k)
-		}
-	}
-	r.mu.Unlock()
-}
-
-func newResolverCache() *resolverCache {
-	rc := &resolverCache{
-		m: map[string]cachedResolver{},
-	}
-	t := time.NewTicker(time.Minute)
-	go func() {
-		for {
-			rc.clean(<-t.C)
-		}
-	}()
-	return rc
-}
-
-func ensureManifestRequested(ctx context.Context, res remotes.Resolver, ref string) {
-	cr, ok := res.(*cachedResolver)
-	if !ok {
-		return
-	}
-	if atomic.LoadInt64(&cr.counter) == 0 {
-		res.Resolve(ctx, ref)
-	}
-}
-
 func platformMatches(img *image.Image, p *ocispec.Platform) bool {
 	if img.Architecture != p.Architecture {
 		return false
diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go
index 5decff8..5aac0cb 100644
--- a/builder/builder-next/controller.go
+++ b/builder/builder-next/controller.go
@@ -34,7 +34,7 @@
 	"github.com/moby/buildkit/frontend/gateway/forwarder"
 	containerdsnapshot "github.com/moby/buildkit/snapshot/containerd"
 	"github.com/moby/buildkit/solver/bboltcachestorage"
-	"github.com/moby/buildkit/util/binfmt_misc"
+	"github.com/moby/buildkit/util/archutil"
 	"github.com/moby/buildkit/util/entitlements"
 	"github.com/moby/buildkit/util/leaseutil"
 	"github.com/moby/buildkit/worker"
@@ -166,7 +166,7 @@
 		return nil, errors.Errorf("snapshotter doesn't support differ")
 	}
 
-	p, err := parsePlatforms(binfmt_misc.SupportedPlatforms(true))
+	p, err := parsePlatforms(archutil.SupportedPlatforms(true))
 	if err != nil {
 		return nil, err
 	}
diff --git a/builder/builder-next/executor_unix.go b/builder/builder-next/executor_unix.go
index d684b9f..c052ec7 100644
--- a/builder/builder-next/executor_unix.go
+++ b/builder/builder-next/executor_unix.go
@@ -95,11 +95,11 @@
 	iface.ep = ep
 }
 
-func (iface *lnInterface) Set(s *specs.Spec) {
+func (iface *lnInterface) Set(s *specs.Spec) error {
 	<-iface.ready
 	if iface.err != nil {
 		logrus.WithError(iface.err).Error("failed to set networking spec")
-		return
+		return iface.err
 	}
 	shortNetCtlrID := stringid.TruncateID(iface.provider.NetworkController.ID())
 	// attach netns to bridge within the container namespace, using reexec in a prestart hook
@@ -109,6 +109,7 @@
 			Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().Daemon.ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
 		}},
 	}
+	return nil
 }
 
 func (iface *lnInterface) Close() error {
diff --git a/builder/builder-next/executor_windows.go b/builder/builder-next/executor_windows.go
index 5f33bcb..f63d8ab 100644
--- a/builder/builder-next/executor_windows.go
+++ b/builder/builder-next/executor_windows.go
@@ -7,7 +7,6 @@
 	"github.com/docker/docker/daemon/config"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/libnetwork"
-	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/executor"
 	"github.com/moby/buildkit/executor/oci"
 )
@@ -19,7 +18,7 @@
 type winExecutor struct {
 }
 
-func (w *winExecutor) Run(ctx context.Context, id string, root cache.Mountable, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
+func (w *winExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
 	return errors.New("buildkit executor not implemented for windows")
 }
 
diff --git a/builder/builder-next/exporter/writer.go b/builder/builder-next/exporter/writer.go
index 64d260f..53305ca 100644
--- a/builder/builder-next/exporter/writer.go
+++ b/builder/builder-next/exporter/writer.go
@@ -26,7 +26,7 @@
 	}
 	img.RootFS.Type = "layers"
 	img.Config.WorkingDir = "/"
-	img.Config.Env = []string{"PATH=" + system.DefaultPathEnv}
+	img.Config.Env = []string{"PATH=" + system.DefaultPathEnvUnix}
 	dt, err := json.Marshal(img)
 	return dt, errors.Wrap(err, "failed to create empty image config")
 }
diff --git a/builder/builder-next/worker/worker.go b/builder/builder-next/worker/worker.go
index f8c3ef9..4dcf1bb 100644
--- a/builder/builder-next/worker/worker.go
+++ b/builder/builder-next/worker/worker.go
@@ -33,13 +33,15 @@
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/solver/llbsolver/mounts"
 	"github.com/moby/buildkit/solver/llbsolver/ops"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/source"
 	"github.com/moby/buildkit/source/git"
 	"github.com/moby/buildkit/source/http"
 	"github.com/moby/buildkit/source/local"
-	"github.com/moby/buildkit/util/binfmt_misc"
+	"github.com/moby/buildkit/util/archutil"
+	"github.com/moby/buildkit/util/compression"
 	"github.com/moby/buildkit/util/contentutil"
 	"github.com/moby/buildkit/util/progress"
 	digest "github.com/opencontainers/go-digest"
@@ -147,7 +149,7 @@
 		for _, p := range w.Opt.Platforms {
 			pm[platforms.Format(p)] = struct{}{}
 		}
-		for _, p := range binfmt_misc.SupportedPlatforms(noCache) {
+		for _, p := range archutil.SupportedPlatforms(noCache) {
 			if _, ok := pm[p]; !ok {
 				pp, _ := platforms.Parse(p)
 				w.Opt.Platforms = append(w.Opt.Platforms, pp)
@@ -170,13 +172,18 @@
 	return w.Opt.ContentStore
 }
 
+// MetadataStore returns the metadata store
+func (w *Worker) MetadataStore() *metadata.Store {
+	return w.Opt.MetadataStore
+}
+
 // LoadRef loads a reference by ID
-func (w *Worker) LoadRef(id string, hidden bool) (cache.ImmutableRef, error) {
+func (w *Worker) LoadRef(ctx context.Context, id string, hidden bool) (cache.ImmutableRef, error) {
 	var opts []cache.RefOption
 	if hidden {
 		opts = append(opts, cache.NoUpdateLastUsed)
 	}
-	return w.CacheManager().Get(context.TODO(), id, opts...)
+	return w.CacheManager().Get(ctx, id, opts...)
 }
 
 // ResolveOp converts a LLB vertex into a LLB operation
@@ -186,9 +193,9 @@
 		case *pb.Op_Source:
 			return ops.NewSourceOp(v, op, baseOp.Platform, w.SourceManager, sm, w)
 		case *pb.Op_Exec:
-			return ops.NewExecOp(v, op, baseOp.Platform, w.CacheManager(), sm, w.MetadataStore, w.Executor(), w)
+			return ops.NewExecOp(v, op, baseOp.Platform, w.CacheManager(), sm, w.Opt.MetadataStore, w.Executor(), w)
 		case *pb.Op_File:
-			return ops.NewFileOp(v, op, w.CacheManager(), w.MetadataStore, w)
+			return ops.NewFileOp(v, op, w.CacheManager(), w.Opt.MetadataStore, w)
 		case *pb.Op_Build:
 			return ops.NewBuildOp(v, op, s, w)
 		}
@@ -230,7 +237,7 @@
 }
 
 // GetRemote returns a remote snapshot reference for a local one
-func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error) {
+func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool, _ compression.Type, _ session.Group) (*solver.Remote, error) {
 	var diffIDs []layer.DiffID
 	var err error
 	if !createIfNeeded {
@@ -265,13 +272,13 @@
 
 // PruneCacheMounts removes the current cache snapshots for specified IDs
 func (w *Worker) PruneCacheMounts(ctx context.Context, ids []string) error {
-	mu := ops.CacheMountsLocker()
+	mu := mounts.CacheMountsLocker()
 	mu.Lock()
 	defer mu.Unlock()
 
 	for _, id := range ids {
 		id = "cache-dir:" + id
-		sis, err := w.MetadataStore.Search(id)
+		sis, err := w.Opt.MetadataStore.Search(id)
 		if err != nil {
 			return err
 		}
@@ -300,7 +307,7 @@
 		}
 	}
 
-	ops.ClearActiveCacheMounts()
+	mounts.ClearActiveCacheMounts()
 	return nil
 }
 
@@ -422,7 +429,10 @@
 
 func (ld *layerDescriptor) Download(ctx context.Context, progressOutput pkgprogress.Output) (io.ReadCloser, int64, error) {
 	done := oneOffProgress(ld.pctx, fmt.Sprintf("pulling %s", ld.desc.Digest))
-	if err := contentutil.Copy(ctx, ld.w.ContentStore(), ld.provider, ld.desc); err != nil {
+
+	// TODO should this write output to progressOutput? Or use something similar to loggerFromContext()? see https://github.com/moby/buildkit/commit/aa29e7729464f3c2a773e27795e584023c751cb8
+	discardLogs := func(_ []byte) {}
+	if err := contentutil.Copy(ctx, ld.w.ContentStore(), ld.provider, ld.desc, discardLogs); err != nil {
 		return nil, 0, done(err)
 	}
 	_ = done(nil)
diff --git a/builder/dockerfile/builder.go b/builder/dockerfile/builder.go
index c7784e2..a0bfb28 100644
--- a/builder/dockerfile/builder.go
+++ b/builder/dockerfile/builder.go
@@ -85,10 +85,6 @@
 	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
-	if config.Options.SessionID != "" {
-		return nil, errors.New("experimental session with v1 builder is no longer supported, use builder version v2 (BuildKit) instead")
-	}
-
 	builderOptions := builderOptions{
 		Options:        config.Options,
 		ProgressWriter: config.ProgressWriter,
@@ -239,8 +235,10 @@
 	}); err != nil {
 		return err
 	}
-	args.AddArg(meta.Key, meta.Value)
-	args.AddMetaArg(meta.Key, meta.Value)
+	for _, arg := range meta.Args {
+		args.AddArg(arg.Key, arg.Value)
+		args.AddMetaArg(arg.Key, arg.Value)
+	}
 	return nil
 }
 
diff --git a/builder/dockerfile/dispatchers.go b/builder/dockerfile/dispatchers.go
index bf28a66..36335df 100644
--- a/builder/dockerfile/dispatchers.go
+++ b/builder/dockerfile/dispatchers.go
@@ -587,14 +587,21 @@
 // to builder using the --build-arg flag for expansion/substitution or passing to 'run'.
 // Dockerfile author may optionally set a default value of this variable.
 func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
-
-	commitStr := "ARG " + c.Key
-	if c.Value != nil {
-		commitStr += "=" + *c.Value
+	var commitStr strings.Builder
+	commitStr.WriteString("ARG ")
+	for i, arg := range c.Args {
+		if i > 0 {
+			commitStr.WriteString(" ")
+		}
+		commitStr.WriteString(arg.Key)
+		if arg.Value != nil {
+			commitStr.WriteString("=")
+			commitStr.WriteString(*arg.Value)
+		}
+		d.state.buildArgs.AddArg(arg.Key, arg.Value)
 	}
 
-	d.state.buildArgs.AddArg(c.Key, c.Value)
-	return d.builder.commit(d.state, commitStr)
+	return d.builder.commit(d.state, commitStr.String())
 }
 
 // SHELL powershell -command
diff --git a/builder/dockerfile/dispatchers_test.go b/builder/dockerfile/dispatchers_test.go
index 03e0245..d5f6bb9 100644
--- a/builder/dockerfile/dispatchers_test.go
+++ b/builder/dockerfile/dispatchers_test.go
@@ -139,10 +139,10 @@
 	args := NewBuildArgs(make(map[string]*string))
 
 	val := "sometag"
-	metaArg := instructions.ArgCommand{KeyValuePairOptional: instructions.KeyValuePairOptional{
+	metaArg := instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{
 		Key:   "THETAG",
 		Value: &val,
-	}}
+	}}}
 	cmd := &instructions.Stage{
 		BaseName: "alpine:${THETAG}",
 	}
@@ -395,7 +395,7 @@
 
 	argName := "foo"
 	argVal := "bar"
-	cmd := &instructions.ArgCommand{KeyValuePairOptional: instructions.KeyValuePairOptional{Key: argName, Value: &argVal}}
+	cmd := &instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{Key: argName, Value: &argVal}}}
 	err := dispatch(sb, cmd)
 	assert.NilError(t, err)
 
diff --git a/builder/dockerignore/deprecated.go b/builder/dockerignore/deprecated.go
new file mode 100644
index 0000000..e387cc8
--- /dev/null
+++ b/builder/dockerignore/deprecated.go
@@ -0,0 +1,17 @@
+// Package dockerignore is deprecated. Use github.com/moby/buildkit/frontend/dockerfile/dockerignore instead.
+package dockerignore
+
+import (
+	"io"
+
+	"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
+)
+
+// ReadAll reads a .dockerignore file and returns the list of file patterns
+// to ignore. Note this will trim whitespace from each line as well
+// as use GO's "clean" func to get the shortest/cleanest path for each.
+//
+// Deprecated: use github.com/moby/buildkit/frontend/dockerfile/dockerignore.ReadAll instead.
+func ReadAll(reader io.Reader) ([]string, error) {
+	return dockerignore.ReadAll(reader)
+}
diff --git a/builder/dockerignore/dockerignore_test.go b/builder/dockerignore/dockerignore_test.go
deleted file mode 100644
index 655bd6f..0000000
--- a/builder/dockerignore/dockerignore_test.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package dockerignore // import "github.com/docker/docker/builder/dockerignore"
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"testing"
-)
-
-func TestReadAll(t *testing.T) {
-	tmpDir, err := ioutil.TempDir("", "dockerignore-test")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(tmpDir)
-
-	di, err := ReadAll(nil)
-	if err != nil {
-		t.Fatalf("Expected not to have error, got %v", err)
-	}
-
-	if diLen := len(di); diLen != 0 {
-		t.Fatalf("Expected to have zero dockerignore entry, got %d", diLen)
-	}
-
-	diName := filepath.Join(tmpDir, ".dockerignore")
-	content := fmt.Sprintf("test1\n/test2\n/a/file/here\n\nlastfile\n# this is a comment\n! /inverted/abs/path\n!\n! \n")
-	err = ioutil.WriteFile(diName, []byte(content), 0777)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	diFd, err := os.Open(diName)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer diFd.Close()
-
-	di, err = ReadAll(diFd)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if len(di) != 7 {
-		t.Fatalf("Expected 7 entries, got %v", len(di))
-	}
-	if di[0] != "test1" {
-		t.Fatal("First element is not test1")
-	}
-	if di[1] != "test2" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar
-		t.Fatal("Second element is not test2")
-	}
-	if di[2] != "a/file/here" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar
-		t.Fatal("Third element is not a/file/here")
-	}
-	if di[3] != "lastfile" {
-		t.Fatal("Fourth element is not lastfile")
-	}
-	if di[4] != "!inverted/abs/path" {
-		t.Fatal("Fifth element is not !inverted/abs/path")
-	}
-	if di[5] != "!" {
-		t.Fatalf("Sixth element is not !, but %s", di[5])
-	}
-	if di[6] != "!" {
-		t.Fatalf("Seventh element is not !, but %s", di[6])
-	}
-}
diff --git a/builder/remotecontext/detect.go b/builder/remotecontext/detect.go
index a1953dd..9b126ef 100644
--- a/builder/remotecontext/detect.go
+++ b/builder/remotecontext/detect.go
@@ -11,10 +11,10 @@
 	"github.com/containerd/continuity/driver"
 	"github.com/docker/docker/api/types/backend"
 	"github.com/docker/docker/builder"
-	"github.com/docker/docker/builder/dockerignore"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/urlutil"
+	"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
 	"github.com/moby/buildkit/frontend/dockerfile/parser"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -33,12 +33,7 @@
 	case remoteURL == "":
 		remote, dockerfile, err = newArchiveRemote(config.Source, dockerfilePath)
 	case remoteURL == ClientSessionRemote:
-		res, err := parser.Parse(config.Source)
-		if err != nil {
-			return nil, nil, errdefs.InvalidParameter(err)
-		}
-
-		return nil, res, nil
+		return nil, nil, errdefs.InvalidParameter(errors.New("experimental session with v1 builder is no longer supported, use builder version v2 (BuildKit) instead"))
 	case urlutil.IsGitURL(remoteURL):
 		remote, dockerfile, err = newGitRemote(remoteURL, dockerfilePath)
 	case urlutil.IsURL(remoteURL):
diff --git a/cmd/dockerd/config.go b/cmd/dockerd/config.go
index 8dfe8a3..73d5b81 100644
--- a/cmd/dockerd/config.go
+++ b/cmd/dockerd/config.go
@@ -97,11 +97,9 @@
 	conf.MaxDownloadAttempts = &maxDownloadAttempts
 
 	flags.StringVar(&conf.ContainerdNamespace, "containerd-namespace", daemon.ContainersNamespace, "Containerd namespace to use")
-	if err := flags.MarkHidden("containerd-namespace"); err != nil {
-		return err
-	}
 	flags.StringVar(&conf.ContainerdPluginNamespace, "containerd-plugins-namespace", containerd.PluginNamespace, "Containerd namespace to use for plugins")
-	return flags.MarkHidden("containerd-plugins-namespace")
+
+	return nil
 }
 
 func installRegistryServiceFlags(options *registry.ServiceOptions, flags *pflag.FlagSet) {
diff --git a/cmd/dockerd/config_unix.go b/cmd/dockerd/config_unix.go
index 50c89c4..7ae5828 100644
--- a/cmd/dockerd/config_unix.go
+++ b/cmd/dockerd/config_unix.go
@@ -5,11 +5,11 @@
 import (
 	"os/exec"
 
+	"github.com/containerd/cgroups"
 	"github.com/docker/docker/daemon/config"
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/rootless"
 	units "github.com/docker/go-units"
-	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/pkg/errors"
 	"github.com/spf13/pflag"
 )
@@ -67,7 +67,7 @@
 	// Note that defaultUserlandProxyPath and honorXDG are configured according to the value of rootless.RunningWithRootlessKit, not the value of --rootless.
 	flags.BoolVar(&conf.Rootless, "rootless", rootless.RunningWithRootlessKit(), "Enable rootless mode; typically used with RootlessKit")
 	defaultCgroupNamespaceMode := "host"
-	if cgroups.IsCgroup2UnifiedMode() {
+	if cgroups.Mode() == cgroups.Unified {
 		defaultCgroupNamespaceMode = "private"
 	}
 	flags.StringVar(&conf.CgroupNamespaceMode, "default-cgroupns-mode", defaultCgroupNamespaceMode, `Default mode for containers cgroup namespace ("host" | "private")`)
diff --git a/daemon/cluster/convert/task.go b/daemon/cluster/convert/task.go
index e218dc0..b29cf48 100644
--- a/daemon/cluster/convert/task.go
+++ b/daemon/cluster/convert/task.go
@@ -51,6 +51,12 @@
 		task.NetworksAttachments = append(task.NetworksAttachments, networkAttachmentFromGRPC(na))
 	}
 
+	if t.JobIteration != nil {
+		task.JobIteration = &types.Version{
+			Index: t.JobIteration.Index,
+		}
+	}
+
 	if t.Status.PortStatus == nil {
 		return task, nil
 	}
@@ -65,11 +71,5 @@
 		})
 	}
 
-	if t.JobIteration != nil {
-		task.JobIteration = &types.Version{
-			Index: t.JobIteration.Index,
-		}
-	}
-
 	return task, nil
 }
diff --git a/daemon/content.go b/daemon/content.go
new file mode 100644
index 0000000..01d1e23
--- /dev/null
+++ b/daemon/content.go
@@ -0,0 +1,30 @@
+package daemon
+
+import (
+	"os"
+	"path/filepath"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/content/local"
+	"github.com/containerd/containerd/leases"
+	"github.com/containerd/containerd/metadata"
+	"github.com/pkg/errors"
+	"go.etcd.io/bbolt"
+)
+
+func (d *Daemon) configureLocalContentStore() (content.Store, leases.Manager, error) {
+	if err := os.MkdirAll(filepath.Join(d.root, "content"), 0700); err != nil {
+		return nil, nil, errors.Wrap(err, "error creating dir for content store")
+	}
+	db, err := bbolt.Open(filepath.Join(d.root, "content", "metadata.db"), 0600, nil)
+	if err != nil {
+		return nil, nil, errors.Wrap(err, "error opening bolt db for content metadata store")
+	}
+	cs, err := local.NewStore(filepath.Join(d.root, "content", "data"))
+	if err != nil {
+		return nil, nil, errors.Wrap(err, "error setting up content store")
+	}
+	md := metadata.NewDB(db, cs, nil)
+	d.mdDB = db
+	return md.ContentStore(), metadata.NewLeaseManager(md), nil
+}
diff --git a/daemon/daemon.go b/daemon/daemon.go
index f81f45a..9e3a0fa 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -20,6 +20,7 @@
 	"time"
 
 	"github.com/docker/docker/pkg/fileutils"
+	"go.etcd.io/bbolt"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/backoff"
 
@@ -129,6 +130,11 @@
 
 	attachmentStore       network.AttachmentStore
 	attachableNetworkLock *locker.Locker
+
+	// This is used for Windows which doesn't currently support running on containerd
+	// It stores metadata for the content store (used for manifest caching)
+	// This needs to be closed on daemon exit
+	mdDB *bbolt.DB
 }
 
 // StoreHosts stores the addresses the daemon is listening on
@@ -1066,10 +1072,7 @@
 
 	d.linkIndex = newLinkIndex()
 
-	// TODO: imageStore, distributionMetadataStore, and ReferenceStore are only
-	// used above to run migration. They could be initialized in ImageService
-	// if migration is called from daemon/images. layerStore might move as well.
-	d.imageService = images.NewImageService(images.ImageServiceConfig{
+	imgSvcConfig := images.ImageServiceConfig{
 		ContainerStore:            d.containers,
 		DistributionMetadataStore: distributionMetadataStore,
 		EventsService:             d.EventsService,
@@ -1081,7 +1084,28 @@
 		ReferenceStore:            rs,
 		RegistryService:           registryService,
 		TrustKey:                  trustKey,
-	})
+		ContentNamespace:          config.ContainerdNamespace,
+	}
+
+	// containerd is not currently supported with Windows.
+	// So sometimes d.containerdCli will be nil
+	// In that case we'll create a local content store... but otherwise we'll use containerd
+	if d.containerdCli != nil {
+		imgSvcConfig.Leases = d.containerdCli.LeasesService()
+		imgSvcConfig.ContentStore = d.containerdCli.ContentStore()
+	} else {
+		cs, lm, err := d.configureLocalContentStore()
+		if err != nil {
+			return nil, err
+		}
+		imgSvcConfig.ContentStore = cs
+		imgSvcConfig.Leases = lm
+	}
+
+	// TODO: imageStore, distributionMetadataStore, and ReferenceStore are only
+	// used above to run migration. They could be initialized in ImageService
+	// if migration is called from daemon/images. layerStore might move as well.
+	d.imageService = images.NewImageService(imgSvcConfig)
 
 	go d.execCommandGC()
 
@@ -1246,6 +1270,10 @@
 		daemon.containerdCli.Close()
 	}
 
+	if daemon.mdDB != nil {
+		daemon.mdDB.Close()
+	}
+
 	return daemon.cleanupMounts()
 }
 
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index d9de559..6951475 100644
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -16,6 +16,7 @@
 	"strings"
 	"time"
 
+	"github.com/containerd/cgroups"
 	statsV1 "github.com/containerd/cgroups/stats/v1"
 	statsV2 "github.com/containerd/cgroups/v2/stats"
 	"github.com/containerd/containerd/sys"
@@ -43,7 +44,6 @@
 	"github.com/docker/libnetwork/options"
 	lntypes "github.com/docker/libnetwork/types"
 	"github.com/moby/sys/mount"
-	"github.com/opencontainers/runc/libcontainer/cgroups"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/opencontainers/selinux/go-selinux/label"
 	"github.com/pkg/errors"
@@ -362,11 +362,11 @@
 	if hostConfig.CgroupnsMode.IsEmpty() {
 		// for cgroup v2: unshare cgroupns even for privileged containers
 		// https://github.com/containers/libpod/pull/4374#issuecomment-549776387
-		if hostConfig.Privileged && !cgroups.IsCgroup2UnifiedMode() {
+		if hostConfig.Privileged && cgroups.Mode() != cgroups.Unified {
 			hostConfig.CgroupnsMode = containertypes.CgroupnsMode("host")
 		} else {
 			m := "host"
-			if cgroups.IsCgroup2UnifiedMode() {
+			if cgroups.Mode() == cgroups.Unified {
 				m = "private"
 			}
 			if daemon.configStore != nil {
@@ -637,7 +637,7 @@
 		return true
 	}
 	// On cgroup v2 hosts, default to systemd driver
-	if getCD(config) == "" && cgroups.IsCgroup2UnifiedMode() && IsRunningSystemd() {
+	if getCD(config) == "" && cgroups.Mode() == cgroups.Unified && IsRunningSystemd() {
 		return true
 	}
 	return false
@@ -761,7 +761,7 @@
 		}
 	}
 
-	if conf.Rootless && UsingSystemd(conf) && !cgroups.IsCgroup2UnifiedMode() {
+	if conf.Rootless && UsingSystemd(conf) && cgroups.Mode() != cgroups.Unified {
 		return fmt.Errorf("exec-opt native.cgroupdriver=systemd requires cgroup v2 for rootless mode")
 	}
 
diff --git a/daemon/graphdriver/copy/copy_test.go b/daemon/graphdriver/copy/copy_test.go
index 491bf78..5fac6fc 100644
--- a/daemon/graphdriver/copy/copy_test.go
+++ b/daemon/graphdriver/copy/copy_test.go
@@ -53,7 +53,6 @@
 		}
 
 		dstPath := filepath.Join(dstDir, relPath)
-		assert.NilError(t, err)
 
 		// If we add non-regular dirs and files to the test
 		// then we need to add more checks here.
diff --git a/daemon/images/image_pull.go b/daemon/images/image_pull.go
index 4eedfdd..ed9099b 100644
--- a/daemon/images/image_pull.go
+++ b/daemon/images/image_pull.go
@@ -6,6 +6,8 @@
 	"strings"
 	"time"
 
+	"github.com/containerd/containerd/leases"
+	"github.com/containerd/containerd/namespaces"
 	dist "github.com/docker/distribution"
 	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
@@ -16,6 +18,7 @@
 	"github.com/docker/docker/registry"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
 )
 
 // PullImage initiates a pull operation. image is the repository name to pull, and
@@ -65,6 +68,25 @@
 		close(writesDone)
 	}()
 
+	ctx = namespaces.WithNamespace(ctx, i.contentNamespace)
+	// Take out a temporary lease for everything that gets persisted to the content store.
+	// Before the lease is cancelled, any content we want to keep should have it's own lease applied.
+	ctx, done, err := tempLease(ctx, i.leases)
+	if err != nil {
+		return err
+	}
+	defer done(ctx)
+
+	cs := &contentStoreForPull{
+		ContentStore: i.content,
+		leases:       i.leases,
+	}
+	imageStore := &imageStoreForPull{
+		ImageConfigStore: distribution.NewImageConfigStoreFromStore(i.imageStore),
+		ingested:         cs,
+		leases:           i.leases,
+	}
+
 	imagePullConfig := &distribution.ImagePullConfig{
 		Config: distribution.Config{
 			MetaHeaders:      metaHeaders,
@@ -73,7 +95,7 @@
 			RegistryService:  i.registryService,
 			ImageEventLogger: i.LogImageEvent,
 			MetadataStore:    i.distributionMetadataStore,
-			ImageStore:       distribution.NewImageConfigStoreFromStore(i.imageStore),
+			ImageStore:       imageStore,
 			ReferenceStore:   i.referenceStore,
 		},
 		DownloadManager: i.downloadManager,
@@ -81,7 +103,7 @@
 		Platform:        platform,
 	}
 
-	err := distribution.Pull(ctx, ref, imagePullConfig)
+	err = distribution.Pull(ctx, ref, imagePullConfig, cs)
 	close(progressChan)
 	<-writesDone
 	return err
@@ -124,3 +146,29 @@
 	}
 	return repository, confirmedV2, lastError
 }
+
+func tempLease(ctx context.Context, mgr leases.Manager) (context.Context, func(context.Context) error, error) {
+	nop := func(context.Context) error { return nil }
+	_, ok := leases.FromContext(ctx)
+	if ok {
+		return ctx, nop, nil
+	}
+
+	// Use an expiration that ensures the lease is cleaned up at some point if there is a crash, SIGKILL, etc.
+	opts := []leases.Opt{
+		leases.WithRandomID(),
+		leases.WithExpiration(24 * time.Hour),
+		leases.WithLabels(map[string]string{
+			"moby.lease/temporary": time.Now().UTC().Format(time.RFC3339Nano),
+		}),
+	}
+	l, err := mgr.Create(ctx, opts...)
+	if err != nil {
+		return ctx, nop, errors.Wrap(err, "error creating temporary lease")
+	}
+
+	ctx = leases.WithLease(ctx, l.ID)
+	return ctx, func(ctx context.Context) error {
+		return mgr.Delete(ctx, l)
+	}, nil
+}
diff --git a/daemon/images/service.go b/daemon/images/service.go
index 388aa2d..e0297c3 100644
--- a/daemon/images/service.go
+++ b/daemon/images/service.go
@@ -5,6 +5,8 @@
 	"os"
 	"runtime"
 
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/leases"
 	"github.com/docker/docker/container"
 	daemonevents "github.com/docker/docker/daemon/events"
 	"github.com/docker/docker/distribution"
@@ -42,6 +44,9 @@
 	ReferenceStore            dockerreference.Store
 	RegistryService           registry.Service
 	TrustKey                  libtrust.PrivateKey
+	ContentStore              content.Store
+	Leases                    leases.Manager
+	ContentNamespace          string
 }
 
 // NewImageService returns a new ImageService from a configuration
@@ -54,12 +59,15 @@
 		distributionMetadataStore: config.DistributionMetadataStore,
 		downloadManager:           xfer.NewLayerDownloadManager(config.LayerStores, config.MaxConcurrentDownloads, xfer.WithMaxDownloadAttempts(config.MaxDownloadAttempts)),
 		eventsService:             config.EventsService,
-		imageStore:                config.ImageStore,
+		imageStore:                &imageStoreWithLease{Store: config.ImageStore, leases: config.Leases, ns: config.ContentNamespace},
 		layerStores:               config.LayerStores,
 		referenceStore:            config.ReferenceStore,
 		registryService:           config.RegistryService,
 		trustKey:                  config.TrustKey,
 		uploadManager:             xfer.NewLayerUploadManager(config.MaxConcurrentUploads),
+		leases:                    config.Leases,
+		content:                   config.ContentStore,
+		contentNamespace:          config.ContentNamespace,
 	}
 }
 
@@ -76,6 +84,9 @@
 	registryService           registry.Service
 	trustKey                  libtrust.PrivateKey
 	uploadManager             *xfer.LayerUploadManager
+	leases                    leases.Manager
+	content                   content.Store
+	contentNamespace          string
 }
 
 // DistributionServices provides daemon image storage services
diff --git a/daemon/images/store.go b/daemon/images/store.go
new file mode 100644
index 0000000..2c8d481
--- /dev/null
+++ b/daemon/images/store.go
@@ -0,0 +1,155 @@
+package images
+
+import (
+	"context"
+	"sync"
+
+	"github.com/containerd/containerd/content"
+	c8derrdefs "github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/leases"
+	"github.com/containerd/containerd/log"
+	"github.com/containerd/containerd/namespaces"
+	"github.com/docker/docker/distribution"
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
+	digest "github.com/opencontainers/go-digest"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+func imageKey(dgst digest.Digest) string {
+	return "moby-image-" + dgst.String()
+}
+
+// imageStoreWithLease wraps the configured image store with one that deletes the lease
+// reigstered for a given image ID, if one exists
+//
+// This is used by the main image service to wrap delete calls to the real image store.
+type imageStoreWithLease struct {
+	image.Store
+	leases leases.Manager
+
+	// Normally we'd pass namespace down through a context.Context, however...
+	// The interface for image store doesn't allow this, so we store it here.
+	ns string
+}
+
+func (s *imageStoreWithLease) Delete(id image.ID) ([]layer.Metadata, error) {
+	ctx := namespaces.WithNamespace(context.TODO(), s.ns)
+	if err := s.leases.Delete(ctx, leases.Lease{ID: imageKey(digest.Digest(id))}); err != nil && !c8derrdefs.IsNotFound(err) {
+		return nil, errors.Wrap(err, "error deleting lease")
+	}
+	return s.Store.Delete(id)
+}
+
+// iamgeStoreForPull is created for each pull It wraps an underlying image store
+// to handle registering leases for content fetched in a single image pull.
+type imageStoreForPull struct {
+	distribution.ImageConfigStore
+	leases   leases.Manager
+	ingested *contentStoreForPull
+}
+
+func (s *imageStoreForPull) Put(ctx context.Context, config []byte) (digest.Digest, error) {
+	id, err := s.ImageConfigStore.Put(ctx, config)
+	if err != nil {
+		return "", err
+	}
+	return id, s.updateLease(ctx, id)
+}
+
+func (s *imageStoreForPull) Get(ctx context.Context, dgst digest.Digest) ([]byte, error) {
+	id, err := s.ImageConfigStore.Get(ctx, dgst)
+	if err != nil {
+		return nil, err
+	}
+	return id, s.updateLease(ctx, dgst)
+}
+
+func (s *imageStoreForPull) updateLease(ctx context.Context, dgst digest.Digest) error {
+	leaseID := imageKey(dgst)
+	lease, err := s.leases.Create(ctx, leases.WithID(leaseID))
+	if err != nil {
+		if !c8derrdefs.IsAlreadyExists(err) {
+			return errors.Wrap(err, "error creating lease")
+		}
+		lease = leases.Lease{ID: leaseID}
+	}
+
+	digested := s.ingested.getDigested()
+	resource := leases.Resource{
+		Type: "content",
+	}
+	for _, dgst := range digested {
+		log.G(ctx).WithFields(logrus.Fields{
+			"digest": dgst,
+			"lease":  lease.ID,
+		}).Debug("Adding content digest to lease")
+
+		resource.ID = dgst.String()
+		if err := s.leases.AddResource(ctx, lease, resource); err != nil {
+			return errors.Wrapf(err, "error adding content digest to lease: %s", dgst)
+		}
+	}
+	return nil
+}
+
+// contentStoreForPull is used to wrap the configured content store to
+// add lease management for a single `pull`
+// It stores all committed digests so that `imageStoreForPull` can add
+// the digsted resources to the lease for an image.
+type contentStoreForPull struct {
+	distribution.ContentStore
+	leases leases.Manager
+
+	mu       sync.Mutex
+	digested []digest.Digest
+}
+
+func (c *contentStoreForPull) addDigested(dgst digest.Digest) {
+	c.mu.Lock()
+	c.digested = append(c.digested, dgst)
+	c.mu.Unlock()
+}
+
+func (c *contentStoreForPull) getDigested() []digest.Digest {
+	c.mu.Lock()
+	digested := make([]digest.Digest, len(c.digested))
+	copy(digested, c.digested)
+	c.mu.Unlock()
+	return digested
+}
+
+func (c *contentStoreForPull) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
+	w, err := c.ContentStore.Writer(ctx, opts...)
+	if err != nil {
+		if c8derrdefs.IsAlreadyExists(err) {
+			var cfg content.WriterOpts
+			for _, o := range opts {
+				if err := o(&cfg); err != nil {
+					return nil, err
+				}
+
+			}
+			c.addDigested(cfg.Desc.Digest)
+		}
+		return nil, err
+	}
+	return &contentWriter{
+		cs:     c,
+		Writer: w,
+	}, nil
+}
+
+type contentWriter struct {
+	cs *contentStoreForPull
+	content.Writer
+}
+
+func (w *contentWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
+	err := w.Writer.Commit(ctx, size, expected, opts...)
+	if err == nil || c8derrdefs.IsAlreadyExists(err) {
+		w.cs.addDigested(expected)
+	}
+	return err
+}
diff --git a/daemon/images/store_test.go b/daemon/images/store_test.go
new file mode 100644
index 0000000..212e362
--- /dev/null
+++ b/daemon/images/store_test.go
@@ -0,0 +1,124 @@
+package images
+
+import (
+	"context"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/content/local"
+	c8derrdefs "github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/leases"
+	"github.com/containerd/containerd/metadata"
+	"github.com/containerd/containerd/namespaces"
+	"github.com/docker/docker/image"
+	digest "github.com/opencontainers/go-digest"
+	v1 "github.com/opencontainers/image-spec/specs-go/v1"
+	"go.etcd.io/bbolt"
+	"gotest.tools/v3/assert"
+	"gotest.tools/v3/assert/cmp"
+)
+
+func setupTestStores(t *testing.T) (context.Context, content.Store, *imageStoreWithLease, func(t *testing.T)) {
+	dir, err := ioutil.TempDir("", t.Name())
+	assert.NilError(t, err)
+
+	backend, err := image.NewFSStoreBackend(filepath.Join(dir, "images"))
+	assert.NilError(t, err)
+	is, err := image.NewImageStore(backend, nil)
+	assert.NilError(t, err)
+
+	db, err := bbolt.Open(filepath.Join(dir, "metadata.db"), 0600, nil)
+	assert.NilError(t, err)
+
+	cs, err := local.NewStore(filepath.Join(dir, "content"))
+	assert.NilError(t, err)
+	mdb := metadata.NewDB(db, cs, nil)
+
+	cleanup := func(t *testing.T) {
+		assert.Check(t, db.Close())
+		assert.Check(t, os.RemoveAll(dir))
+	}
+	ctx := namespaces.WithNamespace(context.Background(), t.Name())
+	images := &imageStoreWithLease{Store: is, ns: t.Name(), leases: metadata.NewLeaseManager(mdb)}
+
+	return ctx, cs, images, cleanup
+}
+
+func TestImageDelete(t *testing.T) {
+	ctx, _, images, cleanup := setupTestStores(t)
+	defer cleanup(t)
+
+	t.Run("no lease", func(t *testing.T) {
+		id, err := images.Create([]byte(`{"rootFS": {}}`))
+		assert.NilError(t, err)
+		defer images.Delete(id)
+
+		ls, err := images.leases.List(ctx)
+		assert.NilError(t, err)
+		assert.Equal(t, len(ls), 0, ls)
+
+		_, err = images.Delete(id)
+		assert.NilError(t, err, "should not error when there is no lease")
+	})
+
+	t.Run("lease exists", func(t *testing.T) {
+		id, err := images.Create([]byte(`{"rootFS": {}}`))
+		assert.NilError(t, err)
+		defer images.Delete(id)
+
+		leaseID := imageKey(digest.Digest(id))
+		_, err = images.leases.Create(ctx, leases.WithID(leaseID))
+		assert.NilError(t, err)
+		defer images.leases.Delete(ctx, leases.Lease{ID: leaseID})
+
+		ls, err := images.leases.List(ctx)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.Equal(len(ls), 1), ls)
+
+		_, err = images.Delete(id)
+		assert.NilError(t, err)
+
+		ls, err = images.leases.List(ctx)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.Equal(len(ls), 0), ls)
+	})
+}
+
+func TestContentStoreForPull(t *testing.T) {
+	ctx, cs, is, cleanup := setupTestStores(t)
+	defer cleanup(t)
+
+	csP := &contentStoreForPull{
+		ContentStore: cs,
+		leases:       is.leases,
+	}
+
+	data := []byte(`{}`)
+	desc := v1.Descriptor{
+		Digest: digest.Canonical.FromBytes(data),
+		Size:   int64(len(data)),
+	}
+
+	w, err := csP.Writer(ctx, content.WithRef(t.Name()), content.WithDescriptor(desc))
+	assert.NilError(t, err)
+
+	_, err = w.Write(data)
+	assert.NilError(t, err)
+	defer w.Close()
+
+	err = w.Commit(ctx, desc.Size, desc.Digest)
+	assert.NilError(t, err)
+
+	assert.Equal(t, len(csP.digested), 1)
+	assert.Check(t, cmp.Equal(csP.digested[0], desc.Digest))
+
+	// Test already exists
+	csP.digested = nil
+	_, err = csP.Writer(ctx, content.WithRef(t.Name()), content.WithDescriptor(desc))
+	assert.Check(t, c8derrdefs.IsAlreadyExists(err))
+	assert.Equal(t, len(csP.digested), 1)
+	assert.Check(t, cmp.Equal(csP.digested[0], desc.Digest))
+}
diff --git a/daemon/logger/loggerutils/file_unix.go b/daemon/logger/loggerutils/file_unix.go
index eb39d4b..e7b6095 100644
--- a/daemon/logger/loggerutils/file_unix.go
+++ b/daemon/logger/loggerutils/file_unix.go
@@ -7,3 +7,7 @@
 func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
 	return os.OpenFile(name, flag, perm)
 }
+
+func open(name string) (*os.File, error) {
+	return os.Open(name)
+}
diff --git a/daemon/logger/loggerutils/file_windows.go b/daemon/logger/loggerutils/file_windows.go
index 507da68..b16bf01 100644
--- a/daemon/logger/loggerutils/file_windows.go
+++ b/daemon/logger/loggerutils/file_windows.go
@@ -4,17 +4,19 @@
 	"os"
 	"syscall"
 	"unsafe"
-
-	"github.com/pkg/errors"
 )
 
+func open(name string) (*os.File, error) {
+	return openFile(name, os.O_RDONLY, 0)
+}
+
 func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
 	if name == "" {
 		return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOENT}
 	}
 	h, err := syscallOpen(fixLongPath(name), flag|syscall.O_CLOEXEC, syscallMode(perm))
 	if err != nil {
-		return nil, errors.Wrap(err, "error opening file")
+		return nil, &os.PathError{Op: "open", Path: name, Err: err}
 	}
 	return os.NewFile(uintptr(h), name), nil
 }
diff --git a/daemon/logger/loggerutils/logfile.go b/daemon/logger/loggerutils/logfile.go
index 2b01192..6b42d9d 100644
--- a/daemon/logger/loggerutils/logfile.go
+++ b/daemon/logger/loggerutils/logfile.go
@@ -68,7 +68,7 @@
 	if rc.counter[fileName] <= 0 {
 		delete(rc.counter, fileName)
 		err := os.Remove(fileName)
-		if err != nil {
+		if err != nil && !os.IsNotExist(err) {
 			return err
 		}
 	}
@@ -87,7 +87,7 @@
 	compress        bool       // whether old versions of log files are compressed
 	lastTimestamp   time.Time  // timestamp of the last log
 	filesRefCounter refCounter // keep reference-counted of decompressed files
-	notifyRotate    *pubsub.Publisher
+	notifyReaders   *pubsub.Publisher
 	marshal         logger.MarshalFunc
 	createDecoder   MakeDecoderFn
 	getTailReader   GetTailReaderFunc
@@ -141,7 +141,7 @@
 		maxFiles:        maxFiles,
 		compress:        compress,
 		filesRefCounter: refCounter{counter: make(map[string]int)},
-		notifyRotate:    pubsub.NewPublisher(0, 1),
+		notifyReaders:   pubsub.NewPublisher(0, 1),
 		marshal:         marshaller,
 		createDecoder:   decodeFunc,
 		perms:           perms,
@@ -167,7 +167,7 @@
 
 	if err := w.checkCapacityAndRotate(); err != nil {
 		w.mu.Unlock()
-		return err
+		return errors.Wrap(err, "error rotating log file")
 	}
 
 	n, err := w.f.Write(b)
@@ -175,49 +175,77 @@
 		w.currentSize += int64(n)
 		w.lastTimestamp = msg.Timestamp
 	}
+
 	w.mu.Unlock()
-	return err
+	return errors.Wrap(err, "error writing log entry")
 }
 
-func (w *LogFile) checkCapacityAndRotate() error {
+func (w *LogFile) checkCapacityAndRotate() (retErr error) {
 	if w.capacity == -1 {
 		return nil
 	}
-
-	if w.currentSize >= w.capacity {
-		w.rotateMu.Lock()
-		fname := w.f.Name()
-		if err := w.f.Close(); err != nil {
-			// if there was an error during a prior rotate, the file could already be closed
-			if !errors.Is(err, os.ErrClosed) {
-				w.rotateMu.Unlock()
-				return errors.Wrap(err, "error closing file")
-			}
-		}
-		if err := rotate(fname, w.maxFiles, w.compress); err != nil {
-			w.rotateMu.Unlock()
-			return err
-		}
-		file, err := openFile(fname, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, w.perms)
-		if err != nil {
-			w.rotateMu.Unlock()
-			return err
-		}
-		w.f = file
-		w.currentSize = 0
-		w.notifyRotate.Publish(struct{}{})
-
-		if w.maxFiles <= 1 || !w.compress {
-			w.rotateMu.Unlock()
-			return nil
-		}
-
-		go func() {
-			compressFile(fname+".1", w.lastTimestamp)
-			w.rotateMu.Unlock()
-		}()
+	if w.currentSize < w.capacity {
+		return nil
 	}
 
+	w.rotateMu.Lock()
+	noCompress := w.maxFiles <= 1 || !w.compress
+	defer func() {
+		// If we aren't going to run the goroutine to compress the log file, then we need to unlock in this function.
+		// Otherwise the lock will be released in the goroutine that handles compression.
+		if retErr != nil || noCompress {
+			w.rotateMu.Unlock()
+		}
+	}()
+
+	fname := w.f.Name()
+	if err := w.f.Close(); err != nil {
+		// if there was an error during a prior rotate, the file could already be closed
+		if !errors.Is(err, os.ErrClosed) {
+			return errors.Wrap(err, "error closing file")
+		}
+	}
+
+	if err := rotate(fname, w.maxFiles, w.compress); err != nil {
+		logrus.WithError(err).Warn("Error rotating log file, log data may have been lost")
+	} else {
+		var renameErr error
+		for i := 0; i < 10; i++ {
+			if renameErr = os.Rename(fname, fname+".1"); renameErr != nil && !os.IsNotExist(renameErr) {
+				logrus.WithError(renameErr).WithField("file", fname).Debug("Error rotating current container log file, evicting readers and retrying")
+				w.notifyReaders.Publish(renameErr)
+				time.Sleep(100 * time.Millisecond)
+				continue
+			}
+			break
+		}
+		if renameErr != nil {
+			logrus.WithError(renameErr).Error("Error renaming current log file")
+		}
+	}
+
+	file, err := openFile(fname, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, w.perms)
+	if err != nil {
+		return err
+	}
+	w.f = file
+	w.currentSize = 0
+
+	w.notifyReaders.Publish(struct{}{})
+
+	if noCompress {
+		return nil
+	}
+
+	ts := w.lastTimestamp
+
+	go func() {
+		if err := compressFile(fname+".1", ts); err != nil {
+			logrus.WithError(err).Error("Error compressing log file after rotation")
+		}
+		w.rotateMu.Unlock()
+	}()
+
 	return nil
 }
 
@@ -240,41 +268,44 @@
 	for i := maxFiles - 1; i > 1; i-- {
 		toPath := name + "." + strconv.Itoa(i) + extension
 		fromPath := name + "." + strconv.Itoa(i-1) + extension
+		logrus.WithField("source", fromPath).WithField("target", toPath).Trace("Rotating log file")
 		if err := os.Rename(fromPath, toPath); err != nil && !os.IsNotExist(err) {
 			return err
 		}
 	}
 
-	if err := os.Rename(name, name+".1"); err != nil && !os.IsNotExist(err) {
-		return err
-	}
-
 	return nil
 }
 
-func compressFile(fileName string, lastTimestamp time.Time) {
-	file, err := os.Open(fileName)
+func compressFile(fileName string, lastTimestamp time.Time) (retErr error) {
+	file, err := open(fileName)
 	if err != nil {
-		logrus.Errorf("Failed to open log file: %v", err)
-		return
+		if os.IsNotExist(err) {
+			logrus.WithField("file", fileName).WithError(err).Debug("Could not open log file to compress")
+			return nil
+		}
+		return errors.Wrap(err, "failed to open log file")
 	}
 	defer func() {
 		file.Close()
-		err := os.Remove(fileName)
-		if err != nil {
-			logrus.Errorf("Failed to remove source log file: %v", err)
+		if retErr == nil {
+			err := os.Remove(fileName)
+			if err != nil && !os.IsNotExist(err) {
+				retErr = errors.Wrap(err, "failed to remove source log file")
+			}
 		}
 	}()
 
 	outFile, err := openFile(fileName+".gz", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0640)
 	if err != nil {
-		logrus.Errorf("Failed to open or create gzip log file: %v", err)
-		return
+		return errors.Wrap(err, "failed to open or create gzip log file")
 	}
 	defer func() {
 		outFile.Close()
-		if err != nil {
-			os.Remove(fileName + ".gz")
+		if retErr != nil {
+			if err := os.Remove(fileName + ".gz"); err != nil && !os.IsExist(err) {
+				logrus.WithError(err).Error("Error cleaning up after failed log compression")
+			}
 		}
 	}()
 
@@ -292,9 +323,10 @@
 
 	_, err = pools.Copy(compressWriter, file)
 	if err != nil {
-		logrus.WithError(err).WithField("module", "container.logs").WithField("file", fileName).Error("Error compressing log file")
-		return
+		return errors.Wrapf(err, "error compressing log file %s", fileName)
 	}
+
+	return nil
 }
 
 // MaxFiles return maximum number of files
@@ -309,7 +341,7 @@
 	if w.closed {
 		return nil
 	}
-	if err := w.f.Close(); err != nil {
+	if err := w.f.Close(); err != nil && !errors.Is(err, os.ErrClosed) {
 		return err
 	}
 	w.closed = true
@@ -322,7 +354,7 @@
 // TODO: Consider a different implementation which can effectively follow logs under frequent rotations.
 func (w *LogFile) ReadLogs(config logger.ReadConfig, watcher *logger.LogWatcher) {
 	w.mu.RLock()
-	currentFile, err := os.Open(w.f.Name())
+	currentFile, err := open(w.f.Name())
 	if err != nil {
 		w.mu.RUnlock()
 		watcher.Err <- err
@@ -340,6 +372,12 @@
 		return
 	}
 
+	notifyEvict := w.notifyReaders.SubscribeTopicWithBuffer(func(i interface{}) bool {
+		_, ok := i.(error)
+		return ok
+	}, 1)
+	defer w.notifyReaders.Evict(notifyEvict)
+
 	if config.Tail != 0 {
 		// TODO(@cpuguy83): Instead of opening every file, only get the files which
 		// are needed to tail.
@@ -358,7 +396,7 @@
 				if strings.HasSuffix(fileName, tmpLogfileSuffix) {
 					err := w.filesRefCounter.Dereference(fileName)
 					if err != nil {
-						logrus.Errorf("Failed to dereference the log file %q: %v", fileName, err)
+						logrus.WithError(err).WithField("file", fileName).Error("Failed to dereference the log file")
 					}
 				}
 			}
@@ -378,9 +416,11 @@
 			readers = append(readers, currentChunk)
 		}
 
-		tailFiles(readers, watcher, dec, w.getTailReader, config)
+		ok := tailFiles(readers, watcher, dec, w.getTailReader, config, notifyEvict)
 		closeFiles()
-
+		if !ok {
+			return
+		}
 		w.mu.RLock()
 	}
 
@@ -390,9 +430,13 @@
 	}
 	w.mu.RUnlock()
 
-	notifyRotate := w.notifyRotate.Subscribe()
-	defer w.notifyRotate.Evict(notifyRotate)
-	followLogs(currentFile, watcher, notifyRotate, dec, config.Since, config.Until)
+	notifyRotate := w.notifyReaders.SubscribeTopic(func(i interface{}) bool {
+		_, ok := i.(struct{})
+		return ok
+	})
+	defer w.notifyReaders.Evict(notifyRotate)
+
+	followLogs(currentFile, watcher, notifyRotate, notifyEvict, dec, config.Since, config.Until)
 }
 
 func (w *LogFile) openRotatedFiles(config logger.ReadConfig) (files []*os.File, err error) {
@@ -415,7 +459,7 @@
 	}()
 
 	for i := w.maxFiles; i > 1; i-- {
-		f, err := os.Open(fmt.Sprintf("%s.%d", w.f.Name(), i-1))
+		f, err := open(fmt.Sprintf("%s.%d", w.f.Name(), i-1))
 		if err != nil {
 			if !os.IsNotExist(err) {
 				return nil, errors.Wrap(err, "error opening rotated log file")
@@ -425,7 +469,7 @@
 			decompressedFileName := fileName + tmpLogfileSuffix
 			tmpFile, err := w.filesRefCounter.GetReference(decompressedFileName, func(refFileName string, exists bool) (*os.File, error) {
 				if exists {
-					return os.Open(refFileName)
+					return open(refFileName)
 				}
 				return decompressfile(fileName, refFileName, config.Since)
 			})
@@ -451,7 +495,7 @@
 }
 
 func decompressfile(fileName, destFileName string, since time.Time) (*os.File, error) {
-	cf, err := os.Open(fileName)
+	cf, err := open(fileName)
 	if err != nil {
 		return nil, errors.Wrap(err, "error opening file for decompression")
 	}
@@ -498,16 +542,25 @@
 	return io.NewSectionReader(f, 0, size), nil
 }
 
-func tailFiles(files []SizeReaderAt, watcher *logger.LogWatcher, dec Decoder, getTailReader GetTailReaderFunc, config logger.ReadConfig) {
+func tailFiles(files []SizeReaderAt, watcher *logger.LogWatcher, dec Decoder, getTailReader GetTailReaderFunc, config logger.ReadConfig, notifyEvict <-chan interface{}) (cont bool) {
 	nLines := config.Tail
 
 	ctx, cancel := context.WithCancel(context.Background())
 	defer cancel()
+
+	cont = true
 	// TODO(@cpuguy83): we should plumb a context through instead of dealing with `WatchClose()` here.
 	go func() {
 		select {
+		case err := <-notifyEvict:
+			if err != nil {
+				watcher.Err <- err.(error)
+				cont = false
+				cancel()
+			}
 		case <-ctx.Done():
 		case <-watcher.WatchConsumerGone():
+			cont = false
 			cancel()
 		}
 	}()
@@ -555,7 +608,7 @@
 	}
 }
 
-func followLogs(f *os.File, logWatcher *logger.LogWatcher, notifyRotate chan interface{}, dec Decoder, since, until time.Time) {
+func followLogs(f *os.File, logWatcher *logger.LogWatcher, notifyRotate, notifyEvict chan interface{}, dec Decoder, since, until time.Time) {
 	dec.Reset(f)
 
 	name := f.Name()
@@ -566,6 +619,7 @@
 	}
 	defer func() {
 		f.Close()
+		dec.Close()
 		fileWatcher.Close()
 	}()
 
@@ -576,7 +630,7 @@
 
 		// retry when the file doesn't exist
 		for retries := 0; retries <= 5; retries++ {
-			f, err = os.Open(name)
+			f, err = open(name)
 			if err == nil || !os.IsNotExist(err) {
 				break
 			}
@@ -593,8 +647,22 @@
 
 	errRetry := errors.New("retry")
 	errDone := errors.New("done")
+
+	handleMustClose := func(evictErr error) {
+		f.Close()
+		dec.Close()
+		logWatcher.Err <- errors.Wrap(err, "log reader evicted due to errors")
+		logrus.WithField("file", f.Name()).Error("Log reader notified that it must re-open log file, some log data may not be streamed to the client.")
+	}
+
 	waitRead := func() error {
 		select {
+		case e := <-notifyEvict:
+			if e != nil {
+				err := e.(error)
+				handleMustClose(err)
+			}
+			return errDone
 		case e := <-fileWatcher.Events():
 			switch e.Op {
 			case fsnotify.Write:
@@ -668,6 +736,14 @@
 
 	// main loop
 	for {
+		select {
+		case err := <-notifyEvict:
+			if err != nil {
+				handleMustClose(err.(error))
+			}
+			return
+		default:
+		}
 		msg, err := dec.Decode()
 		if err != nil {
 			if err := handleDecodeErr(err); err != nil {
@@ -691,6 +767,13 @@
 		}
 		// send the message, unless the consumer is gone
 		select {
+		case e := <-notifyEvict:
+			if e != nil {
+				err := e.(error)
+				logrus.WithError(err).Debug("Reader evicted while sending log message")
+				logWatcher.Err <- err
+			}
+			return
 		case logWatcher.Msg <- msg:
 		case <-logWatcher.WatchConsumerGone():
 			return
diff --git a/daemon/logger/loggerutils/logfile_test.go b/daemon/logger/loggerutils/logfile_test.go
index ab4a542..af951c7 100644
--- a/daemon/logger/loggerutils/logfile_test.go
+++ b/daemon/logger/loggerutils/logfile_test.go
@@ -1,14 +1,18 @@
-package loggerutils
+package loggerutils // import "github.com/docker/docker/daemon/logger/loggerutils"
 
 import (
 	"bufio"
+	"bytes"
 	"context"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
+	"sync/atomic"
 	"testing"
+	"text/tabwriter"
 	"time"
 
 	"github.com/docker/docker/daemon/logger"
@@ -51,6 +55,7 @@
 
 	files := []SizeReaderAt{s1, s2, s3}
 	watcher := logger.NewLogWatcher()
+	defer watcher.ConsumerGone()
 
 	tailReader := func(ctx context.Context, r SizeReaderAt, lines int) (io.Reader, int, error) {
 		return tailfile.NewTailReader(ctx, r, lines)
@@ -62,7 +67,7 @@
 			started := make(chan struct{})
 			go func() {
 				close(started)
-				tailFiles(files, watcher, dec, tailReader, config)
+				tailFiles(files, watcher, dec, tailReader, config, make(chan interface{}))
 			}()
 			<-started
 		})
@@ -72,7 +77,7 @@
 	started := make(chan struct{})
 	go func() {
 		close(started)
-		tailFiles(files, watcher, dec, tailReader, config)
+		tailFiles(files, watcher, dec, tailReader, config, make(chan interface{}))
 	}()
 	<-started
 
@@ -121,7 +126,7 @@
 	followLogsDone := make(chan struct{})
 	var since, until time.Time
 	go func() {
-		followLogs(f, lw, make(chan interface{}), dec, since, until)
+		followLogs(f, lw, make(chan interface{}), make(chan interface{}), dec, since, until)
 		close(followLogsDone)
 	}()
 
@@ -157,19 +162,20 @@
 
 func TestFollowLogsProducerGone(t *testing.T) {
 	lw := logger.NewLogWatcher()
+	defer lw.ConsumerGone()
 
 	f, err := ioutil.TempFile("", t.Name())
 	assert.NilError(t, err)
 	defer os.Remove(f.Name())
 
-	var sent, received, closed int
+	var sent, received, closed int32
 	dec := &dummyWrapper{fn: func() error {
-		switch closed {
+		switch atomic.LoadInt32(&closed) {
 		case 0:
-			sent++
+			atomic.AddInt32(&sent, 1)
 			return nil
 		case 1:
-			closed++
+			atomic.AddInt32(&closed, 1)
 			t.Logf("logDecode() closed after sending %d messages\n", sent)
 			return io.EOF
 		default:
@@ -181,7 +187,7 @@
 
 	followLogsDone := make(chan struct{})
 	go func() {
-		followLogs(f, lw, make(chan interface{}), dec, since, until)
+		followLogs(f, lw, make(chan interface{}), make(chan interface{}), dec, since, until)
 		close(followLogsDone)
 	}()
 
@@ -198,7 +204,7 @@
 	}
 
 	// "stop" the "container"
-	closed = 1
+	atomic.StoreInt32(&closed, 1)
 	lw.ProducerGone()
 
 	// should receive all the messages sent
@@ -209,7 +215,7 @@
 			select {
 			case <-lw.Msg:
 				received++
-				if received == sent {
+				if received == atomic.LoadInt32(&sent) {
 					return
 				}
 			case err := <-lw.Err:
@@ -223,7 +229,7 @@
 		t.Fatalf("timeout waiting for log messages to be read (sent: %d, received: %d", sent, received)
 	}
 
-	t.Logf("messages sent: %d, received: %d", sent, received)
+	t.Logf("messages sent: %d, received: %d", atomic.LoadInt32(&sent), received)
 
 	// followLogs() should be done by now
 	select {
@@ -248,21 +254,30 @@
 	assert.NilError(t, err)
 
 	l := &LogFile{
-		f:            f,
-		capacity:     5,
-		maxFiles:     3,
-		compress:     true,
-		notifyRotate: pubsub.NewPublisher(0, 1),
-		perms:        0600,
+		f:               f,
+		capacity:        5,
+		maxFiles:        3,
+		compress:        true,
+		notifyReaders:   pubsub.NewPublisher(0, 1),
+		perms:           0600,
+		filesRefCounter: refCounter{counter: make(map[string]int)},
+		getTailReader: func(ctx context.Context, r SizeReaderAt, lines int) (io.Reader, int, error) {
+			return tailfile.NewTailReader(ctx, r, lines)
+		},
+		createDecoder: func(io.Reader) Decoder {
+			return dummyDecoder{}
+		},
 		marshal: func(msg *logger.Message) ([]byte, error) {
 			return msg.Line, nil
 		},
 	}
 	defer l.Close()
 
+	ls := dirStringer{dir}
+
 	assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world!")}))
 	_, err = os.Stat(f.Name() + ".1")
-	assert.Assert(t, os.IsNotExist(err), dirStringer{dir})
+	assert.Assert(t, os.IsNotExist(err), ls)
 
 	assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world!")}))
 	poll.WaitOn(t, checkFileExists(f.Name()+".1.gz"), poll.WithDelay(time.Millisecond), poll.WithTimeout(30*time.Second))
@@ -271,11 +286,48 @@
 	poll.WaitOn(t, checkFileExists(f.Name()+".1.gz"), poll.WithDelay(time.Millisecond), poll.WithTimeout(30*time.Second))
 	poll.WaitOn(t, checkFileExists(f.Name()+".2.gz"), poll.WithDelay(time.Millisecond), poll.WithTimeout(30*time.Second))
 
-	// Now let's simulate a failed rotation where the file was able to be closed but something else happened elsewhere
-	// down the line.
-	// We want to make sure that we can recover in the case that `l.f` was closed while attempting a rotation.
-	l.f.Close()
-	assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world!")}))
+	t.Run("closed log file", func(t *testing.T) {
+		// Now let's simulate a failed rotation where the file was able to be closed but something else happened elsewhere
+		// down the line.
+		// We want to make sure that we can recover in the case that `l.f` was closed while attempting a rotation.
+		l.f.Close()
+		assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world!")}))
+		assert.NilError(t, os.Remove(f.Name()+".2.gz"))
+	})
+
+	t.Run("with log reader", func(t *testing.T) {
+		// Make sure rotate works with an active reader
+		lw := logger.NewLogWatcher()
+		defer lw.ConsumerGone()
+		go l.ReadLogs(logger.ReadConfig{Follow: true, Tail: 1000}, lw)
+
+		assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world 0!")}), ls)
+		// make sure the log reader is primed
+		waitForMsg(t, lw, 30*time.Second)
+
+		assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world 1!")}), ls)
+		assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world 2!")}), ls)
+		assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world 3!")}), ls)
+		assert.NilError(t, l.WriteLogEntry(&logger.Message{Line: []byte("hello world 4!")}), ls)
+		poll.WaitOn(t, checkFileExists(f.Name()+".2.gz"), poll.WithDelay(time.Millisecond), poll.WithTimeout(30*time.Second))
+	})
+}
+
+func waitForMsg(t *testing.T, lw *logger.LogWatcher, timeout time.Duration) {
+	t.Helper()
+
+	timer := time.NewTimer(timeout)
+	defer timer.Stop()
+
+	select {
+	case <-lw.Msg:
+	case <-lw.WatchProducerGone():
+		t.Fatal("log producer gone before log message arrived")
+	case err := <-lw.Err:
+		assert.NilError(t, err)
+	case <-timer.C:
+		t.Fatal("timeout waiting for log message")
+	}
 }
 
 type dirStringer struct {
@@ -287,13 +339,18 @@
 	if err != nil {
 		return ""
 	}
-	var s strings.Builder
-	s.WriteString("\n")
+	buf := bytes.NewBuffer(nil)
+	tw := tabwriter.NewWriter(buf, 1, 8, 1, '\t', 0)
+	buf.WriteString("\n")
+
+	btw := bufio.NewWriter(tw)
 
 	for _, fi := range ls {
-		s.WriteString(fi.Name() + "\n")
+		btw.WriteString(fmt.Sprintf("%s\t%s\t%dB\t%s\n", fi.Name(), fi.Mode(), fi.Size(), fi.ModTime()))
 	}
-	return s.String()
+	btw.Flush()
+	tw.Flush()
+	return buf.String()
 }
 
 func checkFileExists(name string) poll.Check {
@@ -305,7 +362,7 @@
 		case os.IsNotExist(err):
 			return poll.Continue("waiting for %s to exist", name)
 		default:
-			t.Logf("%s", dirStringer{filepath.Dir(name)})
+			t.Logf("waiting for %s: %v: %s", name, err, dirStringer{filepath.Dir(name)})
 			return poll.Error(err)
 		}
 	}
diff --git a/daemon/monitor.go b/daemon/monitor.go
index 04d7212..6b3efb4 100644
--- a/daemon/monitor.go
+++ b/daemon/monitor.go
@@ -26,15 +26,17 @@
 
 func (daemon *Daemon) handleContainerExit(c *container.Container, e *libcontainerdtypes.EventInfo) error {
 	c.Lock()
-
-	ec, et, err := daemon.containerd.DeleteTask(context.Background(), c.ID)
+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+	ec, et, err := daemon.containerd.DeleteTask(ctx, c.ID)
+	cancel()
 	if err != nil {
-		logrus.WithError(err).Warnf("failed to delete container %s from containerd", c.ID)
+		logrus.WithError(err).WithField("container", c.ID).Warnf("failed to delete container from containerd")
 	}
 
-	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+	ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
 	c.StreamConfig.Wait(ctx)
 	cancel()
+
 	c.Reset(false)
 
 	exitStatus := container.ExitStatus{
diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go
index 4cc6c9b..3ef7c90 100644
--- a/daemon/oci_linux.go
+++ b/daemon/oci_linux.go
@@ -11,6 +11,7 @@
 	"strconv"
 	"strings"
 
+	cdcgroups "github.com/containerd/cgroups"
 	"github.com/containerd/containerd/containers"
 	coci "github.com/containerd/containerd/oci"
 	"github.com/containerd/containerd/sys"
@@ -89,7 +90,7 @@
 	return func(_ context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
 		var v2Controllers []string
 		if daemon.getCgroupDriver() == cgroupSystemdDriver {
-			if !cgroups.IsCgroup2UnifiedMode() {
+			if cdcgroups.Mode() != cdcgroups.Unified {
 				return errors.New("rootless systemd driver doesn't support cgroup v1")
 			}
 			rootlesskitParentEUID := os.Getenv("ROOTLESSKIT_PARENT_EUID")
@@ -814,7 +815,7 @@
 			return nil
 		}
 
-		if cgroups.IsCgroup2UnifiedMode() {
+		if cdcgroups.Mode() == cdcgroups.Unified {
 			return errors.New("daemon-scoped cpu-rt-period and cpu-rt-runtime are not implemented for cgroup v2")
 		}
 
diff --git a/daemon/start.go b/daemon/start.go
index 049eb68..d9bc082 100644
--- a/daemon/start.go
+++ b/daemon/start.go
@@ -5,9 +5,6 @@
 	"runtime"
 	"time"
 
-	"github.com/containerd/containerd"
-	"github.com/containerd/containerd/containers"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/container"
@@ -181,12 +178,7 @@
 
 	ctx := context.TODO()
 
-	imageRef, err := reference.ParseNormalizedNamed(container.Config.Image)
-	if err != nil {
-		return err
-	}
-
-	err = daemon.containerd.Create(ctx, container.ID, spec, shim, createOptions, withImageName(imageRef.String()))
+	err = daemon.containerd.Create(ctx, container.ID, spec, shim, createOptions)
 	if err != nil {
 		if errdefs.IsConflict(err) {
 			logrus.WithError(err).WithField("container", container.ID).Error("Container not cleaned up from containerd from previous run")
@@ -195,7 +187,7 @@
 			if err := daemon.containerd.Delete(ctx, container.ID); err != nil && !errdefs.IsNotFound(err) {
 				logrus.WithError(err).WithField("container", container.ID).Error("Error cleaning up stale containerd container object")
 			}
-			err = daemon.containerd.Create(ctx, container.ID, spec, shim, createOptions, withImageName(imageRef.String()))
+			err = daemon.containerd.Create(ctx, container.ID, spec, shim, createOptions)
 		}
 		if err != nil {
 			return translateContainerdStartErr(container.Path, container.SetExitCode, err)
@@ -272,10 +264,3 @@
 		logrus.Errorf("%s cleanup: failed to delete container from containerd: %v", container.ID, err)
 	}
 }
-
-func withImageName(n string) containerd.NewContainerOpts {
-	return func(ctx context.Context, _ *containerd.Client, c *containers.Container) error {
-		c.Image = n
-		return nil
-	}
-}
diff --git a/daemon/start_unix.go b/daemon/start_unix.go
index b2908fb..7b70451 100644
--- a/daemon/start_unix.go
+++ b/daemon/start_unix.go
@@ -3,9 +3,9 @@
 package daemon // import "github.com/docker/docker/daemon"
 
 import (
+	"github.com/containerd/cgroups"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/errdefs"
-	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
@@ -27,7 +27,7 @@
 		rt.Shim = defaultV2ShimConfig(daemon.configStore, p)
 	}
 	if rt.Shim.Binary == linuxShimV1 {
-		if cgroups.IsCgroup2UnifiedMode() {
+		if cgroups.Mode() == cgroups.Unified {
 			return "", nil, errdefs.InvalidParameter(errors.Errorf("runtime %q is not supported while cgroups v2 (unified hierarchy) is being used", container.HostConfig.Runtime))
 		}
 		logrus.Warnf("Configured runtime %q is deprecated and will be removed in the next release", container.HostConfig.Runtime)
diff --git a/distribution/config.go b/distribution/config.go
index f96df7b..2e3dd7b 100644
--- a/distribution/config.go
+++ b/distribution/config.go
@@ -84,8 +84,8 @@
 // by digest. Allows getting an image configurations rootfs from the
 // configuration.
 type ImageConfigStore interface {
-	Put([]byte) (digest.Digest, error)
-	Get(digest.Digest) ([]byte, error)
+	Put(context.Context, []byte) (digest.Digest, error)
+	Get(context.Context, digest.Digest) ([]byte, error)
 	RootFSFromConfig([]byte) (*image.RootFS, error)
 	PlatformFromConfig([]byte) (*specs.Platform, error)
 }
@@ -128,12 +128,12 @@
 	}
 }
 
-func (s *imageConfigStore) Put(c []byte) (digest.Digest, error) {
+func (s *imageConfigStore) Put(_ context.Context, c []byte) (digest.Digest, error) {
 	id, err := s.Store.Create(c)
 	return digest.Digest(id), err
 }
 
-func (s *imageConfigStore) Get(d digest.Digest) ([]byte, error) {
+func (s *imageConfigStore) Get(_ context.Context, d digest.Digest) ([]byte, error) {
 	img, err := s.Store.Get(image.IDFromDigest(d))
 	if err != nil {
 		return nil, err
diff --git a/distribution/errors.go b/distribution/errors.go
index 194287d..02f5870 100644
--- a/distribution/errors.go
+++ b/distribution/errors.go
@@ -112,6 +112,23 @@
 	return errdefs.Unknown(err)
 }
 
+func isNotFound(err error) bool {
+	switch v := err.(type) {
+	case errcode.Errors:
+		for _, e := range v {
+			if isNotFound(e) {
+				return true
+			}
+		}
+	case errcode.Error:
+		switch v.Code {
+		case errcode.ErrorCodeDenied, v2.ErrorCodeManifestUnknown, v2.ErrorCodeNameUnknown:
+			return true
+		}
+	}
+	return false
+}
+
 // continueOnError returns true if we should fallback to the next endpoint
 // as a result of this error.
 func continueOnError(err error, mirrorEndpoint bool) bool {
diff --git a/distribution/manifest.go b/distribution/manifest.go
new file mode 100644
index 0000000..a97373b
--- /dev/null
+++ b/distribution/manifest.go
@@ -0,0 +1,195 @@
+package distribution
+
+import (
+	"context"
+	"encoding/json"
+	"io"
+	"io/ioutil"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/log"
+	"github.com/containerd/containerd/remotes"
+	"github.com/docker/distribution"
+	"github.com/docker/distribution/manifest/schema1"
+	digest "github.com/opencontainers/go-digest"
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+)
+
+// This is used by manifestStore to pare down the requirements to implement a
+// full distribution.ManifestService, since `Get` is all we use here.
+type manifestGetter interface {
+	Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error)
+}
+
+type manifestStore struct {
+	local  ContentStore
+	remote manifestGetter
+}
+
+// ContentStore is the interface used to persist registry blobs
+//
+// Currently this is only used to persist manifests and manifest lists.
+// It is exported because `distribution.Pull` takes one as an argument.
+type ContentStore interface {
+	content.Ingester
+	content.Provider
+	Info(ctx context.Context, dgst digest.Digest) (content.Info, error)
+	Abort(ctx context.Context, ref string) error
+}
+
+func (m *manifestStore) getLocal(ctx context.Context, desc specs.Descriptor) (distribution.Manifest, error) {
+	ra, err := m.local.ReaderAt(ctx, desc)
+	if err != nil {
+		return nil, errors.Wrap(err, "error getting content store reader")
+	}
+	defer ra.Close()
+
+	r := io.NewSectionReader(ra, 0, ra.Size())
+	data, err := ioutil.ReadAll(r)
+	if err != nil {
+		return nil, errors.Wrap(err, "error reading manifest from content store")
+	}
+
+	manifest, _, err := distribution.UnmarshalManifest(desc.MediaType, data)
+	if err != nil {
+		return nil, errors.Wrap(err, "error unmarshaling manifest from content store")
+	}
+	return manifest, nil
+}
+
+func (m *manifestStore) getMediaType(ctx context.Context, desc specs.Descriptor) (string, error) {
+	ra, err := m.local.ReaderAt(ctx, desc)
+	if err != nil {
+		return "", errors.Wrap(err, "error getting reader to detect media type")
+	}
+	defer ra.Close()
+
+	mt, err := detectManifestMediaType(ra)
+	if err != nil {
+		return "", errors.Wrap(err, "error detecting media type")
+	}
+	return mt, nil
+}
+
+func (m *manifestStore) Get(ctx context.Context, desc specs.Descriptor) (distribution.Manifest, error) {
+	l := log.G(ctx)
+
+	if desc.MediaType == "" {
+		// When pulling by digest we will not have the media type on the
+		// descriptor since we have not made a request to the registry yet
+		//
+		// We already have the digest, so we only lookup locally... by digest.
+		//
+		// Let's try to detect the media type so we can have a good ref key
+		// here. We may not even have the content locally, and this is fine, but
+		// if we do we should determine that.
+		mt, err := m.getMediaType(ctx, desc)
+		if err != nil && !errdefs.IsNotFound(err) {
+			l.WithError(err).Warn("Error looking up media type of content")
+		}
+		desc.MediaType = mt
+	}
+
+	key := remotes.MakeRefKey(ctx, desc)
+
+	// Here we open a writer to the requested content. This both gives us a
+	// reference to write to if indeed we need to persist it and increments the
+	// ref count on the content.
+	w, err := m.local.Writer(ctx, content.WithDescriptor(desc), content.WithRef(key))
+	if err != nil {
+		if errdefs.IsAlreadyExists(err) {
+			var manifest distribution.Manifest
+			if manifest, err = m.getLocal(ctx, desc); err == nil {
+				return manifest, nil
+			}
+		}
+		// always fallback to the remote if there is an error with the local store
+	}
+	if w != nil {
+		defer w.Close()
+	}
+
+	l.WithError(err).Debug("Fetching manifest from remote")
+
+	manifest, err := m.remote.Get(ctx, desc.Digest)
+	if err != nil {
+		if err := m.local.Abort(ctx, key); err != nil {
+			l.WithError(err).Warn("Error while attempting to abort content ingest")
+		}
+		return nil, err
+	}
+
+	if w != nil {
+		// if `w` is nil here, something happened with the content store, so don't bother trying to persist.
+		if err := m.Put(ctx, manifest, desc, w); err != nil {
+			if err := m.local.Abort(ctx, key); err != nil {
+				l.WithError(err).Warn("error aborting content ingest")
+			}
+			l.WithError(err).Warn("Error persisting manifest")
+		}
+	}
+	return manifest, nil
+}
+
+func (m *manifestStore) Put(ctx context.Context, manifest distribution.Manifest, desc specs.Descriptor, w content.Writer) error {
+	mt, payload, err := manifest.Payload()
+	if err != nil {
+		return err
+	}
+	desc.Size = int64(len(payload))
+	desc.MediaType = mt
+
+	if _, err = w.Write(payload); err != nil {
+		return errors.Wrap(err, "error writing manifest to content store")
+	}
+
+	if err := w.Commit(ctx, desc.Size, desc.Digest); err != nil {
+		return errors.Wrap(err, "error committing manifest to content store")
+	}
+	return nil
+}
+
+func detectManifestMediaType(ra content.ReaderAt) (string, error) {
+	dt := make([]byte, ra.Size())
+	if _, err := ra.ReadAt(dt, 0); err != nil {
+		return "", err
+	}
+
+	return detectManifestBlobMediaType(dt)
+}
+
+// This is used when the manifest store does not know the media type of a sha it
+// was told to get. This would currently only happen when pulling by digest.
+// The media type is needed so the blob can be unmarshalled properly.
+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
+	}
+
+	if err := json.Unmarshal(dt, &mfst); err != nil {
+		return "", err
+	}
+
+	// We may have a media type specified in the json, in which case that should be used.
+	// 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.
+	// 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 != "":
+		return mfst.MediaType, nil
+	case mfst.FSLayers != nil:
+		return schema1.MediaTypeManifest, nil
+	case mfst.Config != nil:
+		return specs.MediaTypeImageManifest, nil
+	default:
+		return specs.MediaTypeImageIndex, nil
+	}
+}
diff --git a/distribution/manifest_test.go b/distribution/manifest_test.go
new file mode 100644
index 0000000..0976a71
--- /dev/null
+++ b/distribution/manifest_test.go
@@ -0,0 +1,351 @@
+package distribution
+
+import (
+	"context"
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"strings"
+	"sync"
+	"testing"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/content/local"
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/remotes"
+	"github.com/docker/distribution"
+	"github.com/docker/distribution/manifest/ocischema"
+	"github.com/docker/distribution/manifest/schema1"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	digest "github.com/opencontainers/go-digest"
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"gotest.tools/v3/assert"
+	"gotest.tools/v3/assert/cmp"
+)
+
+type mockManifestGetter struct {
+	manifests map[digest.Digest]distribution.Manifest
+	gets      int
+}
+
+func (m *mockManifestGetter) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) {
+	m.gets++
+	manifest, ok := m.manifests[dgst]
+	if !ok {
+		return nil, distribution.ErrManifestUnknown{Tag: dgst.String()}
+	}
+	return manifest, nil
+}
+
+type memoryLabelStore struct {
+	mu     sync.Mutex
+	labels map[digest.Digest]map[string]string
+}
+
+// Get returns all the labels for the given digest
+func (s *memoryLabelStore) Get(dgst digest.Digest) (map[string]string, error) {
+	s.mu.Lock()
+	labels := s.labels[dgst]
+	s.mu.Unlock()
+	return labels, nil
+}
+
+// Set sets all the labels for a given digest
+func (s *memoryLabelStore) Set(dgst digest.Digest, labels map[string]string) error {
+	s.mu.Lock()
+	if s.labels == nil {
+		s.labels = make(map[digest.Digest]map[string]string)
+	}
+	s.labels[dgst] = labels
+	s.mu.Unlock()
+	return nil
+}
+
+// Update replaces the given labels for a digest,
+// a key with an empty value removes a label.
+func (s *memoryLabelStore) Update(dgst digest.Digest, update map[string]string) (map[string]string, error) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	labels, ok := s.labels[dgst]
+	if !ok {
+		labels = map[string]string{}
+	}
+	for k, v := range update {
+		labels[k] = v
+	}
+
+	s.labels[dgst] = labels
+
+	return labels, nil
+}
+
+type testingContentStoreWrapper struct {
+	ContentStore
+	errorOnWriter error
+	errorOnCommit error
+}
+
+func (s *testingContentStoreWrapper) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
+	if s.errorOnWriter != nil {
+		return nil, s.errorOnWriter
+	}
+
+	w, err := s.ContentStore.Writer(ctx, opts...)
+	if err != nil {
+		return nil, err
+	}
+
+	if s.errorOnCommit != nil {
+		w = &testingContentWriterWrapper{w, s.errorOnCommit}
+	}
+	return w, nil
+}
+
+type testingContentWriterWrapper struct {
+	content.Writer
+	err error
+}
+
+func (w *testingContentWriterWrapper) Commit(ctx context.Context, size int64, dgst digest.Digest, opts ...content.Opt) error {
+	if w.err != nil {
+		// The contract for `Commit` is to always close.
+		// Since this is returning early before hitting the real `Commit`, we should close it here.
+		w.Close()
+		return w.err
+	}
+	return w.Writer.Commit(ctx, size, dgst, opts...)
+}
+
+func TestManifestStore(t *testing.T) {
+	ociManifest := &specs.Manifest{}
+	serialized, err := json.Marshal(ociManifest)
+	assert.NilError(t, err)
+	dgst := digest.Canonical.FromBytes(serialized)
+
+	setupTest := func(t *testing.T) (specs.Descriptor, *mockManifestGetter, *manifestStore, content.Store, func(*testing.T)) {
+		root, err := ioutil.TempDir("", strings.Replace(t.Name(), "/", "_", -1))
+		assert.NilError(t, err)
+		defer func() {
+			if t.Failed() {
+				os.RemoveAll(root)
+			}
+		}()
+
+		cs, err := local.NewLabeledStore(root, &memoryLabelStore{})
+		assert.NilError(t, err)
+
+		mg := &mockManifestGetter{manifests: make(map[digest.Digest]distribution.Manifest)}
+		store := &manifestStore{local: cs, remote: mg}
+		desc := specs.Descriptor{Digest: dgst, MediaType: specs.MediaTypeImageManifest, Size: int64(len(serialized))}
+
+		return desc, mg, store, cs, func(t *testing.T) {
+			assert.Check(t, os.RemoveAll(root))
+		}
+	}
+
+	ctx := context.Background()
+
+	m, _, err := distribution.UnmarshalManifest(specs.MediaTypeImageManifest, serialized)
+	assert.NilError(t, err)
+
+	writeManifest := func(t *testing.T, cs ContentStore, desc specs.Descriptor, opts ...content.Opt) {
+		ingestKey := remotes.MakeRefKey(ctx, desc)
+		w, err := cs.Writer(ctx, content.WithDescriptor(desc), content.WithRef(ingestKey))
+		assert.NilError(t, err)
+		defer func() {
+			if err := w.Close(); err != nil {
+				t.Log(err)
+			}
+			if t.Failed() {
+				if err := cs.Abort(ctx, ingestKey); err != nil {
+					t.Log(err)
+				}
+			}
+		}()
+
+		_, err = w.Write(serialized)
+		assert.NilError(t, err)
+
+		err = w.Commit(ctx, desc.Size, desc.Digest, opts...)
+		assert.NilError(t, err)
+
+	}
+
+	// All tests should end up with no active ingest
+	checkIngest := func(t *testing.T, cs content.Store, desc specs.Descriptor) {
+		ingestKey := remotes.MakeRefKey(ctx, desc)
+		_, err := cs.Status(ctx, ingestKey)
+		assert.Check(t, errdefs.IsNotFound(err), err)
+	}
+
+	t.Run("no remote or local", func(t *testing.T) {
+		desc, _, store, cs, teardown := setupTest(t)
+		defer teardown(t)
+
+		_, err = store.Get(ctx, desc)
+		checkIngest(t, cs, desc)
+		// This error is what our digest getter returns when it doesn't know about the manifest
+		assert.Error(t, err, distribution.ErrManifestUnknown{Tag: dgst.String()}.Error())
+	})
+
+	t.Run("no local cache", func(t *testing.T) {
+		desc, mg, store, cs, teardown := setupTest(t)
+		defer teardown(t)
+
+		mg.manifests[desc.Digest] = m
+
+		m2, err := store.Get(ctx, desc)
+		checkIngest(t, cs, desc)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+		assert.Check(t, cmp.Equal(mg.gets, 1))
+
+		i, err := cs.Info(ctx, desc.Digest)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.Equal(i.Digest, desc.Digest))
+
+		// Now check again, this should not hit the remote
+		m2, err = store.Get(ctx, desc)
+		checkIngest(t, cs, desc)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+		assert.Check(t, cmp.Equal(mg.gets, 1))
+	})
+
+	t.Run("with local cache", func(t *testing.T) {
+		desc, mg, store, cs, teardown := setupTest(t)
+		defer teardown(t)
+
+		// first add the manifest to the coontent store
+		writeManifest(t, cs, desc)
+
+		// now do the get
+		m2, err := store.Get(ctx, desc)
+		checkIngest(t, cs, desc)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+		assert.Check(t, cmp.Equal(mg.gets, 0))
+
+		i, err := cs.Info(ctx, desc.Digest)
+		assert.NilError(t, err)
+		assert.Check(t, cmp.Equal(i.Digest, desc.Digest))
+	})
+
+	// This is for the case of pull by digest where we don't know the media type of the manifest until it's actually pulled.
+	t.Run("unknown media type", func(t *testing.T) {
+		t.Run("no cache", func(t *testing.T) {
+			desc, mg, store, cs, teardown := setupTest(t)
+			defer teardown(t)
+
+			mg.manifests[desc.Digest] = m
+			desc.MediaType = ""
+
+			m2, err := store.Get(ctx, desc)
+			checkIngest(t, cs, desc)
+			assert.NilError(t, err)
+			assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+			assert.Check(t, cmp.Equal(mg.gets, 1))
+		})
+
+		t.Run("with cache", func(t *testing.T) {
+			t.Run("cached manifest has media type", func(t *testing.T) {
+				desc, mg, store, cs, teardown := setupTest(t)
+				defer teardown(t)
+
+				writeManifest(t, cs, desc)
+				desc.MediaType = ""
+
+				m2, err := store.Get(ctx, desc)
+				checkIngest(t, cs, desc)
+				assert.NilError(t, err)
+				assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+				assert.Check(t, cmp.Equal(mg.gets, 0))
+			})
+
+			t.Run("cached manifest has no media type", func(t *testing.T) {
+				desc, mg, store, cs, teardown := setupTest(t)
+				defer teardown(t)
+
+				desc.MediaType = ""
+				writeManifest(t, cs, desc)
+
+				m2, err := store.Get(ctx, desc)
+				checkIngest(t, cs, desc)
+				assert.NilError(t, err)
+				assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+				assert.Check(t, cmp.Equal(mg.gets, 0))
+			})
+		})
+	})
+
+	// Test that if there is an error with the content store, for whatever
+	// reason, that doesn't stop us from getting the manifest.
+	//
+	// Also makes sure the ingests are aborted.
+	t.Run("error persisting manifest", func(t *testing.T) {
+		t.Run("error on writer", func(t *testing.T) {
+			desc, mg, store, cs, teardown := setupTest(t)
+			defer teardown(t)
+			mg.manifests[desc.Digest] = m
+
+			csW := &testingContentStoreWrapper{ContentStore: store.local, errorOnWriter: errors.New("random error")}
+			store.local = csW
+
+			m2, err := store.Get(ctx, desc)
+			checkIngest(t, cs, desc)
+			assert.NilError(t, err)
+			assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+			assert.Check(t, cmp.Equal(mg.gets, 1))
+
+			_, err = cs.Info(ctx, desc.Digest)
+			// Nothing here since we couldn't persist
+			assert.Check(t, errdefs.IsNotFound(err), err)
+		})
+
+		t.Run("error on commit", func(t *testing.T) {
+			desc, mg, store, cs, teardown := setupTest(t)
+			defer teardown(t)
+			mg.manifests[desc.Digest] = m
+
+			csW := &testingContentStoreWrapper{ContentStore: store.local, errorOnCommit: errors.New("random error")}
+			store.local = csW
+
+			m2, err := store.Get(ctx, desc)
+			checkIngest(t, cs, desc)
+			assert.NilError(t, err)
+			assert.Check(t, cmp.DeepEqual(m, m2, cmpopts.IgnoreUnexported(ocischema.DeserializedManifest{})))
+			assert.Check(t, cmp.Equal(mg.gets, 1))
+
+			_, err = cs.Info(ctx, desc.Digest)
+			// Nothing here since we couldn't persist
+			assert.Check(t, errdefs.IsNotFound(err), err)
+		})
+	})
+}
+
+func TestDetectManifestBlobMediaType(t *testing.T) {
+	type testCase struct {
+		json     []byte
+		expected string
+	}
+	cases := map[string]testCase{
+		"mediaType is set":   {[]byte(`{"mediaType": "bananas"}`), "bananas"},
+		"oci manifest":       {[]byte(`{"config": {}}`), specs.MediaTypeImageManifest},
+		"schema1":            {[]byte(`{"fsLayers": []}`), schema1.MediaTypeManifest},
+		"oci index fallback": {[]byte(`{}`), specs.MediaTypeImageIndex},
+		// Make sure we prefer mediaType
+		"mediaType and config set":   {[]byte(`{"mediaType": "bananas", "config": {}}`), "bananas"},
+		"mediaType and fsLayers set": {[]byte(`{"mediaType": "bananas", "fsLayers": []}`), "bananas"},
+	}
+
+	for name, tc := range cases {
+		t.Run(name, func(t *testing.T) {
+			mt, err := detectManifestBlobMediaType(tc.json)
+			assert.NilError(t, err)
+			assert.Equal(t, mt, tc.expected)
+		})
+	}
+
+}
diff --git a/distribution/pull.go b/distribution/pull.go
index ecf2f98..c8ddd4c 100644
--- a/distribution/pull.go
+++ b/distribution/pull.go
@@ -29,7 +29,7 @@
 // whether a v1 or v2 puller will be created. The other parameters are passed
 // through to the underlying puller implementation for use during the actual
 // pull operation.
-func newPuller(endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, imagePullConfig *ImagePullConfig) (Puller, error) {
+func newPuller(endpoint registry.APIEndpoint, repoInfo *registry.RepositoryInfo, imagePullConfig *ImagePullConfig, local ContentStore) (Puller, error) {
 	switch endpoint.Version {
 	case registry.APIVersion2:
 		return &v2Puller{
@@ -37,6 +37,9 @@
 			endpoint:          endpoint,
 			config:            imagePullConfig,
 			repoInfo:          repoInfo,
+			manifestStore: &manifestStore{
+				local: local,
+			},
 		}, nil
 	case registry.APIVersion1:
 		return nil, fmt.Errorf("protocol version %d no longer supported. Please contact admins of registry %s", endpoint.Version, endpoint.URL)
@@ -46,7 +49,7 @@
 
 // Pull initiates a pull operation. image is the repository name to pull, and
 // tag may be either empty, or indicate a specific tag to pull.
-func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullConfig) error {
+func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullConfig, local ContentStore) error {
 	// Resolve the Repository name from fqn to RepositoryInfo
 	repoInfo, err := imagePullConfig.RegistryService.ResolveRepository(ref)
 	if err != nil {
@@ -104,7 +107,7 @@
 
 		logrus.Debugf("Trying to pull %s from %s %s", reference.FamiliarName(repoInfo.Name), endpoint.URL, endpoint.Version)
 
-		puller, err := newPuller(endpoint, repoInfo, imagePullConfig)
+		puller, err := newPuller(endpoint, repoInfo, imagePullConfig, local)
 		if err != nil {
 			lastErr = err
 			continue
diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go
index 54b66d0..12497ea 100644
--- a/distribution/pull_v2.go
+++ b/distribution/pull_v2.go
@@ -11,6 +11,7 @@
 	"runtime"
 	"strings"
 
+	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/platforms"
 	"github.com/docker/distribution"
 	"github.com/docker/distribution/manifest/manifestlist"
@@ -62,7 +63,8 @@
 	repo              distribution.Repository
 	// confirmedV2 is set to true if we confirm we're talking to a v2
 	// registry. This is used to limit fallbacks to the v1 protocol.
-	confirmedV2 bool
+	confirmedV2   bool
+	manifestStore *manifestStore
 }
 
 func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform *specs.Platform) (err error) {
@@ -73,6 +75,11 @@
 		return err
 	}
 
+	p.manifestStore.remote, err = p.repo.Manifests(ctx)
+	if err != nil {
+		return err
+	}
+
 	if err = p.pullV2Repository(ctx, ref, platform); err != nil {
 		if _, ok := err.(fallbackError); ok {
 			return err
@@ -330,31 +337,75 @@
 }
 
 func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named, platform *specs.Platform) (tagUpdated bool, err error) {
-	manSvc, err := p.repo.Manifests(ctx)
-	if err != nil {
-		return false, err
-	}
 
 	var (
-		manifest    distribution.Manifest
 		tagOrDigest string // Used for logging/progress only
+		dgst        digest.Digest
+		mt          string
+		size        int64
+		tagged      reference.NamedTagged
+		isTagged    bool
 	)
 	if digested, isDigested := ref.(reference.Canonical); isDigested {
-		manifest, err = manSvc.Get(ctx, digested.Digest())
-		if err != nil {
-			return false, err
-		}
-		tagOrDigest = digested.Digest().String()
-	} else if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
-		manifest, err = manSvc.Get(ctx, "", distribution.WithTag(tagged.Tag()))
+		dgst = digested.Digest()
+		tagOrDigest = digested.String()
+	} else if tagged, isTagged = ref.(reference.NamedTagged); isTagged {
+		tagService := p.repo.Tags(ctx)
+		desc, err := tagService.Get(ctx, tagged.Tag())
 		if err != nil {
 			return false, allowV1Fallback(err)
 		}
+
+		dgst = desc.Digest
 		tagOrDigest = tagged.Tag()
+		mt = desc.MediaType
+		size = desc.Size
 	} else {
 		return false, fmt.Errorf("internal error: reference has neither a tag nor a digest: %s", reference.FamiliarString(ref))
 	}
 
+	ctx = log.WithLogger(ctx, logrus.WithFields(
+		logrus.Fields{
+			"digest": dgst,
+			"remote": ref,
+		}))
+
+	desc := specs.Descriptor{
+		MediaType: mt,
+		Digest:    dgst,
+		Size:      size,
+	}
+	manifest, err := p.manifestStore.Get(ctx, desc)
+	if err != nil {
+		if isTagged && isNotFound(errors.Cause(err)) {
+			logrus.WithField("ref", ref).WithError(err).Debug("Falling back to pull manifest by tag")
+
+			msg := `%s Failed to pull manifest by the resolved digest. This registry does not
+	appear to conform to the distribution registry specification; falling back to
+	pull by tag.  This fallback is DEPRECATED, and will be removed in a future
+	release.  Please contact admins of %s. %s
+`
+
+			warnEmoji := "\U000026A0\U0000FE0F"
+			progress.Messagef(p.config.ProgressOutput, "WARNING", msg, warnEmoji, p.endpoint.URL, warnEmoji)
+
+			// Fetch by tag worked, but fetch by digest didn't.
+			// This is a broken registry implementation.
+			// We'll fallback to the old behavior and get the manifest by tag.
+			var ms distribution.ManifestService
+			ms, err = p.repo.Manifests(ctx)
+			if err != nil {
+				return false, err
+			}
+
+			manifest, err = ms.Get(ctx, "", distribution.WithTag(tagged.Tag()))
+			err = errors.Wrap(err, "error after falling back to get manifest by tag")
+		}
+		if err != nil {
+			return false, err
+		}
+	}
+
 	if manifest == nil {
 		return false, fmt.Errorf("image manifest does not exist for tag or digest %q", tagOrDigest)
 	}
@@ -553,7 +604,7 @@
 		return "", "", err
 	}
 
-	imageID, err := p.config.ImageStore.Put(config)
+	imageID, err := p.config.ImageStore.Put(ctx, config)
 	if err != nil {
 		return "", "", err
 	}
@@ -564,7 +615,7 @@
 }
 
 func (p *v2Puller) pullSchema2Layers(ctx context.Context, target distribution.Descriptor, layers []distribution.Descriptor, platform *specs.Platform) (id digest.Digest, err error) {
-	if _, err := p.config.ImageStore.Get(target.Digest); err == nil {
+	if _, err := p.config.ImageStore.Get(ctx, target.Digest); err == nil {
 		// If the image already exists locally, no need to pull
 		// anything.
 		return target.Digest, nil
@@ -721,7 +772,7 @@
 		}
 	}
 
-	imageID, err := p.config.ImageStore.Put(configJSON)
+	imageID, err := p.config.ImageStore.Put(ctx, configJSON)
 	if err != nil {
 		return "", err
 	}
@@ -791,23 +842,23 @@
 	if len(manifestMatches) > 1 {
 		logrus.Debugf("found multiple matches in manifest list, choosing best match %s", manifestMatches[0].Digest.String())
 	}
-	manifestDigest := manifestMatches[0].Digest
+	match := manifestMatches[0]
 
-	if err := checkImageCompatibility(manifestMatches[0].Platform.OS, manifestMatches[0].Platform.OSVersion); err != nil {
+	if err := checkImageCompatibility(match.Platform.OS, match.Platform.OSVersion); err != nil {
 		return "", "", err
 	}
 
-	manSvc, err := p.repo.Manifests(ctx)
+	desc := specs.Descriptor{
+		Digest:    match.Digest,
+		Size:      match.Size,
+		MediaType: match.MediaType,
+	}
+	manifest, err := p.manifestStore.Get(ctx, desc)
 	if err != nil {
 		return "", "", err
 	}
 
-	manifest, err := manSvc.Get(ctx, manifestDigest)
-	if err != nil {
-		return "", "", err
-	}
-
-	manifestRef, err := reference.WithDigest(reference.TrimNamed(ref), manifestDigest)
+	manifestRef, err := reference.WithDigest(reference.TrimNamed(ref), match.Digest)
 	if err != nil {
 		return "", "", err
 	}
diff --git a/distribution/push_v2.go b/distribution/push_v2.go
index b64230f..764149c 100644
--- a/distribution/push_v2.go
+++ b/distribution/push_v2.go
@@ -116,7 +116,7 @@
 func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id digest.Digest) error {
 	logrus.Debugf("Pushing repository: %s", reference.FamiliarString(ref))
 
-	imgConfig, err := p.config.ImageStore.Get(id)
+	imgConfig, err := p.config.ImageStore.Get(ctx, id)
 	if err != nil {
 		return fmt.Errorf("could not find image from tag %s: %v", reference.FamiliarString(ref), err)
 	}
diff --git a/distribution/registry_unit_test.go b/distribution/registry_unit_test.go
index 3651c46..60fbeb9 100644
--- a/distribution/registry_unit_test.go
+++ b/distribution/registry_unit_test.go
@@ -69,7 +69,7 @@
 		},
 		Schema2Types: ImageTypes,
 	}
-	puller, err := newPuller(endpoint, repoInfo, imagePullConfig)
+	puller, err := newPuller(endpoint, repoInfo, imagePullConfig, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/errdefs/helpers.go b/errdefs/helpers.go
index c9916e0..fe06fb6 100644
--- a/errdefs/helpers.go
+++ b/errdefs/helpers.go
@@ -10,6 +10,10 @@
 	return e.error
 }
 
+func (e errNotFound) Unwrap() error {
+	return e.error
+}
+
 // NotFound is a helper to create an error of the class with the same name from any error type
 func NotFound(err error) error {
 	if err == nil || IsNotFound(err) {
@@ -26,6 +30,10 @@
 	return e.error
 }
 
+func (e errInvalidParameter) Unwrap() error {
+	return e.error
+}
+
 // InvalidParameter is a helper to create an error of the class with the same name from any error type
 func InvalidParameter(err error) error {
 	if err == nil || IsInvalidParameter(err) {
@@ -42,6 +50,10 @@
 	return e.error
 }
 
+func (e errConflict) Unwrap() error {
+	return e.error
+}
+
 // Conflict is a helper to create an error of the class with the same name from any error type
 func Conflict(err error) error {
 	if err == nil || IsConflict(err) {
@@ -58,6 +70,10 @@
 	return e.error
 }
 
+func (e errUnauthorized) Unwrap() error {
+	return e.error
+}
+
 // Unauthorized is a helper to create an error of the class with the same name from any error type
 func Unauthorized(err error) error {
 	if err == nil || IsUnauthorized(err) {
@@ -74,6 +90,10 @@
 	return e.error
 }
 
+func (e errUnavailable) Unwrap() error {
+	return e.error
+}
+
 // Unavailable is a helper to create an error of the class with the same name from any error type
 func Unavailable(err error) error {
 	if err == nil || IsUnavailable(err) {
@@ -90,6 +110,10 @@
 	return e.error
 }
 
+func (e errForbidden) Unwrap() error {
+	return e.error
+}
+
 // Forbidden is a helper to create an error of the class with the same name from any error type
 func Forbidden(err error) error {
 	if err == nil || IsForbidden(err) {
@@ -106,6 +130,10 @@
 	return e.error
 }
 
+func (e errSystem) Unwrap() error {
+	return e.error
+}
+
 // System is a helper to create an error of the class with the same name from any error type
 func System(err error) error {
 	if err == nil || IsSystem(err) {
@@ -122,6 +150,10 @@
 	return e.error
 }
 
+func (e errNotModified) Unwrap() error {
+	return e.error
+}
+
 // NotModified is a helper to create an error of the class with the same name from any error type
 func NotModified(err error) error {
 	if err == nil || IsNotModified(err) {
@@ -138,6 +170,10 @@
 	return e.error
 }
 
+func (e errNotImplemented) Unwrap() error {
+	return e.error
+}
+
 // NotImplemented is a helper to create an error of the class with the same name from any error type
 func NotImplemented(err error) error {
 	if err == nil || IsNotImplemented(err) {
@@ -154,6 +190,10 @@
 	return e.error
 }
 
+func (e errUnknown) Unwrap() error {
+	return e.error
+}
+
 // Unknown is a helper to create an error of the class with the same name from any error type
 func Unknown(err error) error {
 	if err == nil || IsUnknown(err) {
@@ -170,6 +210,10 @@
 	return e.error
 }
 
+func (e errCancelled) Unwrap() error {
+	return e.error
+}
+
 // Cancelled is a helper to create an error of the class with the same name from any error type
 func Cancelled(err error) error {
 	if err == nil || IsCancelled(err) {
@@ -186,6 +230,10 @@
 	return e.error
 }
 
+func (e errDeadline) Unwrap() error {
+	return e.error
+}
+
 // Deadline is a helper to create an error of the class with the same name from any error type
 func Deadline(err error) error {
 	if err == nil || IsDeadline(err) {
@@ -202,6 +250,10 @@
 	return e.error
 }
 
+func (e errDataLoss) Unwrap() error {
+	return e.error
+}
+
 // DataLoss is a helper to create an error of the class with the same name from any error type
 func DataLoss(err error) error {
 	if err == nil || IsDataLoss(err) {
diff --git a/errdefs/helpers_test.go b/errdefs/helpers_test.go
index 408f44b..4ae27c7 100644
--- a/errdefs/helpers_test.go
+++ b/errdefs/helpers_test.go
@@ -22,6 +22,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected not found error to match errTest")
+	}
 }
 
 func TestConflict(t *testing.T) {
@@ -35,6 +38,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected conflict error to match errTest")
+	}
 }
 
 func TestForbidden(t *testing.T) {
@@ -48,6 +54,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected forbidden error to match errTest")
+	}
 }
 
 func TestInvalidParameter(t *testing.T) {
@@ -61,6 +70,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected invalid argument error to match errTest")
+	}
 }
 
 func TestNotImplemented(t *testing.T) {
@@ -74,6 +86,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected not implemented error to match errTest")
+	}
 }
 
 func TestNotModified(t *testing.T) {
@@ -87,6 +102,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected not modified error to match errTest")
+	}
 }
 
 func TestUnauthorized(t *testing.T) {
@@ -100,6 +118,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected unauthorized error to match errTest")
+	}
 }
 
 func TestUnknown(t *testing.T) {
@@ -113,6 +134,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected unknown error to match errTest")
+	}
 }
 
 func TestCancelled(t *testing.T) {
@@ -126,6 +150,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected cancelled error to match errTest")
+	}
 }
 
 func TestDeadline(t *testing.T) {
@@ -139,6 +166,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected deadline error to match errTest")
+	}
 }
 
 func TestDataLoss(t *testing.T) {
@@ -152,6 +182,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected data loss error to match errTest")
+	}
 }
 
 func TestUnavailable(t *testing.T) {
@@ -165,6 +198,9 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected unavaillable error to match errTest")
+	}
 }
 
 func TestSystem(t *testing.T) {
@@ -178,4 +214,7 @@
 	if cause := e.(causal).Cause(); cause != errTest {
 		t.Fatalf("causual should be errTest, got: %v", cause)
 	}
+	if !errors.Is(e, errTest) {
+		t.Fatalf("expected system error to match errTest")
+	}
 }
diff --git a/hack/ci/windows.ps1 b/hack/ci/windows.ps1
index ebb4030..fe166e9 100644
--- a/hack/ci/windows.ps1
+++ b/hack/ci/windows.ps1
@@ -1012,9 +1012,6 @@
     Throw $_
 }
 Finally {
-    # Preserve the LastExitCode of the tests
-    $tmpLastExitCode = $LastExitCode
-
     $ErrorActionPreference="SilentlyContinue"
     $global:ProgressPreference=$origProgressPreference
     Write-Host  -ForegroundColor Green "INFO: Tidying up at end of run"
@@ -1053,6 +1050,4 @@
 
     $Dur=New-TimeSpan -Start $StartTime -End $(Get-Date)
     Write-Host -ForegroundColor $FinallyColour "`nINFO: executeCI.ps1 exiting at $(date). Duration $dur`n"
-
-    exit $tmpLastExitCode
 }
diff --git a/hack/dockerfile/install/containerd.installer b/hack/dockerfile/install/containerd.installer
index 5f02f5b..b656a56 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:=c623d1b36f09f8ef6536a057bd658b3aa8632828}" # v1.4.1
+: "${CONTAINERD_COMMIT:=269548fa27e0089a8b8278fc4fc781d7f65a939b}" # v1.4.3
 
 install_containerd() (
 	echo "Install containerd version $CONTAINERD_COMMIT"
diff --git a/hack/dockerfile/install/proxy.installer b/hack/dockerfile/install/proxy.installer
index d8caa0c..046d038 100755
--- a/hack/dockerfile/install/proxy.installer
+++ b/hack/dockerfile/install/proxy.installer
@@ -3,7 +3,7 @@
 # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When
 # updating the binary version, consider updating github.com/docker/libnetwork
 # in vendor.conf accordingly
-: "${LIBNETWORK_COMMIT:=d511c60c5c23e6753631244f271a1ec6097254a5}"
+: "${LIBNETWORK_COMMIT:=a543cbc4871f904b0efe205708eb45d72e65fd8b}"
 
 install_proxy() {
 	case "$1" in
diff --git a/hack/dockerfile/install/rootlesskit.installer b/hack/dockerfile/install/rootlesskit.installer
index 8841dd8..43b84d3 100755
--- a/hack/dockerfile/install/rootlesskit.installer
+++ b/hack/dockerfile/install/rootlesskit.installer
@@ -1,7 +1,7 @@
 #!/bin/sh
 
-# v0.10.0
-: ${ROOTLESSKIT_COMMIT:=f766387c3b360bc6dc6c2f353e9e630cf2c6ee86}
+# v0.11.0
+: ${ROOTLESSKIT_COMMIT:=2886253e467c5444a4d2ac7084e53aa3cc50055d}
 
 install_rootlesskit() {
 	case "$1" in
diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go
index 720a909..76ce061 100644
--- a/integration-cli/docker_api_containers_test.go
+++ b/integration-cli/docker_api_containers_test.go
@@ -30,7 +30,6 @@
 	"github.com/docker/docker/testutil/request"
 	"github.com/docker/docker/volume"
 	"github.com/docker/go-connections/nat"
-	"github.com/moby/sys/mount"
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 	"gotest.tools/v3/poll"
@@ -2056,7 +2055,7 @@
 			assert.NilError(c, err)
 			defer os.RemoveAll(tmpDir3)
 
-			assert.Assert(c, mount.Mount(tmpDir3, tmpDir3, "none", "bind,shared") == nil)
+			assert.Assert(c, mountWrapper(tmpDir3, tmpDir3, "none", "bind,shared") == nil)
 
 			cases = append(cases, []testCase{
 				{
diff --git a/integration-cli/docker_api_containers_unix_test.go b/integration-cli/docker_api_containers_unix_test.go
new file mode 100644
index 0000000..05c667f
--- /dev/null
+++ b/integration-cli/docker_api_containers_unix_test.go
@@ -0,0 +1,9 @@
+// +build !windows
+
+package main
+
+import "github.com/moby/sys/mount"
+
+func mountWrapper(device, target, mType, options string) error {
+	return mount.Mount(device, target, mType, options)
+}
diff --git a/integration-cli/docker_api_containers_windows_test.go b/integration-cli/docker_api_containers_windows_test.go
index 0423d18..1038506 100644
--- a/integration-cli/docker_api_containers_windows_test.go
+++ b/integration-cli/docker_api_containers_windows_test.go
@@ -15,6 +15,7 @@
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/mount"
+	"github.com/pkg/errors"
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 )
@@ -75,3 +76,8 @@
 	assert.NilError(c, err)
 	assert.Check(c, is.Equal(text, strings.TrimSpace(string(b))))
 }
+
+func mountWrapper(device, target, mType, options string) error {
+	// This should never be called.
+	return errors.Errorf("there is no implementation of Mount on this platform")
+}
diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go
index 1acc491..c7dc934 100644
--- a/integration-cli/docker_cli_build_test.go
+++ b/integration-cli/docker_cli_build_test.go
@@ -5608,30 +5608,6 @@
 
 }
 
-func (s *DockerSuite) TestBuildContChar(c *testing.T) {
-	name := "testbuildcontchar"
-
-	buildImage(name, build.WithDockerfile(`FROM busybox\`)).Assert(c, icmd.Expected{
-		Out: "Step 1/1 : FROM busybox",
-	})
-
-	result := buildImage(name, build.WithDockerfile(`FROM busybox
-		 RUN echo hi \`))
-	result.Assert(c, icmd.Success)
-	assert.Assert(c, strings.Contains(result.Combined(), "Step 1/2 : FROM busybox"))
-	assert.Assert(c, strings.Contains(result.Combined(), "Step 2/2 : RUN echo hi\n"))
-	result = buildImage(name, build.WithDockerfile(`FROM busybox
-		 RUN echo hi \\`))
-	result.Assert(c, icmd.Success)
-	assert.Assert(c, strings.Contains(result.Combined(), "Step 1/2 : FROM busybox"))
-	assert.Assert(c, strings.Contains(result.Combined(), "Step 2/2 : RUN echo hi \\\n"))
-	result = buildImage(name, build.WithDockerfile(`FROM busybox
-		 RUN echo hi \\\`))
-	result.Assert(c, icmd.Success)
-	assert.Assert(c, strings.Contains(result.Combined(), "Step 1/2 : FROM busybox"))
-	assert.Assert(c, strings.Contains(result.Combined(), "Step 2/2 : RUN echo hi \\\\\n"))
-}
-
 func (s *DockerSuite) TestBuildMultiStageCopyFromSyntax(c *testing.T) {
 	dockerfile := `
 		FROM busybox AS first
diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go
index 7c22cfc..e0c1bbe 100644
--- a/integration-cli/docker_cli_run_test.go
+++ b/integration-cli/docker_cli_run_test.go
@@ -34,7 +34,6 @@
 	"github.com/docker/go-connections/nat"
 	"github.com/docker/libnetwork/resolvconf"
 	"github.com/docker/libnetwork/types"
-	"github.com/moby/sys/mount"
 	"github.com/moby/sys/mountinfo"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/icmd"
@@ -3764,86 +3763,6 @@
 	}
 }
 
-func (s *DockerSuite) TestRunVolumesMountedAsShared(c *testing.T) {
-	// Volume propagation is linux only. Also it creates directories for
-	// bind mounting, so needs to be same host.
-	testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon, NotUserNamespace)
-
-	// Prepare a source directory to bind mount
-	tmpDir, err := ioutil.TempDir("", "volume-source")
-	if err != nil {
-		c.Fatal(err)
-	}
-	defer os.RemoveAll(tmpDir)
-
-	if err := os.Mkdir(path.Join(tmpDir, "mnt1"), 0755); err != nil {
-		c.Fatal(err)
-	}
-
-	// Convert this directory into a shared mount point so that we do
-	// not rely on propagation properties of parent mount.
-	icmd.RunCommand("mount", "--bind", tmpDir, tmpDir).Assert(c, icmd.Success)
-	icmd.RunCommand("mount", "--make-private", "--make-shared", tmpDir).Assert(c, icmd.Success)
-
-	dockerCmd(c, "run", "--privileged", "-v", fmt.Sprintf("%s:/volume-dest:shared", tmpDir), "busybox", "mount", "--bind", "/volume-dest/mnt1", "/volume-dest/mnt1")
-
-	// Make sure a bind mount under a shared volume propagated to host.
-	if mounted, _ := mountinfo.Mounted(path.Join(tmpDir, "mnt1")); !mounted {
-		c.Fatalf("Bind mount under shared volume did not propagate to host")
-	}
-
-	mount.Unmount(path.Join(tmpDir, "mnt1"))
-}
-
-func (s *DockerSuite) TestRunVolumesMountedAsSlave(c *testing.T) {
-	// Volume propagation is linux only. Also it creates directories for
-	// bind mounting, so needs to be same host.
-	testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon, NotUserNamespace)
-
-	// Prepare a source directory to bind mount
-	tmpDir, err := ioutil.TempDir("", "volume-source")
-	if err != nil {
-		c.Fatal(err)
-	}
-	defer os.RemoveAll(tmpDir)
-
-	if err := os.Mkdir(path.Join(tmpDir, "mnt1"), 0755); err != nil {
-		c.Fatal(err)
-	}
-
-	// Prepare a source directory with file in it. We will bind mount this
-	// directory and see if file shows up.
-	tmpDir2, err := ioutil.TempDir("", "volume-source2")
-	if err != nil {
-		c.Fatal(err)
-	}
-	defer os.RemoveAll(tmpDir2)
-
-	if err := ioutil.WriteFile(path.Join(tmpDir2, "slave-testfile"), []byte("Test"), 0644); err != nil {
-		c.Fatal(err)
-	}
-
-	// Convert this directory into a shared mount point so that we do
-	// not rely on propagation properties of parent mount.
-	icmd.RunCommand("mount", "--bind", tmpDir, tmpDir).Assert(c, icmd.Success)
-	icmd.RunCommand("mount", "--make-private", "--make-shared", tmpDir).Assert(c, icmd.Success)
-
-	dockerCmd(c, "run", "-i", "-d", "--name", "parent", "-v", fmt.Sprintf("%s:/volume-dest:slave", tmpDir), "busybox", "top")
-
-	// Bind mount tmpDir2/ onto tmpDir/mnt1. If mount propagates inside
-	// container then contents of tmpDir2/slave-testfile should become
-	// visible at "/volume-dest/mnt1/slave-testfile"
-	icmd.RunCommand("mount", "--bind", tmpDir2, path.Join(tmpDir, "mnt1")).Assert(c, icmd.Success)
-
-	out, _ := dockerCmd(c, "exec", "parent", "cat", "/volume-dest/mnt1/slave-testfile")
-
-	mount.Unmount(path.Join(tmpDir, "mnt1"))
-
-	if out != "Test" {
-		c.Fatalf("Bind mount under slave volume did not propagate to container")
-	}
-}
-
 func (s *DockerSuite) TestRunNamedVolumesMountedAsShared(c *testing.T) {
 	testRequires(c, DaemonIsLinux, NotUserNamespace)
 	out, exitCode, _ := dockerCmdWithError("run", "-v", "foo:/test:shared", "busybox", "touch", "/test/somefile")
diff --git a/integration/container/mounts_linux_test.go b/integration/container/mounts_linux_test.go
index 1ebdb32..d65bc99 100644
--- a/integration/container/mounts_linux_test.go
+++ b/integration/container/mounts_linux_test.go
@@ -16,6 +16,7 @@
 	"github.com/docker/docker/integration/internal/container"
 	"github.com/docker/docker/pkg/system"
 	"github.com/moby/sys/mount"
+	"github.com/moby/sys/mountinfo"
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 	"gotest.tools/v3/fs"
@@ -266,3 +267,127 @@
 		poll.WaitOn(t, container.IsSuccessful(ctx, client, c), poll.WithDelay(100*time.Millisecond))
 	}
 }
+
+func TestContainerVolumesMountedAsShared(t *testing.T) {
+	// Volume propagation is linux only. Also it creates directories for
+	// bind mounting, so needs to be same host.
+	skip.If(t, testEnv.IsRemoteDaemon)
+	skip.If(t, testEnv.IsUserNamespace)
+	skip.If(t, testEnv.IsRootless, "cannot be tested because RootlessKit executes the daemon in private mount namespace (https://github.com/rootless-containers/rootlesskit/issues/97)")
+
+	defer setupTest(t)()
+
+	// Prepare a source directory to bind mount
+	tmpDir1 := fs.NewDir(t, "volume-source", fs.WithMode(0755),
+		fs.WithDir("mnt1", fs.WithMode(0755)))
+	defer tmpDir1.Remove()
+	tmpDir1Mnt := filepath.Join(tmpDir1.Path(), "mnt1")
+
+	// Convert this directory into a shared mount point so that we do
+	// not rely on propagation properties of parent mount.
+	if err := mount.Mount(tmpDir1.Path(), tmpDir1.Path(), "none", "bind,private"); err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		if err := mount.Unmount(tmpDir1.Path()); err != nil {
+			t.Fatal(err)
+		}
+	}()
+	if err := mount.Mount("none", tmpDir1.Path(), "none", "shared"); err != nil {
+		t.Fatal(err)
+	}
+
+	sharedMount := mounttypes.Mount{
+		Type:   mounttypes.TypeBind,
+		Source: tmpDir1.Path(),
+		Target: "/volume-dest",
+		BindOptions: &mounttypes.BindOptions{
+			Propagation: mounttypes.PropagationShared,
+		},
+	}
+
+	bindMountCmd := []string{"mount", "--bind", "/volume-dest/mnt1", "/volume-dest/mnt1"}
+
+	ctx := context.Background()
+	client := testEnv.APIClient()
+	containerID := container.Run(ctx, t, client, container.WithPrivileged(true), container.WithMount(sharedMount), container.WithCmd(bindMountCmd...))
+	poll.WaitOn(t, container.IsSuccessful(ctx, client, containerID), poll.WithDelay(100*time.Millisecond))
+
+	// Make sure a bind mount under a shared volume propagated to host.
+	if mounted, _ := mountinfo.Mounted(tmpDir1Mnt); !mounted {
+		t.Fatalf("Bind mount under shared volume did not propagate to host")
+	}
+
+	mount.Unmount(tmpDir1Mnt)
+}
+
+func TestContainerVolumesMountedAsSlave(t *testing.T) {
+	// Volume propagation is linux only. Also it creates directories for
+	// bind mounting, so needs to be same host.
+	skip.If(t, testEnv.IsRemoteDaemon)
+	skip.If(t, testEnv.IsUserNamespace)
+	skip.If(t, testEnv.IsRootless, "cannot be tested because RootlessKit executes the daemon in private mount namespace (https://github.com/rootless-containers/rootlesskit/issues/97)")
+
+	// Prepare a source directory to bind mount
+	tmpDir1 := fs.NewDir(t, "volume-source", fs.WithMode(0755),
+		fs.WithDir("mnt1", fs.WithMode(0755)))
+	defer tmpDir1.Remove()
+	tmpDir1Mnt := filepath.Join(tmpDir1.Path(), "mnt1")
+
+	// Prepare a source directory with file in it. We will bind mount this
+	// directory and see if file shows up.
+	tmpDir2 := fs.NewDir(t, "volume-source2", fs.WithMode(0755),
+		fs.WithFile("slave-testfile", "Test", fs.WithMode(0644)))
+	defer tmpDir2.Remove()
+
+	// Convert this directory into a shared mount point so that we do
+	// not rely on propagation properties of parent mount.
+	if err := mount.Mount(tmpDir1.Path(), tmpDir1.Path(), "none", "bind,private"); err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		if err := mount.Unmount(tmpDir1.Path()); err != nil {
+			t.Fatal(err)
+		}
+	}()
+	if err := mount.Mount("none", tmpDir1.Path(), "none", "shared"); err != nil {
+		t.Fatal(err)
+	}
+
+	slaveMount := mounttypes.Mount{
+		Type:   mounttypes.TypeBind,
+		Source: tmpDir1.Path(),
+		Target: "/volume-dest",
+		BindOptions: &mounttypes.BindOptions{
+			Propagation: mounttypes.PropagationSlave,
+		},
+	}
+
+	topCmd := []string{"top"}
+
+	ctx := context.Background()
+	client := testEnv.APIClient()
+	containerID := container.Run(ctx, t, client, container.WithTty(true), container.WithMount(slaveMount), container.WithCmd(topCmd...))
+
+	// Bind mount tmpDir2/ onto tmpDir1/mnt1. If mount propagates inside
+	// container then contents of tmpDir2/slave-testfile should become
+	// visible at "/volume-dest/mnt1/slave-testfile"
+	if err := mount.Mount(tmpDir2.Path(), tmpDir1Mnt, "none", "bind"); err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		if err := mount.Unmount(tmpDir1Mnt); err != nil {
+			t.Fatal(err)
+		}
+	}()
+
+	mountCmd := []string{"cat", "/volume-dest/mnt1/slave-testfile"}
+
+	if result, err := container.Exec(ctx, client, containerID, mountCmd); err == nil {
+		if result.Stdout() != "Test" {
+			t.Fatalf("Bind mount under slave volume did not propagate to container")
+		}
+	} else {
+		t.Fatal(err)
+	}
+}
diff --git a/libcontainerd/remote/client.go b/libcontainerd/remote/client.go
index 1e58768..43f549f 100644
--- a/libcontainerd/remote/client.go
+++ b/libcontainerd/remote/client.go
@@ -862,6 +862,13 @@
 				ei = libcontainerdtypes.EventInfo{
 					ContainerID: t.ContainerID,
 				}
+			case *apievents.TaskDelete:
+				c.logger.WithFields(logrus.Fields{
+					"topic":     ev.Topic,
+					"type":      reflect.TypeOf(t),
+					"container": t.ContainerID},
+				).Info("ignoring event")
+				continue
 			default:
 				c.logger.WithFields(logrus.Fields{
 					"topic": ev.Topic,
diff --git a/oci/fixtures/default.json b/oci/fixtures/default.json
old mode 100755
new mode 100644
diff --git a/oci/fixtures/example.json b/oci/fixtures/example.json
old mode 100755
new mode 100644
diff --git a/opts/hosts_unix.go b/opts/hosts_unix.go
index 9d5bb64..2986419 100644
--- a/opts/hosts_unix.go
+++ b/opts/hosts_unix.go
@@ -2,7 +2,10 @@
 
 package opts // import "github.com/docker/docker/opts"
 
-import "fmt"
+const (
+	// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080
+	DefaultHTTPHost = "localhost"
 
-// DefaultHost constant defines the default host string used by docker on other hosts than Windows
-var DefaultHost = fmt.Sprintf("unix://%s", DefaultUnixSocket)
+	// DefaultHost constant defines the default host string used by docker on other hosts than Windows
+	DefaultHost = "unix://" + DefaultUnixSocket
+)
diff --git a/opts/hosts_windows.go b/opts/hosts_windows.go
index 906eba5..576236b 100644
--- a/opts/hosts_windows.go
+++ b/opts/hosts_windows.go
@@ -1,4 +1,60 @@
 package opts // import "github.com/docker/docker/opts"
 
-// DefaultHost constant defines the default host string used by docker on Windows
-var DefaultHost = "npipe://" + DefaultNamedPipe
+const (
+	// TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5.
+	//
+	// On Windows, this mitigates a problem with the default options of running
+	// a docker client against a local docker daemon on TP5.
+	//
+	// What was found that if the default host is "localhost", even if the client
+	// (and daemon as this is local) is not physically on a network, and the DNS
+	// cache is flushed (ipconfig /flushdns), then the client will pause for
+	// exactly one second when connecting to the daemon for calls. For example
+	// using docker run windowsservercore cmd, the CLI will send a create followed
+	// by an attach. You see the delay between the attach finishing and the attach
+	// being seen by the daemon.
+	//
+	// Here's some daemon debug logs with additional debug spew put in. The
+	// AfterWriteJSON log is the very last thing the daemon does as part of the
+	// create call. The POST /attach is the second CLI call. Notice the second
+	// time gap.
+	//
+	// time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs"
+	// time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig"
+	// time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...."
+	// time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking....
+	// time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...."
+	// time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...."
+	// time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func"
+	// time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create"
+	// time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2"
+	// time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate"
+	// time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON"
+	// ... 1 second gap here....
+	// time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach"
+	// time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1"
+	//
+	// We suspect this is either a bug introduced in GOLang 1.5.1, or that a change
+	// in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory,
+	// the Windows networking stack is supposed to resolve "localhost" internally,
+	// without hitting DNS, or even reading the hosts file (which is why localhost
+	// is commented out in the hosts file on Windows).
+	//
+	// We have validated that working around this using the actual IPv4 localhost
+	// address does not cause the delay.
+	//
+	// This does not occur with the docker client built with 1.4.3 on the same
+	// Windows build, regardless of whether the daemon is built using 1.5.1
+	// or 1.4.3. It does not occur on Linux. We also verified we see the same thing
+	// on a cross-compiled Windows binary (from Linux).
+	//
+	// Final note: This is a mitigation, not a 'real' fix. It is still susceptible
+	// to the delay if a user were to do 'docker run -H=tcp://localhost:2375...'
+	// explicitly.
+
+	// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080
+	DefaultHTTPHost = "127.0.0.1"
+
+	// DefaultHost constant defines the default host string used by docker on Windows
+	DefaultHost = "npipe://" + DefaultNamedPipe
+)
diff --git a/opts/opts_unix.go b/opts/opts_unix.go
deleted file mode 100644
index 0c32367..0000000
--- a/opts/opts_unix.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// +build !windows
-
-package opts // import "github.com/docker/docker/opts"
-
-// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080
-const DefaultHTTPHost = "localhost"
diff --git a/opts/opts_windows.go b/opts/opts_windows.go
deleted file mode 100644
index 4455c9d..0000000
--- a/opts/opts_windows.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package opts // import "github.com/docker/docker/opts"
-
-// TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5.
-//
-// On Windows, this mitigates a problem with the default options of running
-// a docker client against a local docker daemon on TP5.
-//
-// What was found that if the default host is "localhost", even if the client
-// (and daemon as this is local) is not physically on a network, and the DNS
-// cache is flushed (ipconfig /flushdns), then the client will pause for
-// exactly one second when connecting to the daemon for calls. For example
-// using docker run windowsservercore cmd, the CLI will send a create followed
-// by an attach. You see the delay between the attach finishing and the attach
-// being seen by the daemon.
-//
-// Here's some daemon debug logs with additional debug spew put in. The
-// AfterWriteJSON log is the very last thing the daemon does as part of the
-// create call. The POST /attach is the second CLI call. Notice the second
-// time gap.
-//
-// time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs"
-// time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig"
-// time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...."
-// time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking....
-// time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...."
-// time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...."
-// time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func"
-// time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create"
-// time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2"
-// time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate"
-// time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON"
-// ... 1 second gap here....
-// time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach"
-// time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1"
-//
-// We suspect this is either a bug introduced in GOLang 1.5.1, or that a change
-// in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory,
-// the Windows networking stack is supposed to resolve "localhost" internally,
-// without hitting DNS, or even reading the hosts file (which is why localhost
-// is commented out in the hosts file on Windows).
-//
-// We have validated that working around this using the actual IPv4 localhost
-// address does not cause the delay.
-//
-// This does not occur with the docker client built with 1.4.3 on the same
-// Windows build, regardless of whether the daemon is built using 1.5.1
-// or 1.4.3. It does not occur on Linux. We also verified we see the same thing
-// on a cross-compiled Windows binary (from Linux).
-//
-// Final note: This is a mitigation, not a 'real' fix. It is still susceptible
-// to the delay if a user were to do 'docker run -H=tcp://localhost:2375...'
-// explicitly.
-
-// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080
-const DefaultHTTPHost = "127.0.0.1"
diff --git a/pkg/devicemapper/devmapper_wrapper.go b/pkg/devicemapper/devmapper_wrapper.go
index 56facd4..d518657 100644
--- a/pkg/devicemapper/devmapper_wrapper.go
+++ b/pkg/devicemapper/devmapper_wrapper.go
@@ -150,12 +150,11 @@
 	}
 
 	// golang issue: https://github.com/golang/go/issues/11925
-	hdr := reflect.SliceHeader{
-		Data: uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))),
-		Len:  int(Cdeps.count),
-		Cap:  int(Cdeps.count),
-	}
-	devices := *(*[]C.uint64_t)(unsafe.Pointer(&hdr))
+	var devices []C.uint64_t
+	devicesHdr := (*reflect.SliceHeader)(unsafe.Pointer(&devices))
+	devicesHdr.Data = uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps)))
+	devicesHdr.Len = int(Cdeps.count)
+	devicesHdr.Cap = int(Cdeps.count)
 
 	deps := &Deps{
 		Count:  uint32(Cdeps.count),
diff --git a/pkg/mount/deprecated.go b/pkg/mount/deprecated.go
index 70406e11..16c8e59 100644
--- a/pkg/mount/deprecated.go
+++ b/pkg/mount/deprecated.go
@@ -4,52 +4,9 @@
 // Use github.com/moby/sys/mount and github.com/moby/sys/mountinfo instead.
 
 import (
-	sysmount "github.com/moby/sys/mount"
 	"github.com/moby/sys/mountinfo"
 )
 
-// Deprecated: use github.com/moby/sys/mount instead.
-//nolint:golint
-var (
-	Mount            = sysmount.Mount
-	ForceMount       = sysmount.Mount // a deprecated synonym
-	Unmount          = sysmount.Unmount
-	RecursiveUnmount = sysmount.RecursiveUnmount
-)
-
-// Deprecated: use github.com/moby/sys/mount instead.
-//nolint:golint
-const (
-	RDONLY      = sysmount.RDONLY
-	NOSUID      = sysmount.NOSUID
-	NOEXEC      = sysmount.NOEXEC
-	SYNCHRONOUS = sysmount.SYNCHRONOUS
-	NOATIME     = sysmount.NOATIME
-	BIND        = sysmount.BIND
-	DIRSYNC     = sysmount.DIRSYNC
-	MANDLOCK    = sysmount.MANDLOCK
-	NODEV       = sysmount.NODEV
-	NODIRATIME  = sysmount.NODIRATIME
-	UNBINDABLE  = sysmount.UNBINDABLE
-	RUNBINDABLE = sysmount.RUNBINDABLE
-	PRIVATE     = sysmount.PRIVATE
-	RPRIVATE    = sysmount.RPRIVATE
-	SHARED      = sysmount.SHARED
-	RSHARED     = sysmount.RSHARED
-	SLAVE       = sysmount.SLAVE
-	RSLAVE      = sysmount.RSLAVE
-	RBIND       = sysmount.RBIND
-	RELATIME    = sysmount.RELATIME
-	REMOUNT     = sysmount.REMOUNT
-	STRICTATIME = sysmount.STRICTATIME
-)
-
-// Deprecated: use github.com/moby/sys/mount instead.
-//nolint:golint
-var (
-	MergeTmpfsOptions = sysmount.MergeTmpfsOptions
-)
-
 //nolint:golint
 type (
 	// FilterFunc is a type.
diff --git a/pkg/mount/deprecated_unix.go b/pkg/mount/deprecated_unix.go
new file mode 100644
index 0000000..1787f20
--- /dev/null
+++ b/pkg/mount/deprecated_unix.go
@@ -0,0 +1,52 @@
+// +build !darwin,!windows
+
+package mount // import "github.com/docker/docker/pkg/mount"
+
+// Deprecated: this package is not maintained and will be removed.
+// Use github.com/moby/sys/mount and github.com/moby/sys/mountinfo instead.
+
+import (
+	sysmount "github.com/moby/sys/mount"
+)
+
+// Deprecated: use github.com/moby/sys/mount instead.
+//nolint:golint
+var (
+	Mount            = sysmount.Mount
+	ForceMount       = sysmount.Mount // a deprecated synonym
+	Unmount          = sysmount.Unmount
+	RecursiveUnmount = sysmount.RecursiveUnmount
+)
+
+// Deprecated: use github.com/moby/sys/mount instead.
+//nolint:golint
+const (
+	RDONLY      = sysmount.RDONLY
+	NOSUID      = sysmount.NOSUID
+	NOEXEC      = sysmount.NOEXEC
+	SYNCHRONOUS = sysmount.SYNCHRONOUS
+	NOATIME     = sysmount.NOATIME
+	BIND        = sysmount.BIND
+	DIRSYNC     = sysmount.DIRSYNC
+	MANDLOCK    = sysmount.MANDLOCK
+	NODEV       = sysmount.NODEV
+	NODIRATIME  = sysmount.NODIRATIME
+	UNBINDABLE  = sysmount.UNBINDABLE
+	RUNBINDABLE = sysmount.RUNBINDABLE
+	PRIVATE     = sysmount.PRIVATE
+	RPRIVATE    = sysmount.RPRIVATE
+	SHARED      = sysmount.SHARED
+	RSHARED     = sysmount.RSHARED
+	SLAVE       = sysmount.SLAVE
+	RSLAVE      = sysmount.RSLAVE
+	RBIND       = sysmount.RBIND
+	RELATIME    = sysmount.RELATIME
+	REMOUNT     = sysmount.REMOUNT
+	STRICTATIME = sysmount.STRICTATIME
+)
+
+// Deprecated: use github.com/moby/sys/mount instead.
+//nolint:golint
+var (
+	MergeTmpfsOptions = sysmount.MergeTmpfsOptions
+)
diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go
index cabae5e..42709a4 100644
--- a/pkg/sysinfo/sysinfo_linux.go
+++ b/pkg/sysinfo/sysinfo_linux.go
@@ -8,6 +8,7 @@
 	"strings"
 	"sync"
 
+	cdcgroups "github.com/containerd/cgroups"
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
@@ -56,7 +57,7 @@
 	for _, o := range options {
 		o(&opts)
 	}
-	if cgroups.IsCgroup2UnifiedMode() {
+	if cdcgroups.Mode() == cdcgroups.Unified {
 		return newV2(quiet, &opts)
 	}
 
diff --git a/pkg/system/chtimes_unix_test.go b/pkg/system/chtimes_linux_test.go
similarity index 98%
rename from pkg/system/chtimes_unix_test.go
rename to pkg/system/chtimes_linux_test.go
index 779ed4b..273fc0a 100644
--- a/pkg/system/chtimes_unix_test.go
+++ b/pkg/system/chtimes_linux_test.go
@@ -1,5 +1,3 @@
-// +build !windows
-
 package system // import "github.com/docker/docker/pkg/system"
 
 import (
diff --git a/pkg/system/chtimes_unix.go b/pkg/system/chtimes_nowindows.go
similarity index 100%
rename from pkg/system/chtimes_unix.go
rename to pkg/system/chtimes_nowindows.go
diff --git a/pkg/system/rm_unix.go b/pkg/system/rm.go
similarity index 98%
rename from pkg/system/rm_unix.go
rename to pkg/system/rm.go
index 6ba3fb3..c5d80eb 100644
--- a/pkg/system/rm_unix.go
+++ b/pkg/system/rm.go
@@ -1,4 +1,4 @@
-// +build !windows
+// +build !darwin,!windows
 
 package system // import "github.com/docker/docker/pkg/system"
 
diff --git a/pkg/system/rm_nodarwin_test.go b/pkg/system/rm_nodarwin_test.go
new file mode 100644
index 0000000..f3db37e
--- /dev/null
+++ b/pkg/system/rm_nodarwin_test.go
@@ -0,0 +1,36 @@
+// +build !darwin
+
+package system // import "github.com/docker/docker/pkg/system"
+
+import (
+	"io/ioutil"
+	"testing"
+)
+
+func TestEnsureRemoveAllNotExist(t *testing.T) {
+	// should never return an error for a non-existent path
+	if err := EnsureRemoveAll("/non/existent/path"); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestEnsureRemoveAllWithDir(t *testing.T) {
+	dir, err := ioutil.TempDir("", "test-ensure-removeall-with-dir")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := EnsureRemoveAll(dir); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestEnsureRemoveAllWithFile(t *testing.T) {
+	tmp, err := ioutil.TempFile("", "test-ensure-removeall-with-dir")
+	if err != nil {
+		t.Fatal(err)
+	}
+	tmp.Close()
+	if err := EnsureRemoveAll(tmp.Name()); err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/pkg/system/rm_test.go b/pkg/system/rm_test.go
index 4ba2c8f..245edb2 100644
--- a/pkg/system/rm_test.go
+++ b/pkg/system/rm_test.go
@@ -1,10 +1,11 @@
+// +build !darwin,!windows
+
 package system // import "github.com/docker/docker/pkg/system"
 
 import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"runtime"
 	"testing"
 	"time"
 
@@ -12,36 +13,7 @@
 	"gotest.tools/v3/skip"
 )
 
-func TestEnsureRemoveAllNotExist(t *testing.T) {
-	// should never return an error for a non-existent path
-	if err := EnsureRemoveAll("/non/existent/path"); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestEnsureRemoveAllWithDir(t *testing.T) {
-	dir, err := ioutil.TempDir("", "test-ensure-removeall-with-dir")
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err := EnsureRemoveAll(dir); err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestEnsureRemoveAllWithFile(t *testing.T) {
-	tmp, err := ioutil.TempFile("", "test-ensure-removeall-with-dir")
-	if err != nil {
-		t.Fatal(err)
-	}
-	tmp.Close()
-	if err := EnsureRemoveAll(tmp.Name()); err != nil {
-		t.Fatal(err)
-	}
-}
-
 func TestEnsureRemoveAllWithMount(t *testing.T) {
-	skip.If(t, runtime.GOOS == "windows", "mount not supported on Windows")
 	skip.If(t, os.Getuid() != 0, "skipping test that requires root")
 
 	dir1, err := ioutil.TempDir("", "test-ensure-removeall-with-dir1")
diff --git a/profiles/seccomp/default.json b/profiles/seccomp/default.json
index edf8ee2..3ae143c 100644
--- a/profiles/seccomp/default.json
+++ b/profiles/seccomp/default.json
@@ -232,6 +232,8 @@
 				"openat",
 				"openat2",
 				"pause",
+				"pidfd_open",
+				"pidfd_send_signal",
 				"pipe",
 				"pipe2",
 				"poll",
@@ -721,6 +723,7 @@
 		{
 			"names": [
 				"kcmp",
+				"pidfd_getfd",
 				"process_vm_readv",
 				"process_vm_writev",
 				"ptrace"
diff --git a/profiles/seccomp/default_linux.go b/profiles/seccomp/default_linux.go
index 18b5cb0..232a414 100644
--- a/profiles/seccomp/default_linux.go
+++ b/profiles/seccomp/default_linux.go
@@ -225,6 +225,8 @@
 				"openat",
 				"openat2",
 				"pause",
+				"pidfd_open",
+				"pidfd_send_signal",
 				"pipe",
 				"pipe2",
 				"poll",
@@ -622,6 +624,7 @@
 		{
 			Names: []string{
 				"kcmp",
+				"pidfd_getfd",
 				"process_vm_readv",
 				"process_vm_writev",
 				"ptrace",
diff --git a/registry/auth.go b/registry/auth.go
index 0b2f66c..2d0ecde 100644
--- a/registry/auth.go
+++ b/registry/auth.go
@@ -77,22 +77,21 @@
 // endpoint will be pinged to get authorization challenges. These challenges
 // will be used to authenticate against the registry to validate credentials.
 func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent string) (string, string, error) {
-	logrus.Debugf("attempting v2 login to registry endpoint %s", strings.TrimRight(endpoint.URL.String(), "/")+"/v2/")
+	var (
+		endpointStr          = strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
+		modifiers            = Headers(userAgent, nil)
+		authTransport        = transport.NewTransport(NewTransport(endpoint.TLSConfig), modifiers...)
+		credentialAuthConfig = *authConfig
+		creds                = loginCredentialStore{authConfig: &credentialAuthConfig}
+	)
 
-	modifiers := Headers(userAgent, nil)
-	authTransport := transport.NewTransport(NewTransport(endpoint.TLSConfig), modifiers...)
-
-	credentialAuthConfig := *authConfig
-	creds := loginCredentialStore{
-		authConfig: &credentialAuthConfig,
-	}
+	logrus.Debugf("attempting v2 login to registry endpoint %s", endpointStr)
 
 	loginClient, foundV2, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil)
 	if err != nil {
 		return "", "", err
 	}
 
-	endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
 	req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
 	if err != nil {
 		if !foundV2 {
diff --git a/testutil/daemon/daemon_unix.go b/testutil/daemon/daemon_unix.go
index 8b7e53f..788f420 100644
--- a/testutil/daemon/daemon_unix.go
+++ b/testutil/daemon/daemon_unix.go
@@ -11,7 +11,7 @@
 	"syscall"
 	"testing"
 
-	"github.com/docker/docker/pkg/mount"
+	"github.com/moby/sys/mount"
 	"golang.org/x/sys/unix"
 	"gotest.tools/v3/assert"
 )
diff --git a/vendor.conf b/vendor.conf
index ea4a1dc..c50dcf5 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -1,13 +1,13 @@
 github.com/Azure/go-ansiterm                        d6e3b3328b783f23731bc4d058875b0371ff8109
 github.com/Microsoft/hcsshim                        9dcb42f100215f8d375b4a9265e5bba009217a85 # moby branch
-github.com/Microsoft/go-winio                       5b44b70ab3ab4d291a7c1d28afe7b4afeced0ed4 # v0.4.15-0.20200908182639-5b44b70ab3ab
+github.com/Microsoft/go-winio                       5b44b70ab3ab4d291a7c1d28afe7b4afeced0ed4 # v0.4.15
 github.com/docker/libtrust                          9cbd2a1374f46905c68a4eb3694a130610adc62a
 github.com/golang/gddo                              72a348e765d293ed6d1ded7b699591f14d6cd921
 github.com/google/uuid                              0cd6bf5da1e1c83f8b45653022c74f71af0538a4 # v1.1.1
 github.com/gorilla/mux                              98cb6bf42e086f6af920b965c38cacc07402d51b # v1.8.0
 github.com/Microsoft/opengcs                        a10967154e143a36014584a6f664344e3bb0aa64
 github.com/moby/locker                              281af2d563954745bea9d1487c965f24d30742fe # v1.0.1
-github.com/moby/term                                7f0af18e79f2784809e9cef63d0df5aa2c79d76e
+github.com/moby/term                                bea5bbe245bf407372d477f1361d2ff042d2f556
 
 # Note that this dependency uses submodules, providing the github.com/moby/sys/mount,
 # github.com/moby/sys/mountinfo, and github.com/moby/sys/symlink modules. Our vendoring
@@ -16,7 +16,7 @@
 # which could be either `mountinfo/vX.Y.Z`, `mount/vX.Y.Z`, or `symlink/vX.Y.Z`.
 github.com/moby/sys                                 1bc8673b57550ddf85262eb0fed0aac651a37dab # symlink/v0.1.0
 
-github.com/creack/pty                               3a6a957789163cacdfe0e291617a1c8e80612c11 # v1.1.9
+github.com/creack/pty                               2a38352e8b4d7ab6c336eef107e42a55e72e7fbc # v1.1.11
 github.com/sirupsen/logrus                          6699a89a232f3db797f2e280639854bbc4b89725 # v1.7.0
 github.com/tchap/go-patricia                        a7f0089c6f496e8e70402f61733606daa326cac5 # v2.3.0
 golang.org/x/net                                    ab34263943818b32f575efc978a3d24e80b04bd7
@@ -33,20 +33,21 @@
 golang.org/x/sync                                   cd5d95a43a6e21273425c7ae415d3df9ea832eeb
 
 # buildkit
-github.com/moby/buildkit                            4d1f260e8490ec438ab66e08bb105577aca0ce06
-github.com/tonistiigi/fsutil                        ae3a8d753069d0f76fbee396457e8b6cfd7cb8c3
+github.com/moby/buildkit                            950603da215ae03b843f3f66fbe86c4876a6f5a1
+github.com/tonistiigi/fsutil                        0834f99b7b85462efb69b4f571a4fa3ca7da5ac9
+github.com/tonistiigi/units                         6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
 github.com/grpc-ecosystem/grpc-opentracing          8e809c8a86450a29b90dcc9efbf062d0fe6d9746
-github.com/opentracing/opentracing-go               1361b9cd60be79c4c3a7fa9841b3c132e40066a7
+github.com/opentracing/opentracing-go               d34af3eaa63c4d08ab54863a4bdd0daa45212e12 # v1.2.0
 github.com/google/shlex                             e7afc7fbc51079733e9468cdfd1efcd7d196cd1d
-github.com/opentracing-contrib/go-stdlib            b1a47cfbdd7543e70e9ef3e73d0802ad306cc1cc
-github.com/mitchellh/hashstructure                  2bca23e0e452137f789efbc8610126fd8b94f73b
+github.com/opentracing-contrib/go-stdlib            8a6ff1ad1691a29e4f7b5d46604f97634997c8c4 # v1.0.0
+github.com/mitchellh/hashstructure                  a38c50148365edc8df43c1580c48fb2b3a1e9cd7 # v1.0.0
 github.com/gofrs/flock                              6caa7350c26b838538005fae7dbee4e69d9398db # v0.7.3
 github.com/grpc-ecosystem/go-grpc-middleware        3c51f7f332123e8be5a157c0802a228ac85bf9db # v1.2.0
 
 # libnetwork
 
 # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly
-github.com/docker/libnetwork                        d511c60c5c23e6753631244f271a1ec6097254a5 
+github.com/docker/libnetwork                        a543cbc4871f904b0efe205708eb45d72e65fd8b
 github.com/docker/go-events                         e31b211e4f1cd09aa76fe4ac244571fab96ae47f
 github.com/armon/go-radix                           e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
 github.com/armon/go-metrics                         eb0af217e5e9747e41dd5303755356b62d28e3ec
@@ -129,14 +130,14 @@
 google.golang.org/genproto                          3f1135a288c9a07e340ae8ba4cc6c7065a3160e8
 
 # containerd
-github.com/containerd/containerd                    c623d1b36f09f8ef6536a057bd658b3aa8632828 # v1.4.1
-github.com/containerd/fifo                          f15a3290365b9d2627d189e619ab4008e0069caf
+github.com/containerd/containerd                    0edc412565dcc6e3d6125ff9e4b009ad4b89c638 # master (v1.5.0-dev)
+github.com/containerd/fifo                          0724c46b320cf96bb172a0550c19a4b1fca4dacb
 github.com/containerd/continuity                    efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
-github.com/containerd/cgroups                       318312a373405e5e91134d8063d04d59768a1bff
+github.com/containerd/cgroups                       0b889c03f102012f1d93a97ddd3ef71cd6f4f510
 github.com/containerd/console                       5d7e1412f07b502a01029ea20e20e0d2be31fa7c # v1.0.1
-github.com/containerd/go-runc                       7016d3ce2328dd2cb1192b2076ebd565c4e8df0c
+github.com/containerd/go-runc                       16b287bc67d069a60fa48db15f330b790b74365b
 github.com/containerd/typeurl                       cd3ce7159eae562a4f60ceff37dada11a939d247 # v1.0.1
-github.com/containerd/ttrpc                         72bb1b21c5b0a4a107f59dd85f6ab58e564b68d6 # v1.0.1
+github.com/containerd/ttrpc                         bfba540dc45464586c106b1f31c8547933c1eb41 # v1.0.2
 github.com/gogo/googleapis                          01e0f9cca9b92166042241267ee2a5cdf5cff46c # v1.3.2
 github.com/cilium/ebpf                              1c8d4c9ef7759622653a1d319284a44652333b28
 
@@ -147,7 +148,7 @@
 github.com/cloudflare/cfssl                         5d63dbd981b5c408effbb58c442d54761ff94fbd # 1.3.2
 github.com/fernet/fernet-go                         9eac43b88a5efb8651d24de9b68e87567e029736
 github.com/google/certificate-transparency-go       37a384cd035e722ea46e55029093e26687138edf # v1.0.20
-golang.org/x/crypto                                 75b288015ac94e66e3d6715fb68a9b41bf046ec2
+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
@@ -167,7 +168,7 @@
 github.com/cespare/xxhash/v2                        d7df74196a9e781ede915320c11c378c1b2f3a1f # v2.1.1
 
 # cli
-github.com/spf13/cobra                              a684a6d7f5e37385d954dd3b5a14fc6912c6ab9d # v1.0.0
+github.com/spf13/cobra                              86f8bfd7fef868a174e1b606783bd7f5c82ddf8f # v1.1.1
 github.com/spf13/pflag                              2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab # v1.0.5
 github.com/inconshreveable/mousetrap                76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0.0
 github.com/morikuni/aec                             39771216ff4c63d11f5e604076f9c45e8be1067b # v1.0.0
diff --git a/vendor/github.com/containerd/cgroups/memory.go b/vendor/github.com/containerd/cgroups/memory.go
index d3810c5..e271866 100644
--- a/vendor/github.com/containerd/cgroups/memory.go
+++ b/vendor/github.com/containerd/cgroups/memory.go
@@ -24,7 +24,6 @@
 	"path/filepath"
 	"strconv"
 	"strings"
-	"syscall"
 
 	v1 "github.com/containerd/cgroups/stats/v1"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -207,21 +206,6 @@
 	if resources.Memory == nil {
 		return nil
 	}
-	if resources.Memory.Kernel != nil {
-		// Check if kernel memory is enabled
-		// We have to limit the kernel memory here as it won't be accounted at all
-		// until a limit is set on the cgroup and limit cannot be set once the
-		// cgroup has children, or if there are already tasks in the cgroup.
-		for _, i := range []int64{1, -1} {
-			if err := retryingWriteFile(
-				filepath.Join(m.Path(path), "memory.kmem.limit_in_bytes"),
-				[]byte(strconv.FormatInt(i, 10)),
-				defaultFilePerm,
-			); err != nil {
-				return checkEBUSY(err)
-			}
-		}
-	}
 	return m.set(path, getMemorySettings(resources))
 }
 
@@ -248,18 +232,28 @@
 }
 
 func (m *memoryController) Stat(path string, stats *v1.Metrics) error {
-	f, err := os.Open(filepath.Join(m.Path(path), "memory.stat"))
+	fMemStat, err := os.Open(filepath.Join(m.Path(path), "memory.stat"))
 	if err != nil {
 		return err
 	}
-	defer f.Close()
+	defer fMemStat.Close()
 	stats.Memory = &v1.MemoryStat{
 		Usage:     &v1.MemoryEntry{},
 		Swap:      &v1.MemoryEntry{},
 		Kernel:    &v1.MemoryEntry{},
 		KernelTCP: &v1.MemoryEntry{},
 	}
-	if err := m.parseStats(f, stats.Memory); err != nil {
+	if err := m.parseStats(fMemStat, stats.Memory); err != nil {
+		return err
+	}
+
+	fMemOomControl, err := os.Open(filepath.Join(m.Path(path), "memory.oom_control"))
+	if err != nil {
+		return err
+	}
+	defer fMemOomControl.Close()
+	stats.MemoryOomControl = &v1.MemoryOomControl{}
+	if err := m.parseOomControlStats(fMemOomControl, stats.MemoryOomControl); err != nil {
 		return err
 	}
 	for _, t := range []struct {
@@ -374,6 +368,29 @@
 	return nil
 }
 
+func (m *memoryController) parseOomControlStats(r io.Reader, stat *v1.MemoryOomControl) error {
+	var (
+		raw  = make(map[string]uint64)
+		sc   = bufio.NewScanner(r)
+		line int
+	)
+	for sc.Scan() {
+		key, v, err := parseKV(sc.Text())
+		if err != nil {
+			return fmt.Errorf("%d: %v", line, err)
+		}
+		raw[key] = v
+		line++
+	}
+	if err := sc.Err(); err != nil {
+		return err
+	}
+	stat.OomKillDisable = raw["oom_kill_disable"]
+	stat.UnderOom = raw["under_oom"]
+	stat.OomKill = raw["oom_kill"]
+	return nil
+}
+
 func (m *memoryController) set(path string, settings []memorySettings) error {
 	for _, t := range settings {
 		if t.value != nil {
@@ -433,18 +450,6 @@
 	}
 }
 
-func checkEBUSY(err error) error {
-	if pathErr, ok := err.(*os.PathError); ok {
-		if errNo, ok := pathErr.Err.(syscall.Errno); ok {
-			if errNo == unix.EBUSY {
-				return fmt.Errorf(
-					"failed to set memory.kmem.limit_in_bytes, because either tasks have already joined this cgroup or it has children")
-			}
-		}
-	}
-	return err
-}
-
 func getOomControlValue(mem *specs.LinuxMemory) *int64 {
 	if mem.DisableOOMKiller != nil && *mem.DisableOOMKiller {
 		i := int64(1)
diff --git a/vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go b/vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go
index 713376d..a530f1d 100644
--- a/vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go
+++ b/vendor/github.com/containerd/cgroups/stats/v1/metrics.pb.go
@@ -33,6 +33,7 @@
 	Rdma                 *RdmaStat      `protobuf:"bytes,6,opt,name=rdma,proto3" json:"rdma,omitempty"`
 	Network              []*NetworkStat `protobuf:"bytes,7,rep,name=network,proto3" json:"network,omitempty"`
 	CgroupStats          *CgroupStats   `protobuf:"bytes,8,opt,name=cgroup_stats,json=cgroupStats,proto3" json:"cgroup_stats,omitempty"`
+	MemoryOomControl     *MemoryOomControl `protobuf:"bytes,9,opt,name=memory_oom_control,json=MemoryOomControl,proto3" json:"memory_oom_control,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
 	XXX_unrecognized     []byte         `json:"-"`
 	XXX_sizecache        int32          `json:"-"`
@@ -392,6 +393,47 @@
 
 var xxx_messageInfo_MemoryEntry proto.InternalMessageInfo
 
+type MemoryOomControl struct {
+	OomKillDisable   uint64   `protobuf:"varint,1,opt,name=oom_kill_disable,proto3" json:oom_kill_disable",omitempty"`
+	UnderOom         uint64   `protobuf:"varint,2,opt,name=under_oom,proto3" json:"under_oom,omitempty"`
+	OomKill          uint64   `protobuf:"varint,3,opt,name=oom_kill,proto3" json:"oom_kill,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *MemoryOomControl) Reset()  { *m = MemoryOomControl{} }
+func (*MemoryOomControl) ProtoMessage() {}
+func (*MemoryOomControl) Descriptor() ([]byte, []int) {
+	return fileDescriptor_a17b2d87c332bfaa, []int{8}
+}
+func (m *MemoryOomControl) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *MemoryOomControl) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_MemoryOomControl.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalTo(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *MemoryOomControl) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_MemoryOomControl.Merge(m, src)
+}
+func (m *MemoryOomControl) XXX_Size() int {
+	return m.Size()
+}
+func (m *MemoryOomControl) XXX_DiscardUnknown() {
+	xxx_messageInfo_MemoryOomControl.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MemoryOomControl proto.InternalMessageInfo
+
 type BlkIOStat struct {
 	IoServiceBytesRecursive []*BlkIOEntry `protobuf:"bytes,1,rep,name=io_service_bytes_recursive,json=ioServiceBytesRecursive,proto3" json:"io_service_bytes_recursive,omitempty"`
 	IoServicedRecursive     []*BlkIOEntry `protobuf:"bytes,2,rep,name=io_serviced_recursive,json=ioServicedRecursive,proto3" json:"io_serviced_recursive,omitempty"`
@@ -409,7 +451,7 @@
 func (m *BlkIOStat) Reset()      { *m = BlkIOStat{} }
 func (*BlkIOStat) ProtoMessage() {}
 func (*BlkIOStat) Descriptor() ([]byte, []int) {
-	return fileDescriptor_a17b2d87c332bfaa, []int{8}
+	return fileDescriptor_a17b2d87c332bfaa, []int{9}
 }
 func (m *BlkIOStat) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -452,7 +494,7 @@
 func (m *BlkIOEntry) Reset()      { *m = BlkIOEntry{} }
 func (*BlkIOEntry) ProtoMessage() {}
 func (*BlkIOEntry) Descriptor() ([]byte, []int) {
-	return fileDescriptor_a17b2d87c332bfaa, []int{9}
+	return fileDescriptor_a17b2d87c332bfaa, []int{10}
 }
 func (m *BlkIOEntry) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -492,7 +534,7 @@
 func (m *RdmaStat) Reset()      { *m = RdmaStat{} }
 func (*RdmaStat) ProtoMessage() {}
 func (*RdmaStat) Descriptor() ([]byte, []int) {
-	return fileDescriptor_a17b2d87c332bfaa, []int{10}
+	return fileDescriptor_a17b2d87c332bfaa, []int{11}
 }
 func (m *RdmaStat) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -533,7 +575,7 @@
 func (m *RdmaEntry) Reset()      { *m = RdmaEntry{} }
 func (*RdmaEntry) ProtoMessage() {}
 func (*RdmaEntry) Descriptor() ([]byte, []int) {
-	return fileDescriptor_a17b2d87c332bfaa, []int{11}
+	return fileDescriptor_a17b2d87c332bfaa, []int{12}
 }
 func (m *RdmaEntry) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -580,7 +622,7 @@
 func (m *NetworkStat) Reset()      { *m = NetworkStat{} }
 func (*NetworkStat) ProtoMessage() {}
 func (*NetworkStat) Descriptor() ([]byte, []int) {
-	return fileDescriptor_a17b2d87c332bfaa, []int{12}
+	return fileDescriptor_a17b2d87c332bfaa, []int{13}
 }
 func (m *NetworkStat) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -629,7 +671,7 @@
 func (m *CgroupStats) Reset()      { *m = CgroupStats{} }
 func (*CgroupStats) ProtoMessage() {}
 func (*CgroupStats) Descriptor() ([]byte, []int) {
-	return fileDescriptor_a17b2d87c332bfaa, []int{13}
+	return fileDescriptor_a17b2d87c332bfaa, []int{14}
 }
 func (m *CgroupStats) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -667,6 +709,7 @@
 	proto.RegisterType((*Throttle)(nil), "io.containerd.cgroups.v1.Throttle")
 	proto.RegisterType((*MemoryStat)(nil), "io.containerd.cgroups.v1.MemoryStat")
 	proto.RegisterType((*MemoryEntry)(nil), "io.containerd.cgroups.v1.MemoryEntry")
+	proto.RegisterType((*MemoryOomControl)(nil), "io.containerd.cgroups.v1.MemoryOomControl")
 	proto.RegisterType((*BlkIOStat)(nil), "io.containerd.cgroups.v1.BlkIOStat")
 	proto.RegisterType((*BlkIOEntry)(nil), "io.containerd.cgroups.v1.BlkIOEntry")
 	proto.RegisterType((*RdmaStat)(nil), "io.containerd.cgroups.v1.RdmaStat")
@@ -887,6 +930,16 @@
 		}
 		i += n6
 	}
+	if m.MemoryOomControl != nil {
+		dAtA[i] = 0x4a
+		i++
+		i = encodeVarintMetrics(dAtA, i, uint64(m.MemoryOomControl.Size()))
+		n7, err := m.MemoryOomControl.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n7
+	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
 	}
@@ -1400,6 +1453,39 @@
 	return i, nil
 }
 
+func (m *MemoryOomControl) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *MemoryOomControl) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.OomKillDisable != 0 {
+		dAtA[i] = 0x8
+		i++
+		i = encodeVarintMetrics(dAtA, i, uint64(m.OomKillDisable))
+	}
+	if m.UnderOom != 0 {
+		dAtA[i] = 0x10
+		i++
+		i = encodeVarintMetrics(dAtA, i, uint64(m.UnderOom))
+	}
+	if m.OomKill != 0 {
+		dAtA[i] = 0x18
+		i++
+		i = encodeVarintMetrics(dAtA, i, uint64(m.OomKill))
+	}
+	return i, nil
+}
+
 func (m *BlkIOStat) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -1811,6 +1897,10 @@
 		l = m.CgroupStats.Size()
 		n += 1 + l + sovMetrics(uint64(l))
 	}
+	if m.MemoryOomControl != nil {
+		l = m.MemoryOomControl.Size()
+		n += 1 + l + sovMetrics(uint64(l))
+	}
 	if m.XXX_unrecognized != nil {
 		n += len(m.XXX_unrecognized)
 	}
@@ -2077,6 +2167,27 @@
 	return n
 }
 
+func (m *MemoryOomControl) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.OomKillDisable != 0 {
+		n += 1 + sovMetrics(uint64(m.OomKillDisable))
+	}
+	if m.UnderOom != 0 {
+		n += 1 + sovMetrics(uint64(m.UnderOom))
+	}
+	if m.OomKill != 0 {
+		n += 1 + sovMetrics(uint64(m.OomKill))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
 func (m *BlkIOStat) Size() (n int) {
 	if m == nil {
 		return 0
@@ -2301,6 +2412,7 @@
 		`Pids:` + strings.Replace(fmt.Sprintf("%v", this.Pids), "PidsStat", "PidsStat", 1) + `,`,
 		`CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`,
 		`Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`,
+		`MemoryOomControl:` + strings.Replace(fmt.Sprintf("%v", this.MemoryOomControl), "MemoryOomControl", "MemoryOomControl", 1) + `,`,
 		`Blkio:` + strings.Replace(fmt.Sprintf("%v", this.Blkio), "BlkIOStat", "BlkIOStat", 1) + `,`,
 		`Rdma:` + strings.Replace(fmt.Sprintf("%v", this.Rdma), "RdmaStat", "RdmaStat", 1) + `,`,
 		`Network:` + strings.Replace(fmt.Sprintf("%v", this.Network), "NetworkStat", "NetworkStat", 1) + `,`,
@@ -2435,6 +2547,19 @@
 	}, "")
 	return s
 }
+func (this *MemoryOomControl) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&MemoryOomControl{`,
+		`OomKillDisable:` + fmt.Sprintf("%v", this.OomKillDisable) + `,`,
+		`UnderOom:` + fmt.Sprintf("%v", this.UnderOom) + `,`,
+		`OomKill:` + fmt.Sprintf("%v", this.OomKill) + `,`,
+		`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *BlkIOStat) String() string {
 	if this == nil {
 		return "nil"
@@ -2848,6 +2973,41 @@
 				return err
 			}
 			iNdEx = postIndex
+		case 9:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field MemoryOomControl", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowMetrics
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthMetrics
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthMetrics
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.MemoryOomControl == nil {
+				m.MemoryOomControl = &MemoryOomControl{}
+			}
+			if err := m.MemoryOomControl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
 		default:
 			iNdEx = preIndex
 			skippy, err := skipMetrics(dAtA[iNdEx:])
@@ -4468,6 +4628,117 @@
 	}
 	return nil
 }
+func (m *MemoryOomControl) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowMetrics
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: MemoryOomControl: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: MemoryOomControl: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OomKillDisable", wireType)
+			}
+			m.OomKillDisable = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowMetrics
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.OomKillDisable |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field UnderOom", wireType)
+			}
+			m.UnderOom = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowMetrics
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.UnderOom |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field OomKill", wireType)
+			}
+			m.OomKill = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowMetrics
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.OomKill |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipMetrics(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthMetrics
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthMetrics
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *BlkIOStat) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
diff --git a/vendor/github.com/containerd/cgroups/stats/v1/metrics.proto b/vendor/github.com/containerd/cgroups/stats/v1/metrics.proto
index ba6be85..b3f6cc3 100644
--- a/vendor/github.com/containerd/cgroups/stats/v1/metrics.proto
+++ b/vendor/github.com/containerd/cgroups/stats/v1/metrics.proto
@@ -13,6 +13,7 @@
 	RdmaStat rdma = 6;
 	repeated NetworkStat network = 7;
 	CgroupStats cgroup_stats = 8;
+	MemoryOomControl memory_oom_control = 9;
 }
 
 message HugetlbStat {
@@ -94,6 +95,12 @@
 	uint64 failcnt = 4;
 }
 
+message MemoryOomControl {
+	uint64 oom_kill_disable = 1;
+	uint64 under_oom = 2;
+	uint64 oom_kill = 3;
+}
+
 message BlkIOStat {
 	repeated BlkIOEntry io_service_bytes_recursive = 1;
 	repeated BlkIOEntry io_serviced_recursive = 2;
diff --git a/vendor/github.com/containerd/containerd/README.md b/vendor/github.com/containerd/containerd/README.md
index a973d51..0633148 100644
--- a/vendor/github.com/containerd/containerd/README.md
+++ b/vendor/github.com/containerd/containerd/README.md
@@ -1,6 +1,6 @@
 ![containerd banner](https://raw.githubusercontent.com/cncf/artwork/master/projects/containerd/horizontal/color/containerd-horizontal-color.png)
 
-[![GoDoc](https://godoc.org/github.com/containerd/containerd?status.svg)](https://godoc.org/github.com/containerd/containerd)
+[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/containerd)](https://pkg.go.dev/github.com/containerd/containerd)
 [![Build Status](https://github.com/containerd/containerd/workflows/CI/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ACI)
 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/containerd/containerd?branch=master&svg=true)](https://ci.appveyor.com/project/mlaventure/containerd-3g73f?branch=master)
 [![Nightlies](https://github.com/containerd/containerd/workflows/Nightly/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ANightly)
@@ -10,10 +10,24 @@
 
 containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.
 
+containerd is a member of CNCF with ['graduated'](https://landscape.cncf.io/selected=containerd) status.
+
 containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users.
 
 ![architecture](design/architecture.png)
 
+## Now Recruiting
+
+We are a large inclusive OSS project that is welcoming help of any kind shape or form:
+* Documentation help is needed to make the product easier to consume and extend.
+* We need OSS community outreach / organizing help to get the word out; manage
+and create messaging and educational content; and to help with social media, community forums/groups, and google groups.
+* We are actively inviting new [security advisors](https://github.com/containerd/project/blob/master/GOVERNANCE.md#security-advisors) to join the team.
+* New sub-projects are being created, core and non-core that could use additional development help.
+* Each of the [containerd projects](https://github.com/containerd) has a list of issues currently being worked on or that need help resolving.
+  - If the issue has not already been assigned to someone, or has not made recent progress and you are interested, please inquire.
+  - If you are interested in starting with a smaller / beginner level issue, look for issues with an `exp/beginner` tag, for example [containerd/containerd beginner issues.](https://github.com/containerd/containerd/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%2Fbeginner)
+
 ## Getting Started
 
 See our documentation on [containerd.io](https://containerd.io):
@@ -250,10 +264,7 @@
 For async communication and long running discussions please use issues and pull requests on the github repo.
 This will be the best place to discuss design and implementation.
 
-For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development.
-
-**Slack:** Catch us in the #containerd and #containerd-dev channels on dockercommunity.slack.com.
-[Click here for an invite to docker community slack.](https://dockr.ly/slack)
+For sync communication catch us in the `#containerd` and `#containerd-dev` slack channels on Cloud Native Computing Foundation's (CNCF) slack - `cloud-native.slack.com`. Everyone is welcome to join and chat. [Get Invite to CNCF slack.](https://slack.cncf.io)
 
 ### Security audit
 
diff --git a/vendor/github.com/containerd/containerd/cio/io.go b/vendor/github.com/containerd/containerd/cio/io.go
index 6637999..003c663 100644
--- a/vendor/github.com/containerd/containerd/cio/io.go
+++ b/vendor/github.com/containerd/containerd/cio/io.go
@@ -260,6 +260,26 @@
 	}
 }
 
+// TerminalBinaryIO forwards container STDOUT|STDERR directly to a logging binary
+// It also sets the terminal option to true
+func TerminalBinaryIO(binary string, args map[string]string) Creator {
+	return func(_ string) (IO, error) {
+		uri, err := LogURIGenerator("binary", binary, args)
+		if err != nil {
+			return nil, err
+		}
+
+		res := uri.String()
+		return &logURI{
+			config: Config{
+				Stdout:   res,
+				Stderr:   res,
+				Terminal: true,
+			},
+		}, nil
+	}
+}
+
 // LogFile creates a file on disk that logs the task's STDOUT,STDERR.
 // If the log file already exists, the logs will be appended to the file.
 func LogFile(path string) Creator {
diff --git a/vendor/github.com/containerd/containerd/container_restore_opts.go b/vendor/github.com/containerd/containerd/container_restore_opts.go
index 03722db..fb60e8d 100644
--- a/vendor/github.com/containerd/containerd/container_restore_opts.go
+++ b/vendor/github.com/containerd/containerd/container_restore_opts.go
@@ -87,21 +87,21 @@
 				return err
 			}
 		}
-		var options *ptypes.Any
+		var options ptypes.Any
 		if m != nil {
 			store := client.ContentStore()
 			data, err := content.ReadBlob(ctx, store, *m)
 			if err != nil {
 				return errors.Wrap(err, "unable to read checkpoint runtime")
 			}
-			if err := proto.Unmarshal(data, options); err != nil {
+			if err := proto.Unmarshal(data, &options); err != nil {
 				return err
 			}
 		}
 
 		c.Runtime = containers.RuntimeInfo{
 			Name:    name,
-			Options: options,
+			Options: &options,
 		}
 		return nil
 	}
diff --git a/vendor/github.com/containerd/containerd/content/helpers.go b/vendor/github.com/containerd/containerd/content/helpers.go
index c1c20461..4c4a353 100644
--- a/vendor/github.com/containerd/containerd/content/helpers.go
+++ b/vendor/github.com/containerd/containerd/content/helpers.go
@@ -229,9 +229,47 @@
 	return r, nil
 }
 
+// copyWithBuffer is very similar to  io.CopyBuffer https://golang.org/pkg/io/#CopyBuffer
+// but instead of using Read to read from the src, we use ReadAtLeast to make sure we have
+// a full buffer before we do a write operation to dst to reduce overheads associated
+// with the write operations of small buffers.
 func copyWithBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
-	buf := bufPool.Get().(*[]byte)
-	written, err = io.CopyBuffer(dst, src, *buf)
-	bufPool.Put(buf)
+	// If the reader has a WriteTo method, use it to do the copy.
+	// Avoids an allocation and a copy.
+	if wt, ok := src.(io.WriterTo); ok {
+		return wt.WriteTo(dst)
+	}
+	// Similarly, if the writer has a ReadFrom method, use it to do the copy.
+	if rt, ok := dst.(io.ReaderFrom); ok {
+		return rt.ReadFrom(src)
+	}
+	bufRef := bufPool.Get().(*[]byte)
+	defer bufPool.Put(bufRef)
+	buf := *bufRef
+	for {
+		nr, er := io.ReadAtLeast(src, buf, len(buf))
+		if nr > 0 {
+			nw, ew := dst.Write(buf[0:nr])
+			if nw > 0 {
+				written += int64(nw)
+			}
+			if ew != nil {
+				err = ew
+				break
+			}
+			if nr != nw {
+				err = io.ErrShortWrite
+				break
+			}
+		}
+		if er != nil {
+			// If an EOF happens after reading fewer than the requested bytes,
+			// ReadAtLeast returns ErrUnexpectedEOF.
+			if er != io.EOF && er != io.ErrUnexpectedEOF {
+				err = er
+			}
+			break
+		}
+	}
 	return
 }
diff --git a/vendor/github.com/containerd/containerd/content/local/store_unix.go b/vendor/github.com/containerd/containerd/content/local/store_unix.go
index f5f34fd..270b8db 100644
--- a/vendor/github.com/containerd/containerd/content/local/store_unix.go
+++ b/vendor/github.com/containerd/containerd/content/local/store_unix.go
@@ -1,4 +1,4 @@
-// +build linux solaris darwin freebsd
+// +build linux solaris darwin freebsd netbsd
 
 /*
    Copyright The containerd Authors.
diff --git a/vendor/github.com/containerd/containerd/content/proxy/content_reader.go b/vendor/github.com/containerd/containerd/content/proxy/content_reader.go
index b06e48f..2947a7c 100644
--- a/vendor/github.com/containerd/containerd/content/proxy/content_reader.go
+++ b/vendor/github.com/containerd/containerd/content/proxy/content_reader.go
@@ -40,7 +40,13 @@
 		Offset: off,
 		Size_:  int64(len(p)),
 	}
-	rc, err := ra.client.Read(ra.ctx, rr)
+	// we need a child context with cancel, or the eventually called
+	// grpc.NewStream will leak the goroutine until the whole thing is cleared.
+	// See comment at https://godoc.org/google.golang.org/grpc#ClientConn.NewStream
+	childCtx, cancel := context.WithCancel(ra.ctx)
+	// we MUST cancel the child context; see comment above
+	defer cancel()
+	rc, err := ra.client.Read(childCtx, rr)
 	if err != nil {
 		return 0, err
 	}
diff --git a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go b/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go
deleted file mode 100644
index b7cf176..0000000
--- a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-   Copyright The containerd Authors.
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-package seccomp
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-
-	"github.com/containerd/containerd/containers"
-	"github.com/containerd/containerd/oci"
-	"github.com/opencontainers/runtime-spec/specs-go"
-)
-
-// WithProfile receives the name of a file stored on disk comprising a json
-// formatted seccomp profile, as specified by the opencontainers/runtime-spec.
-// The profile is read from the file, unmarshaled, and set to the spec.
-func WithProfile(profile string) oci.SpecOpts {
-	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
-		s.Linux.Seccomp = &specs.LinuxSeccomp{}
-		f, err := ioutil.ReadFile(profile)
-		if err != nil {
-			return fmt.Errorf("cannot load seccomp profile %q: %v", profile, err)
-		}
-		if err := json.Unmarshal(f, s.Linux.Seccomp); err != nil {
-			return fmt.Errorf("decoding seccomp profile failed %q: %v", profile, err)
-		}
-		return nil
-	}
-}
-
-// WithDefaultProfile sets the default seccomp profile to the spec.
-// Note: must follow the setting of process capabilities
-func WithDefaultProfile() oci.SpecOpts {
-	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
-		s.Linux.Seccomp = DefaultProfile(s)
-		return nil
-	}
-}
diff --git a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp_default.go b/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp_default.go
deleted file mode 100644
index f1337e6..0000000
--- a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp_default.go
+++ /dev/null
@@ -1,651 +0,0 @@
-// +build linux
-
-/*
-   Copyright The containerd Authors.
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-package seccomp
-
-import (
-	"runtime"
-
-	"golang.org/x/sys/unix"
-
-	"github.com/opencontainers/runtime-spec/specs-go"
-)
-
-func arches() []specs.Arch {
-	switch runtime.GOARCH {
-	case "amd64":
-		return []specs.Arch{specs.ArchX86_64, specs.ArchX86, specs.ArchX32}
-	case "arm64":
-		return []specs.Arch{specs.ArchARM, specs.ArchAARCH64}
-	case "mips64":
-		return []specs.Arch{specs.ArchMIPS, specs.ArchMIPS64, specs.ArchMIPS64N32}
-	case "mips64n32":
-		return []specs.Arch{specs.ArchMIPS, specs.ArchMIPS64, specs.ArchMIPS64N32}
-	case "mipsel64":
-		return []specs.Arch{specs.ArchMIPSEL, specs.ArchMIPSEL64, specs.ArchMIPSEL64N32}
-	case "mipsel64n32":
-		return []specs.Arch{specs.ArchMIPSEL, specs.ArchMIPSEL64, specs.ArchMIPSEL64N32}
-	case "s390x":
-		return []specs.Arch{specs.ArchS390, specs.ArchS390X}
-	default:
-		return []specs.Arch{}
-	}
-}
-
-// DefaultProfile defines the allowed syscalls for the default seccomp profile.
-func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
-	syscalls := []specs.LinuxSyscall{
-		{
-			Names: []string{
-				"accept",
-				"accept4",
-				"access",
-				"adjtimex",
-				"alarm",
-				"bind",
-				"brk",
-				"capget",
-				"capset",
-				"chdir",
-				"chmod",
-				"chown",
-				"chown32",
-				"clock_adjtime",
-				"clock_adjtime64",
-				"clock_getres",
-				"clock_getres_time64",
-				"clock_gettime",
-				"clock_gettime64",
-				"clock_nanosleep",
-				"clock_nanosleep_time64",
-				"close",
-				"connect",
-				"copy_file_range",
-				"creat",
-				"dup",
-				"dup2",
-				"dup3",
-				"epoll_create",
-				"epoll_create1",
-				"epoll_ctl",
-				"epoll_ctl_old",
-				"epoll_pwait",
-				"epoll_wait",
-				"epoll_wait_old",
-				"eventfd",
-				"eventfd2",
-				"execve",
-				"execveat",
-				"exit",
-				"exit_group",
-				"faccessat",
-				"faccessat2",
-				"fadvise64",
-				"fadvise64_64",
-				"fallocate",
-				"fanotify_mark",
-				"fchdir",
-				"fchmod",
-				"fchmodat",
-				"fchown",
-				"fchown32",
-				"fchownat",
-				"fcntl",
-				"fcntl64",
-				"fdatasync",
-				"fgetxattr",
-				"flistxattr",
-				"flock",
-				"fork",
-				"fremovexattr",
-				"fsetxattr",
-				"fstat",
-				"fstat64",
-				"fstatat64",
-				"fstatfs",
-				"fstatfs64",
-				"fsync",
-				"ftruncate",
-				"ftruncate64",
-				"futex",
-				"futex_time64",
-				"futimesat",
-				"getcpu",
-				"getcwd",
-				"getdents",
-				"getdents64",
-				"getegid",
-				"getegid32",
-				"geteuid",
-				"geteuid32",
-				"getgid",
-				"getgid32",
-				"getgroups",
-				"getgroups32",
-				"getitimer",
-				"getpeername",
-				"getpgid",
-				"getpgrp",
-				"getpid",
-				"getppid",
-				"getpriority",
-				"getrandom",
-				"getresgid",
-				"getresgid32",
-				"getresuid",
-				"getresuid32",
-				"getrlimit",
-				"get_robust_list",
-				"getrusage",
-				"getsid",
-				"getsockname",
-				"getsockopt",
-				"get_thread_area",
-				"gettid",
-				"gettimeofday",
-				"getuid",
-				"getuid32",
-				"getxattr",
-				"inotify_add_watch",
-				"inotify_init",
-				"inotify_init1",
-				"inotify_rm_watch",
-				"io_cancel",
-				"ioctl",
-				"io_destroy",
-				"io_getevents",
-				"io_pgetevents",
-				"io_pgetevents_time64",
-				"ioprio_get",
-				"ioprio_set",
-				"io_setup",
-				"io_submit",
-				"io_uring_enter",
-				"io_uring_register",
-				"io_uring_setup",
-				"ipc",
-				"kill",
-				"lchown",
-				"lchown32",
-				"lgetxattr",
-				"link",
-				"linkat",
-				"listen",
-				"listxattr",
-				"llistxattr",
-				"_llseek",
-				"lremovexattr",
-				"lseek",
-				"lsetxattr",
-				"lstat",
-				"lstat64",
-				"madvise",
-				"membarrier",
-				"memfd_create",
-				"mincore",
-				"mkdir",
-				"mkdirat",
-				"mknod",
-				"mknodat",
-				"mlock",
-				"mlock2",
-				"mlockall",
-				"mmap",
-				"mmap2",
-				"mprotect",
-				"mq_getsetattr",
-				"mq_notify",
-				"mq_open",
-				"mq_timedreceive",
-				"mq_timedreceive_time64",
-				"mq_timedsend",
-				"mq_timedsend_time64",
-				"mq_unlink",
-				"mremap",
-				"msgctl",
-				"msgget",
-				"msgrcv",
-				"msgsnd",
-				"msync",
-				"munlock",
-				"munlockall",
-				"munmap",
-				"nanosleep",
-				"newfstatat",
-				"_newselect",
-				"open",
-				"openat",
-				"openat2",
-				"pause",
-				"pipe",
-				"pipe2",
-				"poll",
-				"ppoll",
-				"ppoll_time64",
-				"prctl",
-				"pread64",
-				"preadv",
-				"preadv2",
-				"prlimit64",
-				"pselect6",
-				"pselect6_time64",
-				"pwrite64",
-				"pwritev",
-				"pwritev2",
-				"read",
-				"readahead",
-				"readlink",
-				"readlinkat",
-				"readv",
-				"recv",
-				"recvfrom",
-				"recvmmsg",
-				"recvmmsg_time64",
-				"recvmsg",
-				"remap_file_pages",
-				"removexattr",
-				"rename",
-				"renameat",
-				"renameat2",
-				"restart_syscall",
-				"rmdir",
-				"rseq",
-				"rt_sigaction",
-				"rt_sigpending",
-				"rt_sigprocmask",
-				"rt_sigqueueinfo",
-				"rt_sigreturn",
-				"rt_sigsuspend",
-				"rt_sigtimedwait",
-				"rt_sigtimedwait_time64",
-				"rt_tgsigqueueinfo",
-				"sched_getaffinity",
-				"sched_getattr",
-				"sched_getparam",
-				"sched_get_priority_max",
-				"sched_get_priority_min",
-				"sched_getscheduler",
-				"sched_rr_get_interval",
-				"sched_rr_get_interval_time64",
-				"sched_setaffinity",
-				"sched_setattr",
-				"sched_setparam",
-				"sched_setscheduler",
-				"sched_yield",
-				"seccomp",
-				"select",
-				"semctl",
-				"semget",
-				"semop",
-				"semtimedop",
-				"semtimedop_time64",
-				"send",
-				"sendfile",
-				"sendfile64",
-				"sendmmsg",
-				"sendmsg",
-				"sendto",
-				"setfsgid",
-				"setfsgid32",
-				"setfsuid",
-				"setfsuid32",
-				"setgid",
-				"setgid32",
-				"setgroups",
-				"setgroups32",
-				"setitimer",
-				"setpgid",
-				"setpriority",
-				"setregid",
-				"setregid32",
-				"setresgid",
-				"setresgid32",
-				"setresuid",
-				"setresuid32",
-				"setreuid",
-				"setreuid32",
-				"setrlimit",
-				"set_robust_list",
-				"setsid",
-				"setsockopt",
-				"set_thread_area",
-				"set_tid_address",
-				"setuid",
-				"setuid32",
-				"setxattr",
-				"shmat",
-				"shmctl",
-				"shmdt",
-				"shmget",
-				"shutdown",
-				"sigaltstack",
-				"signalfd",
-				"signalfd4",
-				"sigprocmask",
-				"sigreturn",
-				"socket",
-				"socketcall",
-				"socketpair",
-				"splice",
-				"stat",
-				"stat64",
-				"statfs",
-				"statfs64",
-				"statx",
-				"symlink",
-				"symlinkat",
-				"sync",
-				"sync_file_range",
-				"syncfs",
-				"sysinfo",
-				"tee",
-				"tgkill",
-				"time",
-				"timer_create",
-				"timer_delete",
-				"timer_getoverrun",
-				"timer_gettime",
-				"timer_gettime64",
-				"timer_settime",
-				"timer_settime64",
-				"timerfd_create",
-				"timerfd_gettime",
-				"timerfd_gettime64",
-				"timerfd_settime",
-				"timerfd_settime64",
-				"times",
-				"tkill",
-				"truncate",
-				"truncate64",
-				"ugetrlimit",
-				"umask",
-				"uname",
-				"unlink",
-				"unlinkat",
-				"utime",
-				"utimensat",
-				"utimensat_time64",
-				"utimes",
-				"vfork",
-				"vmsplice",
-				"wait4",
-				"waitid",
-				"waitpid",
-				"write",
-				"writev",
-			},
-			Action: specs.ActAllow,
-			Args:   []specs.LinuxSeccompArg{},
-		},
-		{
-			Names:  []string{"personality"},
-			Action: specs.ActAllow,
-			Args: []specs.LinuxSeccompArg{
-				{
-					Index: 0,
-					Value: 0x0,
-					Op:    specs.OpEqualTo,
-				},
-			},
-		},
-		{
-			Names:  []string{"personality"},
-			Action: specs.ActAllow,
-			Args: []specs.LinuxSeccompArg{
-				{
-					Index: 0,
-					Value: 0x0008,
-					Op:    specs.OpEqualTo,
-				},
-			},
-		},
-		{
-			Names:  []string{"personality"},
-			Action: specs.ActAllow,
-			Args: []specs.LinuxSeccompArg{
-				{
-					Index: 0,
-					Value: 0x20000,
-					Op:    specs.OpEqualTo,
-				},
-			},
-		},
-		{
-			Names:  []string{"personality"},
-			Action: specs.ActAllow,
-			Args: []specs.LinuxSeccompArg{
-				{
-					Index: 0,
-					Value: 0x20008,
-					Op:    specs.OpEqualTo,
-				},
-			},
-		},
-		{
-			Names:  []string{"personality"},
-			Action: specs.ActAllow,
-			Args: []specs.LinuxSeccompArg{
-				{
-					Index: 0,
-					Value: 0xffffffff,
-					Op:    specs.OpEqualTo,
-				},
-			},
-		},
-	}
-
-	s := &specs.LinuxSeccomp{
-		DefaultAction: specs.ActErrno,
-		Architectures: arches(),
-		Syscalls:      syscalls,
-	}
-
-	// include by arch
-	switch runtime.GOARCH {
-	case "ppc64le":
-		s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-			Names: []string{
-				"sync_file_range2",
-			},
-			Action: specs.ActAllow,
-			Args:   []specs.LinuxSeccompArg{},
-		})
-	case "arm", "arm64":
-		s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-			Names: []string{
-				"arm_fadvise64_64",
-				"arm_sync_file_range",
-				"sync_file_range2",
-				"breakpoint",
-				"cacheflush",
-				"set_tls",
-			},
-			Action: specs.ActAllow,
-			Args:   []specs.LinuxSeccompArg{},
-		})
-	case "amd64":
-		s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-			Names: []string{
-				"arch_prctl",
-				"modify_ldt",
-			},
-			Action: specs.ActAllow,
-			Args:   []specs.LinuxSeccompArg{},
-		})
-	case "386":
-		s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-			Names: []string{
-				"modify_ldt",
-			},
-			Action: specs.ActAllow,
-			Args:   []specs.LinuxSeccompArg{},
-		})
-	case "s390", "s390x":
-		s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-			Names: []string{
-				"s390_pci_mmio_read",
-				"s390_pci_mmio_write",
-				"s390_runtime_instr",
-			},
-			Action: specs.ActAllow,
-			Args:   []specs.LinuxSeccompArg{},
-		})
-	}
-
-	admin := false
-	for _, c := range sp.Process.Capabilities.Bounding {
-		switch c {
-		case "CAP_DAC_READ_SEARCH":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names:  []string{"open_by_handle_at"},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_ADMIN":
-			admin = true
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"bpf",
-					"clone",
-					"fanotify_init",
-					"lookup_dcookie",
-					"mount",
-					"name_to_handle_at",
-					"perf_event_open",
-					"quotactl",
-					"setdomainname",
-					"sethostname",
-					"setns",
-					"syslog",
-					"umount",
-					"umount2",
-					"unshare",
-				},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_BOOT":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names:  []string{"reboot"},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_CHROOT":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names:  []string{"chroot"},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_MODULE":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"delete_module",
-					"init_module",
-					"finit_module",
-				},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_PACCT":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names:  []string{"acct"},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_PTRACE":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"kcmp",
-					"process_vm_readv",
-					"process_vm_writev",
-					"ptrace",
-				},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_RAWIO":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"iopl",
-					"ioperm",
-				},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_TIME":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"settimeofday",
-					"stime",
-					"clock_settime",
-				},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYS_TTY_CONFIG":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names:  []string{"vhangup"},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		case "CAP_SYSLOG":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names:  []string{"syslog"},
-				Action: specs.ActAllow,
-				Args:   []specs.LinuxSeccompArg{},
-			})
-		}
-	}
-
-	if !admin {
-		switch runtime.GOARCH {
-		case "s390", "s390x":
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"clone",
-				},
-				Action: specs.ActAllow,
-				Args: []specs.LinuxSeccompArg{
-					{
-						Index:    1,
-						Value:    unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET | unix.CLONE_NEWCGROUP,
-						ValueTwo: 0,
-						Op:       specs.OpMaskedEqual,
-					},
-				},
-			})
-		default:
-			s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
-				Names: []string{
-					"clone",
-				},
-				Action: specs.ActAllow,
-				Args: []specs.LinuxSeccompArg{
-					{
-						Index:    0,
-						Value:    unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET | unix.CLONE_NEWCGROUP,
-						ValueTwo: 0,
-						Op:       specs.OpMaskedEqual,
-					},
-				},
-			})
-		}
-	}
-
-	return s
-}
diff --git a/vendor/github.com/containerd/containerd/mount/mount_linux.go b/vendor/github.com/containerd/containerd/mount/mount_linux.go
index d12a9c5..6d28f0a 100644
--- a/vendor/github.com/containerd/containerd/mount/mount_linux.go
+++ b/vendor/github.com/containerd/containerd/mount/mount_linux.go
@@ -106,26 +106,37 @@
 	return nil
 }
 
-func isFUSE(dir string) (bool, error) {
-	// fuseSuperMagic is defined in statfs(2)
-	const fuseSuperMagic = 0x65735546
+// fuseSuperMagic is defined in statfs(2)
+const fuseSuperMagic = 0x65735546
+
+func isFUSE(dir string) bool {
 	var st unix.Statfs_t
 	if err := unix.Statfs(dir, &st); err != nil {
-		return false, err
+		return false
 	}
-	return st.Type == fuseSuperMagic, nil
+	return st.Type == fuseSuperMagic
+}
+
+// unmountFUSE attempts to unmount using fusermount/fusermount3 helper binary.
+//
+// For FUSE mounts, using these helper binaries is preferred, see:
+// https://github.com/containerd/containerd/pull/3765#discussion_r342083514
+func unmountFUSE(target string) error {
+	var err error
+	for _, helperBinary := range []string{"fusermount3", "fusermount"} {
+		cmd := exec.Command(helperBinary, "-u", target)
+		err = cmd.Run()
+		if err == nil {
+			return nil
+		}
+	}
+	return err
 }
 
 func unmount(target string, flags int) error {
-	// For FUSE mounts, attempting to execute fusermount helper binary is preferred
-	// https://github.com/containerd/containerd/pull/3765#discussion_r342083514
-	if ok, err := isFUSE(target); err == nil && ok {
-		for _, helperBinary := range []string{"fusermount3", "fusermount"} {
-			cmd := exec.Command(helperBinary, "-u", target)
-			if err := cmd.Run(); err == nil {
-				return nil
-			}
-			// ignore error and try unix.Unmount
+	if isFUSE(target) {
+		if err := unmountFUSE(target); err == nil {
+			return nil
 		}
 	}
 	for i := 0; i < 50; i++ {
diff --git a/vendor/github.com/containerd/containerd/pkg/process/exec.go b/vendor/github.com/containerd/containerd/pkg/process/exec.go
index e77e79a..7790a49 100644
--- a/vendor/github.com/containerd/containerd/pkg/process/exec.go
+++ b/vendor/github.com/containerd/containerd/pkg/process/exec.go
@@ -221,7 +221,7 @@
 		if err != nil {
 			return errors.Wrap(err, "failed to retrieve console master")
 		}
-		if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg); err != nil {
+		if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.id, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg); err != nil {
 			return errors.Wrap(err, "failed to start console copy")
 		}
 	} else {
diff --git a/vendor/github.com/containerd/containerd/pkg/process/init.go b/vendor/github.com/containerd/containerd/pkg/process/init.go
index 5cb2246..28ca5ac 100644
--- a/vendor/github.com/containerd/containerd/pkg/process/init.go
+++ b/vendor/github.com/containerd/containerd/pkg/process/init.go
@@ -157,7 +157,7 @@
 		if err != nil {
 			return errors.Wrap(err, "failed to retrieve console master")
 		}
-		console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg)
+		console, err = p.Platform.CopyConsole(ctx, console, p.id, r.Stdin, r.Stdout, r.Stderr, &p.wg)
 		if err != nil {
 			return errors.Wrap(err, "failed to start console copy")
 		}
diff --git a/vendor/github.com/containerd/containerd/pkg/process/init_state.go b/vendor/github.com/containerd/containerd/pkg/process/init_state.go
index 81c6488..5273a5d 100644
--- a/vendor/github.com/containerd/containerd/pkg/process/init_state.go
+++ b/vendor/github.com/containerd/containerd/pkg/process/init_state.go
@@ -172,7 +172,7 @@
 		if err != nil {
 			return errors.Wrap(err, "failed to retrieve console master")
 		}
-		console, err = p.Platform.CopyConsole(ctx, console, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg)
+		console, err = p.Platform.CopyConsole(ctx, console, p.id, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg)
 		if err != nil {
 			return errors.Wrap(err, "failed to start console copy")
 		}
diff --git a/vendor/github.com/containerd/containerd/pkg/stdio/platform.go b/vendor/github.com/containerd/containerd/pkg/stdio/platform.go
index 6e1b27c..ca8688f 100644
--- a/vendor/github.com/containerd/containerd/pkg/stdio/platform.go
+++ b/vendor/github.com/containerd/containerd/pkg/stdio/platform.go
@@ -26,7 +26,7 @@
 // Platform handles platform-specific behavior that may differs across
 // platform implementations
 type Platform interface {
-	CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string,
+	CopyConsole(ctx context.Context, console console.Console, id, stdin, stdout, stderr string,
 		wg *sync.WaitGroup) (console.Console, error)
 	ShutdownConsole(ctx context.Context, console console.Console) error
 	Close() error
diff --git a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go
index db65a72..0512bc9 100644
--- a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go
+++ b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go
@@ -96,6 +96,15 @@
 		return ""
 	}
 
+	// handle edge case for Raspberry Pi ARMv6 devices (which due to a kernel quirk, report "CPU architecture: 7")
+	// https://www.raspberrypi.org/forums/viewtopic.php?t=12614
+	if runtime.GOARCH == "arm" && variant == "7" {
+		model, err := getCPUInfo("model name")
+		if err == nil && strings.HasPrefix(strings.ToLower(model), "armv6-compatible") {
+			variant = "6"
+		}
+	}
+
 	switch strings.ToLower(variant) {
 	case "8", "aarch64":
 		// special case: if running a 32-bit userspace on aarch64, the variant should be "v7"
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go b/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go
new file mode 100644
index 0000000..f65c6be
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go
@@ -0,0 +1,202 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package auth
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"net/url"
+	"strings"
+	"time"
+
+	"github.com/containerd/containerd/log"
+	remoteserrors "github.com/containerd/containerd/remotes/errors"
+	"github.com/pkg/errors"
+	"golang.org/x/net/context/ctxhttp"
+)
+
+var (
+	// ErrNoToken is returned if a request is successful but the body does not
+	// contain an authorization token.
+	ErrNoToken = errors.New("authorization server did not include a token in the response")
+)
+
+// GenerateTokenOptions generates options for fetching a token based on a challenge
+func GenerateTokenOptions(ctx context.Context, host, username, secret string, c Challenge) (TokenOptions, error) {
+	realm, ok := c.Parameters["realm"]
+	if !ok {
+		return TokenOptions{}, errors.New("no realm specified for token auth challenge")
+	}
+
+	realmURL, err := url.Parse(realm)
+	if err != nil {
+		return TokenOptions{}, errors.Wrap(err, "invalid token auth challenge realm")
+	}
+
+	to := TokenOptions{
+		Realm:    realmURL.String(),
+		Service:  c.Parameters["service"],
+		Username: username,
+		Secret:   secret,
+	}
+
+	scope, ok := c.Parameters["scope"]
+	if ok {
+		to.Scopes = append(to.Scopes, scope)
+	} else {
+		log.G(ctx).WithField("host", host).Debug("no scope specified for token auth challenge")
+	}
+
+	return to, nil
+}
+
+// TokenOptions are optios for requesting a token
+type TokenOptions struct {
+	Realm    string
+	Service  string
+	Scopes   []string
+	Username string
+	Secret   string
+}
+
+// OAuthTokenResponse is response from fetching token with a OAuth POST request
+type OAuthTokenResponse struct {
+	AccessToken  string    `json:"access_token"`
+	RefreshToken string    `json:"refresh_token"`
+	ExpiresIn    int       `json:"expires_in"`
+	IssuedAt     time.Time `json:"issued_at"`
+	Scope        string    `json:"scope"`
+}
+
+// FetchTokenWithOAuth fetches a token using a POST request
+func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.Header, clientID string, to TokenOptions) (*OAuthTokenResponse, error) {
+	form := url.Values{}
+	if len(to.Scopes) > 0 {
+		form.Set("scope", strings.Join(to.Scopes, " "))
+	}
+	form.Set("service", to.Service)
+	form.Set("client_id", clientID)
+
+	if to.Username == "" {
+		form.Set("grant_type", "refresh_token")
+		form.Set("refresh_token", to.Secret)
+	} else {
+		form.Set("grant_type", "password")
+		form.Set("username", to.Username)
+		form.Set("password", to.Secret)
+	}
+
+	req, err := http.NewRequest("POST", to.Realm, strings.NewReader(form.Encode()))
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
+	for k, v := range headers {
+		req.Header[k] = append(req.Header[k], v...)
+	}
+
+	resp, err := ctxhttp.Do(ctx, client, req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
+		return nil, errors.WithStack(remoteserrors.NewUnexpectedStatusErr(resp))
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+
+	var tr OAuthTokenResponse
+	if err = decoder.Decode(&tr); err != nil {
+		return nil, errors.Wrap(err, "unable to decode token response")
+	}
+
+	if tr.AccessToken == "" {
+		return nil, errors.WithStack(ErrNoToken)
+	}
+
+	return &tr, nil
+}
+
+// FetchTokenResponse is response from fetching token with GET request
+type FetchTokenResponse struct {
+	Token        string    `json:"token"`
+	AccessToken  string    `json:"access_token"`
+	ExpiresIn    int       `json:"expires_in"`
+	IssuedAt     time.Time `json:"issued_at"`
+	RefreshToken string    `json:"refresh_token"`
+}
+
+// FetchToken fetches a token using a GET request
+func FetchToken(ctx context.Context, client *http.Client, headers http.Header, to TokenOptions) (*FetchTokenResponse, error) {
+	req, err := http.NewRequest("GET", to.Realm, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	for k, v := range headers {
+		req.Header[k] = append(req.Header[k], v...)
+	}
+
+	reqParams := req.URL.Query()
+
+	if to.Service != "" {
+		reqParams.Add("service", to.Service)
+	}
+
+	for _, scope := range to.Scopes {
+		reqParams.Add("scope", scope)
+	}
+
+	if to.Secret != "" {
+		req.SetBasicAuth(to.Username, to.Secret)
+	}
+
+	req.URL.RawQuery = reqParams.Encode()
+
+	resp, err := ctxhttp.Do(ctx, client, req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
+		return nil, errors.WithStack(remoteserrors.NewUnexpectedStatusErr(resp))
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+
+	var tr FetchTokenResponse
+	if err = decoder.Decode(&tr); err != nil {
+		return nil, errors.Wrap(err, "unable to decode token response")
+	}
+
+	// `access_token` is equivalent to `token` and if both are specified
+	// the choice is undefined.  Canonicalize `access_token` by sticking
+	// things in `token`.
+	if tr.AccessToken != "" {
+		tr.Token = tr.AccessToken
+	}
+
+	if tr.Token == "" {
+		return nil, errors.WithStack(ErrNoToken)
+	}
+
+	return &tr, nil
+}
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth.go b/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go
similarity index 80%
rename from vendor/github.com/containerd/containerd/remotes/docker/auth.go
rename to vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go
index 70cfdea..223fa2d 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/auth.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go
@@ -14,7 +14,7 @@
    limitations under the License.
 */
 
-package docker
+package auth
 
 import (
 	"net/http"
@@ -22,31 +22,35 @@
 	"strings"
 )
 
-type authenticationScheme byte
+// AuthenticationScheme defines scheme of the authentication method
+type AuthenticationScheme byte
 
 const (
-	basicAuth  authenticationScheme = 1 << iota // Defined in RFC 7617
-	digestAuth                                  // Defined in RFC 7616
-	bearerAuth                                  // Defined in RFC 6750
+	// BasicAuth is scheme for Basic HTTP Authentication RFC 7617
+	BasicAuth AuthenticationScheme = 1 << iota
+	// DigestAuth is scheme for HTTP Digest Access Authentication RFC 7616
+	DigestAuth
+	// BearerAuth is scheme for OAuth 2.0 Bearer Tokens RFC 6750
+	BearerAuth
 )
 
-// challenge carries information from a WWW-Authenticate response header.
+// Challenge carries information from a WWW-Authenticate response header.
 // See RFC 2617.
-type challenge struct {
+type Challenge struct {
 	// scheme is the auth-scheme according to RFC 2617
-	scheme authenticationScheme
+	Scheme AuthenticationScheme
 
 	// parameters are the auth-params according to RFC 2617
-	parameters map[string]string
+	Parameters map[string]string
 }
 
-type byScheme []challenge
+type byScheme []Challenge
 
 func (bs byScheme) Len() int      { return len(bs) }
 func (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
 
 // Sort in priority order: token > digest > basic
-func (bs byScheme) Less(i, j int) bool { return bs[i].scheme > bs[j].scheme }
+func (bs byScheme) Less(i, j int) bool { return bs[i].Scheme > bs[j].Scheme }
 
 // Octet types from RFC 2616.
 type octetType byte
@@ -90,22 +94,23 @@
 	}
 }
 
-func parseAuthHeader(header http.Header) []challenge {
-	challenges := []challenge{}
+// ParseAuthHeader parses challenges from WWW-Authenticate header
+func ParseAuthHeader(header http.Header) []Challenge {
+	challenges := []Challenge{}
 	for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
 		v, p := parseValueAndParams(h)
-		var s authenticationScheme
+		var s AuthenticationScheme
 		switch v {
 		case "basic":
-			s = basicAuth
+			s = BasicAuth
 		case "digest":
-			s = digestAuth
+			s = DigestAuth
 		case "bearer":
-			s = bearerAuth
+			s = BearerAuth
 		default:
 			continue
 		}
-		challenges = append(challenges, challenge{scheme: s, parameters: p})
+		challenges = append(challenges, Challenge{Scheme: s, Parameters: p})
 	}
 	sort.Stable(byScheme(challenges))
 	return challenges
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
index 001423a..67e4aea 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
@@ -19,21 +19,17 @@
 import (
 	"context"
 	"encoding/base64"
-	"encoding/json"
 	"fmt"
-	"io"
-	"io/ioutil"
 	"net/http"
-	"net/url"
 	"strings"
 	"sync"
-	"time"
 
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/log"
+	"github.com/containerd/containerd/remotes/docker/auth"
+	remoteerrors "github.com/containerd/containerd/remotes/errors"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	"golang.org/x/net/context/ctxhttp"
 )
 
 type dockerAuthorizer struct {
@@ -135,8 +131,8 @@
 
 	a.mu.Lock()
 	defer a.mu.Unlock()
-	for _, c := range parseAuthHeader(last.Header) {
-		if c.scheme == bearerAuth {
+	for _, c := range auth.ParseAuthHeader(last.Header) {
+		if c.Scheme == auth.BearerAuth {
 			if err := invalidAuthorization(c, responses); err != nil {
 				delete(a.handlers, host)
 				return err
@@ -152,26 +148,35 @@
 				return nil
 			}
 
-			common, err := a.generateTokenOptions(ctx, host, c)
+			var username, secret string
+			if a.credentials != nil {
+				var err error
+				username, secret, err = a.credentials(host)
+				if err != nil {
+					return err
+				}
+			}
+
+			common, err := auth.GenerateTokenOptions(ctx, host, username, secret, c)
 			if err != nil {
 				return err
 			}
 
-			a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
+			a.handlers[host] = newAuthHandler(a.client, a.header, c.Scheme, common)
 			return nil
-		} else if c.scheme == basicAuth && a.credentials != nil {
+		} else if c.Scheme == auth.BasicAuth && a.credentials != nil {
 			username, secret, err := a.credentials(host)
 			if err != nil {
 				return err
 			}
 
 			if username != "" && secret != "" {
-				common := tokenOptions{
-					username: username,
-					secret:   secret,
+				common := auth.TokenOptions{
+					Username: username,
+					Secret:   secret,
 				}
 
-				a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
+				a.handlers[host] = newAuthHandler(a.client, a.header, c.Scheme, common)
 				return nil
 			}
 		}
@@ -179,38 +184,6 @@
 	return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
 }
 
-func (a *dockerAuthorizer) generateTokenOptions(ctx context.Context, host string, c challenge) (tokenOptions, error) {
-	realm, ok := c.parameters["realm"]
-	if !ok {
-		return tokenOptions{}, errors.New("no realm specified for token auth challenge")
-	}
-
-	realmURL, err := url.Parse(realm)
-	if err != nil {
-		return tokenOptions{}, errors.Wrap(err, "invalid token auth challenge realm")
-	}
-
-	to := tokenOptions{
-		realm:   realmURL.String(),
-		service: c.parameters["service"],
-	}
-
-	scope, ok := c.parameters["scope"]
-	if ok {
-		to.scopes = append(to.scopes, scope)
-	} else {
-		log.G(ctx).WithField("host", host).Debug("no scope specified for token auth challenge")
-	}
-
-	if a.credentials != nil {
-		to.username, to.secret, err = a.credentials(host)
-		if err != nil {
-			return tokenOptions{}, err
-		}
-	}
-	return to, nil
-}
-
 // authResult is used to control limit rate.
 type authResult struct {
 	sync.WaitGroup
@@ -227,17 +200,17 @@
 	client *http.Client
 
 	// only support basic and bearer schemes
-	scheme authenticationScheme
+	scheme auth.AuthenticationScheme
 
 	// common contains common challenge answer
-	common tokenOptions
+	common auth.TokenOptions
 
 	// scopedTokens caches token indexed by scopes, which used in
 	// bearer auth case
 	scopedTokens map[string]*authResult
 }
 
-func newAuthHandler(client *http.Client, hdr http.Header, scheme authenticationScheme, opts tokenOptions) *authHandler {
+func newAuthHandler(client *http.Client, hdr http.Header, scheme auth.AuthenticationScheme, opts auth.TokenOptions) *authHandler {
 	return &authHandler{
 		header:       hdr,
 		client:       client,
@@ -249,17 +222,17 @@
 
 func (ah *authHandler) authorize(ctx context.Context) (string, error) {
 	switch ah.scheme {
-	case basicAuth:
+	case auth.BasicAuth:
 		return ah.doBasicAuth(ctx)
-	case bearerAuth:
+	case auth.BearerAuth:
 		return ah.doBearerAuth(ctx)
 	default:
-		return "", errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
+		return "", errors.Wrapf(errdefs.ErrNotImplemented, "failed to find supported auth scheme: %s", string(ah.scheme))
 	}
 }
 
 func (ah *authHandler) doBasicAuth(ctx context.Context) (string, error) {
-	username, secret := ah.common.username, ah.common.secret
+	username, secret := ah.common.Username, ah.common.Secret
 
 	if username == "" || secret == "" {
 		return "", fmt.Errorf("failed to handle basic auth because missing username or secret")
@@ -269,14 +242,14 @@
 	return fmt.Sprintf("Basic %s", auth), nil
 }
 
-func (ah *authHandler) doBearerAuth(ctx context.Context) (string, error) {
+func (ah *authHandler) doBearerAuth(ctx context.Context) (token string, err error) {
 	// copy common tokenOptions
 	to := ah.common
 
-	to.scopes = GetTokenScopes(ctx, to.scopes)
+	to.Scopes = GetTokenScopes(ctx, to.Scopes)
 
 	// Docs: https://docs.docker.com/registry/spec/auth/scope
-	scoped := strings.Join(to.scopes, " ")
+	scoped := strings.Join(to.Scopes, " ")
 
 	ah.Lock()
 	if r, exist := ah.scopedTokens[scoped]; exist {
@@ -291,174 +264,52 @@
 	ah.scopedTokens[scoped] = r
 	ah.Unlock()
 
+	defer func() {
+		token = fmt.Sprintf("Bearer %s", token)
+		r.token, r.err = token, err
+		r.Done()
+	}()
+
 	// fetch token for the resource scope
-	var (
-		token string
-		err   error
-	)
-	if to.secret != "" {
+	if to.Secret != "" {
+		defer func() {
+			err = errors.Wrap(err, "failed to fetch oauth token")
+		}()
 		// credential information is provided, use oauth POST endpoint
-		token, err = ah.fetchTokenWithOAuth(ctx, to)
-		err = errors.Wrap(err, "failed to fetch oauth token")
-	} else {
-		// do request anonymously
-		token, err = ah.fetchToken(ctx, to)
-		err = errors.Wrap(err, "failed to fetch anonymous token")
-	}
-	token = fmt.Sprintf("Bearer %s", token)
-
-	r.token, r.err = token, err
-	r.Done()
-	return r.token, r.err
-}
-
-type tokenOptions struct {
-	realm    string
-	service  string
-	scopes   []string
-	username string
-	secret   string
-}
-
-type postTokenResponse struct {
-	AccessToken  string    `json:"access_token"`
-	RefreshToken string    `json:"refresh_token"`
-	ExpiresIn    int       `json:"expires_in"`
-	IssuedAt     time.Time `json:"issued_at"`
-	Scope        string    `json:"scope"`
-}
-
-func (ah *authHandler) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
-	form := url.Values{}
-	if len(to.scopes) > 0 {
-		form.Set("scope", strings.Join(to.scopes, " "))
-	}
-	form.Set("service", to.service)
-	// TODO: Allow setting client_id
-	form.Set("client_id", "containerd-client")
-
-	if to.username == "" {
-		form.Set("grant_type", "refresh_token")
-		form.Set("refresh_token", to.secret)
-	} else {
-		form.Set("grant_type", "password")
-		form.Set("username", to.username)
-		form.Set("password", to.secret)
-	}
-
-	req, err := http.NewRequest("POST", to.realm, strings.NewReader(form.Encode()))
-	if err != nil {
-		return "", err
-	}
-	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
-	if ah.header != nil {
-		for k, v := range ah.header {
-			req.Header[k] = append(req.Header[k], v...)
+		// TODO: Allow setting client_id
+		resp, err := auth.FetchTokenWithOAuth(ctx, ah.client, ah.header, "containerd-client", to)
+		if err != nil {
+			var errStatus remoteerrors.ErrUnexpectedStatus
+			if errors.As(err, &errStatus) {
+				// Registries without support for POST may return 404 for POST /v2/token.
+				// As of September 2017, GCR is known to return 404.
+				// As of February 2018, JFrog Artifactory is known to return 401.
+				if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
+					resp, err := auth.FetchToken(ctx, ah.client, ah.header, to)
+					if err != nil {
+						return "", err
+					}
+					return resp.Token, nil
+				}
+				log.G(ctx).WithFields(logrus.Fields{
+					"status": errStatus.Status,
+					"body":   string(errStatus.Body),
+				}).Debugf("token request failed")
+			}
+			return "", err
 		}
+		return resp.AccessToken, nil
 	}
-
-	resp, err := ctxhttp.Do(ctx, ah.client, req)
+	// do request anonymously
+	resp, err := auth.FetchToken(ctx, ah.client, ah.header, to)
 	if err != nil {
-		return "", err
+		return "", errors.Wrap(err, "failed to fetch anonymous token")
 	}
-	defer resp.Body.Close()
-
-	// Registries without support for POST may return 404 for POST /v2/token.
-	// As of September 2017, GCR is known to return 404.
-	// As of February 2018, JFrog Artifactory is known to return 401.
-	if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
-		return ah.fetchToken(ctx, to)
-	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
-		log.G(ctx).WithFields(logrus.Fields{
-			"status": resp.Status,
-			"body":   string(b),
-		}).Debugf("token request failed")
-		// TODO: handle error body and write debug output
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
-	}
-
-	decoder := json.NewDecoder(resp.Body)
-
-	var tr postTokenResponse
-	if err = decoder.Decode(&tr); err != nil {
-		return "", fmt.Errorf("unable to decode token response: %s", err)
-	}
-
-	return tr.AccessToken, nil
+	return resp.Token, nil
 }
 
-type getTokenResponse struct {
-	Token        string    `json:"token"`
-	AccessToken  string    `json:"access_token"`
-	ExpiresIn    int       `json:"expires_in"`
-	IssuedAt     time.Time `json:"issued_at"`
-	RefreshToken string    `json:"refresh_token"`
-}
-
-// fetchToken fetches a token using a GET request
-func (ah *authHandler) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
-	req, err := http.NewRequest("GET", to.realm, nil)
-	if err != nil {
-		return "", err
-	}
-
-	if ah.header != nil {
-		for k, v := range ah.header {
-			req.Header[k] = append(req.Header[k], v...)
-		}
-	}
-
-	reqParams := req.URL.Query()
-
-	if to.service != "" {
-		reqParams.Add("service", to.service)
-	}
-
-	for _, scope := range to.scopes {
-		reqParams.Add("scope", scope)
-	}
-
-	if to.secret != "" {
-		req.SetBasicAuth(to.username, to.secret)
-	}
-
-	req.URL.RawQuery = reqParams.Encode()
-
-	resp, err := ctxhttp.Do(ctx, ah.client, req)
-	if err != nil {
-		return "", err
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		// TODO: handle error body and write debug output
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
-	}
-
-	decoder := json.NewDecoder(resp.Body)
-
-	var tr getTokenResponse
-	if err = decoder.Decode(&tr); err != nil {
-		return "", fmt.Errorf("unable to decode token response: %s", err)
-	}
-
-	// `access_token` is equivalent to `token` and if both are specified
-	// the choice is undefined.  Canonicalize `access_token` by sticking
-	// things in `token`.
-	if tr.AccessToken != "" {
-		tr.Token = tr.AccessToken
-	}
-
-	if tr.Token == "" {
-		return "", ErrNoToken
-	}
-
-	return tr.Token, nil
-}
-
-func invalidAuthorization(c challenge, responses []*http.Response) error {
-	errStr := c.parameters["error"]
+func invalidAuthorization(c auth.Challenge, responses []*http.Response) error {
+	errStr := c.Parameters["error"]
 	if errStr == "" {
 		return nil
 	}
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go b/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
index cd0168b..9d6708d 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
@@ -45,7 +45,7 @@
 		return nil, errors.Wrap(errdefs.ErrNotFound, "no pull hosts")
 	}
 
-	ctx, err := contextWithRepositoryScope(ctx, r.refspec, false)
+	ctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go b/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go
index 9175b6a..704eba4 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go
@@ -121,7 +121,7 @@
 
 		rc, err := hrs.open(hrs.offset)
 		if err != nil {
-			return nil, errors.Wrapf(err, "httpReaderSeeker: failed open")
+			return nil, errors.Wrapf(err, "httpReadSeeker: failed open")
 		}
 
 		if hrs.rc != nil {
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/pusher.go b/vendor/github.com/containerd/containerd/remotes/docker/pusher.go
index 98ea515..0a69c8c 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/pusher.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/pusher.go
@@ -30,6 +30,7 @@
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/remotes"
+	remoteserrors "github.com/containerd/containerd/remotes/errors"
 	digest "github.com/opencontainers/go-digest"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
@@ -44,7 +45,7 @@
 }
 
 func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {
-	ctx, err := contextWithRepositoryScope(ctx, p.refspec, true)
+	ctx, err := ContextWithRepositoryScope(ctx, p.refspec, true)
 	if err != nil {
 		return nil, err
 	}
@@ -112,8 +113,9 @@
 				return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
 			}
 		} else if resp.StatusCode != http.StatusNotFound {
-			// TODO: log error
-			return nil, errors.Errorf("unexpected response: %s", resp.Status)
+			err := remoteserrors.NewUnexpectedStatusErr(resp)
+			log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response")
+			return nil, err
 		}
 	}
 
@@ -128,7 +130,7 @@
 		var resp *http.Response
 		if fromRepo := selectRepositoryMountCandidate(p.refspec, desc.Annotations); fromRepo != "" {
 			preq := requestWithMountFrom(req, desc.Digest.String(), fromRepo)
-			pctx := contextWithAppendPullRepositoryScope(ctx, fromRepo)
+			pctx := ContextWithAppendPullRepositoryScope(ctx, fromRepo)
 
 			// NOTE: the fromRepo might be private repo and
 			// auth service still can grant token without error.
@@ -166,8 +168,9 @@
 			})
 			return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
 		default:
-			// TODO: log error
-			return nil, errors.Errorf("unexpected response: %s", resp.Status)
+			err := remoteserrors.NewUnexpectedStatusErr(resp)
+			log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response")
+			return nil, err
 		}
 
 		var (
@@ -219,7 +222,7 @@
 	// TODO: Support chunked upload
 
 	pr, pw := io.Pipe()
-	respC := make(chan *http.Response, 1)
+	respC := make(chan response, 1)
 	body := ioutil.NopCloser(pr)
 
 	req.body = func() (io.ReadCloser, error) {
@@ -237,6 +240,7 @@
 		defer close(respC)
 		resp, err := req.do(ctx)
 		if err != nil {
+			respC <- response{err: err}
 			pr.CloseWithError(err)
 			return
 		}
@@ -244,10 +248,11 @@
 		switch resp.StatusCode {
 		case http.StatusOK, http.StatusCreated, http.StatusNoContent:
 		default:
-			// TODO: log error
-			pr.CloseWithError(errors.Errorf("unexpected response: %s", resp.Status))
+			err := remoteserrors.NewUnexpectedStatusErr(resp)
+			log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response")
+			pr.CloseWithError(err)
 		}
-		respC <- resp
+		respC <- response{Response: resp}
 	}()
 
 	return &pushWriter{
@@ -280,12 +285,17 @@
 	return []string{"manifests", object}
 }
 
+type response struct {
+	*http.Response
+	err error
+}
+
 type pushWriter struct {
 	base *dockerBase
 	ref  string
 
 	pipe       *io.PipeWriter
-	responseC  <-chan *http.Response
+	responseC  <-chan response
 	isManifest bool
 
 	expected digest.Digest
@@ -335,8 +345,8 @@
 
 	// TODO: timeout waiting for response
 	resp := <-pw.responseC
-	if resp == nil {
-		return errors.New("no response")
+	if resp.err != nil {
+		return resp.err
 	}
 
 	// 201 is specified return status, some registries return
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go
index 53e42ec..5258d71 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go
@@ -41,10 +41,6 @@
 )
 
 var (
-	// ErrNoToken is returned if a request is successful but the body does not
-	// contain an authorization token.
-	ErrNoToken = errors.New("authorization server did not include a token in the response")
-
 	// ErrInvalidAuthorization is used when credentials are passed to a server but
 	// those credentials are rejected.
 	ErrInvalidAuthorization = errors.New("authorization failed")
@@ -267,7 +263,7 @@
 		return "", ocispec.Descriptor{}, errors.Wrap(errdefs.ErrNotFound, "no resolve hosts")
 	}
 
-	ctx, err = contextWithRepositoryScope(ctx, refspec, false)
+	ctx, err = ContextWithRepositoryScope(ctx, refspec, false)
 	if err != nil {
 		return "", ocispec.Descriptor{}, err
 	}
diff --git a/vendor/github.com/containerd/containerd/remotes/docker/scope.go b/vendor/github.com/containerd/containerd/remotes/docker/scope.go
index c8541c4..fe57f02 100644
--- a/vendor/github.com/containerd/containerd/remotes/docker/scope.go
+++ b/vendor/github.com/containerd/containerd/remotes/docker/scope.go
@@ -26,10 +26,10 @@
 	"github.com/containerd/containerd/reference"
 )
 
-// repositoryScope returns a repository scope string such as "repository:foo/bar:pull"
+// RepositoryScope returns a repository scope string such as "repository:foo/bar:pull"
 // for "host/foo/bar:baz".
 // When push is true, both pull and push are added to the scope.
-func repositoryScope(refspec reference.Spec, push bool) (string, error) {
+func RepositoryScope(refspec reference.Spec, push bool) (string, error) {
 	u, err := url.Parse("dummy://" + refspec.Locator)
 	if err != nil {
 		return "", err
@@ -45,9 +45,9 @@
 // value: []string (e.g. {"registry:foo/bar:pull"})
 type tokenScopesKey struct{}
 
-// contextWithRepositoryScope returns a context with tokenScopesKey{} and the repository scope value.
-func contextWithRepositoryScope(ctx context.Context, refspec reference.Spec, push bool) (context.Context, error) {
-	s, err := repositoryScope(refspec, push)
+// ContextWithRepositoryScope returns a context with tokenScopesKey{} and the repository scope value.
+func ContextWithRepositoryScope(ctx context.Context, refspec reference.Spec, push bool) (context.Context, error) {
+	s, err := RepositoryScope(refspec, push)
 	if err != nil {
 		return nil, err
 	}
@@ -66,9 +66,9 @@
 	return context.WithValue(ctx, tokenScopesKey{}, scopes)
 }
 
-// contextWithAppendPullRepositoryScope is used to append repository pull
+// ContextWithAppendPullRepositoryScope is used to append repository pull
 // scope into existing scopes indexed by the tokenScopesKey{}.
-func contextWithAppendPullRepositoryScope(ctx context.Context, repo string) context.Context {
+func ContextWithAppendPullRepositoryScope(ctx context.Context, repo string) context.Context {
 	return WithScope(ctx, fmt.Sprintf("repository:%s:pull", repo))
 }
 
diff --git a/vendor/github.com/containerd/containerd/remotes/errors/errors.go b/vendor/github.com/containerd/containerd/remotes/errors/errors.go
new file mode 100644
index 0000000..e58e4af
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/remotes/errors/errors.go
@@ -0,0 +1,46 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package errors
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+)
+
+var _ error = ErrUnexpectedStatus{}
+
+// ErrUnexpectedStatus is returned if a registry API request returned with unexpected HTTP status
+type ErrUnexpectedStatus struct {
+	Status     string
+	StatusCode int
+	Body       []byte
+}
+
+func (e ErrUnexpectedStatus) Error() string {
+	return fmt.Sprintf("unexpected status: %s", e.Status)
+}
+
+// NewUnexpectedStatusErr creates an ErrUnexpectedStatus from HTTP response
+func NewUnexpectedStatusErr(resp *http.Response) error {
+	var b []byte
+	if resp.Body != nil {
+		b, _ = ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
+	}
+	return ErrUnexpectedStatus{Status: resp.Status, StatusCode: resp.StatusCode, Body: b}
+}
diff --git a/vendor/github.com/containerd/containerd/runtime/io.go b/vendor/github.com/containerd/containerd/runtime/io.go
new file mode 100644
index 0000000..87414c8
--- /dev/null
+++ b/vendor/github.com/containerd/containerd/runtime/io.go
@@ -0,0 +1,53 @@
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package runtime
+
+import (
+	"net/url"
+	"os"
+	"os/exec"
+)
+
+// NewBinaryCmd returns a Cmd to be used to start a logging binary.
+// The Cmd is generated from the provided uri, and the container ID and
+// namespace are appended to the Cmd environment.
+func NewBinaryCmd(binaryURI *url.URL, id, ns string) *exec.Cmd {
+	var args []string
+	for k, vs := range binaryURI.Query() {
+		args = append(args, k)
+		if len(vs) > 0 {
+			args = append(args, vs[0])
+		}
+	}
+
+	cmd := exec.Command(binaryURI.Path, args...)
+
+	cmd.Env = append(cmd.Env,
+		"CONTAINER_ID="+id,
+		"CONTAINER_NAMESPACE="+ns,
+	)
+
+	return cmd
+}
+
+// CloseFiles closes any files passed in.
+// It it used for cleanup in the event of unexpected errors.
+func CloseFiles(files ...*os.File) {
+	for _, file := range files {
+		file.Close()
+	}
+}
diff --git a/vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
index 65a8666..98ee4cf 100644
--- a/vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
+++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
@@ -19,10 +19,14 @@
 import (
 	"context"
 	"io"
+	"net/url"
+	"os"
 	"sync"
 	"syscall"
 
 	"github.com/containerd/console"
+	"github.com/containerd/containerd/namespaces"
+	"github.com/containerd/containerd/runtime"
 	"github.com/containerd/fifo"
 	"github.com/pkg/errors"
 )
@@ -31,7 +35,7 @@
 	epoller *console.Epoller
 }
 
-func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg *sync.WaitGroup) (console.Console, error) {
+func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, id, stdin, stdout, stderr string, wg *sync.WaitGroup) (cons console.Console, retErr error) {
 	if p.epoller == nil {
 		return nil, errors.New("uninitialized epoller")
 	}
@@ -59,26 +63,98 @@
 		}()
 	}
 
-	outw, err := fifo.OpenFifo(ctx, stdout, syscall.O_WRONLY, 0)
+	uri, err := url.Parse(stdout)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrap(err, "unable to parse stdout uri")
 	}
-	outr, err := fifo.OpenFifo(ctx, stdout, syscall.O_RDONLY, 0)
-	if err != nil {
-		return nil, err
+
+	switch uri.Scheme {
+	case "binary":
+		ns, err := namespaces.NamespaceRequired(ctx)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd := runtime.NewBinaryCmd(uri, id, ns)
+
+		// In case of unexpected errors during logging binary start, close open pipes
+		var filesToClose []*os.File
+
+		defer func() {
+			if retErr != nil {
+				runtime.CloseFiles(filesToClose...)
+			}
+		}()
+
+		// Create pipe to be used by logging binary for Stdout
+		outR, outW, err := os.Pipe()
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to create stdout pipes")
+		}
+		filesToClose = append(filesToClose, outR)
+
+		// Stderr is created for logging binary but unused when terminal is true
+		serrR, _, err := os.Pipe()
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to create stderr pipes")
+		}
+		filesToClose = append(filesToClose, serrR)
+
+		r, w, err := os.Pipe()
+		if err != nil {
+			return nil, err
+		}
+		filesToClose = append(filesToClose, r)
+
+		cmd.ExtraFiles = append(cmd.ExtraFiles, outR, serrR, w)
+
+		wg.Add(1)
+		cwg.Add(1)
+		go func() {
+			cwg.Done()
+			io.Copy(outW, epollConsole)
+			outW.Close()
+			wg.Done()
+		}()
+
+		if err := cmd.Start(); err != nil {
+			return nil, errors.Wrap(err, "failed to start logging binary process")
+		}
+
+		// Close our side of the pipe after start
+		if err := w.Close(); err != nil {
+			return nil, errors.Wrap(err, "failed to close write pipe after start")
+		}
+
+		// Wait for the logging binary to be ready
+		b := make([]byte, 1)
+		if _, err := r.Read(b); err != nil && err != io.EOF {
+			return nil, errors.Wrap(err, "failed to read from logging binary")
+		}
+		cwg.Wait()
+
+	default:
+		outw, err := fifo.OpenFifo(ctx, stdout, syscall.O_WRONLY, 0)
+		if err != nil {
+			return nil, err
+		}
+		outr, err := fifo.OpenFifo(ctx, stdout, syscall.O_RDONLY, 0)
+		if err != nil {
+			return nil, err
+		}
+		wg.Add(1)
+		cwg.Add(1)
+		go func() {
+			cwg.Done()
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+			io.CopyBuffer(outw, epollConsole, *p)
+			outw.Close()
+			outr.Close()
+			wg.Done()
+		}()
+		cwg.Wait()
 	}
-	wg.Add(1)
-	cwg.Add(1)
-	go func() {
-		cwg.Done()
-		p := bufPool.Get().(*[]byte)
-		defer bufPool.Put(p)
-		io.CopyBuffer(outw, epollConsole, *p)
-		outw.Close()
-		outr.Close()
-		wg.Done()
-	}()
-	cwg.Wait()
 	return epollConsole, nil
 }
 
diff --git a/vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go
index 3c61453..93c9f59 100644
--- a/vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go
+++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go
@@ -21,17 +21,22 @@
 import (
 	"context"
 	"io"
+	"net/url"
+	"os"
 	"sync"
 	"syscall"
 
 	"github.com/containerd/console"
+	"github.com/containerd/containerd/namespaces"
+	"github.com/containerd/containerd/runtime"
 	"github.com/containerd/fifo"
+	"github.com/pkg/errors"
 )
 
 type unixPlatform struct {
 }
 
-func (p *unixPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg *sync.WaitGroup) (console.Console, error) {
+func (p *unixPlatform) CopyConsole(ctx context.Context, console console.Console, id, stdin, stdout, stderr string, wg *sync.WaitGroup) (cons console.Console, retErr error) {
 	var cwg sync.WaitGroup
 	if stdin != "" {
 		in, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY, 0)
@@ -47,28 +52,98 @@
 			io.CopyBuffer(console, in, *p)
 		}()
 	}
-	outw, err := fifo.OpenFifo(ctx, stdout, syscall.O_WRONLY, 0)
+	uri, err := url.Parse(stdout)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrap(err, "unable to parse stdout uri")
 	}
-	outr, err := fifo.OpenFifo(ctx, stdout, syscall.O_RDONLY, 0)
-	if err != nil {
-		return nil, err
-	}
-	wg.Add(1)
-	cwg.Add(1)
-	go func() {
-		cwg.Done()
-		p := bufPool.Get().(*[]byte)
-		defer bufPool.Put(p)
 
-		io.CopyBuffer(outw, console, *p)
-		console.Close()
-		outr.Close()
-		outw.Close()
-		wg.Done()
-	}()
-	cwg.Wait()
+	switch uri.Scheme {
+	case "binary":
+		ns, err := namespaces.NamespaceRequired(ctx)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd := runtime.NewBinaryCmd(uri, id, ns)
+
+		// In case of unexpected errors during logging binary start, close open pipes
+		var filesToClose []*os.File
+
+		defer func() {
+			if retErr != nil {
+				runtime.CloseFiles(filesToClose...)
+			}
+		}()
+
+		// Create pipe to be used by logging binary for Stdout
+		outR, outW, err := os.Pipe()
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to create stdout pipes")
+		}
+		filesToClose = append(filesToClose, outR)
+
+		// Stderr is created for logging binary but unused when terminal is true
+		serrR, _, err := os.Pipe()
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to create stderr pipes")
+		}
+		filesToClose = append(filesToClose, serrR)
+
+		r, w, err := os.Pipe()
+		if err != nil {
+			return nil, err
+		}
+		filesToClose = append(filesToClose, r)
+
+		cmd.ExtraFiles = append(cmd.ExtraFiles, outR, serrR, w)
+
+		wg.Add(1)
+		cwg.Add(1)
+		go func() {
+			cwg.Done()
+			io.Copy(outW, console)
+			outW.Close()
+			wg.Done()
+		}()
+
+		if err := cmd.Start(); err != nil {
+			return nil, errors.Wrap(err, "failed to start logging binary process")
+		}
+
+		// Close our side of the pipe after start
+		if err := w.Close(); err != nil {
+			return nil, errors.Wrap(err, "failed to close write pipe after start")
+		}
+
+		// Wait for the logging binary to be ready
+		b := make([]byte, 1)
+		if _, err := r.Read(b); err != nil && err != io.EOF {
+			return nil, errors.Wrap(err, "failed to read from logging binary")
+		}
+		cwg.Wait()
+
+	default:
+		outw, err := fifo.OpenFifo(ctx, stdout, syscall.O_WRONLY, 0)
+		if err != nil {
+			return nil, err
+		}
+		outr, err := fifo.OpenFifo(ctx, stdout, syscall.O_RDONLY, 0)
+		if err != nil {
+			return nil, err
+		}
+		wg.Add(1)
+		cwg.Add(1)
+		go func() {
+			cwg.Done()
+			p := bufPool.Get().(*[]byte)
+			defer bufPool.Put(p)
+			io.CopyBuffer(outw, console, *p)
+			outw.Close()
+			outr.Close()
+			wg.Done()
+		}()
+		cwg.Wait()
+	}
 	return console, nil
 }
 
diff --git a/vendor/github.com/containerd/containerd/sys/stat_bsd.go b/vendor/github.com/containerd/containerd/sys/stat_bsd.go
index b9c95d9..4f03cd6 100644
--- a/vendor/github.com/containerd/containerd/sys/stat_bsd.go
+++ b/vendor/github.com/containerd/containerd/sys/stat_bsd.go
@@ -1,4 +1,4 @@
-// +build darwin freebsd
+// +build darwin freebsd netbsd
 
 /*
    Copyright The containerd Authors.
diff --git a/vendor/github.com/containerd/containerd/vendor.conf b/vendor/github.com/containerd/containerd/vendor.conf
index 59ec791..79f6f2a 100644
--- a/vendor/github.com/containerd/containerd/vendor.conf
+++ b/vendor/github.com/containerd/containerd/vendor.conf
@@ -1,13 +1,14 @@
 github.com/beorn7/perks                             v1.0.1
 github.com/BurntSushi/toml                          v0.3.1
 github.com/cespare/xxhash/v2                        v2.1.1
-github.com/containerd/btrfs                         153935315f4ab9be5bf03650a1341454b05efa5d
-github.com/containerd/cgroups                       318312a373405e5e91134d8063d04d59768a1bff
-github.com/containerd/console                       v1.0.0
+github.com/containerd/btrfs                         404b9149801e455c8076f615b06dc0abee0a977a
+github.com/containerd/cgroups                       0b889c03f102012f1d93a97ddd3ef71cd6f4f510
+github.com/containerd/console                       v1.0.1
 github.com/containerd/continuity                    efbc4488d8fe1bdc16bde3b2d2990d9b3a899165
-github.com/containerd/fifo                          f15a3290365b9d2627d189e619ab4008e0069caf
+github.com/containerd/fifo                          0724c46b320cf96bb172a0550c19a4b1fca4dacb
 github.com/containerd/go-runc                       7016d3ce2328dd2cb1192b2076ebd565c4e8df0c
-github.com/containerd/ttrpc                         v1.0.1
+github.com/containerd/nri                           eb1350a75164f76de48e3605389e7a3fbc85d06e
+github.com/containerd/ttrpc                         v1.0.2
 github.com/containerd/typeurl                       v1.0.1
 github.com/coreos/go-systemd/v22                    v22.1.0
 github.com/cpuguy83/go-md2man/v2                    v2.0.0
@@ -25,10 +26,10 @@
 github.com/hashicorp/go-multierror                  v1.0.0
 github.com/hashicorp/golang-lru                     v0.5.3
 github.com/imdario/mergo                            v0.3.7
-github.com/konsorten/go-windows-terminal-sequences  v1.0.3
 github.com/matttproud/golang_protobuf_extensions    v1.0.1
 github.com/Microsoft/go-winio                       v0.4.14
-github.com/Microsoft/hcsshim                        v0.8.9
+github.com/Microsoft/hcsshim                        v0.8.10
+github.com/moby/sys                                 symlink/v0.1.0
 github.com/opencontainers/go-digest                 v1.0.0
 github.com/opencontainers/image-spec                v1.0.1
 github.com/opencontainers/runc                      v1.0.0-rc92
@@ -40,14 +41,14 @@
 github.com/prometheus/procfs                        v0.0.11
 github.com/russross/blackfriday/v2                  v2.0.1
 github.com/shurcooL/sanitized_anchor_name           v1.0.0
-github.com/sirupsen/logrus                          v1.6.0
+github.com/sirupsen/logrus                          v1.7.0
 github.com/syndtr/gocapability                      d98352740cb2c55f81556b63d4a1ec64c5a319c2
 github.com/urfave/cli                               v1.22.1 # NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
 go.etcd.io/bbolt                                    v1.3.5
 go.opencensus.io                                    v0.22.0
 golang.org/x/net                                    ab34263943818b32f575efc978a3d24e80b04bd7
 golang.org/x/sync                                   42b317875d0fa942474b76e1b46a6060d720ae6e
-golang.org/x/sys                                    ed371f2e16b4b305ee99df548828de367527b76b
+golang.org/x/sys                                    0aaa2718063a42560507fce2cc04508608ca23b3
 golang.org/x/text                                   v0.3.3
 google.golang.org/genproto                          e50cd9704f63023d62cd06a1994b98227fc4d21a
 google.golang.org/grpc                              v1.27.1
@@ -57,9 +58,7 @@
 github.com/cilium/ebpf                              1c8d4c9ef7759622653a1d319284a44652333b28
 
 # cri dependencies
-github.com/containerd/cri                           4e6644c8cf7fb825f62e0007421b7d83dfeab5a1 # master
 github.com/davecgh/go-spew                          v1.1.1
-github.com/docker/docker                            4634ce647cf2ce2c6031129ccd109e557244986f
 github.com/docker/spdystream                        449fdfce4d962303d702fec724ef0ad181c92528
 github.com/emicklei/go-restful                      v2.9.5
 github.com/go-logr/logr                             v0.2.0
@@ -68,21 +67,24 @@
 github.com/modern-go/concurrent                     1.0.3
 github.com/modern-go/reflect2                       v1.0.1
 github.com/opencontainers/selinux                   v1.6.0
+github.com/pmezard/go-difflib                       v1.0.0
+github.com/stretchr/testify                         v1.4.0
 github.com/tchap/go-patricia                        v2.2.6
-github.com/willf/bitset                             d5bec3311243426a3c6d1b7a795f24b17c686dbb # 1.1.10+ used by selinux pkg
+github.com/willf/bitset                             v1.1.11
 golang.org/x/crypto                                 75b288015ac94e66e3d6715fb68a9b41bf046ec2
 golang.org/x/oauth2                                 858c2ad4c8b6c5d10852cb89079f6ca1c7309787
 golang.org/x/time                                   555d28b269f0569763d25dbe1a237ae74c6bcc82
 gopkg.in/inf.v0                                     v0.9.1
 gopkg.in/yaml.v2                                    v2.2.8
-k8s.io/api                                          v0.19.0-rc.4
-k8s.io/apimachinery                                 v0.19.0-rc.4
-k8s.io/apiserver                                    v0.19.0-rc.4
-k8s.io/client-go                                    v0.19.0-rc.4
-k8s.io/cri-api                                      v0.19.0-rc.4
+k8s.io/api                                          v0.19.4
+k8s.io/apimachinery                                 v0.19.4
+k8s.io/apiserver                                    v0.19.4
+k8s.io/client-go                                    v0.19.4
+k8s.io/component-base                               v0.19.4
+k8s.io/cri-api                                      v0.19.4
 k8s.io/klog/v2                                      v2.2.0
-k8s.io/utils                                        2df71ebbae66f39338aed4cd0bb82d2212ee33cc
-sigs.k8s.io/structured-merge-diff/v3                v3.0.0
+k8s.io/utils                                        d5654de09c73da55eb19ae4ab4f734f7a61747a6
+sigs.k8s.io/structured-merge-diff/v4                v4.0.1
 sigs.k8s.io/yaml                                    v1.2.0
 
 # cni dependencies
@@ -98,8 +100,8 @@
 gopkg.in/square/go-jose.v2                          v2.3.1
 
 # zfs dependencies
-github.com/containerd/zfs                           9abf673ca6ff9ab8d9bd776a4ceff8f6dc699c3d
+github.com/containerd/zfs                           0a33824f23a2ab8ec84166f47b571ecb793b0354
 github.com/mistifyio/go-zfs                         f784269be439d704d3dfa1906f45dd848fed2beb
 
 # aufs dependencies
-github.com/containerd/aufs                          371312c1e31c210a21e49bf3dfd3f31729ed9f2f
+github.com/containerd/aufs                          dab0cbea06f43329c07667afe1a70411ad555a86
diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go
index 9a23540..3eb8c90 100644
--- a/vendor/github.com/containerd/containerd/version/version.go
+++ b/vendor/github.com/containerd/containerd/version/version.go
@@ -23,7 +23,7 @@
 	Package = "github.com/containerd/containerd"
 
 	// Version holds the complete version number. Filled in at linking time.
-	Version = "1.4.1+unknown"
+	Version = "1.4.0+unknown"
 
 	// Revision is filled with the VCS (e.g. git) revision being used to build
 	// the program at linking time.
diff --git a/vendor/github.com/containerd/fifo/fifo.go b/vendor/github.com/containerd/fifo/fifo.go
index 71f9aef..96c214f 100644
--- a/vendor/github.com/containerd/fifo/fifo.go
+++ b/vendor/github.com/containerd/fifo/fifo.go
@@ -25,6 +25,7 @@
 	"syscall"
 
 	"github.com/pkg/errors"
+	"golang.org/x/sys/unix"
 )
 
 type fifo struct {
@@ -41,6 +42,21 @@
 
 var leakCheckWg *sync.WaitGroup
 
+// OpenFifoDup2 is same as OpenFifo, but additionally creates a copy of the FIFO file descriptor with dup2 syscall.
+func OpenFifoDup2(ctx context.Context, fn string, flag int, perm os.FileMode, fd int) (io.ReadWriteCloser, error) {
+	f, err := openFifo(ctx, fn, flag, perm)
+	if err != nil {
+		return nil, errors.Wrap(err, "fifo error")
+	}
+
+	if err := unix.Dup2(int(f.file.Fd()), fd); err != nil {
+		_ = f.Close()
+		return nil, errors.Wrap(err, "dup2 error")
+	}
+
+	return f, nil
+}
+
 // OpenFifo opens a fifo. Returns io.ReadWriteCloser.
 // Context can be used to cancel this function until open(2) has not returned.
 // Accepted flags:
@@ -52,6 +68,10 @@
 //     fifo isn't open. read/write will be connected after the actual fifo is
 //     open or after fifo is closed.
 func OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
+	return openFifo(ctx, fn, flag, perm)
+}
+
+func openFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (*fifo, error) {
 	if _, err := os.Stat(fn); err != nil {
 		if os.IsNotExist(err) && flag&syscall.O_CREAT != 0 {
 			if err := mkfifo(fn, uint32(perm&os.ModePerm)); err != nil && !os.IsExist(err) {
diff --git a/vendor/github.com/containerd/go-runc/go.mod b/vendor/github.com/containerd/go-runc/go.mod
index d833ee1..f69c26f 100644
--- a/vendor/github.com/containerd/go-runc/go.mod
+++ b/vendor/github.com/containerd/go-runc/go.mod
@@ -3,8 +3,9 @@
 go 1.13
 
 require (
-	github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e
-	github.com/opencontainers/runtime-spec v1.0.1
-	github.com/pkg/errors v0.8.1
-	golang.org/x/sys v0.0.0-20191210023423-ac6580df4449
+	github.com/containerd/console v1.0.1
+	github.com/opencontainers/runtime-spec v1.0.2
+	github.com/pkg/errors v0.9.1
+	github.com/sirupsen/logrus v1.7.0
+	golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
 )
diff --git a/vendor/github.com/containerd/go-runc/io_unix.go b/vendor/github.com/containerd/go-runc/io_unix.go
index 567cd07..ccf1dd4 100644
--- a/vendor/github.com/containerd/go-runc/io_unix.go
+++ b/vendor/github.com/containerd/go-runc/io_unix.go
@@ -20,7 +20,9 @@
 
 import (
 	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
 	"golang.org/x/sys/unix"
+	"runtime"
 )
 
 // NewPipeIO creates pipe pairs to be used with runc
@@ -47,7 +49,13 @@
 		}
 		pipes = append(pipes, stdin)
 		if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil {
-			return nil, errors.Wrap(err, "failed to chown stdin")
+			// TODO: revert with proper darwin solution, skipping for now
+			// as darwin chown is returning EINVAL on anonymous pipe
+			if runtime.GOOS == "darwin" {
+				logrus.WithError(err).Debug("failed to chown stdin, ignored")
+			} else {
+				return nil, errors.Wrap(err, "failed to chown stdin")
+			}
 		}
 	}
 	if option.OpenStdout {
@@ -56,7 +64,13 @@
 		}
 		pipes = append(pipes, stdout)
 		if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil {
-			return nil, errors.Wrap(err, "failed to chown stdout")
+			// TODO: revert with proper darwin solution, skipping for now
+			// as darwin chown is returning EINVAL on anonymous pipe
+			if runtime.GOOS == "darwin" {
+				logrus.WithError(err).Debug("failed to chown stdout, ignored")
+			} else {
+				return nil, errors.Wrap(err, "failed to chown stdout")
+			}
 		}
 	}
 	if option.OpenStderr {
@@ -65,7 +79,13 @@
 		}
 		pipes = append(pipes, stderr)
 		if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil {
-			return nil, errors.Wrap(err, "failed to chown stderr")
+			// TODO: revert with proper darwin solution, skipping for now
+			// as darwin chown is returning EINVAL on anonymous pipe
+			if runtime.GOOS == "darwin" {
+				logrus.WithError(err).Debug("failed to chown stderr, ignored")
+			} else {
+				return nil, errors.Wrap(err, "failed to chown stderr")
+			}
 		}
 	}
 	return &pipeIO{
diff --git a/vendor/github.com/containerd/go-runc/runc.go b/vendor/github.com/containerd/go-runc/runc.go
index c3a95af..f5f03ae 100644
--- a/vendor/github.com/containerd/go-runc/runc.go
+++ b/vendor/github.com/containerd/go-runc/runc.go
@@ -29,7 +29,6 @@
 	"path/filepath"
 	"strconv"
 	"strings"
-	"syscall"
 	"time"
 
 	specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -55,24 +54,9 @@
 	DefaultCommand = "runc"
 )
 
-// Runc is the client to the runc cli
-type Runc struct {
-	//If command is empty, DefaultCommand is used
-	Command       string
-	Root          string
-	Debug         bool
-	Log           string
-	LogFormat     Format
-	PdeathSignal  syscall.Signal
-	Setpgid       bool
-	Criu          string
-	SystemdCgroup bool
-	Rootless      *bool // nil stands for "auto"
-}
-
 // List returns all containers created inside the provided runc root directory
 func (r *Runc) List(context context.Context) ([]*Container, error) {
-	data, err := cmdOutput(r.command(context, "list", "--format=json"), false)
+	data, err := cmdOutput(r.command(context, "list", "--format=json"), false, nil)
 	defer putBuf(data)
 	if err != nil {
 		return nil, err
@@ -86,7 +70,7 @@
 
 // State returns the state for the container provided by id
 func (r *Runc) State(context context.Context, id string) (*Container, error) {
-	data, err := cmdOutput(r.command(context, "state", id), true)
+	data, err := cmdOutput(r.command(context, "state", id), true, nil)
 	defer putBuf(data)
 	if err != nil {
 		return nil, fmt.Errorf("%s: %s", err, data.String())
@@ -111,6 +95,7 @@
 	NoPivot       bool
 	NoNewKeyring  bool
 	ExtraFiles    []*os.File
+	Started       chan<- int
 }
 
 func (o *CreateOpts) args() (out []string, err error) {
@@ -156,7 +141,7 @@
 	cmd.ExtraFiles = opts.ExtraFiles
 
 	if cmd.Stdout == nil && cmd.Stderr == nil {
-		data, err := cmdOutput(cmd, true)
+		data, err := cmdOutput(cmd, true, nil)
 		defer putBuf(data)
 		if err != nil {
 			return fmt.Errorf("%s: %s", err, data.String())
@@ -176,7 +161,7 @@
 	}
 	status, err := Monitor.Wait(cmd, ec)
 	if err == nil && status != 0 {
-		err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
+		err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
 	}
 	return err
 }
@@ -191,6 +176,7 @@
 	PidFile       string
 	ConsoleSocket ConsoleSocket
 	Detach        bool
+	Started       chan<- int
 }
 
 func (o *ExecOpts) args() (out []string, err error) {
@@ -210,9 +196,12 @@
 	return out, nil
 }
 
-// Exec executres and additional process inside the container based on a full
+// Exec executes an additional process inside the container based on a full
 // OCI Process specification
 func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts *ExecOpts) error {
+	if opts.Started != nil {
+		defer close(opts.Started)
+	}
 	f, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "runc-process")
 	if err != nil {
 		return err
@@ -236,10 +225,10 @@
 		opts.Set(cmd)
 	}
 	if cmd.Stdout == nil && cmd.Stderr == nil {
-		data, err := cmdOutput(cmd, true)
+		data, err := cmdOutput(cmd, true, opts.Started)
 		defer putBuf(data)
 		if err != nil {
-			return fmt.Errorf("%s: %s", err, data.String())
+			return fmt.Errorf("%w: %s", err, data.String())
 		}
 		return nil
 	}
@@ -247,6 +236,9 @@
 	if err != nil {
 		return err
 	}
+	if opts.Started != nil {
+		opts.Started <- cmd.Process.Pid
+	}
 	if opts != nil && opts.IO != nil {
 		if c, ok := opts.IO.(StartCloser); ok {
 			if err := c.CloseAfterStart(); err != nil {
@@ -256,7 +248,7 @@
 	}
 	status, err := Monitor.Wait(cmd, ec)
 	if err == nil && status != 0 {
-		err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
+		err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
 	}
 	return err
 }
@@ -264,6 +256,9 @@
 // Run runs the create, start, delete lifecycle of the container
 // and returns its exit status after it has exited
 func (r *Runc) Run(context context.Context, id, bundle string, opts *CreateOpts) (int, error) {
+	if opts.Started != nil {
+		defer close(opts.Started)
+	}
 	args := []string{"run", "--bundle", bundle}
 	if opts != nil {
 		oargs, err := opts.args()
@@ -280,9 +275,12 @@
 	if err != nil {
 		return -1, err
 	}
+	if opts.Started != nil {
+		opts.Started <- cmd.Process.Pid
+	}
 	status, err := Monitor.Wait(cmd, ec)
 	if err == nil && status != 0 {
-		err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
+		err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
 	}
 	return status, err
 }
@@ -403,7 +401,7 @@
 
 // Ps lists all the processes inside the container returning their pids
 func (r *Runc) Ps(context context.Context, id string) ([]int, error) {
-	data, err := cmdOutput(r.command(context, "ps", "--format", "json", id), true)
+	data, err := cmdOutput(r.command(context, "ps", "--format", "json", id), true, nil)
 	defer putBuf(data)
 	if err != nil {
 		return nil, fmt.Errorf("%s: %s", err, data.String())
@@ -417,7 +415,7 @@
 
 // Top lists all the processes inside the container returning the full ps data
 func (r *Runc) Top(context context.Context, id string, psOptions string) (*TopResults, error) {
-	data, err := cmdOutput(r.command(context, "ps", "--format", "table", id, psOptions), true)
+	data, err := cmdOutput(r.command(context, "ps", "--format", "table", id, psOptions), true, nil)
 	defer putBuf(data)
 	if err != nil {
 		return nil, fmt.Errorf("%s: %s", err, data.String())
@@ -452,6 +450,10 @@
 	// EmptyNamespaces creates a namespace for the container but does not save its properties
 	// Provide the namespaces you wish to be checkpointed without their settings on restore
 	EmptyNamespaces []string
+	// LazyPages uses userfaultfd to lazily restore memory pages
+	LazyPages bool
+	// StatusFile is the file criu writes \0 to once lazy-pages is ready
+	StatusFile *os.File
 }
 
 type CgroupMode string
@@ -493,6 +495,9 @@
 	for _, ns := range o.EmptyNamespaces {
 		out = append(out, "--empty-ns", ns)
 	}
+	if o.LazyPages {
+		out = append(out, "--lazy-pages")
+	}
 	return out
 }
 
@@ -511,13 +516,23 @@
 // Checkpoint allows you to checkpoint a container using criu
 func (r *Runc) Checkpoint(context context.Context, id string, opts *CheckpointOpts, actions ...CheckpointAction) error {
 	args := []string{"checkpoint"}
+	extraFiles := []*os.File{}
 	if opts != nil {
 		args = append(args, opts.args()...)
+		if opts.StatusFile != nil {
+			// pass the status file to the child process
+			extraFiles = []*os.File{opts.StatusFile}
+			// set status-fd to 3 as this will be the file descriptor
+			// of the first file passed with cmd.ExtraFiles
+			args = append(args, "--status-fd", "3")
+		}
 	}
 	for _, a := range actions {
 		args = a(args)
 	}
-	return r.runOrError(r.command(context, append(args, id)...))
+	cmd := r.command(context, append(args, id)...)
+	cmd.ExtraFiles = extraFiles
+	return r.runOrError(cmd)
 }
 
 type RestoreOpts struct {
@@ -583,7 +598,7 @@
 	}
 	status, err := Monitor.Wait(cmd, ec)
 	if err == nil && status != 0 {
-		err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
+		err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
 	}
 	return status, err
 }
@@ -612,7 +627,7 @@
 
 // Version returns the runc and runtime-spec versions
 func (r *Runc) Version(context context.Context) (Version, error) {
-	data, err := cmdOutput(r.command(context, "--version"), false)
+	data, err := cmdOutput(r.command(context, "--version"), false, nil)
 	defer putBuf(data)
 	if err != nil {
 		return Version{}, err
@@ -680,11 +695,11 @@
 		}
 		status, err := Monitor.Wait(cmd, ec)
 		if err == nil && status != 0 {
-			err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
+			err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
 		}
 		return err
 	}
-	data, err := cmdOutput(cmd, true)
+	data, err := cmdOutput(cmd, true, nil)
 	defer putBuf(data)
 	if err != nil {
 		return fmt.Errorf("%s: %s", err, data.String())
@@ -694,7 +709,7 @@
 
 // callers of cmdOutput are expected to call putBuf on the returned Buffer
 // to ensure it is released back to the shared pool after use.
-func cmdOutput(cmd *exec.Cmd, combined bool) (*bytes.Buffer, error) {
+func cmdOutput(cmd *exec.Cmd, combined bool, started chan<- int) (*bytes.Buffer, error) {
 	b := getBuf()
 
 	cmd.Stdout = b
@@ -705,11 +720,22 @@
 	if err != nil {
 		return nil, err
 	}
+	if started != nil {
+		started <- cmd.Process.Pid
+	}
 
 	status, err := Monitor.Wait(cmd, ec)
 	if err == nil && status != 0 {
-		err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
+		err = fmt.Errorf("%s did not terminate successfully: %w", cmd.Args[0], &ExitError{status})
 	}
 
 	return b, err
 }
+
+type ExitError struct {
+	Status int
+}
+
+func (e *ExitError) Error() string {
+	return fmt.Sprintf("exit status %d", e.Status)
+}
diff --git a/vendor/github.com/containerd/go-runc/runc_unix.go b/vendor/github.com/containerd/go-runc/runc_unix.go
new file mode 100644
index 0000000..548ffd6
--- /dev/null
+++ b/vendor/github.com/containerd/go-runc/runc_unix.go
@@ -0,0 +1,38 @@
+//+build !windows
+
+/*
+   Copyright The containerd Authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package runc
+
+import (
+	"golang.org/x/sys/unix"
+)
+
+// Runc is the client to the runc cli
+type Runc struct {
+	//If command is empty, DefaultCommand is used
+	Command       string
+	Root          string
+	Debug         bool
+	Log           string
+	LogFormat     Format
+	PdeathSignal  unix.Signal
+	Setpgid       bool
+	Criu          string
+	SystemdCgroup bool
+	Rootless      *bool // nil stands for "auto"
+}
diff --git a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp_default_unsupported.go b/vendor/github.com/containerd/go-runc/runc_windows.go
similarity index 63%
rename from vendor/github.com/containerd/containerd/contrib/seccomp/seccomp_default_unsupported.go
rename to vendor/github.com/containerd/go-runc/runc_windows.go
index 6d70510..c5873de 100644
--- a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp_default_unsupported.go
+++ b/vendor/github.com/containerd/go-runc/runc_windows.go
@@ -1,5 +1,3 @@
-// +build !linux
-
 /*
    Copyright The containerd Authors.
 
@@ -16,11 +14,18 @@
    limitations under the License.
 */
 
-package seccomp
+package runc
 
-import specs "github.com/opencontainers/runtime-spec/specs-go"
-
-// DefaultProfile defines the allowed syscalls for the default seccomp profile.
-func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
-	return &specs.LinuxSeccomp{}
+// Runc is the client to the runc cli
+type Runc struct {
+	//If command is empty, DefaultCommand is used
+	Command       string
+	Root          string
+	Debug         bool
+	Log           string
+	LogFormat     Format
+	Setpgid       bool
+	Criu          string
+	SystemdCgroup bool
+	Rootless      *bool // nil stands for "auto"
 }
diff --git a/vendor/github.com/containerd/ttrpc/client.go b/vendor/github.com/containerd/ttrpc/client.go
index e816941..30c9b73 100644
--- a/vendor/github.com/containerd/ttrpc/client.go
+++ b/vendor/github.com/containerd/ttrpc/client.go
@@ -47,8 +47,9 @@
 	ctx    context.Context
 	closed func()
 
-	closeOnce     sync.Once
-	userCloseFunc func()
+	closeOnce       sync.Once
+	userCloseFunc   func()
+	userCloseWaitCh chan struct{}
 
 	errOnce     sync.Once
 	err         error
@@ -75,14 +76,15 @@
 func NewClient(conn net.Conn, opts ...ClientOpts) *Client {
 	ctx, cancel := context.WithCancel(context.Background())
 	c := &Client{
-		codec:         codec{},
-		conn:          conn,
-		channel:       newChannel(conn),
-		calls:         make(chan *callRequest),
-		closed:        cancel,
-		ctx:           ctx,
-		userCloseFunc: func() {},
-		interceptor:   defaultClientInterceptor,
+		codec:           codec{},
+		conn:            conn,
+		channel:         newChannel(conn),
+		calls:           make(chan *callRequest),
+		closed:          cancel,
+		ctx:             ctx,
+		userCloseFunc:   func() {},
+		userCloseWaitCh: make(chan struct{}),
+		interceptor:     defaultClientInterceptor,
 	}
 
 	for _, o := range opts {
@@ -175,6 +177,17 @@
 	return nil
 }
 
+// UserOnCloseWait is used to blocks untils the user's on-close callback
+// finishes.
+func (c *Client) UserOnCloseWait(ctx context.Context) error {
+	select {
+	case <-c.userCloseWaitCh:
+		return nil
+	case <-ctx.Done():
+		return ctx.Err()
+	}
+}
+
 type message struct {
 	messageHeader
 	p   []byte
@@ -251,6 +264,7 @@
 	defer func() {
 		c.conn.Close()
 		c.userCloseFunc()
+		close(c.userCloseWaitCh)
 	}()
 
 	for {
@@ -339,7 +353,8 @@
 		return ErrClosed
 	default:
 		// if we have an epipe on a write or econnreset on a read , we cast to errclosed
-		if oerr, ok := err.(*net.OpError); ok && (oerr.Op == "write" || oerr.Op == "read") {
+		var oerr *net.OpError
+		if errors.As(err, &oerr) && (oerr.Op == "write" || oerr.Op == "read") {
 			serr, sok := oerr.Err.(*os.SyscallError)
 			if sok && ((serr.Err == syscall.EPIPE && oerr.Op == "write") ||
 				(serr.Err == syscall.ECONNRESET && oerr.Op == "read")) {
diff --git a/vendor/github.com/creack/pty/run.go b/vendor/github.com/creack/pty/run.go
index 959be26..b079425 100644
--- a/vendor/github.com/creack/pty/run.go
+++ b/vendor/github.com/creack/pty/run.go
@@ -11,6 +11,8 @@
 // Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
 // and c.Stderr, calls c.Start, and returns the File of the tty's
 // corresponding pty.
+//
+// Starts the process in a new session and sets the controlling terminal.
 func Start(c *exec.Cmd) (pty *os.File, err error) {
 	return StartWithSize(c, nil)
 }
@@ -19,16 +21,35 @@
 // and c.Stderr, calls c.Start, and returns the File of the tty's
 // corresponding pty.
 //
-// This will resize the pty to the specified size before starting the command
+// This will resize the pty to the specified size before starting the command.
+// Starts the process in a new session and sets the controlling terminal.
 func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) {
+	if c.SysProcAttr == nil {
+		c.SysProcAttr = &syscall.SysProcAttr{}
+	}
+	c.SysProcAttr.Setsid = true
+	c.SysProcAttr.Setctty = true
+	return StartWithAttrs(c, sz, c.SysProcAttr)
+}
+
+// StartWithAttrs assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout,
+// and c.Stderr, calls c.Start, and returns the File of the tty's
+// corresponding pty.
+//
+// This will resize the pty to the specified size before starting the command if a size is provided.
+// The `attrs` parameter overrides the one set in c.SysProcAttr.
+//
+// This should generally not be needed. Used in some edge cases where it is needed to create a pty
+// without a controlling terminal.
+func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (pty *os.File, err error) {
 	pty, tty, err := Open()
 	if err != nil {
 		return nil, err
 	}
 	defer tty.Close()
+
 	if sz != nil {
-		err = Setsize(pty, sz)
-		if err != nil {
+		if err := Setsize(pty, sz); err != nil {
 			pty.Close()
 			return nil, err
 		}
@@ -42,15 +63,11 @@
 	if c.Stdin == nil {
 		c.Stdin = tty
 	}
-	if c.SysProcAttr == nil {
-		c.SysProcAttr = &syscall.SysProcAttr{}
-	}
-	c.SysProcAttr.Setctty = true
-	c.SysProcAttr.Setsid = true
-	c.SysProcAttr.Ctty = int(tty.Fd())
-	err = c.Start()
-	if err != nil {
-		pty.Close()
+
+	c.SysProcAttr = attrs
+
+	if err := c.Start(); err != nil {
+		_ = pty.Close()
 		return nil, err
 	}
 	return pty, err
diff --git a/vendor/github.com/creack/pty/ztypes_freebsd_arm64.go b/vendor/github.com/creack/pty/ztypes_freebsd_arm64.go
new file mode 100644
index 0000000..4418139
--- /dev/null
+++ b/vendor/github.com/creack/pty/ztypes_freebsd_arm64.go
@@ -0,0 +1,13 @@
+// Code generated by cmd/cgo -godefs; DO NOT EDIT.
+// cgo -godefs types_freebsd.go
+
+package pty
+
+const (
+	_C_SPECNAMELEN = 0xff
+)
+
+type fiodgnameArg struct {
+	Len int32
+	Buf *byte
+}
diff --git a/vendor/github.com/creack/pty/ztypes_openbsd_386.go b/vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go
similarity index 61%
rename from vendor/github.com/creack/pty/ztypes_openbsd_386.go
rename to vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go
index ccb3aab..d7cab4a 100644
--- a/vendor/github.com/creack/pty/ztypes_openbsd_386.go
+++ b/vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go
@@ -1,5 +1,5 @@
-// Created by cgo -godefs - DO NOT EDIT
-// cgo -godefs types_openbsd.go
+// +build openbsd
+// +build 386 amd64 arm arm64
 
 package pty
 
diff --git a/vendor/github.com/creack/pty/ztypes_openbsd_amd64.go b/vendor/github.com/creack/pty/ztypes_openbsd_amd64.go
deleted file mode 100644
index e670516..0000000
--- a/vendor/github.com/creack/pty/ztypes_openbsd_amd64.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Created by cgo -godefs - DO NOT EDIT
-// cgo -godefs types_openbsd.go
-
-package pty
-
-type ptmget struct {
-	Cfd int32
-	Sfd int32
-	Cn  [16]int8
-	Sn  [16]int8
-}
-
-var ioctl_PTMGET = 0x40287401
diff --git a/vendor/github.com/docker/libnetwork/endpoint.go b/vendor/github.com/docker/libnetwork/endpoint.go
index 8debc99..d79bd33 100644
--- a/vendor/github.com/docker/libnetwork/endpoint.go
+++ b/vendor/github.com/docker/libnetwork/endpoint.go
@@ -1055,7 +1055,7 @@
 
 // JoinOptionPriority function returns an option setter for priority option to
 // be passed to the endpoint.Join() method.
-func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
+func JoinOptionPriority(prio int) EndpointOption {
 	return func(ep *endpoint) {
 		// ep lock already acquired
 		c := ep.network.getController()
diff --git a/vendor/github.com/docker/libnetwork/portmapper/mapper.go b/vendor/github.com/docker/libnetwork/portmapper/mapper.go
index f447f3f..ae74145 100644
--- a/vendor/github.com/docker/libnetwork/portmapper/mapper.go
+++ b/vendor/github.com/docker/libnetwork/portmapper/mapper.go
@@ -151,7 +151,7 @@
 	}
 
 	containerIP, containerPort := getIPAndPort(m.container)
-	if hostIP.To4() != nil || hostIP.To16() != nil {
+	if pm.checkIP(hostIP) {
 		if err := pm.AppendForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
 			return nil, err
 		}
@@ -160,7 +160,7 @@
 	cleanup := func() error {
 		// need to undo the iptables rules before we return
 		m.userlandProxy.Stop()
-		if hostIP.To4() != nil || hostIP.To16() != nil {
+		if pm.checkIP(hostIP) {
 			pm.DeleteForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
 			if err := pm.Allocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
 				return err
diff --git a/vendor/github.com/docker/libnetwork/portmapper/mapper_linux.go b/vendor/github.com/docker/libnetwork/portmapper/mapper_linux.go
index 0e76c54..c565efd 100644
--- a/vendor/github.com/docker/libnetwork/portmapper/mapper_linux.go
+++ b/vendor/github.com/docker/libnetwork/portmapper/mapper_linux.go
@@ -44,3 +44,11 @@
 	}
 	return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort, pm.bridgeName)
 }
+
+// checkIP checks if IP is valid and matching to chain version
+func (pm *PortMapper) checkIP(ip net.IP) bool {
+	if pm.chain == nil || pm.chain.IPTable.Version == iptables.IPv4 {
+		return ip.To4() != nil
+	}
+	return ip.To16() != nil
+}
diff --git a/vendor/github.com/docker/libnetwork/portmapper/mapper_windows.go b/vendor/github.com/docker/libnetwork/portmapper/mapper_windows.go
index 89651e5..d1f703f 100644
--- a/vendor/github.com/docker/libnetwork/portmapper/mapper_windows.go
+++ b/vendor/github.com/docker/libnetwork/portmapper/mapper_windows.go
@@ -29,3 +29,9 @@
 func (pm *PortMapper) DeleteForwardingTableEntry(proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
 	return nil
 }
+
+// checkIP checks if IP is valid and matching to chain version
+func (pm *PortMapper) checkIP(ip net.IP) bool {
+	// no IPv6 for port mapper on windows -> only IPv4 valid
+	return ip.To4() != nil
+}
diff --git a/vendor/github.com/docker/libnetwork/service_linux.go b/vendor/github.com/docker/libnetwork/service_linux.go
index 66c8be6..514c65a 100644
--- a/vendor/github.com/docker/libnetwork/service_linux.go
+++ b/vendor/github.com/docker/libnetwork/service_linux.go
@@ -67,11 +67,12 @@
 	if !ok {
 		return nil, nil, fmt.Errorf("Unable to get sandbox for %s(%s) in for %s", ep.Name(), ep.ID(), n.ID())
 	}
-	ep = sb.getEndpoint(ep.ID())
-	if ep == nil {
+	var sep *endpoint
+	sep = sb.getEndpoint(ep.ID())
+	if sep == nil {
 		return nil, nil, fmt.Errorf("Load balancing endpoint %s(%s) removed from %s", ep.Name(), ep.ID(), n.ID())
 	}
-	return ep, sb, nil
+	return sep, sb, nil
 }
 
 // Searches the OS sandbox for the name of the endpoint interface
diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
new file mode 100644
index 0000000..f0d66be
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
@@ -0,0 +1,1290 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2015 The Go Authors.  All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON.
+It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json.
+
+This package produces a different output than the standard "encoding/json" package,
+which does not operate correctly on protocol buffers.
+*/
+package jsonpb
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"math"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/golang/protobuf/proto"
+
+	stpb "github.com/golang/protobuf/ptypes/struct"
+)
+
+const secondInNanos = int64(time.Second / time.Nanosecond)
+const maxSecondsInDuration = 315576000000
+
+// Marshaler is a configurable object for converting between
+// protocol buffer objects and a JSON representation for them.
+type Marshaler struct {
+	// Whether to render enum values as integers, as opposed to string values.
+	EnumsAsInts bool
+
+	// Whether to render fields with zero values.
+	EmitDefaults bool
+
+	// A string to indent each level by. The presence of this field will
+	// also cause a space to appear between the field separator and
+	// value, and for newlines to be appear between fields and array
+	// elements.
+	Indent string
+
+	// Whether to use the original (.proto) name for fields.
+	OrigName bool
+
+	// A custom URL resolver to use when marshaling Any messages to JSON.
+	// If unset, the default resolution strategy is to extract the
+	// fully-qualified type name from the type URL and pass that to
+	// proto.MessageType(string).
+	AnyResolver AnyResolver
+}
+
+// AnyResolver takes a type URL, present in an Any message, and resolves it into
+// an instance of the associated message.
+type AnyResolver interface {
+	Resolve(typeUrl string) (proto.Message, error)
+}
+
+func defaultResolveAny(typeUrl string) (proto.Message, error) {
+	// Only the part of typeUrl after the last slash is relevant.
+	mname := typeUrl
+	if slash := strings.LastIndex(mname, "/"); slash >= 0 {
+		mname = mname[slash+1:]
+	}
+	mt := proto.MessageType(mname)
+	if mt == nil {
+		return nil, fmt.Errorf("unknown message type %q", mname)
+	}
+	return reflect.New(mt.Elem()).Interface().(proto.Message), nil
+}
+
+// JSONPBMarshaler is implemented by protobuf messages that customize the
+// way they are marshaled to JSON. Messages that implement this should
+// also implement JSONPBUnmarshaler so that the custom format can be
+// parsed.
+//
+// The JSON marshaling must follow the proto to JSON specification:
+//	https://developers.google.com/protocol-buffers/docs/proto3#json
+type JSONPBMarshaler interface {
+	MarshalJSONPB(*Marshaler) ([]byte, error)
+}
+
+// JSONPBUnmarshaler is implemented by protobuf messages that customize
+// the way they are unmarshaled from JSON. Messages that implement this
+// should also implement JSONPBMarshaler so that the custom format can be
+// produced.
+//
+// The JSON unmarshaling must follow the JSON to proto specification:
+//	https://developers.google.com/protocol-buffers/docs/proto3#json
+type JSONPBUnmarshaler interface {
+	UnmarshalJSONPB(*Unmarshaler, []byte) error
+}
+
+// Marshal marshals a protocol buffer into JSON.
+func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
+	v := reflect.ValueOf(pb)
+	if pb == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
+		return errors.New("Marshal called with nil")
+	}
+	// Check for unset required fields first.
+	if err := checkRequiredFields(pb); err != nil {
+		return err
+	}
+	writer := &errWriter{writer: out}
+	return m.marshalObject(writer, pb, "", "")
+}
+
+// MarshalToString converts a protocol buffer object to JSON string.
+func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) {
+	var buf bytes.Buffer
+	if err := m.Marshal(&buf, pb); err != nil {
+		return "", err
+	}
+	return buf.String(), nil
+}
+
+type int32Slice []int32
+
+var nonFinite = map[string]float64{
+	`"NaN"`:       math.NaN(),
+	`"Infinity"`:  math.Inf(1),
+	`"-Infinity"`: math.Inf(-1),
+}
+
+// For sorting extensions ids to ensure stable output.
+func (s int32Slice) Len() int           { return len(s) }
+func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
+func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+
+type wkt interface {
+	XXX_WellKnownType() string
+}
+
+var (
+	wktType     = reflect.TypeOf((*wkt)(nil)).Elem()
+	messageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
+)
+
+// marshalObject writes a struct to the Writer.
+func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error {
+	if jsm, ok := v.(JSONPBMarshaler); ok {
+		b, err := jsm.MarshalJSONPB(m)
+		if err != nil {
+			return err
+		}
+		if typeURL != "" {
+			// we are marshaling this object to an Any type
+			var js map[string]*json.RawMessage
+			if err = json.Unmarshal(b, &js); err != nil {
+				return fmt.Errorf("type %T produced invalid JSON: %v", v, err)
+			}
+			turl, err := json.Marshal(typeURL)
+			if err != nil {
+				return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
+			}
+			js["@type"] = (*json.RawMessage)(&turl)
+			if m.Indent != "" {
+				b, err = json.MarshalIndent(js, indent, m.Indent)
+			} else {
+				b, err = json.Marshal(js)
+			}
+			if err != nil {
+				return err
+			}
+		}
+
+		out.write(string(b))
+		return out.err
+	}
+
+	s := reflect.ValueOf(v).Elem()
+
+	// Handle well-known types.
+	if wkt, ok := v.(wkt); ok {
+		switch wkt.XXX_WellKnownType() {
+		case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
+			"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
+			// "Wrappers use the same representation in JSON
+			//  as the wrapped primitive type, ..."
+			sprop := proto.GetProperties(s.Type())
+			return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent)
+		case "Any":
+			// Any is a bit more involved.
+			return m.marshalAny(out, v, indent)
+		case "Duration":
+			s, ns := s.Field(0).Int(), s.Field(1).Int()
+			if s < -maxSecondsInDuration || s > maxSecondsInDuration {
+				return fmt.Errorf("seconds out of range %v", s)
+			}
+			if ns <= -secondInNanos || ns >= secondInNanos {
+				return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
+			}
+			if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
+				return errors.New("signs of seconds and nanos do not match")
+			}
+			// Generated output always contains 0, 3, 6, or 9 fractional digits,
+			// depending on required precision, followed by the suffix "s".
+			f := "%d.%09d"
+			if ns < 0 {
+				ns = -ns
+				if s == 0 {
+					f = "-%d.%09d"
+				}
+			}
+			x := fmt.Sprintf(f, s, ns)
+			x = strings.TrimSuffix(x, "000")
+			x = strings.TrimSuffix(x, "000")
+			x = strings.TrimSuffix(x, ".000")
+			out.write(`"`)
+			out.write(x)
+			out.write(`s"`)
+			return out.err
+		case "Struct", "ListValue":
+			// Let marshalValue handle the `Struct.fields` map or the `ListValue.values` slice.
+			// TODO: pass the correct Properties if needed.
+			return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent)
+		case "Timestamp":
+			// "RFC 3339, where generated output will always be Z-normalized
+			//  and uses 0, 3, 6 or 9 fractional digits."
+			s, ns := s.Field(0).Int(), s.Field(1).Int()
+			if ns < 0 || ns >= secondInNanos {
+				return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
+			}
+			t := time.Unix(s, ns).UTC()
+			// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
+			x := t.Format("2006-01-02T15:04:05.000000000")
+			x = strings.TrimSuffix(x, "000")
+			x = strings.TrimSuffix(x, "000")
+			x = strings.TrimSuffix(x, ".000")
+			out.write(`"`)
+			out.write(x)
+			out.write(`Z"`)
+			return out.err
+		case "Value":
+			// Value has a single oneof.
+			kind := s.Field(0)
+			if kind.IsNil() {
+				// "absence of any variant indicates an error"
+				return errors.New("nil Value")
+			}
+			// oneof -> *T -> T -> T.F
+			x := kind.Elem().Elem().Field(0)
+			// TODO: pass the correct Properties if needed.
+			return m.marshalValue(out, &proto.Properties{}, x, indent)
+		}
+	}
+
+	out.write("{")
+	if m.Indent != "" {
+		out.write("\n")
+	}
+
+	firstField := true
+
+	if typeURL != "" {
+		if err := m.marshalTypeURL(out, indent, typeURL); err != nil {
+			return err
+		}
+		firstField = false
+	}
+
+	for i := 0; i < s.NumField(); i++ {
+		value := s.Field(i)
+		valueField := s.Type().Field(i)
+		if strings.HasPrefix(valueField.Name, "XXX_") {
+			continue
+		}
+
+		// IsNil will panic on most value kinds.
+		switch value.Kind() {
+		case reflect.Chan, reflect.Func, reflect.Interface:
+			if value.IsNil() {
+				continue
+			}
+		}
+
+		if !m.EmitDefaults {
+			switch value.Kind() {
+			case reflect.Bool:
+				if !value.Bool() {
+					continue
+				}
+			case reflect.Int32, reflect.Int64:
+				if value.Int() == 0 {
+					continue
+				}
+			case reflect.Uint32, reflect.Uint64:
+				if value.Uint() == 0 {
+					continue
+				}
+			case reflect.Float32, reflect.Float64:
+				if value.Float() == 0 {
+					continue
+				}
+			case reflect.String:
+				if value.Len() == 0 {
+					continue
+				}
+			case reflect.Map, reflect.Ptr, reflect.Slice:
+				if value.IsNil() {
+					continue
+				}
+			}
+		}
+
+		// Oneof fields need special handling.
+		if valueField.Tag.Get("protobuf_oneof") != "" {
+			// value is an interface containing &T{real_value}.
+			sv := value.Elem().Elem() // interface -> *T -> T
+			value = sv.Field(0)
+			valueField = sv.Type().Field(0)
+		}
+		prop := jsonProperties(valueField, m.OrigName)
+		if !firstField {
+			m.writeSep(out)
+		}
+		if err := m.marshalField(out, prop, value, indent); err != nil {
+			return err
+		}
+		firstField = false
+	}
+
+	// Handle proto2 extensions.
+	if ep, ok := v.(proto.Message); ok {
+		extensions := proto.RegisteredExtensions(v)
+		// Sort extensions for stable output.
+		ids := make([]int32, 0, len(extensions))
+		for id, desc := range extensions {
+			if !proto.HasExtension(ep, desc) {
+				continue
+			}
+			ids = append(ids, id)
+		}
+		sort.Sort(int32Slice(ids))
+		for _, id := range ids {
+			desc := extensions[id]
+			if desc == nil {
+				// unknown extension
+				continue
+			}
+			ext, extErr := proto.GetExtension(ep, desc)
+			if extErr != nil {
+				return extErr
+			}
+			value := reflect.ValueOf(ext)
+			var prop proto.Properties
+			prop.Parse(desc.Tag)
+			prop.JSONName = fmt.Sprintf("[%s]", desc.Name)
+			if !firstField {
+				m.writeSep(out)
+			}
+			if err := m.marshalField(out, &prop, value, indent); err != nil {
+				return err
+			}
+			firstField = false
+		}
+
+	}
+
+	if m.Indent != "" {
+		out.write("\n")
+		out.write(indent)
+	}
+	out.write("}")
+	return out.err
+}
+
+func (m *Marshaler) writeSep(out *errWriter) {
+	if m.Indent != "" {
+		out.write(",\n")
+	} else {
+		out.write(",")
+	}
+}
+
+func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error {
+	// "If the Any contains a value that has a special JSON mapping,
+	//  it will be converted as follows: {"@type": xxx, "value": yyy}.
+	//  Otherwise, the value will be converted into a JSON object,
+	//  and the "@type" field will be inserted to indicate the actual data type."
+	v := reflect.ValueOf(any).Elem()
+	turl := v.Field(0).String()
+	val := v.Field(1).Bytes()
+
+	var msg proto.Message
+	var err error
+	if m.AnyResolver != nil {
+		msg, err = m.AnyResolver.Resolve(turl)
+	} else {
+		msg, err = defaultResolveAny(turl)
+	}
+	if err != nil {
+		return err
+	}
+
+	if err := proto.Unmarshal(val, msg); err != nil {
+		return err
+	}
+
+	if _, ok := msg.(wkt); ok {
+		out.write("{")
+		if m.Indent != "" {
+			out.write("\n")
+		}
+		if err := m.marshalTypeURL(out, indent, turl); err != nil {
+			return err
+		}
+		m.writeSep(out)
+		if m.Indent != "" {
+			out.write(indent)
+			out.write(m.Indent)
+			out.write(`"value": `)
+		} else {
+			out.write(`"value":`)
+		}
+		if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil {
+			return err
+		}
+		if m.Indent != "" {
+			out.write("\n")
+			out.write(indent)
+		}
+		out.write("}")
+		return out.err
+	}
+
+	return m.marshalObject(out, msg, indent, turl)
+}
+
+func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error {
+	if m.Indent != "" {
+		out.write(indent)
+		out.write(m.Indent)
+	}
+	out.write(`"@type":`)
+	if m.Indent != "" {
+		out.write(" ")
+	}
+	b, err := json.Marshal(typeURL)
+	if err != nil {
+		return err
+	}
+	out.write(string(b))
+	return out.err
+}
+
+// marshalField writes field description and value to the Writer.
+func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
+	if m.Indent != "" {
+		out.write(indent)
+		out.write(m.Indent)
+	}
+	out.write(`"`)
+	out.write(prop.JSONName)
+	out.write(`":`)
+	if m.Indent != "" {
+		out.write(" ")
+	}
+	if err := m.marshalValue(out, prop, v, indent); err != nil {
+		return err
+	}
+	return nil
+}
+
+// marshalValue writes the value to the Writer.
+func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
+	var err error
+	v = reflect.Indirect(v)
+
+	// Handle nil pointer
+	if v.Kind() == reflect.Invalid {
+		out.write("null")
+		return out.err
+	}
+
+	// Handle repeated elements.
+	if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
+		out.write("[")
+		comma := ""
+		for i := 0; i < v.Len(); i++ {
+			sliceVal := v.Index(i)
+			out.write(comma)
+			if m.Indent != "" {
+				out.write("\n")
+				out.write(indent)
+				out.write(m.Indent)
+				out.write(m.Indent)
+			}
+			if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil {
+				return err
+			}
+			comma = ","
+		}
+		if m.Indent != "" {
+			out.write("\n")
+			out.write(indent)
+			out.write(m.Indent)
+		}
+		out.write("]")
+		return out.err
+	}
+
+	// Handle well-known types.
+	// Most are handled up in marshalObject (because 99% are messages).
+	if v.Type().Implements(wktType) {
+		wkt := v.Interface().(wkt)
+		switch wkt.XXX_WellKnownType() {
+		case "NullValue":
+			out.write("null")
+			return out.err
+		}
+	}
+
+	// Handle enumerations.
+	if !m.EnumsAsInts && prop.Enum != "" {
+		// Unknown enum values will are stringified by the proto library as their
+		// value. Such values should _not_ be quoted or they will be interpreted
+		// as an enum string instead of their value.
+		enumStr := v.Interface().(fmt.Stringer).String()
+		var valStr string
+		if v.Kind() == reflect.Ptr {
+			valStr = strconv.Itoa(int(v.Elem().Int()))
+		} else {
+			valStr = strconv.Itoa(int(v.Int()))
+		}
+		isKnownEnum := enumStr != valStr
+		if isKnownEnum {
+			out.write(`"`)
+		}
+		out.write(enumStr)
+		if isKnownEnum {
+			out.write(`"`)
+		}
+		return out.err
+	}
+
+	// Handle nested messages.
+	if v.Kind() == reflect.Struct {
+		return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent, "")
+	}
+
+	// Handle maps.
+	// Since Go randomizes map iteration, we sort keys for stable output.
+	if v.Kind() == reflect.Map {
+		out.write(`{`)
+		keys := v.MapKeys()
+		sort.Sort(mapKeys(keys))
+		for i, k := range keys {
+			if i > 0 {
+				out.write(`,`)
+			}
+			if m.Indent != "" {
+				out.write("\n")
+				out.write(indent)
+				out.write(m.Indent)
+				out.write(m.Indent)
+			}
+
+			// TODO handle map key prop properly
+			b, err := json.Marshal(k.Interface())
+			if err != nil {
+				return err
+			}
+			s := string(b)
+
+			// If the JSON is not a string value, encode it again to make it one.
+			if !strings.HasPrefix(s, `"`) {
+				b, err := json.Marshal(s)
+				if err != nil {
+					return err
+				}
+				s = string(b)
+			}
+
+			out.write(s)
+			out.write(`:`)
+			if m.Indent != "" {
+				out.write(` `)
+			}
+
+			vprop := prop
+			if prop != nil && prop.MapValProp != nil {
+				vprop = prop.MapValProp
+			}
+			if err := m.marshalValue(out, vprop, v.MapIndex(k), indent+m.Indent); err != nil {
+				return err
+			}
+		}
+		if m.Indent != "" {
+			out.write("\n")
+			out.write(indent)
+			out.write(m.Indent)
+		}
+		out.write(`}`)
+		return out.err
+	}
+
+	// Handle non-finite floats, e.g. NaN, Infinity and -Infinity.
+	if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
+		f := v.Float()
+		var sval string
+		switch {
+		case math.IsInf(f, 1):
+			sval = `"Infinity"`
+		case math.IsInf(f, -1):
+			sval = `"-Infinity"`
+		case math.IsNaN(f):
+			sval = `"NaN"`
+		}
+		if sval != "" {
+			out.write(sval)
+			return out.err
+		}
+	}
+
+	// Default handling defers to the encoding/json library.
+	b, err := json.Marshal(v.Interface())
+	if err != nil {
+		return err
+	}
+	needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64)
+	if needToQuote {
+		out.write(`"`)
+	}
+	out.write(string(b))
+	if needToQuote {
+		out.write(`"`)
+	}
+	return out.err
+}
+
+// Unmarshaler is a configurable object for converting from a JSON
+// representation to a protocol buffer object.
+type Unmarshaler struct {
+	// Whether to allow messages to contain unknown fields, as opposed to
+	// failing to unmarshal.
+	AllowUnknownFields bool
+
+	// A custom URL resolver to use when unmarshaling Any messages from JSON.
+	// If unset, the default resolution strategy is to extract the
+	// fully-qualified type name from the type URL and pass that to
+	// proto.MessageType(string).
+	AnyResolver AnyResolver
+}
+
+// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
+// This function is lenient and will decode any options permutations of the
+// related Marshaler.
+func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
+	inputValue := json.RawMessage{}
+	if err := dec.Decode(&inputValue); err != nil {
+		return err
+	}
+	if err := u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil); err != nil {
+		return err
+	}
+	return checkRequiredFields(pb)
+}
+
+// Unmarshal unmarshals a JSON object stream into a protocol
+// buffer. This function is lenient and will decode any options
+// permutations of the related Marshaler.
+func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error {
+	dec := json.NewDecoder(r)
+	return u.UnmarshalNext(dec, pb)
+}
+
+// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
+// This function is lenient and will decode any options permutations of the
+// related Marshaler.
+func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
+	return new(Unmarshaler).UnmarshalNext(dec, pb)
+}
+
+// Unmarshal unmarshals a JSON object stream into a protocol
+// buffer. This function is lenient and will decode any options
+// permutations of the related Marshaler.
+func Unmarshal(r io.Reader, pb proto.Message) error {
+	return new(Unmarshaler).Unmarshal(r, pb)
+}
+
+// UnmarshalString will populate the fields of a protocol buffer based
+// on a JSON string. This function is lenient and will decode any options
+// permutations of the related Marshaler.
+func UnmarshalString(str string, pb proto.Message) error {
+	return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb)
+}
+
+// unmarshalValue converts/copies a value into the target.
+// prop may be nil.
+func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error {
+	targetType := target.Type()
+
+	// Allocate memory for pointer fields.
+	if targetType.Kind() == reflect.Ptr {
+		// If input value is "null" and target is a pointer type, then the field should be treated as not set
+		// UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue.
+		_, isJSONPBUnmarshaler := target.Interface().(JSONPBUnmarshaler)
+		if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) && !isJSONPBUnmarshaler {
+			return nil
+		}
+		target.Set(reflect.New(targetType.Elem()))
+
+		return u.unmarshalValue(target.Elem(), inputValue, prop)
+	}
+
+	if jsu, ok := target.Addr().Interface().(JSONPBUnmarshaler); ok {
+		return jsu.UnmarshalJSONPB(u, []byte(inputValue))
+	}
+
+	// Handle well-known types that are not pointers.
+	if w, ok := target.Addr().Interface().(wkt); ok {
+		switch w.XXX_WellKnownType() {
+		case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
+			"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
+			return u.unmarshalValue(target.Field(0), inputValue, prop)
+		case "Any":
+			// Use json.RawMessage pointer type instead of value to support pre-1.8 version.
+			// 1.8 changed RawMessage.MarshalJSON from pointer type to value type, see
+			// https://github.com/golang/go/issues/14493
+			var jsonFields map[string]*json.RawMessage
+			if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
+				return err
+			}
+
+			val, ok := jsonFields["@type"]
+			if !ok || val == nil {
+				return errors.New("Any JSON doesn't have '@type'")
+			}
+
+			var turl string
+			if err := json.Unmarshal([]byte(*val), &turl); err != nil {
+				return fmt.Errorf("can't unmarshal Any's '@type': %q", *val)
+			}
+			target.Field(0).SetString(turl)
+
+			var m proto.Message
+			var err error
+			if u.AnyResolver != nil {
+				m, err = u.AnyResolver.Resolve(turl)
+			} else {
+				m, err = defaultResolveAny(turl)
+			}
+			if err != nil {
+				return err
+			}
+
+			if _, ok := m.(wkt); ok {
+				val, ok := jsonFields["value"]
+				if !ok {
+					return errors.New("Any JSON doesn't have 'value'")
+				}
+
+				if err := u.unmarshalValue(reflect.ValueOf(m).Elem(), *val, nil); err != nil {
+					return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err)
+				}
+			} else {
+				delete(jsonFields, "@type")
+				nestedProto, err := json.Marshal(jsonFields)
+				if err != nil {
+					return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err)
+				}
+
+				if err = u.unmarshalValue(reflect.ValueOf(m).Elem(), nestedProto, nil); err != nil {
+					return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err)
+				}
+			}
+
+			b, err := proto.Marshal(m)
+			if err != nil {
+				return fmt.Errorf("can't marshal proto %T into Any.Value: %v", m, err)
+			}
+			target.Field(1).SetBytes(b)
+
+			return nil
+		case "Duration":
+			unq, err := unquote(string(inputValue))
+			if err != nil {
+				return err
+			}
+
+			d, err := time.ParseDuration(unq)
+			if err != nil {
+				return fmt.Errorf("bad Duration: %v", err)
+			}
+
+			ns := d.Nanoseconds()
+			s := ns / 1e9
+			ns %= 1e9
+			target.Field(0).SetInt(s)
+			target.Field(1).SetInt(ns)
+			return nil
+		case "Timestamp":
+			unq, err := unquote(string(inputValue))
+			if err != nil {
+				return err
+			}
+
+			t, err := time.Parse(time.RFC3339Nano, unq)
+			if err != nil {
+				return fmt.Errorf("bad Timestamp: %v", err)
+			}
+
+			target.Field(0).SetInt(t.Unix())
+			target.Field(1).SetInt(int64(t.Nanosecond()))
+			return nil
+		case "Struct":
+			var m map[string]json.RawMessage
+			if err := json.Unmarshal(inputValue, &m); err != nil {
+				return fmt.Errorf("bad StructValue: %v", err)
+			}
+
+			target.Field(0).Set(reflect.ValueOf(map[string]*stpb.Value{}))
+			for k, jv := range m {
+				pv := &stpb.Value{}
+				if err := u.unmarshalValue(reflect.ValueOf(pv).Elem(), jv, prop); err != nil {
+					return fmt.Errorf("bad value in StructValue for key %q: %v", k, err)
+				}
+				target.Field(0).SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(pv))
+			}
+			return nil
+		case "ListValue":
+			var s []json.RawMessage
+			if err := json.Unmarshal(inputValue, &s); err != nil {
+				return fmt.Errorf("bad ListValue: %v", err)
+			}
+
+			target.Field(0).Set(reflect.ValueOf(make([]*stpb.Value, len(s))))
+			for i, sv := range s {
+				if err := u.unmarshalValue(target.Field(0).Index(i), sv, prop); err != nil {
+					return err
+				}
+			}
+			return nil
+		case "Value":
+			ivStr := string(inputValue)
+			if ivStr == "null" {
+				target.Field(0).Set(reflect.ValueOf(&stpb.Value_NullValue{}))
+			} else if v, err := strconv.ParseFloat(ivStr, 0); err == nil {
+				target.Field(0).Set(reflect.ValueOf(&stpb.Value_NumberValue{v}))
+			} else if v, err := unquote(ivStr); err == nil {
+				target.Field(0).Set(reflect.ValueOf(&stpb.Value_StringValue{v}))
+			} else if v, err := strconv.ParseBool(ivStr); err == nil {
+				target.Field(0).Set(reflect.ValueOf(&stpb.Value_BoolValue{v}))
+			} else if err := json.Unmarshal(inputValue, &[]json.RawMessage{}); err == nil {
+				lv := &stpb.ListValue{}
+				target.Field(0).Set(reflect.ValueOf(&stpb.Value_ListValue{lv}))
+				return u.unmarshalValue(reflect.ValueOf(lv).Elem(), inputValue, prop)
+			} else if err := json.Unmarshal(inputValue, &map[string]json.RawMessage{}); err == nil {
+				sv := &stpb.Struct{}
+				target.Field(0).Set(reflect.ValueOf(&stpb.Value_StructValue{sv}))
+				return u.unmarshalValue(reflect.ValueOf(sv).Elem(), inputValue, prop)
+			} else {
+				return fmt.Errorf("unrecognized type for Value %q", ivStr)
+			}
+			return nil
+		}
+	}
+
+	// Handle enums, which have an underlying type of int32,
+	// and may appear as strings.
+	// The case of an enum appearing as a number is handled
+	// at the bottom of this function.
+	if inputValue[0] == '"' && prop != nil && prop.Enum != "" {
+		vmap := proto.EnumValueMap(prop.Enum)
+		// Don't need to do unquoting; valid enum names
+		// are from a limited character set.
+		s := inputValue[1 : len(inputValue)-1]
+		n, ok := vmap[string(s)]
+		if !ok {
+			return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum)
+		}
+		if target.Kind() == reflect.Ptr { // proto2
+			target.Set(reflect.New(targetType.Elem()))
+			target = target.Elem()
+		}
+		if targetType.Kind() != reflect.Int32 {
+			return fmt.Errorf("invalid target %q for enum %s", targetType.Kind(), prop.Enum)
+		}
+		target.SetInt(int64(n))
+		return nil
+	}
+
+	// Handle nested messages.
+	if targetType.Kind() == reflect.Struct {
+		var jsonFields map[string]json.RawMessage
+		if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
+			return err
+		}
+
+		consumeField := func(prop *proto.Properties) (json.RawMessage, bool) {
+			// Be liberal in what names we accept; both orig_name and camelName are okay.
+			fieldNames := acceptedJSONFieldNames(prop)
+
+			vOrig, okOrig := jsonFields[fieldNames.orig]
+			vCamel, okCamel := jsonFields[fieldNames.camel]
+			if !okOrig && !okCamel {
+				return nil, false
+			}
+			// If, for some reason, both are present in the data, favour the camelName.
+			var raw json.RawMessage
+			if okOrig {
+				raw = vOrig
+				delete(jsonFields, fieldNames.orig)
+			}
+			if okCamel {
+				raw = vCamel
+				delete(jsonFields, fieldNames.camel)
+			}
+			return raw, true
+		}
+
+		sprops := proto.GetProperties(targetType)
+		for i := 0; i < target.NumField(); i++ {
+			ft := target.Type().Field(i)
+			if strings.HasPrefix(ft.Name, "XXX_") {
+				continue
+			}
+
+			valueForField, ok := consumeField(sprops.Prop[i])
+			if !ok {
+				continue
+			}
+
+			if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil {
+				return err
+			}
+		}
+		// Check for any oneof fields.
+		if len(jsonFields) > 0 {
+			for _, oop := range sprops.OneofTypes {
+				raw, ok := consumeField(oop.Prop)
+				if !ok {
+					continue
+				}
+				nv := reflect.New(oop.Type.Elem())
+				target.Field(oop.Field).Set(nv)
+				if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {
+					return err
+				}
+			}
+		}
+		// Handle proto2 extensions.
+		if len(jsonFields) > 0 {
+			if ep, ok := target.Addr().Interface().(proto.Message); ok {
+				for _, ext := range proto.RegisteredExtensions(ep) {
+					name := fmt.Sprintf("[%s]", ext.Name)
+					raw, ok := jsonFields[name]
+					if !ok {
+						continue
+					}
+					delete(jsonFields, name)
+					nv := reflect.New(reflect.TypeOf(ext.ExtensionType).Elem())
+					if err := u.unmarshalValue(nv.Elem(), raw, nil); err != nil {
+						return err
+					}
+					if err := proto.SetExtension(ep, ext, nv.Interface()); err != nil {
+						return err
+					}
+				}
+			}
+		}
+		if !u.AllowUnknownFields && len(jsonFields) > 0 {
+			// Pick any field to be the scapegoat.
+			var f string
+			for fname := range jsonFields {
+				f = fname
+				break
+			}
+			return fmt.Errorf("unknown field %q in %v", f, targetType)
+		}
+		return nil
+	}
+
+	// Handle arrays (which aren't encoded bytes)
+	if targetType.Kind() == reflect.Slice && targetType.Elem().Kind() != reflect.Uint8 {
+		var slc []json.RawMessage
+		if err := json.Unmarshal(inputValue, &slc); err != nil {
+			return err
+		}
+		if slc != nil {
+			l := len(slc)
+			target.Set(reflect.MakeSlice(targetType, l, l))
+			for i := 0; i < l; i++ {
+				if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil {
+					return err
+				}
+			}
+		}
+		return nil
+	}
+
+	// Handle maps (whose keys are always strings)
+	if targetType.Kind() == reflect.Map {
+		var mp map[string]json.RawMessage
+		if err := json.Unmarshal(inputValue, &mp); err != nil {
+			return err
+		}
+		if mp != nil {
+			target.Set(reflect.MakeMap(targetType))
+			for ks, raw := range mp {
+				// Unmarshal map key. The core json library already decoded the key into a
+				// string, so we handle that specially. Other types were quoted post-serialization.
+				var k reflect.Value
+				if targetType.Key().Kind() == reflect.String {
+					k = reflect.ValueOf(ks)
+				} else {
+					k = reflect.New(targetType.Key()).Elem()
+					var kprop *proto.Properties
+					if prop != nil && prop.MapKeyProp != nil {
+						kprop = prop.MapKeyProp
+					}
+					if err := u.unmarshalValue(k, json.RawMessage(ks), kprop); err != nil {
+						return err
+					}
+				}
+
+				// Unmarshal map value.
+				v := reflect.New(targetType.Elem()).Elem()
+				var vprop *proto.Properties
+				if prop != nil && prop.MapValProp != nil {
+					vprop = prop.MapValProp
+				}
+				if err := u.unmarshalValue(v, raw, vprop); err != nil {
+					return err
+				}
+				target.SetMapIndex(k, v)
+			}
+		}
+		return nil
+	}
+
+	// Non-finite numbers can be encoded as strings.
+	isFloat := targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64
+	if isFloat {
+		if num, ok := nonFinite[string(inputValue)]; ok {
+			target.SetFloat(num)
+			return nil
+		}
+	}
+
+	// integers & floats can be encoded as strings. In this case we drop
+	// the quotes and proceed as normal.
+	isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64 ||
+		targetType.Kind() == reflect.Int32 || targetType.Kind() == reflect.Uint32 ||
+		targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64
+	if isNum && strings.HasPrefix(string(inputValue), `"`) {
+		inputValue = inputValue[1 : len(inputValue)-1]
+	}
+
+	// Use the encoding/json for parsing other value types.
+	return json.Unmarshal(inputValue, target.Addr().Interface())
+}
+
+func unquote(s string) (string, error) {
+	var ret string
+	err := json.Unmarshal([]byte(s), &ret)
+	return ret, err
+}
+
+// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute.
+func jsonProperties(f reflect.StructField, origName bool) *proto.Properties {
+	var prop proto.Properties
+	prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
+	if origName || prop.JSONName == "" {
+		prop.JSONName = prop.OrigName
+	}
+	return &prop
+}
+
+type fieldNames struct {
+	orig, camel string
+}
+
+func acceptedJSONFieldNames(prop *proto.Properties) fieldNames {
+	opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName}
+	if prop.JSONName != "" {
+		opts.camel = prop.JSONName
+	}
+	return opts
+}
+
+// Writer wrapper inspired by https://blog.golang.org/errors-are-values
+type errWriter struct {
+	writer io.Writer
+	err    error
+}
+
+func (w *errWriter) write(str string) {
+	if w.err != nil {
+		return
+	}
+	_, w.err = w.writer.Write([]byte(str))
+}
+
+// Map fields may have key types of non-float scalars, strings and enums.
+// The easiest way to sort them in some deterministic order is to use fmt.
+// If this turns out to be inefficient we can always consider other options,
+// such as doing a Schwartzian transform.
+//
+// Numeric keys are sorted in numeric order per
+// https://developers.google.com/protocol-buffers/docs/proto#maps.
+type mapKeys []reflect.Value
+
+func (s mapKeys) Len() int      { return len(s) }
+func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s mapKeys) Less(i, j int) bool {
+	if k := s[i].Kind(); k == s[j].Kind() {
+		switch k {
+		case reflect.String:
+			return s[i].String() < s[j].String()
+		case reflect.Int32, reflect.Int64:
+			return s[i].Int() < s[j].Int()
+		case reflect.Uint32, reflect.Uint64:
+			return s[i].Uint() < s[j].Uint()
+		}
+	}
+	return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
+}
+
+// checkRequiredFields returns an error if any required field in the given proto message is not set.
+// This function is used by both Marshal and Unmarshal.  While required fields only exist in a
+// proto2 message, a proto3 message can contain proto2 message(s).
+func checkRequiredFields(pb proto.Message) error {
+	// Most well-known type messages do not contain required fields.  The "Any" type may contain
+	// a message that has required fields.
+	//
+	// When an Any message is being marshaled, the code will invoked proto.Unmarshal on Any.Value
+	// field in order to transform that into JSON, and that should have returned an error if a
+	// required field is not set in the embedded message.
+	//
+	// When an Any message is being unmarshaled, the code will have invoked proto.Marshal on the
+	// embedded message to store the serialized message in Any.Value field, and that should have
+	// returned an error if a required field is not set.
+	if _, ok := pb.(wkt); ok {
+		return nil
+	}
+
+	v := reflect.ValueOf(pb)
+	// Skip message if it is not a struct pointer.
+	if v.Kind() != reflect.Ptr {
+		return nil
+	}
+	v = v.Elem()
+	if v.Kind() != reflect.Struct {
+		return nil
+	}
+
+	for i := 0; i < v.NumField(); i++ {
+		field := v.Field(i)
+		sfield := v.Type().Field(i)
+
+		if sfield.PkgPath != "" {
+			// blank PkgPath means the field is exported; skip if not exported
+			continue
+		}
+
+		if strings.HasPrefix(sfield.Name, "XXX_") {
+			continue
+		}
+
+		// Oneof field is an interface implemented by wrapper structs containing the actual oneof
+		// field, i.e. an interface containing &T{real_value}.
+		if sfield.Tag.Get("protobuf_oneof") != "" {
+			if field.Kind() != reflect.Interface {
+				continue
+			}
+			v := field.Elem()
+			if v.Kind() != reflect.Ptr || v.IsNil() {
+				continue
+			}
+			v = v.Elem()
+			if v.Kind() != reflect.Struct || v.NumField() < 1 {
+				continue
+			}
+			field = v.Field(0)
+			sfield = v.Type().Field(0)
+		}
+
+		protoTag := sfield.Tag.Get("protobuf")
+		if protoTag == "" {
+			continue
+		}
+		var prop proto.Properties
+		prop.Init(sfield.Type, sfield.Name, protoTag, &sfield)
+
+		switch field.Kind() {
+		case reflect.Map:
+			if field.IsNil() {
+				continue
+			}
+			// Check each map value.
+			keys := field.MapKeys()
+			for _, k := range keys {
+				v := field.MapIndex(k)
+				if err := checkRequiredFieldsInValue(v); err != nil {
+					return err
+				}
+			}
+		case reflect.Slice:
+			// Handle non-repeated type, e.g. bytes.
+			if !prop.Repeated {
+				if prop.Required && field.IsNil() {
+					return fmt.Errorf("required field %q is not set", prop.Name)
+				}
+				continue
+			}
+
+			// Handle repeated type.
+			if field.IsNil() {
+				continue
+			}
+			// Check each slice item.
+			for i := 0; i < field.Len(); i++ {
+				v := field.Index(i)
+				if err := checkRequiredFieldsInValue(v); err != nil {
+					return err
+				}
+			}
+		case reflect.Ptr:
+			if field.IsNil() {
+				if prop.Required {
+					return fmt.Errorf("required field %q is not set", prop.Name)
+				}
+				continue
+			}
+			if err := checkRequiredFieldsInValue(field); err != nil {
+				return err
+			}
+		}
+	}
+
+	// Handle proto2 extensions.
+	for _, ext := range proto.RegisteredExtensions(pb) {
+		if !proto.HasExtension(pb, ext) {
+			continue
+		}
+		ep, err := proto.GetExtension(pb, ext)
+		if err != nil {
+			return err
+		}
+		err = checkRequiredFieldsInValue(reflect.ValueOf(ep))
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func checkRequiredFieldsInValue(v reflect.Value) error {
+	if v.Type().Implements(messageType) {
+		return checkRequiredFields(v.Interface().(proto.Message))
+	}
+	return nil
+}
diff --git a/vendor/github.com/mitchellh/hashstructure/go.mod b/vendor/github.com/mitchellh/hashstructure/go.mod
new file mode 100644
index 0000000..966582a
--- /dev/null
+++ b/vendor/github.com/mitchellh/hashstructure/go.mod
@@ -0,0 +1 @@
+module github.com/mitchellh/hashstructure
diff --git a/vendor/github.com/moby/buildkit/README.md b/vendor/github.com/moby/buildkit/README.md
index 19d7325..4532dd7 100644
--- a/vendor/github.com/moby/buildkit/README.md
+++ b/vendor/github.com/moby/buildkit/README.md
@@ -3,8 +3,9 @@
 # BuildKit
 
 [![GoDoc](https://godoc.org/github.com/moby/buildkit?status.svg)](https://godoc.org/github.com/moby/buildkit/client/llb)
-[![Build Status](https://travis-ci.org/moby/buildkit.svg?branch=master)](https://travis-ci.org/moby/buildkit)
+[![Build Status](https://travis-ci.com/moby/buildkit.svg?branch=master)](https://travis-ci.com/moby/buildkit)
 [![Go Report Card](https://goreportcard.com/badge/github.com/moby/buildkit)](https://goreportcard.com/report/github.com/moby/buildkit)
+[![codecov](https://codecov.io/gh/moby/buildkit/branch/master/graph/badge.svg)](https://codecov.io/gh/moby/buildkit)
 
 BuildKit is a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner.
 
@@ -62,6 +63,7 @@
 - [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service)
   - [Load balancing](#load-balancing)
 - [Containerizing BuildKit](#containerizing-buildkit)
+  - [Podman](#podman)
   - [Kubernetes](#kubernetes)
   - [Daemonless](#daemonless)
 - [Opentracing support](#opentracing-support)
@@ -127,11 +129,6 @@
 The buildkitd daemon listens gRPC API on `/run/buildkit/buildkitd.sock` by default, but you can also use TCP sockets.
 See [Expose BuildKit as a TCP service](#expose-buildkit-as-a-tcp-service).
 
-:information_source: Notice to Fedora 31 users:
-
-* As runc still does not work on cgroup v2 environment like Fedora 31, you need to substitute runc with crun. Run `buildkitd` with `--oci-worker-binary=crun`.
-* If you want to use runc, you need to configure the system to use cgroup v1. Run `sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0"` and reboot.
-
 ### Exploring LLB
 
 BuildKit builds are based on a binary intermediate format called LLB that is used for defining the dependency graph for processes running part of your build. tl;dr: LLB is to Dockerfile what LLVM IR is to C.
@@ -150,6 +147,9 @@
 -   [Mockerfile](https://matt-rickard.com/building-a-new-dockerfile-frontend/)
 -   [Gockerfile](https://github.com/po3rin/gockerfile)
 -   [bldr (Pkgfile)](https://github.com/talos-systems/bldr/)
+-   [HLB](https://github.com/openllb/hlb)
+-   [Earthfile (Earthly)](https://github.com/earthly/earthly)
+-   [Cargo Wharf (Rust)](https://github.com/denzp/cargo-wharf)
 -   (open a PR to add your own language)
 
 ### Exploring Dockerfiles
@@ -353,6 +353,7 @@
 -   `mode=max`: export all the layers of all intermediate steps. Not supported for `inline` cache exporter.
 -   `ref=docker.io/user/image:tag`: reference for `registry` cache exporter
 -   `dest=path/to/output-dir`: directory for `local` cache exporter
+-   `oci-mediatypes=true|false`: whether to use OCI mediatypes in exported manifests for `local` and `registry` exporter. Since BuildKit `v0.8` defaults to true.
 
 #### `--import-cache` options
 -   `type`: `registry` or `local`. Use `registry` to import `inline` cache.
@@ -418,6 +419,16 @@
 buildctl build --help
 ```
 
+### Podman
+To connect to a BuildKit daemon running in a Podman container, use `podman-container://` instead of `docker-container://` .
+
+```bash
+podman run -d --name buildkitd --privileged moby/buildkit:latest
+buildctl --addr=podman-container://buildkitd build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=oci | podman load foo
+```
+
+`sudo` is not required.
+
 ### Kubernetes
 
 For Kubernetes deployments, see [`examples/kubernetes`](./examples/kubernetes).
diff --git a/vendor/github.com/moby/buildkit/api/services/control/generate.go b/vendor/github.com/moby/buildkit/api/services/control/generate.go
index 1c16115..9a3b246 100644
--- a/vendor/github.com/moby/buildkit/api/services/control/generate.go
+++ b/vendor/github.com/moby/buildkit/api/services/control/generate.go
@@ -1,3 +1,3 @@
-package moby_buildkit_v1
+package moby_buildkit_v1 //nolint:golint
 
 //go:generate protoc -I=. -I=../../../vendor/ -I=../../../../../../ --gogo_out=plugins=grpc:. control.proto
diff --git a/vendor/github.com/moby/buildkit/api/types/generate.go b/vendor/github.com/moby/buildkit/api/types/generate.go
index 84007df..984bb74 100644
--- a/vendor/github.com/moby/buildkit/api/types/generate.go
+++ b/vendor/github.com/moby/buildkit/api/types/generate.go
@@ -1,3 +1,3 @@
-package moby_buildkit_v1_types
+package moby_buildkit_v1_types //nolint:golint
 
 //go:generate protoc -I=. -I=../../vendor/ -I=../../../../../ --gogo_out=plugins=grpc:. worker.proto
diff --git a/vendor/github.com/moby/buildkit/cache/blobs.go b/vendor/github.com/moby/buildkit/cache/blobs.go
new file mode 100644
index 0000000..d3648b1
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/cache/blobs.go
@@ -0,0 +1,236 @@
+package cache
+
+import (
+	"context"
+
+	"github.com/containerd/containerd/diff"
+	"github.com/containerd/containerd/leases"
+	"github.com/containerd/containerd/mount"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/util/compression"
+	"github.com/moby/buildkit/util/flightcontrol"
+	"github.com/moby/buildkit/util/winlayers"
+	digest "github.com/opencontainers/go-digest"
+	imagespecidentity "github.com/opencontainers/image-spec/identity"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"golang.org/x/sync/errgroup"
+)
+
+var g flightcontrol.Group
+
+const containerdUncompressed = "containerd.io/uncompressed"
+
+type CompareWithParent interface {
+	CompareWithParent(ctx context.Context, ref string, opts ...diff.Opt) (ocispec.Descriptor, error)
+}
+
+var ErrNoBlobs = errors.Errorf("no blobs for snapshot")
+
+// computeBlobChain ensures every ref in a parent chain has an associated blob in the content store. If
+// a blob is missing and createIfNeeded is true, then the blob will be created, otherwise ErrNoBlobs will
+// be returned. Caller must hold a lease when calling this function.
+func (sr *immutableRef) computeBlobChain(ctx context.Context, createIfNeeded bool, compressionType compression.Type, s session.Group) error {
+	if _, ok := leases.FromContext(ctx); !ok {
+		return errors.Errorf("missing lease requirement for computeBlobChain")
+	}
+
+	if err := sr.Finalize(ctx, true); err != nil {
+		return err
+	}
+
+	if isTypeWindows(sr) {
+		ctx = winlayers.UseWindowsLayerMode(ctx)
+	}
+
+	return computeBlobChain(ctx, sr, createIfNeeded, compressionType, s)
+}
+
+func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool, compressionType compression.Type, s session.Group) error {
+	baseCtx := ctx
+	eg, ctx := errgroup.WithContext(ctx)
+	var currentDescr ocispec.Descriptor
+	if sr.parent != nil {
+		eg.Go(func() error {
+			return computeBlobChain(ctx, sr.parent, createIfNeeded, compressionType, s)
+		})
+	}
+	eg.Go(func() error {
+		dp, err := g.Do(ctx, sr.ID(), func(ctx context.Context) (interface{}, error) {
+			refInfo := sr.Info()
+			if refInfo.Blob != "" {
+				return nil, nil
+			} else if !createIfNeeded {
+				return nil, errors.WithStack(ErrNoBlobs)
+			}
+
+			var mediaType string
+			switch compressionType {
+			case compression.Uncompressed:
+				mediaType = ocispec.MediaTypeImageLayer
+			case compression.Gzip:
+				mediaType = ocispec.MediaTypeImageLayerGzip
+			default:
+				return nil, errors.Errorf("unknown layer compression type: %q", compressionType)
+			}
+
+			var descr ocispec.Descriptor
+			var err error
+
+			if pc, ok := sr.cm.Differ.(CompareWithParent); ok {
+				descr, err = pc.CompareWithParent(ctx, sr.ID(), diff.WithMediaType(mediaType))
+				if err != nil {
+					return nil, err
+				}
+			}
+			if descr.Digest == "" {
+				// reference needs to be committed
+				var lower []mount.Mount
+				if sr.parent != nil {
+					m, err := sr.parent.Mount(ctx, true, s)
+					if err != nil {
+						return nil, err
+					}
+					var release func() error
+					lower, release, err = m.Mount()
+					if err != nil {
+						return nil, err
+					}
+					if release != nil {
+						defer release()
+					}
+				}
+				m, err := sr.Mount(ctx, true, s)
+				if err != nil {
+					return nil, err
+				}
+				upper, release, err := m.Mount()
+				if err != nil {
+					return nil, err
+				}
+				if release != nil {
+					defer release()
+				}
+				descr, err = sr.cm.Differ.Compare(ctx, lower, upper,
+					diff.WithMediaType(mediaType),
+					diff.WithReference(sr.ID()),
+				)
+				if err != nil {
+					return nil, err
+				}
+			}
+
+			if descr.Annotations == nil {
+				descr.Annotations = map[string]string{}
+			}
+
+			info, err := sr.cm.ContentStore.Info(ctx, descr.Digest)
+			if err != nil {
+				return nil, err
+			}
+
+			if diffID, ok := info.Labels[containerdUncompressed]; ok {
+				descr.Annotations[containerdUncompressed] = diffID
+			} else if compressionType == compression.Uncompressed {
+				descr.Annotations[containerdUncompressed] = descr.Digest.String()
+			} else {
+				return nil, errors.Errorf("unknown layer compression type")
+			}
+
+			return descr, nil
+
+		})
+		if err != nil {
+			return err
+		}
+
+		if dp != nil {
+			currentDescr = dp.(ocispec.Descriptor)
+		}
+		return nil
+	})
+	err := eg.Wait()
+	if err != nil {
+		return err
+	}
+	if currentDescr.Digest != "" {
+		if err := sr.setBlob(baseCtx, currentDescr); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// setBlob associates a blob with the cache record.
+// A lease must be held for the blob when calling this function
+// Caller should call Info() for knowing what current values are actually set
+func (sr *immutableRef) setBlob(ctx context.Context, desc ocispec.Descriptor) error {
+	if _, ok := leases.FromContext(ctx); !ok {
+		return errors.Errorf("missing lease requirement for setBlob")
+	}
+
+	diffID, err := diffIDFromDescriptor(desc)
+	if err != nil {
+		return err
+	}
+	if _, err := sr.cm.ContentStore.Info(ctx, desc.Digest); err != nil {
+		return err
+	}
+
+	sr.mu.Lock()
+	defer sr.mu.Unlock()
+
+	if getChainID(sr.md) != "" {
+		return nil
+	}
+
+	if err := sr.finalize(ctx, true); err != nil {
+		return err
+	}
+
+	p := sr.parent
+	var parentChainID digest.Digest
+	var parentBlobChainID digest.Digest
+	if p != nil {
+		pInfo := p.Info()
+		if pInfo.ChainID == "" || pInfo.BlobChainID == "" {
+			return errors.Errorf("failed to set blob for reference with non-addressable parent")
+		}
+		parentChainID = pInfo.ChainID
+		parentBlobChainID = pInfo.BlobChainID
+	}
+
+	if err := sr.cm.LeaseManager.AddResource(ctx, leases.Lease{ID: sr.ID()}, leases.Resource{
+		ID:   desc.Digest.String(),
+		Type: "content",
+	}); err != nil {
+		return err
+	}
+
+	queueDiffID(sr.md, diffID.String())
+	queueBlob(sr.md, desc.Digest.String())
+	chainID := diffID
+	blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
+	if parentChainID != "" {
+		chainID = imagespecidentity.ChainID([]digest.Digest{parentChainID, chainID})
+		blobChainID = imagespecidentity.ChainID([]digest.Digest{parentBlobChainID, blobChainID})
+	}
+	queueChainID(sr.md, chainID.String())
+	queueBlobChainID(sr.md, blobChainID.String())
+	queueMediaType(sr.md, desc.MediaType)
+	queueBlobSize(sr.md, desc.Size)
+	if err := sr.md.Commit(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func isTypeWindows(sr *immutableRef) bool {
+	if GetLayerType(sr) == "windows" {
+		return true
+	}
+	if parent := sr.parent; parent != nil {
+		return isTypeWindows(parent)
+	}
+	return false
+}
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
index 5d42d04..a8335ea 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
@@ -11,12 +11,13 @@
 	"sync"
 
 	"github.com/docker/docker/pkg/idtools"
-	"github.com/docker/docker/pkg/locker"
 	iradix "github.com/hashicorp/go-immutable-radix"
 	"github.com/hashicorp/golang-lru/simplelru"
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/cache/metadata"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/locker"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil"
@@ -44,12 +45,12 @@
 // header, "/dir" is for contents. For the root node "" (empty string) is the
 // key for root, "/" for the root header
 
-func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
-	return getDefaultManager().Checksum(ctx, ref, path, followLinks)
+func Checksum(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool, s session.Group) (digest.Digest, error) {
+	return getDefaultManager().Checksum(ctx, ref, path, followLinks, s)
 }
 
-func ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool) (digest.Digest, error) {
-	return getDefaultManager().ChecksumWildcard(ctx, ref, path, followLinks)
+func ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, path string, followLinks bool, s session.Group) (digest.Digest, error) {
+	return getDefaultManager().ChecksumWildcard(ctx, ref, path, followLinks, s)
 }
 
 func GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
@@ -65,8 +66,8 @@
 }
 
 type CacheContext interface {
-	Checksum(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
-	ChecksumWildcard(ctx context.Context, ref cache.Mountable, p string, followLinks bool) (digest.Digest, error)
+	Checksum(ctx context.Context, ref cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error)
+	ChecksumWildcard(ctx context.Context, ref cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error)
 	HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) error
 }
 
@@ -85,20 +86,20 @@
 	lruMu  sync.Mutex
 }
 
-func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
+func (cm *cacheManager) Checksum(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool, s session.Group) (digest.Digest, error) {
 	cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
 	if err != nil {
 		return "", nil
 	}
-	return cc.Checksum(ctx, ref, p, followLinks)
+	return cc.Checksum(ctx, ref, p, followLinks, s)
 }
 
-func (cm *cacheManager) ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool) (digest.Digest, error) {
+func (cm *cacheManager) ChecksumWildcard(ctx context.Context, ref cache.ImmutableRef, p string, followLinks bool, s session.Group) (digest.Digest, error) {
 	cc, err := cm.GetCacheContext(ctx, ensureOriginMetadata(ref.Metadata()), ref.IdentityMapping())
 	if err != nil {
 		return "", nil
 	}
-	return cc.ChecksumWildcard(ctx, ref, p, followLinks)
+	return cc.ChecksumWildcard(ctx, ref, p, followLinks, s)
 }
 
 func (cm *cacheManager) GetCacheContext(ctx context.Context, md *metadata.StorageItem, idmap *idtools.IdentityMapping) (CacheContext, error) {
@@ -170,13 +171,14 @@
 	mountable cache.Mountable
 	mountPath string
 	unmount   func() error
+	session   session.Group
 }
 
 func (m *mount) mount(ctx context.Context) (string, error) {
 	if m.mountPath != "" {
 		return m.mountPath, nil
 	}
-	mounts, err := m.mountable.Mount(ctx, true)
+	mounts, err := m.mountable.Mount(ctx, true, m.session)
 	if err != nil {
 		return "", err
 	}
@@ -380,13 +382,13 @@
 	return nil
 }
 
-func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
-	m := &mount{mountable: mountable}
+func (cc *cacheContext) ChecksumWildcard(ctx context.Context, mountable cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error) {
+	m := &mount{mountable: mountable, session: s}
 	defer m.clean()
 
 	wildcards, err := cc.wildcards(ctx, m, p)
 	if err != nil {
-		return "", nil
+		return "", err
 	}
 
 	if followLinks {
@@ -413,13 +415,12 @@
 			digester.Hash().Write([]byte(w.Record.Digest))
 		}
 		return digester.Digest(), nil
-	} else {
-		return wildcards[0].Record.Digest, nil
 	}
+	return wildcards[0].Record.Digest, nil
 }
 
-func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string, followLinks bool) (digest.Digest, error) {
-	m := &mount{mountable: mountable}
+func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable, p string, followLinks bool, s session.Group) (digest.Digest, error) {
+	m := &mount{mountable: mountable, session: s}
 	defer m.clean()
 
 	return cc.checksumFollow(ctx, m, p, followLinks)
@@ -688,24 +689,24 @@
 	if p == "/" {
 		p = ""
 	}
-	if v, ok := root.Get(convertPathToKey([]byte(p))); !ok {
+	v, ok := root.Get(convertPathToKey([]byte(p)))
+	if !ok {
 		if p == "" {
 			return true, nil
 		}
 		return cc.needsScanFollow(root, path.Clean(path.Dir(p)), linksWalked)
-	} else {
-		cr := v.(*CacheRecord)
-		if cr.Type == CacheRecordTypeSymlink {
-			if *linksWalked > 255 {
-				return false, errTooManyLinks
-			}
-			*linksWalked++
-			link := path.Clean(cr.Linkname)
-			if !path.IsAbs(cr.Linkname) {
-				link = path.Join("/", path.Dir(p), link)
-			}
-			return cc.needsScanFollow(root, link, linksWalked)
+	}
+	cr := v.(*CacheRecord)
+	if cr.Type == CacheRecordTypeSymlink {
+		if *linksWalked > 255 {
+			return false, errTooManyLinks
 		}
+		*linksWalked++
+		link := path.Clean(cr.Linkname)
+		if !path.IsAbs(cr.Linkname) {
+			link = path.Join("/", path.Dir(p), link)
+		}
+		return cc.needsScanFollow(root, link, linksWalked)
 	}
 	return false, nil
 }
@@ -875,12 +876,15 @@
 }
 
 var pool32K = sync.Pool{
-	New: func() interface{} { return make([]byte, 32*1024) }, // 32K
+	New: func() interface{} {
+		buf := make([]byte, 32*1024) // 32K
+		return &buf
+	},
 }
 
 func poolsCopy(dst io.Writer, src io.Reader) (written int64, err error) {
-	buf := pool32K.Get().([]byte)
-	written, err = io.CopyBuffer(dst, src, buf)
+	buf := pool32K.Get().(*[]byte)
+	written, err = io.CopyBuffer(dst, src, *buf)
 	pool32K.Put(buf)
 	return
 }
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go b/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
index 84018e7..0b52671 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/filehash.go
@@ -40,20 +40,22 @@
 }
 
 func NewFromStat(stat *fstypes.Stat) (hash.Hash, error) {
+	// Clear the socket bit since archive/tar.FileInfoHeader does not handle it
+	stat.Mode &^= uint32(os.ModeSocket)
+
 	fi := &statInfo{stat}
 	hdr, err := tar.FileInfoHeader(fi, stat.Linkname)
 	if err != nil {
 		return nil, err
 	}
 	hdr.Name = "" // note: empty name is different from current has in docker build. Name is added on recursive directory scan instead
-	hdr.Mode = int64(chmodWindowsTarEntry(os.FileMode(hdr.Mode)))
 	hdr.Devmajor = stat.Devmajor
 	hdr.Devminor = stat.Devminor
 
 	if len(stat.Xattrs) > 0 {
-		hdr.Xattrs = make(map[string]string, len(stat.Xattrs))
+		hdr.PAXRecords = make(map[string]string, len(stat.Xattrs))
 		for k, v := range stat.Xattrs {
-			hdr.Xattrs[k] = string(v)
+			hdr.PAXRecords["SCHILY.xattr."+k] = string(v)
 		}
 	}
 	// fmt.Printf("hdr: %#v\n", hdr)
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
index 4f610d7..ccd2ebd 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_unix.go
@@ -12,10 +12,6 @@
 	"golang.org/x/sys/unix"
 )
 
-func chmodWindowsTarEntry(perm os.FileMode) os.FileMode {
-	return perm
-}
-
 func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
 	s := fi.Sys().(*syscall.Stat_t)
 
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
index e15bf1e..c6bfce9 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/filehash_windows.go
@@ -8,16 +8,6 @@
 	fstypes "github.com/tonistiigi/fsutil/types"
 )
 
-// chmodWindowsTarEntry is used to adjust the file permissions used in tar
-// header based on the platform the archival is done.
-func chmodWindowsTarEntry(perm os.FileMode) os.FileMode {
-	perm &= 0755
-	// Add the x bit: make everything +x from windows
-	perm |= 0111
-
-	return perm
-}
-
 func setUnixOpt(path string, fi os.FileInfo, stat *fstypes.Stat) error {
 	return nil
 }
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go b/vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
index de72d6c..a7f192d 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/tarsum.go
@@ -36,11 +36,24 @@
 }
 
 func v1TarHeaderSelect(h *tar.Header) (orderedHeaders [][2]string) {
+	pax := h.PAXRecords
+	if len(h.Xattrs) > 0 { //nolint deprecated
+		if pax == nil {
+			pax = map[string]string{}
+			for k, v := range h.Xattrs { //nolint deprecated
+				pax["SCHILY.xattr."+k] = v
+			}
+		}
+	}
+
 	// Get extended attributes.
-	xAttrKeys := make([]string, len(h.Xattrs))
-	for k := range h.Xattrs {
-		if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
-			xAttrKeys = append(xAttrKeys, k)
+	xAttrKeys := make([]string, len(h.PAXRecords))
+	for k := range pax {
+		if strings.HasPrefix(k, "SCHILY.xattr.") {
+			k = strings.TrimPrefix(k, "SCHILY.xattr.")
+			if k == "security.capability" || !strings.HasPrefix(k, "security.") && !strings.HasPrefix(k, "system.") {
+				xAttrKeys = append(xAttrKeys, k)
+			}
 		}
 	}
 	sort.Strings(xAttrKeys)
@@ -56,7 +69,7 @@
 
 	// Finally, append the sorted xattrs.
 	for _, k := range xAttrKeys {
-		orderedHeaders = append(orderedHeaders, [2]string{k, h.Xattrs[k]})
+		orderedHeaders = append(orderedHeaders, [2]string{k, h.PAXRecords["SCHILY.xattr."+k]})
 	}
 
 	return
diff --git a/vendor/github.com/moby/buildkit/cache/manager.go b/vendor/github.com/moby/buildkit/cache/manager.go
index 3d1e884..0fb0103 100644
--- a/vendor/github.com/moby/buildkit/cache/manager.go
+++ b/vendor/github.com/moby/buildkit/cache/manager.go
@@ -8,6 +8,7 @@
 
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/diff"
+	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/filters"
 	"github.com/containerd/containerd/gc"
 	"github.com/containerd/containerd/leases"
@@ -15,7 +16,9 @@
 	"github.com/moby/buildkit/cache/metadata"
 	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/util/flightcontrol"
 	digest "github.com/opencontainers/go-digest"
 	imagespecidentity "github.com/opencontainers/image-spec/identity"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -38,14 +41,15 @@
 	PruneRefChecker ExternalRefCheckerFunc
 	GarbageCollect  func(ctx context.Context) (gc.Stats, error)
 	Applier         diff.Applier
+	Differ          diff.Comparer
 }
 
 type Accessor interface {
 	GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ImmutableRef, error)
 	Get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error)
 
-	New(ctx context.Context, parent ImmutableRef, opts ...RefOption) (MutableRef, error)
-	GetMutable(ctx context.Context, id string) (MutableRef, error) // Rebase?
+	New(ctx context.Context, parent ImmutableRef, s session.Group, opts ...RefOption) (MutableRef, error)
+	GetMutable(ctx context.Context, id string, opts ...RefOption) (MutableRef, error) // Rebase?
 	IdentityMapping() *idtools.IdentityMapping
 	Metadata(string) *metadata.StorageItem
 }
@@ -74,6 +78,7 @@
 	md *metadata.Store
 
 	muPrune sync.Mutex // make sure parallel prune is not allowed so there will not be inconsistent results
+	unlazyG flightcontrol.Group
 }
 
 func NewManager(opt ManagerOpt) (Manager, error) {
@@ -92,7 +97,7 @@
 	return cm, nil
 }
 
-func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ir ImmutableRef, err error) {
+func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispec.Descriptor, parent ImmutableRef, opts ...RefOption) (ir ImmutableRef, rerr error) {
 	diffID, err := diffIDFromDescriptor(desc)
 	if err != nil {
 		return nil, err
@@ -100,9 +105,12 @@
 	chainID := diffID
 	blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
 
-	if desc.Digest != "" {
-		if _, err := cm.ContentStore.Info(ctx, desc.Digest); err != nil {
-			return nil, errors.Wrapf(err, "failed to get blob %s", desc.Digest)
+	descHandlers := descHandlersOf(opts...)
+	if desc.Digest != "" && (descHandlers == nil || descHandlers[desc.Digest] == nil) {
+		if _, err := cm.ContentStore.Info(ctx, desc.Digest); errors.Is(err, errdefs.ErrNotFound) {
+			return nil, NeedsRemoteProvidersError([]digest.Digest{desc.Digest})
+		} else if err != nil {
+			return nil, err
 		}
 	}
 
@@ -115,7 +123,8 @@
 		}
 		chainID = imagespecidentity.ChainID([]digest.Digest{pInfo.ChainID, chainID})
 		blobChainID = imagespecidentity.ChainID([]digest.Digest{pInfo.BlobChainID, blobChainID})
-		p2, err := cm.Get(ctx, parent.ID(), NoUpdateLastUsed)
+
+		p2, err := cm.Get(ctx, parent.ID(), NoUpdateLastUsed, descHandlers)
 		if err != nil {
 			return nil, err
 		}
@@ -128,7 +137,7 @@
 
 	releaseParent := false
 	defer func() {
-		if releaseParent || err != nil && p != nil {
+		if releaseParent || rerr != nil && p != nil {
 			p.Release(context.TODO())
 		}
 	}()
@@ -141,14 +150,17 @@
 		return nil, err
 	}
 
-	for _, si := range sis {
-		ref, err := cm.get(ctx, si.ID(), opts...)
+	if len(sis) > 0 {
+		ref, err := cm.get(ctx, sis[0].ID(), opts...)
 		if err != nil && !IsNotFound(err) {
-			return nil, errors.Wrapf(err, "failed to get record %s by blobchainid", si.ID())
+			return nil, errors.Wrapf(err, "failed to get record %s by blobchainid", sis[0].ID())
 		}
 		if p != nil {
 			releaseParent = true
 		}
+		if err := setImageRefMetadata(ref, opts...); err != nil {
+			return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", ref.ID())
+		}
 		return ref, nil
 	}
 
@@ -158,13 +170,12 @@
 	}
 
 	var link ImmutableRef
-	for _, si := range sis {
-		ref, err := cm.get(ctx, si.ID(), opts...)
+	if len(sis) > 0 {
+		ref, err := cm.get(ctx, sis[0].ID(), opts...)
 		if err != nil && !IsNotFound(err) {
-			return nil, errors.Wrapf(err, "failed to get record %s by chainid", si.ID())
+			return nil, errors.Wrapf(err, "failed to get record %s by chainid", sis[0].ID())
 		}
 		link = ref
-		break
 	}
 
 	id := identity.NewID()
@@ -188,7 +199,7 @@
 	}
 
 	defer func() {
-		if err != nil {
+		if rerr != nil {
 			if err := cm.ManagerOpt.LeaseManager.Delete(context.TODO(), leases.Lease{
 				ID: l.ID,
 			}); err != nil {
@@ -227,6 +238,10 @@
 		return nil, err
 	}
 
+	if err := setImageRefMetadata(rec, opts...); err != nil {
+		return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", rec.ID())
+	}
+
 	queueDiffID(rec.md, diffID.String())
 	queueBlob(rec.md, desc.Digest.String())
 	queueChainID(rec.md, chainID.String())
@@ -234,6 +249,7 @@
 	queueSnapshotID(rec.md, snapshotID)
 	queueBlobOnly(rec.md, blobOnly)
 	queueMediaType(rec.md, desc.MediaType)
+	queueBlobSize(rec.md, desc.Size)
 	queueCommitted(rec.md)
 
 	if err := rec.md.Commit(); err != nil {
@@ -242,7 +258,7 @@
 
 	cm.records[id] = rec
 
-	return rec.ref(true), nil
+	return rec.ref(true, descHandlers), nil
 }
 
 // init loads all snapshots from metadata state and tries to load the records
@@ -308,25 +324,52 @@
 		}
 	}
 
+	descHandlers := descHandlersOf(opts...)
+
 	if rec.mutable {
 		if len(rec.refs) != 0 {
 			return nil, errors.Wrapf(ErrLocked, "%s is locked", id)
 		}
 		if rec.equalImmutable != nil {
-			return rec.equalImmutable.ref(triggerUpdate), nil
+			return rec.equalImmutable.ref(triggerUpdate, descHandlers), nil
 		}
-		return rec.mref(triggerUpdate).commit(ctx)
+		return rec.mref(triggerUpdate, descHandlers).commit(ctx)
 	}
 
-	return rec.ref(triggerUpdate), nil
+	return rec.ref(triggerUpdate, descHandlers), nil
 }
 
 // getRecord returns record for id. Requires manager lock.
 func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOption) (cr *cacheRecord, retErr error) {
+	checkLazyProviders := func(rec *cacheRecord) error {
+		missing := NeedsRemoteProvidersError(nil)
+		dhs := descHandlersOf(opts...)
+		for {
+			blob := digest.Digest(getBlob(rec.md))
+			if isLazy, err := rec.isLazy(ctx); err != nil {
+				return err
+			} else if isLazy && dhs[blob] == nil {
+				missing = append(missing, blob)
+			}
+
+			if rec.parent == nil {
+				break
+			}
+			rec = rec.parent.cacheRecord
+		}
+		if len(missing) > 0 {
+			return missing
+		}
+		return nil
+	}
+
 	if rec, ok := cm.records[id]; ok {
 		if rec.isDead() {
 			return nil, errors.Wrapf(errNotFound, "failed to get dead record %s", id)
 		}
+		if err := checkLazyProviders(rec); err != nil {
+			return nil, err
+		}
 		return rec, nil
 	}
 
@@ -343,11 +386,17 @@
 			}
 			return nil, err
 		}
+
+		// parent refs are possibly lazy so keep it hold the description handlers.
+		var dhs DescHandlers
+		if mutable.parent != nil {
+			dhs = mutable.parent.descHandlers
+		}
 		rec := &cacheRecord{
 			mu:           &sync.Mutex{},
 			cm:           cm,
 			refs:         make(map[ref]struct{}),
-			parent:       mutable.parentRef(false),
+			parent:       mutable.parentRef(false, dhs),
 			md:           md,
 			equalMutable: &mutableRef{cacheRecord: mutable},
 		}
@@ -393,25 +442,39 @@
 		return nil, err
 	}
 
+	if err := setImageRefMetadata(rec, opts...); err != nil {
+		return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", rec.ID())
+	}
+
 	cm.records[id] = rec
+	if err := checkLazyProviders(rec); err != nil {
+		return nil, err
+	}
 	return rec, nil
 }
 
-func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOption) (mr MutableRef, err error) {
+func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, sess session.Group, opts ...RefOption) (mr MutableRef, err error) {
 	id := identity.NewID()
 
 	var parent *immutableRef
 	var parentID string
 	var parentSnapshotID string
 	if s != nil {
-		p, err := cm.Get(ctx, s.ID(), NoUpdateLastUsed)
-		if err != nil {
+		if _, ok := s.(*immutableRef); ok {
+			parent = s.Clone().(*immutableRef)
+		} else {
+			p, err := cm.Get(ctx, s.ID(), append(opts, NoUpdateLastUsed)...)
+			if err != nil {
+				return nil, err
+			}
+			parent = p.(*immutableRef)
+		}
+		if err := parent.Finalize(ctx, true); err != nil {
 			return nil, err
 		}
-		if err := p.Finalize(ctx, true); err != nil {
+		if err := parent.Extract(ctx, sess); err != nil {
 			return nil, err
 		}
-		parent = p.(*immutableRef)
 		parentSnapshotID = getSnapshotID(parent.md)
 		parentID = parent.ID()
 	}
@@ -469,18 +532,28 @@
 		return nil, err
 	}
 
+	if err := setImageRefMetadata(rec, opts...); err != nil {
+		return nil, errors.Wrapf(err, "failed to append image ref metadata to ref %s", rec.ID())
+	}
+
 	cm.mu.Lock()
 	defer cm.mu.Unlock()
 
 	cm.records[id] = rec // TODO: save to db
 
-	return rec.mref(true), nil
+	// parent refs are possibly lazy so keep it hold the description handlers.
+	var dhs DescHandlers
+	if parent != nil {
+		dhs = parent.descHandlers
+	}
+	return rec.mref(true, dhs), nil
 }
-func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef, error) {
+
+func (cm *cacheManager) GetMutable(ctx context.Context, id string, opts ...RefOption) (MutableRef, error) {
 	cm.mu.Lock()
 	defer cm.mu.Unlock()
 
-	rec, err := cm.getRecord(ctx, id)
+	rec, err := cm.getRecord(ctx, id, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -506,7 +579,7 @@
 		rec.equalImmutable = nil
 	}
 
-	return rec.mref(true), nil
+	return rec.mref(true, descHandlersOf(opts...)), nil
 }
 
 func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo, opts ...client.PruneInfo) error {
@@ -957,6 +1030,31 @@
 	}
 }
 
+// Need a separate type for imageRef because it needs to be called outside
+// initializeMetadata while still being a RefOption, so wrapping it in a
+// different type ensures initializeMetadata won't catch it too and duplicate
+// setting the metadata.
+type imageRefOption func(m withMetadata) error
+
+// WithImageRef appends the given imageRef to the cache ref's metadata
+func WithImageRef(imageRef string) RefOption {
+	return imageRefOption(func(m withMetadata) error {
+		return appendImageRef(m.Metadata(), imageRef)
+	})
+}
+
+func setImageRefMetadata(m withMetadata, opts ...RefOption) error {
+	md := m.Metadata()
+	for _, opt := range opts {
+		if fn, ok := opt.(imageRefOption); ok {
+			if err := fn(m); err != nil {
+				return err
+			}
+		}
+	}
+	return md.Commit()
+}
+
 func initializeMetadata(m withMetadata, parent string, opts ...RefOption) error {
 	md := m.Metadata()
 	if tm := GetCreatedAt(md); !tm.IsZero() {
diff --git a/vendor/github.com/moby/buildkit/cache/metadata.go b/vendor/github.com/moby/buildkit/cache/metadata.go
index bf4041e..a5c7df7 100644
--- a/vendor/github.com/moby/buildkit/cache/metadata.go
+++ b/vendor/github.com/moby/buildkit/cache/metadata.go
@@ -28,6 +28,10 @@
 const keySnapshot = "cache.snapshot"
 const keyBlobOnly = "cache.blobonly"
 const keyMediaType = "cache.mediatype"
+const keyImageRefs = "cache.imageRefs"
+
+// BlobSize is the packed blob size as specified in the oci descriptor
+const keyBlobSize = "cache.blobsize"
 
 const keyDeleted = "cache.deleted"
 
@@ -307,6 +311,63 @@
 	return size
 }
 
+func appendImageRef(si *metadata.StorageItem, s string) error {
+	return si.GetAndSetValue(keyImageRefs, func(v *metadata.Value) (*metadata.Value, error) {
+		var imageRefs []string
+		if v != nil {
+			if err := v.Unmarshal(&imageRefs); err != nil {
+				return nil, err
+			}
+		}
+		for _, existing := range imageRefs {
+			if existing == s {
+				return nil, metadata.ErrSkipSetValue
+			}
+		}
+		imageRefs = append(imageRefs, s)
+		v, err := metadata.NewValue(imageRefs)
+		if err != nil {
+			return nil, errors.Wrap(err, "failed to create imageRefs value")
+		}
+		return v, nil
+	})
+}
+
+func getImageRefs(si *metadata.StorageItem) []string {
+	v := si.Get(keyImageRefs)
+	if v == nil {
+		return nil
+	}
+	var refs []string
+	if err := v.Unmarshal(&refs); err != nil {
+		return nil
+	}
+	return refs
+}
+
+func queueBlobSize(si *metadata.StorageItem, s int64) error {
+	v, err := metadata.NewValue(s)
+	if err != nil {
+		return errors.Wrap(err, "failed to create blobsize value")
+	}
+	si.Queue(func(b *bolt.Bucket) error {
+		return si.SetValue(b, keyBlobSize, v)
+	})
+	return nil
+}
+
+func getBlobSize(si *metadata.StorageItem) int64 {
+	v := si.Get(keyBlobSize)
+	if v == nil {
+		return sizeUnknown
+	}
+	var size int64
+	if err := v.Unmarshal(&size); err != nil {
+		return sizeUnknown
+	}
+	return size
+}
+
 func getEqualMutable(si *metadata.StorageItem) string {
 	v := si.Get(keyEqualMutable)
 	if v == nil {
diff --git a/vendor/github.com/moby/buildkit/cache/metadata/metadata.go b/vendor/github.com/moby/buildkit/cache/metadata/metadata.go
index 42e8cb4..b0b2221 100644
--- a/vendor/github.com/moby/buildkit/cache/metadata/metadata.go
+++ b/vendor/github.com/moby/buildkit/cache/metadata/metadata.go
@@ -372,6 +372,22 @@
 	return nil
 }
 
+var ErrSkipSetValue = errors.New("skip setting metadata value")
+
+func (s *StorageItem) GetAndSetValue(key string, fn func(*Value) (*Value, error)) error {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	return s.Update(func(b *bolt.Bucket) error {
+		v, err := fn(s.values[key])
+		if errors.Is(err, ErrSkipSetValue) {
+			return nil
+		} else if err != nil {
+			return err
+		}
+		return s.SetValue(b, key, v)
+	})
+}
+
 type Value struct {
 	Value json.RawMessage `json:"value,omitempty"`
 	Index string          `json:"index,omitempty"`
diff --git a/vendor/github.com/moby/buildkit/cache/opts.go b/vendor/github.com/moby/buildkit/cache/opts.go
new file mode 100644
index 0000000..911def3
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/cache/opts.go
@@ -0,0 +1,35 @@
+package cache
+
+import (
+	"fmt"
+
+	"github.com/containerd/containerd/content"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/util/progress"
+	digest "github.com/opencontainers/go-digest"
+)
+
+type DescHandler struct {
+	Provider       func(session.Group) content.Provider
+	Progress       progress.Controller
+	SnapshotLabels map[string]string
+}
+
+type DescHandlers map[digest.Digest]*DescHandler
+
+func descHandlersOf(opts ...RefOption) DescHandlers {
+	for _, opt := range opts {
+		if opt, ok := opt.(DescHandlers); ok {
+			return opt
+		}
+	}
+	return nil
+}
+
+type DescHandlerKey digest.Digest
+
+type NeedsRemoteProvidersError []digest.Digest
+
+func (m NeedsRemoteProvidersError) Error() string {
+	return fmt.Sprintf("missing descriptor handlers for lazy blobs %+v", []digest.Digest(m))
+}
diff --git a/vendor/github.com/moby/buildkit/cache/refs.go b/vendor/github.com/moby/buildkit/cache/refs.go
index d932f4e..a17f6e1 100644
--- a/vendor/github.com/moby/buildkit/cache/refs.go
+++ b/vendor/github.com/moby/buildkit/cache/refs.go
@@ -14,14 +14,18 @@
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/moby/buildkit/cache/metadata"
 	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
 	"github.com/moby/buildkit/util/flightcontrol"
 	"github.com/moby/buildkit/util/leaseutil"
+	"github.com/moby/buildkit/util/winlayers"
 	digest "github.com/opencontainers/go-digest"
-	imagespecidentity "github.com/opencontainers/image-spec/identity"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+	"golang.org/x/sync/errgroup"
 )
 
 // Ref is a reference to cacheable objects.
@@ -41,8 +45,8 @@
 	Clone() ImmutableRef
 
 	Info() RefInfo
-	SetBlob(ctx context.Context, desc ocispec.Descriptor) error
-	Extract(ctx context.Context) error // +progress
+	Extract(ctx context.Context, s session.Group) error // +progress
+	GetRemote(ctx context.Context, createIfNeeded bool, compressionType compression.Type, s session.Group) (*solver.Remote, error)
 }
 
 type RefInfo struct {
@@ -61,7 +65,7 @@
 }
 
 type Mountable interface {
-	Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error)
+	Mount(ctx context.Context, readonly bool, s session.Group) (snapshot.Mountable, error)
 }
 
 type ref interface {
@@ -93,15 +97,23 @@
 }
 
 // hold ref lock before calling
-func (cr *cacheRecord) ref(triggerLastUsed bool) *immutableRef {
-	ref := &immutableRef{cacheRecord: cr, triggerLastUsed: triggerLastUsed}
+func (cr *cacheRecord) ref(triggerLastUsed bool, descHandlers DescHandlers) *immutableRef {
+	ref := &immutableRef{
+		cacheRecord:     cr,
+		triggerLastUsed: triggerLastUsed,
+		descHandlers:    descHandlers,
+	}
 	cr.refs[ref] = struct{}{}
 	return ref
 }
 
 // hold ref lock before calling
-func (cr *cacheRecord) mref(triggerLastUsed bool) *mutableRef {
-	ref := &mutableRef{cacheRecord: cr, triggerLastUsed: triggerLastUsed}
+func (cr *cacheRecord) mref(triggerLastUsed bool, descHandlers DescHandlers) *mutableRef {
+	ref := &mutableRef{
+		cacheRecord:     cr,
+		triggerLastUsed: triggerLastUsed,
+		descHandlers:    descHandlers,
+	}
 	cr.refs[ref] = struct{}{}
 	return ref
 }
@@ -131,6 +143,22 @@
 	return cr.dead || (cr.equalImmutable != nil && cr.equalImmutable.dead) || (cr.equalMutable != nil && cr.equalMutable.dead)
 }
 
+func (cr *cacheRecord) isLazy(ctx context.Context) (bool, error) {
+	if !getBlobOnly(cr.md) {
+		return false, nil
+	}
+	dgst := getBlob(cr.md)
+	// special case for moby where there is no compressed blob (empty digest)
+	if dgst == "" {
+		return false, nil
+	}
+	_, err := cr.cm.ContentStore.Info(ctx, digest.Digest(dgst))
+	if errors.Is(err, errdefs.ErrNotFound) {
+		return true, nil
+	}
+	return false, err
+}
+
 func (cr *cacheRecord) IdentityMapping() *idtools.IdentityMapping {
 	return cr.cm.IdentityMapping()
 }
@@ -186,27 +214,18 @@
 	return s.(int64), nil
 }
 
-func (cr *cacheRecord) Parent() ImmutableRef {
-	if p := cr.parentRef(true); p != nil { // avoid returning typed nil pointer
-		return p
-	}
-	return nil
-}
-
-func (cr *cacheRecord) parentRef(hidden bool) *immutableRef {
+func (cr *cacheRecord) parentRef(hidden bool, descHandlers DescHandlers) *immutableRef {
 	p := cr.parent
 	if p == nil {
 		return nil
 	}
 	p.mu.Lock()
 	defer p.mu.Unlock()
-	return p.ref(hidden)
+	return p.ref(hidden, descHandlers)
 }
 
-func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
-	cr.mu.Lock()
-	defer cr.mu.Unlock()
-
+// must be called holding cacheRecord mu
+func (cr *cacheRecord) mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
 	if cr.mutable {
 		m, err := cr.cm.Snapshotter.Mounts(ctx, getSnapshotID(cr.md))
 		if err != nil {
@@ -282,20 +301,29 @@
 type immutableRef struct {
 	*cacheRecord
 	triggerLastUsed bool
+	descHandlers    DescHandlers
 }
 
 type mutableRef struct {
 	*cacheRecord
 	triggerLastUsed bool
+	descHandlers    DescHandlers
 }
 
 func (sr *immutableRef) Clone() ImmutableRef {
 	sr.mu.Lock()
-	ref := sr.ref(false)
+	ref := sr.ref(false, sr.descHandlers)
 	sr.mu.Unlock()
 	return ref
 }
 
+func (sr *immutableRef) Parent() ImmutableRef {
+	if p := sr.parentRef(true, sr.descHandlers); p != nil { // avoid returning typed nil pointer
+		return p
+	}
+	return nil
+}
+
 func (sr *immutableRef) Info() RefInfo {
 	return RefInfo{
 		ChainID:     digest.Digest(getChainID(sr.md)),
@@ -308,25 +336,186 @@
 	}
 }
 
-func (sr *immutableRef) Extract(ctx context.Context) error {
-	_, err := sr.sizeG.Do(ctx, sr.ID()+"-extract", func(ctx context.Context) (interface{}, error) {
+func (sr *immutableRef) ociDesc() (ocispec.Descriptor, error) {
+	desc := ocispec.Descriptor{
+		Digest:      digest.Digest(getBlob(sr.md)),
+		Size:        getBlobSize(sr.md),
+		MediaType:   getMediaType(sr.md),
+		Annotations: make(map[string]string),
+	}
+
+	diffID := getDiffID(sr.md)
+	if diffID != "" {
+		desc.Annotations["containerd.io/uncompressed"] = diffID
+	}
+
+	createdAt := GetCreatedAt(sr.md)
+	if !createdAt.IsZero() {
+		createdAt, err := createdAt.MarshalText()
+		if err != nil {
+			return ocispec.Descriptor{}, err
+		}
+		desc.Annotations["buildkit/createdat"] = string(createdAt)
+	}
+
+	return desc, nil
+}
+
+// order is from parent->child, sr will be at end of slice
+func (sr *immutableRef) parentRefChain() []*immutableRef {
+	var count int
+	for ref := sr; ref != nil; ref = ref.parent {
+		count++
+	}
+	refs := make([]*immutableRef, count)
+	for i, ref := count-1, sr; ref != nil; i, ref = i-1, ref.parent {
+		refs[i] = ref
+	}
+	return refs
+}
+
+func (sr *immutableRef) Mount(ctx context.Context, readonly bool, s session.Group) (snapshot.Mountable, error) {
+	if err := sr.Extract(ctx, s); err != nil {
+		return nil, err
+	}
+
+	sr.mu.Lock()
+	defer sr.mu.Unlock()
+	return sr.mount(ctx, readonly)
+}
+
+func (sr *immutableRef) Extract(ctx context.Context, s session.Group) (rerr error) {
+	if !getBlobOnly(sr.md) {
+		return
+	}
+
+	ctx, done, err := leaseutil.WithLease(ctx, sr.cm.LeaseManager, leaseutil.MakeTemporary)
+	if err != nil {
+		return err
+	}
+	defer done(ctx)
+
+	if GetLayerType(sr) == "windows" {
+		ctx = winlayers.UseWindowsLayerMode(ctx)
+	}
+
+	if sr.cm.Snapshotter.Name() == "stargz" {
+		if _, err := sr.prepareRemoteSnapshots(ctx, sr.descHandlers); err != nil {
+			return err
+		}
+	}
+
+	return sr.extract(ctx, sr.descHandlers, s)
+}
+
+func (sr *immutableRef) prepareRemoteSnapshots(ctx context.Context, dhs DescHandlers) (bool, error) {
+	ok, err := sr.sizeG.Do(ctx, sr.ID()+"-prepare-remote-snapshot", func(ctx context.Context) (_ interface{}, rerr error) {
 		snapshotID := getSnapshotID(sr.md)
 		if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
-			queueBlobOnly(sr.md, false)
-			return nil, sr.md.Commit()
+			return true, nil
+		}
+		desc, err := sr.ociDesc()
+		if err != nil {
+			return false, err
+		}
+		dh := dhs[desc.Digest]
+		if dh == nil {
+			return false, nil
 		}
 
 		parentID := ""
 		if sr.parent != nil {
-			if err := sr.parent.Extract(ctx); err != nil {
-				return nil, err
+			if ok, err := sr.parent.prepareRemoteSnapshots(ctx, dhs); !ok {
+				return false, err
 			}
 			parentID = getSnapshotID(sr.parent.md)
 		}
-		info := sr.Info()
-		key := fmt.Sprintf("extract-%s %s", identity.NewID(), info.ChainID)
 
-		err := sr.cm.Snapshotter.Prepare(ctx, key, parentID)
+		// Hint labels to the snapshotter
+		labels := dh.SnapshotLabels
+		if labels == nil {
+			labels = make(map[string]string)
+		}
+		labels["containerd.io/snapshot.ref"] = snapshotID
+		opt := snapshots.WithLabels(labels)
+
+		// Try to preapre the remote snapshot
+		key := fmt.Sprintf("tmp-%s %s", identity.NewID(), sr.Info().ChainID)
+		if err = sr.cm.Snapshotter.Prepare(ctx, key, parentID, opt); err != nil {
+			if errdefs.IsAlreadyExists(err) {
+				// Check if the targeting snapshot ID has been prepared as a remote
+				// snapshot in the snapshotter.
+				if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
+					// We can use this remote snapshot without unlazying.
+					// Try the next layer as well.
+					return true, nil
+				}
+			}
+		}
+
+		// This layer cannot be prepared without unlazying.
+		return false, nil
+	})
+	if err != nil {
+		return false, err
+	}
+	return ok.(bool), err
+}
+
+func (sr *immutableRef) extract(ctx context.Context, dhs DescHandlers, s session.Group) error {
+	_, err := sr.sizeG.Do(ctx, sr.ID()+"-extract", func(ctx context.Context) (_ interface{}, rerr error) {
+		snapshotID := getSnapshotID(sr.md)
+		if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil {
+			return nil, nil
+		}
+
+		if sr.cm.Applier == nil {
+			return nil, errors.New("extract requires an applier")
+		}
+
+		eg, egctx := errgroup.WithContext(ctx)
+
+		parentID := ""
+		if sr.parent != nil {
+			eg.Go(func() error {
+				if err := sr.parent.extract(egctx, dhs, s); err != nil {
+					return err
+				}
+				parentID = getSnapshotID(sr.parent.md)
+				return nil
+			})
+		}
+
+		desc, err := sr.ociDesc()
+		if err != nil {
+			return nil, err
+		}
+		dh := dhs[desc.Digest]
+
+		eg.Go(func() error {
+			// unlazies if needed, otherwise a no-op
+			return lazyRefProvider{
+				ref:     sr,
+				desc:    desc,
+				dh:      dh,
+				session: s,
+			}.Unlazy(egctx)
+		})
+
+		if err := eg.Wait(); err != nil {
+			return nil, err
+		}
+
+		if dh != nil && dh.Progress != nil {
+			_, stopProgress := dh.Progress.Start(ctx)
+			defer stopProgress(rerr)
+			statusDone := dh.Progress.Status("extracting "+desc.Digest.String(), "extracting")
+			defer statusDone()
+		}
+
+		key := fmt.Sprintf("extract-%s %s", identity.NewID(), sr.Info().ChainID)
+
+		err = sr.cm.Snapshotter.Prepare(ctx, key, parentID)
 		if err != nil {
 			return nil, err
 		}
@@ -339,10 +528,7 @@
 		if err != nil {
 			return nil, err
 		}
-		_, err = sr.cm.Applier.Apply(ctx, ocispec.Descriptor{
-			Digest:    info.Blob,
-			MediaType: info.MediaType,
-		}, mounts)
+		_, err = sr.cm.Applier.Apply(ctx, desc, mounts)
 		if err != nil {
 			unmount()
 			return nil, err
@@ -357,6 +543,7 @@
 			}
 		}
 		queueBlobOnly(sr.md, false)
+		setSize(sr.md, sizeUnknown)
 		if err := sr.md.Commit(); err != nil {
 			return nil, err
 		}
@@ -365,65 +552,6 @@
 	return err
 }
 
-// SetBlob associates a blob with the cache record.
-// A lease must be held for the blob when calling this function
-// Caller should call Info() for knowing what current values are actually set
-func (sr *immutableRef) SetBlob(ctx context.Context, desc ocispec.Descriptor) error {
-	diffID, err := diffIDFromDescriptor(desc)
-	if err != nil {
-		return err
-	}
-	if _, err := sr.cm.ContentStore.Info(ctx, desc.Digest); err != nil {
-		return err
-	}
-
-	sr.mu.Lock()
-	defer sr.mu.Unlock()
-
-	if getChainID(sr.md) != "" {
-		return nil
-	}
-
-	if err := sr.finalize(ctx, true); err != nil {
-		return err
-	}
-
-	p := sr.parent
-	var parentChainID digest.Digest
-	var parentBlobChainID digest.Digest
-	if p != nil {
-		pInfo := p.Info()
-		if pInfo.ChainID == "" || pInfo.BlobChainID == "" {
-			return errors.Errorf("failed to set blob for reference with non-addressable parent")
-		}
-		parentChainID = pInfo.ChainID
-		parentBlobChainID = pInfo.BlobChainID
-	}
-
-	if err := sr.cm.LeaseManager.AddResource(ctx, leases.Lease{ID: sr.ID()}, leases.Resource{
-		ID:   desc.Digest.String(),
-		Type: "content",
-	}); err != nil {
-		return err
-	}
-
-	queueDiffID(sr.md, diffID.String())
-	queueBlob(sr.md, desc.Digest.String())
-	chainID := diffID
-	blobChainID := imagespecidentity.ChainID([]digest.Digest{desc.Digest, diffID})
-	if parentChainID != "" {
-		chainID = imagespecidentity.ChainID([]digest.Digest{parentChainID, chainID})
-		blobChainID = imagespecidentity.ChainID([]digest.Digest{parentBlobChainID, blobChainID})
-	}
-	queueChainID(sr.md, chainID.String())
-	queueBlobChainID(sr.md, blobChainID.String())
-	queueMediaType(sr.md, desc.MediaType)
-	if err := sr.md.Commit(); err != nil {
-		return err
-	}
-	return nil
-}
-
 func (sr *immutableRef) Release(ctx context.Context) error {
 	sr.cm.mu.Lock()
 	defer sr.cm.mu.Unlock()
@@ -555,7 +683,7 @@
 	rec := &cacheRecord{
 		mu:           sr.mu,
 		cm:           sr.cm,
-		parent:       sr.parentRef(false),
+		parent:       sr.parentRef(false, sr.descHandlers),
 		equalMutable: sr,
 		refs:         make(map[ref]struct{}),
 		md:           md,
@@ -588,13 +716,16 @@
 		return nil, err
 	}
 
-	ref := rec.ref(true)
+	ref := rec.ref(true, sr.descHandlers)
 	sr.equalImmutable = ref
 	return ref, nil
 }
 
-func (sr *mutableRef) updatesLastUsed() bool {
-	return sr.triggerLastUsed
+func (sr *mutableRef) Mount(ctx context.Context, readonly bool, s session.Group) (snapshot.Mountable, error) {
+	sr.mu.Lock()
+	defer sr.mu.Unlock()
+
+	return sr.mount(ctx, readonly)
 }
 
 func (sr *mutableRef) Commit(ctx context.Context) (ImmutableRef, error) {
@@ -633,11 +764,10 @@
 			}
 		}
 		return sr.remove(ctx, true)
-	} else {
-		if sr.updateLastUsed() {
-			updateLastUsed(sr.md)
-			sr.triggerLastUsed = false
-		}
+	}
+	if sr.updateLastUsed() {
+		updateLastUsed(sr.md)
+		sr.triggerLastUsed = false
 	}
 	return nil
 }
diff --git a/vendor/github.com/moby/buildkit/cache/remote.go b/vendor/github.com/moby/buildkit/cache/remote.go
new file mode 100644
index 0000000..299a571
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/cache/remote.go
@@ -0,0 +1,205 @@
+package cache
+
+import (
+	"context"
+	"fmt"
+	"net/url"
+	"strings"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/reference"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
+	"github.com/moby/buildkit/util/contentutil"
+	"github.com/moby/buildkit/util/leaseutil"
+	"github.com/moby/buildkit/util/progress/logs"
+	"github.com/moby/buildkit/util/pull/pullprogress"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"golang.org/x/sync/errgroup"
+)
+
+type Unlazier interface {
+	Unlazy(ctx context.Context) error
+}
+
+// GetRemote gets a *solver.Remote from content store for this ref (potentially pulling lazily).
+// Note: Use WorkerRef.GetRemote instead as moby integration requires custom GetRemote implementation.
+func (sr *immutableRef) GetRemote(ctx context.Context, createIfNeeded bool, compressionType compression.Type, s session.Group) (*solver.Remote, error) {
+	ctx, done, err := leaseutil.WithLease(ctx, sr.cm.LeaseManager, leaseutil.MakeTemporary)
+	if err != nil {
+		return nil, err
+	}
+	defer done(ctx)
+
+	err = sr.computeBlobChain(ctx, createIfNeeded, compressionType, s)
+	if err != nil {
+		return nil, err
+	}
+
+	mprovider := &lazyMultiProvider{mprovider: contentutil.NewMultiProvider(nil)}
+	remote := &solver.Remote{
+		Provider: mprovider,
+	}
+
+	for _, ref := range sr.parentRefChain() {
+		desc, err := ref.ociDesc()
+		if err != nil {
+			return nil, err
+		}
+
+		// NOTE: The media type might be missing for some migrated ones
+		// from before lease based storage. If so, we should detect
+		// the media type from blob data.
+		//
+		// Discussion: https://github.com/moby/buildkit/pull/1277#discussion_r352795429
+		if desc.MediaType == "" {
+			desc.MediaType, err = compression.DetectLayerMediaType(ctx, sr.cm.ContentStore, desc.Digest, false)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		// update distribution source annotation for lazy-refs (non-lazy refs
+		// will already have their dsl stored in the content store, which is
+		// used by the push handlers)
+		if isLazy, err := ref.isLazy(ctx); err != nil {
+			return nil, err
+		} else if isLazy {
+			imageRefs := getImageRefs(ref.md)
+			for _, imageRef := range imageRefs {
+				refspec, err := reference.Parse(imageRef)
+				if err != nil {
+					return nil, err
+				}
+
+				u, err := url.Parse("dummy://" + refspec.Locator)
+				if err != nil {
+					return nil, err
+				}
+
+				source, repo := u.Hostname(), strings.TrimPrefix(u.Path, "/")
+				if desc.Annotations == nil {
+					desc.Annotations = make(map[string]string)
+				}
+				dslKey := fmt.Sprintf("%s.%s", "containerd.io/distribution.source", source)
+
+				var existingRepos []string
+				if existings, ok := desc.Annotations[dslKey]; ok {
+					existingRepos = strings.Split(existings, ",")
+				}
+				addNewRepo := true
+				for _, existing := range existingRepos {
+					if existing == repo {
+						addNewRepo = false
+						break
+					}
+				}
+				if addNewRepo {
+					existingRepos = append(existingRepos, repo)
+				}
+				desc.Annotations[dslKey] = strings.Join(existingRepos, ",")
+			}
+		}
+
+		remote.Descriptors = append(remote.Descriptors, desc)
+		mprovider.Add(lazyRefProvider{
+			ref:     ref,
+			desc:    desc,
+			dh:      sr.descHandlers[desc.Digest],
+			session: s,
+		})
+	}
+	return remote, nil
+}
+
+type lazyMultiProvider struct {
+	mprovider *contentutil.MultiProvider
+	plist     []lazyRefProvider
+}
+
+func (mp *lazyMultiProvider) Add(p lazyRefProvider) {
+	mp.mprovider.Add(p.desc.Digest, p)
+	mp.plist = append(mp.plist, p)
+}
+
+func (mp *lazyMultiProvider) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
+	return mp.mprovider.ReaderAt(ctx, desc)
+}
+
+func (mp *lazyMultiProvider) Unlazy(ctx context.Context) error {
+	eg, egctx := errgroup.WithContext(ctx)
+	for _, p := range mp.plist {
+		p := p
+		eg.Go(func() error {
+			return p.Unlazy(egctx)
+		})
+	}
+	return eg.Wait()
+}
+
+type lazyRefProvider struct {
+	ref     *immutableRef
+	desc    ocispec.Descriptor
+	dh      *DescHandler
+	session session.Group
+}
+
+func (p lazyRefProvider) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
+	if desc.Digest != p.desc.Digest {
+		return nil, errdefs.ErrNotFound
+	}
+	if err := p.Unlazy(ctx); err != nil {
+		return nil, err
+	}
+	return p.ref.cm.ContentStore.ReaderAt(ctx, desc)
+}
+
+func (p lazyRefProvider) Unlazy(ctx context.Context) error {
+	_, err := p.ref.cm.unlazyG.Do(ctx, string(p.desc.Digest), func(ctx context.Context) (_ interface{}, rerr error) {
+		if isLazy, err := p.ref.isLazy(ctx); err != nil {
+			return nil, err
+		} else if !isLazy {
+			return nil, nil
+		}
+
+		if p.dh == nil {
+			// shouldn't happen, if you have a lazy immutable ref it already should be validated
+			// that descriptor handlers exist for it
+			return nil, errors.New("unexpected nil descriptor handler")
+		}
+
+		if p.dh.Progress != nil {
+			var stopProgress func(error)
+			ctx, stopProgress = p.dh.Progress.Start(ctx)
+			defer stopProgress(rerr)
+		}
+
+		// For now, just pull down the whole content and then return a ReaderAt from the local content
+		// store. If efficient partial reads are desired in the future, something more like a "tee"
+		// that caches remote partial reads to a local store may need to replace this.
+		err := contentutil.Copy(ctx, p.ref.cm.ContentStore, &pullprogress.ProviderWithProgress{
+			Provider: p.dh.Provider(p.session),
+			Manager:  p.ref.cm.ContentStore,
+		}, p.desc, logs.LoggerFromContext(ctx))
+		if err != nil {
+			return nil, err
+		}
+
+		if imageRefs := getImageRefs(p.ref.md); len(imageRefs) > 0 {
+			// just use the first image ref, it's arbitrary
+			imageRef := imageRefs[0]
+			if GetDescription(p.ref.md) == "" {
+				queueDescription(p.ref.md, "pulled from "+imageRef)
+				err := p.ref.md.Commit()
+				if err != nil {
+					return nil, err
+				}
+			}
+		}
+		return nil, err
+	})
+	return err
+}
diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/export.go b/vendor/github.com/moby/buildkit/cache/remotecache/export.go
index d9d5bab..b39045c 100644
--- a/vendor/github.com/moby/buildkit/cache/remotecache/export.go
+++ b/vendor/github.com/moby/buildkit/cache/remotecache/export.go
@@ -12,8 +12,10 @@
 	v1 "github.com/moby/buildkit/cache/remotecache/v1"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
 	"github.com/moby/buildkit/util/contentutil"
 	"github.com/moby/buildkit/util/progress"
+	"github.com/moby/buildkit/util/progress/logs"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -55,20 +57,17 @@
 	solver.CacheExporterTarget
 	chains   *v1.CacheChains
 	ingester content.Ingester
+	oci      bool
 }
 
-func NewExporter(ingester content.Ingester) Exporter {
+func NewExporter(ingester content.Ingester, oci bool) Exporter {
 	cc := v1.NewCacheChains()
-	return &contentCacheExporter{CacheExporterTarget: cc, chains: cc, ingester: ingester}
+	return &contentCacheExporter{CacheExporterTarget: cc, chains: cc, ingester: ingester, oci: oci}
 }
 
 func (ce *contentCacheExporter) Finalize(ctx context.Context) (map[string]string, error) {
-	return export(ctx, ce.ingester, ce.chains)
-}
-
-func export(ctx context.Context, ingester content.Ingester, cc *v1.CacheChains) (map[string]string, error) {
 	res := make(map[string]string)
-	config, descs, err := cc.Marshal()
+	config, descs, err := ce.chains.Marshal()
 	if err != nil {
 		return nil, err
 	}
@@ -86,6 +85,9 @@
 	var mfst manifestList
 	mfst.SchemaVersion = 2
 	mfst.MediaType = images.MediaTypeDockerSchema2ManifestList
+	if ce.oci {
+		mfst.MediaType = ocispec.MediaTypeImageIndex
+	}
 
 	for _, l := range config.Layers {
 		dgstPair, ok := descs[l.Blob]
@@ -93,13 +95,15 @@
 			return nil, errors.Errorf("missing blob %s", l.Blob)
 		}
 		layerDone := oneOffProgress(ctx, fmt.Sprintf("writing layer %s", l.Blob))
-		if err := contentutil.Copy(ctx, ingester, dgstPair.Provider, dgstPair.Descriptor); err != nil {
+		if err := contentutil.Copy(ctx, ce.ingester, dgstPair.Provider, dgstPair.Descriptor, logs.LoggerFromContext(ctx)); err != nil {
 			return nil, layerDone(errors.Wrap(err, "error writing layer blob"))
 		}
 		layerDone(nil)
 		mfst.Manifests = append(mfst.Manifests, dgstPair.Descriptor)
 	}
 
+	mfst.Manifests = compression.ConvertAllLayerMediaTypes(ce.oci, mfst.Manifests...)
+
 	dt, err := json.Marshal(config)
 	if err != nil {
 		return nil, err
@@ -111,7 +115,7 @@
 		MediaType: v1.CacheConfigMediaTypeV0,
 	}
 	configDone := oneOffProgress(ctx, fmt.Sprintf("writing config %s", dgst))
-	if err := content.WriteBlob(ctx, ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
+	if err := content.WriteBlob(ctx, ce.ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
 		return nil, configDone(errors.Wrap(err, "error writing config blob"))
 	}
 	configDone(nil)
@@ -130,7 +134,7 @@
 		MediaType: mfst.MediaType,
 	}
 	mfstDone := oneOffProgress(ctx, fmt.Sprintf("writing manifest %s", dgst))
-	if err := content.WriteBlob(ctx, ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
+	if err := content.WriteBlob(ctx, ce.ingester, dgst.String(), bytes.NewReader(dt), desc); err != nil {
 		return nil, mfstDone(errors.Wrap(err, "error writing manifest blob"))
 	}
 	descJSON, err := json.Marshal(desc)
diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go b/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go
index dabb235..2ee194a 100644
--- a/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go
+++ b/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"strconv"
 	"time"
 
 	"github.com/containerd/containerd/content"
@@ -17,6 +18,7 @@
 	attrDigest           = "digest"
 	attrSrc              = "src"
 	attrDest             = "dest"
+	attrOCIMediatypes    = "oci-mediatypes"
 	contentStoreIDPrefix = "local:"
 )
 
@@ -27,12 +29,20 @@
 		if store == "" {
 			return nil, errors.New("local cache exporter requires dest")
 		}
+		ociMediatypes := true
+		if v, ok := attrs[attrOCIMediatypes]; ok {
+			b, err := strconv.ParseBool(v)
+			if err != nil {
+				return nil, errors.Wrapf(err, "failed to parse %s", attrOCIMediatypes)
+			}
+			ociMediatypes = b
+		}
 		csID := contentStoreIDPrefix + store
 		cs, err := getContentStore(ctx, sm, g, csID)
 		if err != nil {
 			return nil, err
 		}
-		return remotecache.NewExporter(cs), nil
+		return remotecache.NewExporter(cs, ociMediatypes), nil
 	}
 }
 
@@ -76,7 +86,7 @@
 	timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 	defer cancel()
 
-	caller, err := sm.Get(timeoutCtx, sessionID)
+	caller, err := sm.Get(timeoutCtx, sessionID, false)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go b/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go
index e81fcb9..281d9fa 100644
--- a/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go
+++ b/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"strconv"
 
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/remotes/docker"
@@ -28,7 +29,8 @@
 }
 
 const (
-	attrRef = "ref"
+	attrRef           = "ref"
+	attrOCIMediatypes = "oci-mediatypes"
 )
 
 func ResolveCacheExporterFunc(sm *session.Manager, hosts docker.RegistryHosts) remotecache.ResolveCacheExporterFunc {
@@ -37,12 +39,20 @@
 		if err != nil {
 			return nil, err
 		}
-		remote := resolver.New(hosts, resolver.NewSessionAuthenticator(sm, g))
+		ociMediatypes := true
+		if v, ok := attrs[attrOCIMediatypes]; ok {
+			b, err := strconv.ParseBool(v)
+			if err != nil {
+				return nil, errors.Wrapf(err, "failed to parse %s", attrOCIMediatypes)
+			}
+			ociMediatypes = b
+		}
+		remote := resolver.DefaultPool.GetResolver(hosts, ref, "push", sm, g)
 		pusher, err := remote.Pusher(ctx, ref)
 		if err != nil {
 			return nil, err
 		}
-		return remotecache.NewExporter(contentutil.FromPusher(pusher)), nil
+		return remotecache.NewExporter(contentutil.FromPusher(pusher), ociMediatypes), nil
 	}
 }
 
@@ -52,7 +62,7 @@
 		if err != nil {
 			return nil, specs.Descriptor{}, err
 		}
-		remote := resolver.New(hosts, resolver.NewSessionAuthenticator(sm, g))
+		remote := resolver.DefaultPool.GetResolver(hosts, ref, "pull", sm, g)
 		xref, desc, err := remote.Resolve(ctx, ref)
 		if err != nil {
 			return nil, specs.Descriptor{}, err
diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/v1/cachestorage.go b/vendor/github.com/moby/buildkit/cache/remotecache/v1/cachestorage.go
index 728b85a..dee02f4 100644
--- a/vendor/github.com/moby/buildkit/cache/remotecache/v1/cachestorage.go
+++ b/vendor/github.com/moby/buildkit/cache/remotecache/v1/cachestorage.go
@@ -5,6 +5,7 @@
 	"time"
 
 	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/worker"
 	digest "github.com/opencontainers/go-digest"
@@ -260,7 +261,7 @@
 	return worker.NewWorkerRefResult(ref, cs.w), nil
 }
 
-func (cs *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult) (*solver.Remote, error) {
+func (cs *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult, _ session.Group) (*solver.Remote, error) {
 	if r := cs.byResultID(res.ID); r != nil && r.result != nil {
 		return r.result, nil
 	}
diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go b/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go
index a9b11c3..a76cc69 100644
--- a/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go
+++ b/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go
@@ -23,7 +23,7 @@
 	if strings.HasPrefix(dgst.String(), "random:") {
 		return &nopRecord{}
 	}
-	it := &item{c: c, dgst: dgst}
+	it := &item{c: c, dgst: dgst, backlinks: map[*item]struct{}{}}
 	c.items = append(c.items, it)
 	return it
 }
@@ -44,6 +44,17 @@
 		byKey: map[digest.Digest]*item{},
 	}
 
+	validated := make([]*item, 0, len(c.items))
+	for _, it := range c.items {
+		it.validate()
+	}
+	for _, it := range c.items {
+		if !it.invalid {
+			validated = append(validated, it)
+		}
+	}
+	c.items = validated
+
 	for _, it := range c.items {
 		_, err := normalizeItem(it, st)
 		if err != nil {
@@ -99,7 +110,9 @@
 	result     *solver.Remote
 	resultTime time.Time
 
-	links []map[link]struct{}
+	links     []map[link]struct{}
+	backlinks map[*item]struct{}
+	invalid   bool
 }
 
 type link struct {
@@ -126,6 +139,30 @@
 	}
 
 	c.links[index][link{src: src, selector: selector}] = struct{}{}
+	src.backlinks[c] = struct{}{}
+}
+
+func (c *item) validate() {
+	for _, m := range c.links {
+		if len(m) == 0 {
+			c.invalid = true
+			for bl := range c.backlinks {
+				changed := false
+				for _, m := range bl.links {
+					for l := range m {
+						if l.src == c {
+							delete(m, l)
+							changed = true
+						}
+					}
+				}
+				if changed {
+					bl.validate()
+				}
+			}
+			return
+		}
+	}
 }
 
 func (c *item) walkAllResults(fn func(i *item) error, visited map[*item]struct{}) error {
diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/v1/utils.go b/vendor/github.com/moby/buildkit/cache/remotecache/v1/utils.go
index dfc7fab..fc494aa 100644
--- a/vendor/github.com/moby/buildkit/cache/remotecache/v1/utils.go
+++ b/vendor/github.com/moby/buildkit/cache/remotecache/v1/utils.go
@@ -4,10 +4,9 @@
 	"fmt"
 	"sort"
 
-	"github.com/containerd/containerd/content"
+	"github.com/moby/buildkit/exporter/containerimage/exptypes"
 	"github.com/moby/buildkit/solver"
 	digest "github.com/opencontainers/go-digest"
-	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 )
 
@@ -230,10 +229,6 @@
 	if len(r.Descriptors) == 0 {
 		return ""
 	}
-	type Remote struct {
-		Descriptors []ocispec.Descriptor
-		Provider    content.Provider
-	}
 	var parentID string
 	if len(r.Descriptors) > 1 {
 		r2 := &solver.Remote{
@@ -244,6 +239,10 @@
 	}
 	desc := r.Descriptors[len(r.Descriptors)-1]
 
+	if desc.Digest == exptypes.EmptyGZLayer {
+		return parentID
+	}
+
 	state.descriptors[desc.Digest] = DescriptorProviderPair{
 		Descriptor: desc,
 		Provider:   r.Provider,
diff --git a/vendor/github.com/moby/buildkit/cache/util/fsutil.go b/vendor/github.com/moby/buildkit/cache/util/fsutil.go
index 41e5465..b425a00 100644
--- a/vendor/github.com/moby/buildkit/cache/util/fsutil.go
+++ b/vendor/github.com/moby/buildkit/cache/util/fsutil.go
@@ -8,7 +8,6 @@
 	"path/filepath"
 
 	"github.com/containerd/continuity/fs"
-	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/snapshot"
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil"
@@ -25,12 +24,7 @@
 	Length int
 }
 
-func withMount(ctx context.Context, ref cache.ImmutableRef, cb func(string) error) error {
-	mount, err := ref.Mount(ctx, true)
-	if err != nil {
-		return err
-	}
-
+func withMount(ctx context.Context, mount snapshot.Mountable, cb func(string) error) error {
 	lm := snapshot.LocalMounter(mount)
 
 	root, err := lm.Mount()
@@ -55,10 +49,10 @@
 	return nil
 }
 
-func ReadFile(ctx context.Context, ref cache.ImmutableRef, req ReadRequest) ([]byte, error) {
+func ReadFile(ctx context.Context, mount snapshot.Mountable, req ReadRequest) ([]byte, error) {
 	var dt []byte
 
-	err := withMount(ctx, ref, func(root string) error {
+	err := withMount(ctx, mount, func(root string) error {
 		fp, err := fs.RootPath(root, req.Filename)
 		if err != nil {
 			return errors.WithStack(err)
@@ -90,7 +84,7 @@
 	IncludePattern string
 }
 
-func ReadDir(ctx context.Context, ref cache.ImmutableRef, req ReadDirRequest) ([]*fstypes.Stat, error) {
+func ReadDir(ctx context.Context, mount snapshot.Mountable, req ReadDirRequest) ([]*fstypes.Stat, error) {
 	var (
 		rd []*fstypes.Stat
 		wo fsutil.WalkOpt
@@ -98,7 +92,7 @@
 	if req.IncludePattern != "" {
 		wo.IncludePatterns = append(wo.IncludePatterns, req.IncludePattern)
 	}
-	err := withMount(ctx, ref, func(root string) error {
+	err := withMount(ctx, mount, func(root string) error {
 		fp, err := fs.RootPath(root, req.Path)
 		if err != nil {
 			return errors.WithStack(err)
@@ -123,9 +117,9 @@
 	return rd, err
 }
 
-func StatFile(ctx context.Context, ref cache.ImmutableRef, path string) (*fstypes.Stat, error) {
+func StatFile(ctx context.Context, mount snapshot.Mountable, path string) (*fstypes.Stat, error) {
 	var st *fstypes.Stat
-	err := withMount(ctx, ref, func(root string) error {
+	err := withMount(ctx, mount, func(root string) error {
 		fp, err := fs.RootPath(root, path)
 		if err != nil {
 			return errors.WithStack(err)
diff --git a/vendor/github.com/moby/buildkit/client/build.go b/vendor/github.com/moby/buildkit/client/build.go
index 2518cd7..4cb91d7 100644
--- a/vendor/github.com/moby/buildkit/client/build.go
+++ b/vendor/github.com/moby/buildkit/client/build.go
@@ -45,11 +45,14 @@
 	}
 
 	cb := func(ref string, s *session.Session) error {
-		g, err := grpcclient.New(ctx, feOpts, s.ID(), product, c.gatewayClientForBuild(ref), gworkers)
+		gwClient := c.gatewayClientForBuild(ref)
+		g, err := grpcclient.New(ctx, feOpts, s.ID(), product, gwClient, gworkers)
 		if err != nil {
 			return err
 		}
 
+		gwClient.caps = g.BuildOpts().Caps
+
 		if err := g.Run(ctx, buildFunc); err != nil {
 			return errors.Wrap(err, "failed to run Build function")
 		}
@@ -59,14 +62,18 @@
 	return c.solve(ctx, nil, cb, opt, statusChan)
 }
 
-func (c *Client) gatewayClientForBuild(buildid string) gatewayapi.LLBBridgeClient {
+func (c *Client) gatewayClientForBuild(buildid string) *gatewayClientForBuild {
 	g := gatewayapi.NewLLBBridgeClient(c.conn)
-	return &gatewayClientForBuild{g, buildid}
+	return &gatewayClientForBuild{
+		gateway: g,
+		buildID: buildid,
+	}
 }
 
 type gatewayClientForBuild struct {
 	gateway gatewayapi.LLBBridgeClient
 	buildID string
+	caps    apicaps.CapSet
 }
 
 func (g *gatewayClientForBuild) ResolveImageConfig(ctx context.Context, in *gatewayapi.ResolveImageConfigRequest, opts ...grpc.CallOption) (*gatewayapi.ResolveImageConfigResponse, error) {
@@ -85,11 +92,17 @@
 }
 
 func (g *gatewayClientForBuild) ReadDir(ctx context.Context, in *gatewayapi.ReadDirRequest, opts ...grpc.CallOption) (*gatewayapi.ReadDirResponse, error) {
+	if err := g.caps.Supports(gatewayapi.CapReadDir); err != nil {
+		return nil, err
+	}
 	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
 	return g.gateway.ReadDir(ctx, in, opts...)
 }
 
 func (g *gatewayClientForBuild) StatFile(ctx context.Context, in *gatewayapi.StatFileRequest, opts ...grpc.CallOption) (*gatewayapi.StatFileResponse, error) {
+	if err := g.caps.Supports(gatewayapi.CapStatFile); err != nil {
+		return nil, err
+	}
 	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
 	return g.gateway.StatFile(ctx, in, opts...)
 }
@@ -105,6 +118,33 @@
 }
 
 func (g *gatewayClientForBuild) Inputs(ctx context.Context, in *gatewayapi.InputsRequest, opts ...grpc.CallOption) (*gatewayapi.InputsResponse, error) {
+	if err := g.caps.Supports(gatewayapi.CapFrontendInputs); err != nil {
+		return nil, err
+	}
 	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
 	return g.gateway.Inputs(ctx, in, opts...)
 }
+
+func (g *gatewayClientForBuild) NewContainer(ctx context.Context, in *gatewayapi.NewContainerRequest, opts ...grpc.CallOption) (*gatewayapi.NewContainerResponse, error) {
+	if err := g.caps.Supports(gatewayapi.CapGatewayExec); err != nil {
+		return nil, err
+	}
+	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
+	return g.gateway.NewContainer(ctx, in, opts...)
+}
+
+func (g *gatewayClientForBuild) ReleaseContainer(ctx context.Context, in *gatewayapi.ReleaseContainerRequest, opts ...grpc.CallOption) (*gatewayapi.ReleaseContainerResponse, error) {
+	if err := g.caps.Supports(gatewayapi.CapGatewayExec); err != nil {
+		return nil, err
+	}
+	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
+	return g.gateway.ReleaseContainer(ctx, in, opts...)
+}
+
+func (g *gatewayClientForBuild) ExecProcess(ctx context.Context, opts ...grpc.CallOption) (gatewayapi.LLBBridge_ExecProcessClient, error) {
+	if err := g.caps.Supports(gatewayapi.CapGatewayExec); err != nil {
+		return nil, err
+	}
+	ctx = buildid.AppendToOutgoingContext(ctx, g.buildID)
+	return g.gateway.ExecProcess(ctx, opts...)
+}
diff --git a/vendor/github.com/moby/buildkit/client/client.go b/vendor/github.com/moby/buildkit/client/client.go
index 0546f46..38429ff 100644
--- a/vendor/github.com/moby/buildkit/client/client.go
+++ b/vendor/github.com/moby/buildkit/client/client.go
@@ -6,8 +6,9 @@
 	"crypto/x509"
 	"io/ioutil"
 	"net"
-	"time"
+	"net/url"
 
+	"github.com/containerd/containerd/defaults"
 	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
 	controlapi "github.com/moby/buildkit/api/services/control"
@@ -30,7 +31,10 @@
 
 // New returns a new buildkit client. Address can be empty for the system-default address.
 func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error) {
-	gopts := []grpc.DialOption{}
+	gopts := []grpc.DialOption{
+		grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
+		grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
+	}
 	needDialer := true
 	needWithInsecure := true
 
@@ -54,7 +58,7 @@
 			stream = append(stream, otgrpc.OpenTracingStreamClientInterceptor(wt.tracer))
 		}
 		if wd, ok := o.(*withDialer); ok {
-			gopts = append(gopts, grpc.WithDialer(wd.dialer))
+			gopts = append(gopts, grpc.WithContextDialer(wd.dialer))
 			needDialer = false
 		}
 	}
@@ -63,9 +67,7 @@
 		if err != nil {
 			return nil, err
 		}
-		// TODO(AkihiroSuda): use WithContextDialer (requires grpc 1.19)
-		// https://github.com/grpc/grpc-go/commit/40cb5618f475e7b9d61aa7920ae4b04ef9bbaf89
-		gopts = append(gopts, grpc.WithDialer(dialFn))
+		gopts = append(gopts, grpc.WithContextDialer(dialFn))
 	}
 	if needWithInsecure {
 		gopts = append(gopts, grpc.WithInsecure())
@@ -74,6 +76,15 @@
 		address = appdefaults.Address
 	}
 
+	// grpc-go uses a slightly different naming scheme: https://github.com/grpc/grpc/blob/master/doc/naming.md
+	// This will end up setting rfc non-complient :authority header to address string (e.g. tcp://127.0.0.1:1234).
+	// So, here sets right authority header via WithAuthority DialOption.
+	addressURL, err := url.Parse(address)
+	if err != nil {
+		return nil, err
+	}
+	gopts = append(gopts, grpc.WithAuthority(addressURL.Host))
+
 	unary = append(unary, grpcerrors.UnaryClientInterceptor)
 	stream = append(stream, grpcerrors.StreamClientInterceptor)
 
@@ -118,10 +129,10 @@
 }
 
 type withDialer struct {
-	dialer func(string, time.Duration) (net.Conn, error)
+	dialer func(context.Context, string) (net.Conn, error)
 }
 
-func WithDialer(df func(string, time.Duration) (net.Conn, error)) ClientOpt {
+func WithContextDialer(df func(context.Context, string) (net.Conn, error)) ClientOpt {
 	return &withDialer{dialer: df}
 }
 
@@ -179,17 +190,13 @@
 	tracer opentracing.Tracer
 }
 
-func resolveDialer(address string) (func(string, time.Duration) (net.Conn, error), error) {
+func resolveDialer(address string) (func(context.Context, string) (net.Conn, error), error) {
 	ch, err := connhelper.GetConnectionHelper(address)
 	if err != nil {
 		return nil, err
 	}
 	if ch != nil {
-		f := func(a string, _ time.Duration) (net.Conn, error) {
-			ctx := context.Background()
-			return ch.ContextDialer(ctx, a)
-		}
-		return f, nil
+		return ch.ContextDialer, nil
 	}
 	// basic dialer
 	return dialer, nil
diff --git a/vendor/github.com/moby/buildkit/client/client_unix.go b/vendor/github.com/moby/buildkit/client/client_unix.go
index 93afb95..888a817 100644
--- a/vendor/github.com/moby/buildkit/client/client_unix.go
+++ b/vendor/github.com/moby/buildkit/client/client_unix.go
@@ -3,17 +3,18 @@
 package client
 
 import (
+	"context"
 	"net"
 	"strings"
-	"time"
 
 	"github.com/pkg/errors"
 )
 
-func dialer(address string, timeout time.Duration) (net.Conn, error) {
+func dialer(ctx context.Context, address string) (net.Conn, error) {
 	addrParts := strings.SplitN(address, "://", 2)
 	if len(addrParts) != 2 {
 		return nil, errors.Errorf("invalid address %s", address)
 	}
-	return net.DialTimeout(addrParts[0], addrParts[1], timeout)
+	var d net.Dialer
+	return d.DialContext(ctx, addrParts[0], addrParts[1])
 }
diff --git a/vendor/github.com/moby/buildkit/client/client_windows.go b/vendor/github.com/moby/buildkit/client/client_windows.go
index d0d8a1b..a9eb87f 100644
--- a/vendor/github.com/moby/buildkit/client/client_windows.go
+++ b/vendor/github.com/moby/buildkit/client/client_windows.go
@@ -1,15 +1,15 @@
 package client
 
 import (
+	"context"
 	"net"
 	"strings"
-	"time"
 
 	winio "github.com/Microsoft/go-winio"
 	"github.com/pkg/errors"
 )
 
-func dialer(address string, timeout time.Duration) (net.Conn, error) {
+func dialer(ctx context.Context, address string) (net.Conn, error) {
 	addrParts := strings.SplitN(address, "://", 2)
 	if len(addrParts) != 2 {
 		return nil, errors.Errorf("invalid address %s", address)
@@ -17,8 +17,9 @@
 	switch addrParts[0] {
 	case "npipe":
 		address = strings.Replace(addrParts[1], "/", "\\", -1)
-		return winio.DialPipe(address, &timeout)
+		return winio.DialPipeContext(ctx, address)
 	default:
-		return net.DialTimeout(addrParts[0], addrParts[1], timeout)
+		var d net.Dialer
+		return d.DialContext(ctx, addrParts[0], addrParts[1])
 	}
 }
diff --git a/vendor/github.com/moby/buildkit/client/llb/definition.go b/vendor/github.com/moby/buildkit/client/llb/definition.go
index fe9f7c1..99af7c6 100644
--- a/vendor/github.com/moby/buildkit/client/llb/definition.go
+++ b/vendor/github.com/moby/buildkit/client/llb/definition.go
@@ -16,14 +16,15 @@
 // LLB state can be reconstructed from the definition.
 type DefinitionOp struct {
 	MarshalCache
-	mu        sync.Mutex
-	ops       map[digest.Digest]*pb.Op
-	defs      map[digest.Digest][]byte
-	metas     map[digest.Digest]pb.OpMetadata
-	sources   map[digest.Digest][]*SourceLocation
-	platforms map[digest.Digest]*specs.Platform
-	dgst      digest.Digest
-	index     pb.OutputIndex
+	mu         sync.Mutex
+	ops        map[digest.Digest]*pb.Op
+	defs       map[digest.Digest][]byte
+	metas      map[digest.Digest]pb.OpMetadata
+	sources    map[digest.Digest][]*SourceLocation
+	platforms  map[digest.Digest]*specs.Platform
+	dgst       digest.Digest
+	index      pb.OutputIndex
+	inputCache map[digest.Digest][]*DefinitionOp
 }
 
 // NewDefinitionOp returns a new operation from a marshalled definition.
@@ -89,13 +90,14 @@
 	}
 
 	return &DefinitionOp{
-		ops:       ops,
-		defs:      defs,
-		metas:     def.Metadata,
-		sources:   srcs,
-		platforms: platforms,
-		dgst:      dgst,
-		index:     index,
+		ops:        ops,
+		defs:       defs,
+		metas:      def.Metadata,
+		sources:    srcs,
+		platforms:  platforms,
+		dgst:       dgst,
+		index:      index,
+		inputCache: make(map[digest.Digest][]*DefinitionOp),
 	}, nil
 }
 
@@ -188,14 +190,34 @@
 	d.mu.Unlock()
 
 	for _, input := range op.Inputs {
-		vtx := &DefinitionOp{
-			ops:       d.ops,
-			defs:      d.defs,
-			metas:     d.metas,
-			platforms: d.platforms,
-			dgst:      input.Digest,
-			index:     input.Index,
+		var vtx *DefinitionOp
+		d.mu.Lock()
+		if existingIndexes, ok := d.inputCache[input.Digest]; ok {
+			if int(input.Index) < len(existingIndexes) && existingIndexes[input.Index] != nil {
+				vtx = existingIndexes[input.Index]
+			}
 		}
+		if vtx == nil {
+			vtx = &DefinitionOp{
+				ops:        d.ops,
+				defs:       d.defs,
+				metas:      d.metas,
+				platforms:  d.platforms,
+				dgst:       input.Digest,
+				index:      input.Index,
+				inputCache: d.inputCache,
+			}
+			existingIndexes := d.inputCache[input.Digest]
+			indexDiff := int(input.Index) - len(existingIndexes)
+			if indexDiff >= 0 {
+				// make room in the slice for the new index being set
+				existingIndexes = append(existingIndexes, make([]*DefinitionOp, indexDiff+1)...)
+			}
+			existingIndexes[input.Index] = vtx
+			d.inputCache[input.Digest] = existingIndexes
+		}
+		d.mu.Unlock()
+
 		inputs = append(inputs, &output{vertex: vtx, platform: platform, getIndex: func() (pb.OutputIndex, error) {
 			return pb.OutputIndex(vtx.index), nil
 		}})
diff --git a/vendor/github.com/moby/buildkit/client/llb/exec.go b/vendor/github.com/moby/buildkit/client/llb/exec.go
index 9d27bbc..decc0d7 100644
--- a/vendor/github.com/moby/buildkit/client/llb/exec.go
+++ b/vendor/github.com/moby/buildkit/client/llb/exec.go
@@ -2,7 +2,7 @@
 
 import (
 	"context"
-	_ "crypto/sha256"
+	_ "crypto/sha256" // for opencontainers/go-digest
 	"fmt"
 	"net"
 	"sort"
@@ -153,7 +153,13 @@
 	}
 	if c.Caps != nil {
 		if err := c.Caps.Supports(pb.CapExecMetaSetsDefaultPath); err != nil {
-			env = env.SetDefault("PATH", system.DefaultPathEnv)
+			os := "linux"
+			if c.Platform != nil {
+				os = c.Platform.OS
+			} else if e.constraints.Platform != nil {
+				os = e.constraints.Platform.OS
+			}
+			env = env.SetDefault("PATH", system.DefaultPathEnv(os))
 		} else {
 			addCap(&e.constraints, pb.CapExecMetaSetsDefaultPath)
 		}
@@ -174,11 +180,17 @@
 		return "", nil, nil, nil, err
 	}
 
+	hostname, err := getHostname(e.base)(ctx)
+	if err != nil {
+		return "", nil, nil, nil, err
+	}
+
 	meta := &pb.Meta{
-		Args: args,
-		Env:  env.ToArray(),
-		Cwd:  cwd,
-		User: user,
+		Args:     args,
+		Env:      env.ToArray(),
+		Cwd:      cwd,
+		User:     user,
+		Hostname: hostname,
 	}
 	extraHosts, err := getExtraHosts(e.base)(ctx)
 	if err != nil {
@@ -217,9 +229,9 @@
 
 	if p := e.proxyEnv; p != nil {
 		peo.Meta.ProxyEnv = &pb.ProxyEnv{
-			HttpProxy:  p.HttpProxy,
-			HttpsProxy: p.HttpsProxy,
-			FtpProxy:   p.FtpProxy,
+			HttpProxy:  p.HTTPProxy,
+			HttpsProxy: p.HTTPSProxy,
+			FtpProxy:   p.FTPProxy,
 			NoProxy:    p.NoProxy,
 		}
 		addCap(&e.constraints, pb.CapExecMetaProxy)
@@ -629,9 +641,9 @@
 }
 
 type ProxyEnv struct {
-	HttpProxy  string
-	HttpsProxy string
-	FtpProxy   string
+	HTTPProxy  string
+	HTTPSProxy string
+	FTPProxy   string
 	NoProxy    string
 }
 
diff --git a/vendor/github.com/moby/buildkit/client/llb/fileop.go b/vendor/github.com/moby/buildkit/client/llb/fileop.go
index db5ed00..fdcf992 100644
--- a/vendor/github.com/moby/buildkit/client/llb/fileop.go
+++ b/vendor/github.com/moby/buildkit/client/llb/fileop.go
@@ -2,7 +2,7 @@
 
 import (
 	"context"
-	_ "crypto/sha256"
+	_ "crypto/sha256" // for opencontainers/go-digest
 	"os"
 	"path"
 	"strconv"
@@ -252,13 +252,13 @@
 	mi.ChownOpt = &co
 }
 
-func (cp *ChownOpt) marshal(base pb.InputIndex) *pb.ChownOpt {
-	if cp == nil {
+func (co *ChownOpt) marshal(base pb.InputIndex) *pb.ChownOpt {
+	if co == nil {
 		return nil
 	}
 	return &pb.ChownOpt{
-		User:  cp.User.marshal(base),
-		Group: cp.Group.marshal(base),
+		User:  co.User.marshal(base),
+		Group: co.Group.marshal(base),
 	}
 }
 
@@ -476,17 +476,17 @@
 	}, nil
 }
 
-func (c *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
-	p := path.Clean(c.src)
+func (a *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
+	p := path.Clean(a.src)
 	if !path.IsAbs(p) {
-		if c.state != nil {
-			dir, err := c.state.GetDir(ctx)
+		if a.state != nil {
+			dir, err := a.state.GetDir(ctx)
 			if err != nil {
 				return "", err
 			}
 			p = path.Join("/", dir, p)
-		} else if c.fas != nil {
-			dir, err := c.fas.state.GetDir(ctx)
+		} else if a.fas != nil {
+			dir, err := a.fas.state.GetDir(ctx)
 			if err != nil {
 				return "", err
 			}
diff --git a/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go b/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go
index 0dbd473..97a0cba 100644
--- a/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go
+++ b/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go
@@ -8,10 +8,10 @@
 	"github.com/containerd/containerd/platforms"
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
-	"github.com/docker/docker/pkg/locker"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/util/contentutil"
 	"github.com/moby/buildkit/util/imageutil"
+	"github.com/moby/locker"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 )
diff --git a/vendor/github.com/moby/buildkit/client/llb/meta.go b/vendor/github.com/moby/buildkit/client/llb/meta.go
index ab0f593..80cc18d 100644
--- a/vendor/github.com/moby/buildkit/client/llb/meta.go
+++ b/vendor/github.com/moby/buildkit/client/llb/meta.go
@@ -19,6 +19,7 @@
 	keyDir       = contextKeyT("llb.exec.dir")
 	keyEnv       = contextKeyT("llb.exec.env")
 	keyUser      = contextKeyT("llb.exec.user")
+	keyHostname  = contextKeyT("llb.exec.hostname")
 	keyExtraHost = contextKeyT("llb.exec.extrahost")
 	keyPlatform  = contextKeyT("llb.platform")
 	keyNetwork   = contextKeyT("llb.network")
@@ -143,6 +144,25 @@
 	}
 }
 
+func Hostname(str string) StateOption {
+	return func(s State) State {
+		return s.WithValue(keyHostname, str)
+	}
+}
+
+func getHostname(s State) func(context.Context) (string, error) {
+	return func(ctx context.Context) (string, error) {
+		v, err := s.getValue(keyHostname)(ctx)
+		if err != nil {
+			return "", err
+		}
+		if v != nil {
+			return v.(string), nil
+		}
+		return "", nil
+	}
+}
+
 func args(args ...string) StateOption {
 	return func(s State) State {
 		return s.WithValue(keyArgs, args)
@@ -155,7 +175,7 @@
 	}
 	return func(s State) State {
 		arg, err := shlex.Split(str)
-		if err != nil {
+		if err != nil { //nolint
 			// TODO: handle error
 		}
 		return args(arg...)(s)
diff --git a/vendor/github.com/moby/buildkit/client/llb/source.go b/vendor/github.com/moby/buildkit/client/llb/source.go
index 51fdcf9..af48a1d 100644
--- a/vendor/github.com/moby/buildkit/client/llb/source.go
+++ b/vendor/github.com/moby/buildkit/client/llb/source.go
@@ -2,15 +2,17 @@
 
 import (
 	"context"
-	_ "crypto/sha256"
+	_ "crypto/sha256" // for opencontainers/go-digest
 	"encoding/json"
 	"os"
+	"regexp"
 	"strconv"
 	"strings"
 
 	"github.com/docker/distribution/reference"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/apicaps"
+	"github.com/moby/buildkit/util/sshutil"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 )
@@ -197,15 +199,59 @@
 	RecordType    string
 }
 
-func Git(remote, ref string, opts ...GitOption) State {
-	url := ""
+const (
+	gitProtocolHTTP = iota + 1
+	gitProtocolHTTPS
+	gitProtocolSSH
+	gitProtocolGit
+	gitProtocolUnknown
+)
 
-	for _, prefix := range []string{
-		"http://", "https://", "git://", "git@",
-	} {
+var gitSSHRegex = regexp.MustCompile("^([a-z0-9]+@)?[^:]+:.*$")
+
+func getGitProtocol(remote string) (string, int) {
+	prefixes := map[string]int{
+		"http://":  gitProtocolHTTP,
+		"https://": gitProtocolHTTPS,
+		"git://":   gitProtocolGit,
+		"ssh://":   gitProtocolSSH,
+	}
+	protocolType := gitProtocolUnknown
+	for prefix, potentialType := range prefixes {
 		if strings.HasPrefix(remote, prefix) {
-			url = strings.Split(remote, "#")[0]
 			remote = strings.TrimPrefix(remote, prefix)
+			protocolType = potentialType
+		}
+	}
+
+	if protocolType == gitProtocolUnknown && gitSSHRegex.MatchString(remote) {
+		protocolType = gitProtocolSSH
+	}
+
+	// remove name from ssh
+	if protocolType == gitProtocolSSH {
+		parts := strings.SplitN(remote, "@", 2)
+		if len(parts) == 2 {
+			remote = parts[1]
+		}
+	}
+
+	return remote, protocolType
+}
+
+func Git(remote, ref string, opts ...GitOption) State {
+	url := strings.Split(remote, "#")[0]
+
+	var protocolType int
+	remote, protocolType = getGitProtocol(remote)
+
+	var sshHost string
+	if protocolType == gitProtocolSSH {
+		parts := strings.SplitN(remote, ":", 2)
+		if len(parts) == 2 {
+			sshHost = parts[0]
+			// keep remote consistent with http(s) version
+			remote = parts[0] + "/" + parts[1]
 		}
 	}
 
@@ -233,11 +279,34 @@
 	}
 	if gi.AuthTokenSecret != "" {
 		attrs[pb.AttrAuthTokenSecret] = gi.AuthTokenSecret
-		addCap(&gi.Constraints, pb.CapSourceGitHttpAuth)
+		if gi.addAuthCap {
+			addCap(&gi.Constraints, pb.CapSourceGitHTTPAuth)
+		}
 	}
 	if gi.AuthHeaderSecret != "" {
 		attrs[pb.AttrAuthHeaderSecret] = gi.AuthHeaderSecret
-		addCap(&gi.Constraints, pb.CapSourceGitHttpAuth)
+		if gi.addAuthCap {
+			addCap(&gi.Constraints, pb.CapSourceGitHTTPAuth)
+		}
+	}
+	if protocolType == gitProtocolSSH {
+		if gi.KnownSSHHosts != "" {
+			attrs[pb.AttrKnownSSHHosts] = gi.KnownSSHHosts
+		} else if sshHost != "" {
+			keyscan, err := sshutil.SSHKeyScan(sshHost)
+			if err == nil {
+				// best effort
+				attrs[pb.AttrKnownSSHHosts] = keyscan
+			}
+		}
+		addCap(&gi.Constraints, pb.CapSourceGitKnownSSHHosts)
+
+		if gi.MountSSHSock == "" {
+			attrs[pb.AttrMountSSHSock] = "default"
+		} else {
+			attrs[pb.AttrMountSSHSock] = gi.MountSSHSock
+		}
+		addCap(&gi.Constraints, pb.CapSourceGitMountSSHSock)
 	}
 
 	addCap(&gi.Constraints, pb.CapSourceGit)
@@ -260,6 +329,9 @@
 	KeepGitDir       bool
 	AuthTokenSecret  string
 	AuthHeaderSecret string
+	addAuthCap       bool
+	KnownSSHHosts    string
+	MountSSHSock     string
 }
 
 func KeepGitDir() GitOption {
@@ -271,12 +343,27 @@
 func AuthTokenSecret(v string) GitOption {
 	return gitOptionFunc(func(gi *GitInfo) {
 		gi.AuthTokenSecret = v
+		gi.addAuthCap = true
 	})
 }
 
 func AuthHeaderSecret(v string) GitOption {
 	return gitOptionFunc(func(gi *GitInfo) {
 		gi.AuthHeaderSecret = v
+		gi.addAuthCap = true
+	})
+}
+
+func KnownSSHHosts(key string) GitOption {
+	key = strings.TrimSuffix(key, "\n")
+	return gitOptionFunc(func(gi *GitInfo) {
+		gi.KnownSSHHosts = gi.KnownSSHHosts + key + "\n"
+	})
+}
+
+func MountSSHSock(sshID string) GitOption {
+	return gitOptionFunc(func(gi *GitInfo) {
+		gi.MountSSHSock = sshID
 	})
 }
 
diff --git a/vendor/github.com/moby/buildkit/client/llb/state.go b/vendor/github.com/moby/buildkit/client/llb/state.go
index dac9b87..eca7164 100644
--- a/vendor/github.com/moby/buildkit/client/llb/state.go
+++ b/vendor/github.com/moby/buildkit/client/llb/state.go
@@ -320,6 +320,14 @@
 	return User(v)(s)
 }
 
+func (s State) Hostname(v string) State {
+	return Hostname(v)(s)
+}
+
+func (s State) GetHostname(ctx context.Context) (string, error) {
+	return getHostname(s)(ctx)
+}
+
 func (s State) Platform(p specs.Platform) State {
 	return platform(p)(s)
 }
diff --git a/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go b/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go
index 13f1d50..7bc5834 100644
--- a/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go
+++ b/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go
@@ -6,7 +6,7 @@
 	"os"
 
 	"github.com/gofrs/flock"
-	"github.com/opencontainers/image-spec/specs-go/v1"
+	v1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 )
 
diff --git a/vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go b/vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
index fc2da18..fe3e7ff 100644
--- a/vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
+++ b/vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
@@ -1,5 +1,7 @@
 package config
 
+import "github.com/BurntSushi/toml"
+
 // Config provides containerd configuration data for the server
 type Config struct {
 	Debug bool `toml:"debug"`
@@ -78,7 +80,13 @@
 	// incomplete and the intention is to make it default without config.
 	UserRemapUnsupported string `toml:"userRemapUnsupported"`
 	// For use in storing the OCI worker binary name that will replace buildkit-runc
-	Binary string `toml:"binary"`
+	Binary               string `toml:"binary"`
+	ProxySnapshotterPath string `toml:"proxySnapshotterPath"`
+
+	// StargzSnapshotterConfig is configuration for stargz snapshotter.
+	// Decoding this is delayed in order to remove the dependency from this
+	// config pkg to stargz snapshotter's config pkg.
+	StargzSnapshotterConfig toml.Primitive `toml:"stargzSnapshotter"`
 }
 
 type ContainerdConfig struct {
@@ -89,6 +97,7 @@
 	Namespace string            `toml:"namespace"`
 	GCConfig
 	NetworkConfig
+	Snapshotter string `toml:"snapshotter"`
 }
 
 type GCPolicy struct {
diff --git a/vendor/github.com/moby/buildkit/control/control.go b/vendor/github.com/moby/buildkit/control/control.go
index 0ee110e..048e696 100644
--- a/vendor/github.com/moby/buildkit/control/control.go
+++ b/vendor/github.com/moby/buildkit/control/control.go
@@ -63,7 +63,7 @@
 		cache:            cache,
 		gatewayForwarder: gatewayForwarder,
 	}
-	c.throttledGC = throttle.ThrottleAfter(time.Minute, c.gc)
+	c.throttledGC = throttle.After(time.Minute, c.gc)
 
 	defer func() {
 		time.AfterFunc(time.Second, c.throttledGC)
@@ -305,40 +305,56 @@
 			if !ok {
 				return nil
 			}
-			sr := controlapi.StatusResponse{}
-			for _, v := range ss.Vertexes {
-				sr.Vertexes = append(sr.Vertexes, &controlapi.Vertex{
-					Digest:    v.Digest,
-					Inputs:    v.Inputs,
-					Name:      v.Name,
-					Started:   v.Started,
-					Completed: v.Completed,
-					Error:     v.Error,
-					Cached:    v.Cached,
-				})
-			}
-			for _, v := range ss.Statuses {
-				sr.Statuses = append(sr.Statuses, &controlapi.VertexStatus{
-					ID:        v.ID,
-					Vertex:    v.Vertex,
-					Name:      v.Name,
-					Current:   v.Current,
-					Total:     v.Total,
-					Timestamp: v.Timestamp,
-					Started:   v.Started,
-					Completed: v.Completed,
-				})
-			}
-			for _, v := range ss.Logs {
-				sr.Logs = append(sr.Logs, &controlapi.VertexLog{
-					Vertex:    v.Vertex,
-					Stream:    int64(v.Stream),
-					Msg:       v.Data,
-					Timestamp: v.Timestamp,
-				})
-			}
-			if err := stream.SendMsg(&sr); err != nil {
-				return err
+			logSize := 0
+			retry := false
+			for {
+				sr := controlapi.StatusResponse{}
+				for _, v := range ss.Vertexes {
+					sr.Vertexes = append(sr.Vertexes, &controlapi.Vertex{
+						Digest:    v.Digest,
+						Inputs:    v.Inputs,
+						Name:      v.Name,
+						Started:   v.Started,
+						Completed: v.Completed,
+						Error:     v.Error,
+						Cached:    v.Cached,
+					})
+				}
+				for _, v := range ss.Statuses {
+					sr.Statuses = append(sr.Statuses, &controlapi.VertexStatus{
+						ID:        v.ID,
+						Vertex:    v.Vertex,
+						Name:      v.Name,
+						Current:   v.Current,
+						Total:     v.Total,
+						Timestamp: v.Timestamp,
+						Started:   v.Started,
+						Completed: v.Completed,
+					})
+				}
+				for i, v := range ss.Logs {
+					sr.Logs = append(sr.Logs, &controlapi.VertexLog{
+						Vertex:    v.Vertex,
+						Stream:    int64(v.Stream),
+						Msg:       v.Data,
+						Timestamp: v.Timestamp,
+					})
+					logSize += len(v.Data)
+					// avoid logs growing big and split apart if they do
+					if logSize > 1024*1024 {
+						ss.Vertexes = nil
+						ss.Statuses = nil
+						ss.Logs = ss.Logs[i+1:]
+						retry = true
+						break
+					}
+				}
+				if err := stream.SendMsg(&sr); err != nil {
+					return err
+				}
+				if !retry {
+					break
+				}
 			}
 		}
 	})
diff --git a/vendor/github.com/moby/buildkit/control/gateway/gateway.go b/vendor/github.com/moby/buildkit/control/gateway/gateway.go
index 2d4e8b3..9b91a08 100644
--- a/vendor/github.com/moby/buildkit/control/gateway/gateway.go
+++ b/vendor/github.com/moby/buildkit/control/gateway/gateway.go
@@ -152,3 +152,27 @@
 	}
 	return fwd.StatFile(ctx, req)
 }
+
+func (gwf *GatewayForwarder) NewContainer(ctx context.Context, req *gwapi.NewContainerRequest) (*gwapi.NewContainerResponse, error) {
+	fwd, err := gwf.lookupForwarder(ctx)
+	if err != nil {
+		return nil, errors.Wrap(err, "forwarding NewContainer")
+	}
+	return fwd.NewContainer(ctx, req)
+}
+
+func (gwf *GatewayForwarder) ReleaseContainer(ctx context.Context, req *gwapi.ReleaseContainerRequest) (*gwapi.ReleaseContainerResponse, error) {
+	fwd, err := gwf.lookupForwarder(ctx)
+	if err != nil {
+		return nil, errors.Wrap(err, "forwarding ReleaseContainer")
+	}
+	return fwd.ReleaseContainer(ctx, req)
+}
+
+func (gwf *GatewayForwarder) ExecProcess(srv gwapi.LLBBridge_ExecProcessServer) error {
+	fwd, err := gwf.lookupForwarder(srv.Context())
+	if err != nil {
+		return errors.Wrap(err, "forwarding ExecProcess")
+	}
+	return fwd.ExecProcess(srv)
+}
diff --git a/vendor/github.com/moby/buildkit/executor/executor.go b/vendor/github.com/moby/buildkit/executor/executor.go
index 5ab4252..8fbe4a9 100644
--- a/vendor/github.com/moby/buildkit/executor/executor.go
+++ b/vendor/github.com/moby/buildkit/executor/executor.go
@@ -5,7 +5,7 @@
 	"io"
 	"net"
 
-	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver/pb"
 )
 
@@ -14,6 +14,7 @@
 	Env            []string
 	User           string
 	Cwd            string
+	Hostname       string
 	Tty            bool
 	ReadonlyRootFS bool
 	ExtraHosts     []HostIP
@@ -21,24 +22,34 @@
 	SecurityMode   pb.SecurityMode
 }
 
+type Mountable interface {
+	Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error)
+}
+
 type Mount struct {
-	Src      cache.Mountable
+	Src      Mountable
 	Selector string
 	Dest     string
 	Readonly bool
 }
 
+type WinSize struct {
+	Rows uint32
+	Cols uint32
+}
+
 type ProcessInfo struct {
 	Meta           Meta
 	Stdin          io.ReadCloser
 	Stdout, Stderr io.WriteCloser
+	Resize         <-chan WinSize
 }
 
 type Executor interface {
 	// Run will start a container for the given process with rootfs, mounts.
 	// `id` is an optional name for the container so it can be referenced later via Exec.
 	// `started` is an optional channel that will be closed when the container setup completes and has started running.
-	Run(ctx context.Context, id string, rootfs cache.Mountable, mounts []Mount, process ProcessInfo, started chan<- struct{}) error
+	Run(ctx context.Context, id string, rootfs Mount, mounts []Mount, process ProcessInfo, started chan<- struct{}) error
 	// Exec will start a process in container matching `id`. An error will be returned
 	// if the container failed to start (via Run) or has exited before Exec is called.
 	Exec(ctx context.Context, id string, process ProcessInfo) error
diff --git a/vendor/github.com/moby/buildkit/executor/oci/hosts.go b/vendor/github.com/moby/buildkit/executor/oci/hosts.go
index 552b585..d0505c2 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/hosts.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/hosts.go
@@ -14,28 +14,26 @@
 	"github.com/pkg/errors"
 )
 
-const hostsContent = `
-127.0.0.1	localhost buildkitsandbox
-::1	localhost ip6-localhost ip6-loopback
-`
+const defaultHostname = "buildkitsandbox"
 
-func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping) (string, func(), error) {
-	if len(extraHosts) == 0 {
-		_, err := g.Do(ctx, stateDir, func(ctx context.Context) (interface{}, error) {
-			_, _, err := makeHostsFile(stateDir, nil, idmap)
-			return nil, err
-		})
-		if err != nil {
-			return "", nil, err
-		}
-		return filepath.Join(stateDir, "hosts"), func() {}, nil
+func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping, hostname string) (string, func(), error) {
+	if len(extraHosts) != 0 || hostname != defaultHostname {
+		return makeHostsFile(stateDir, extraHosts, idmap, hostname)
 	}
-	return makeHostsFile(stateDir, extraHosts, idmap)
+
+	_, err := g.Do(ctx, stateDir, func(ctx context.Context) (interface{}, error) {
+		_, _, err := makeHostsFile(stateDir, nil, idmap, hostname)
+		return nil, err
+	})
+	if err != nil {
+		return "", nil, err
+	}
+	return filepath.Join(stateDir, "hosts"), func() {}, nil
 }
 
-func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping) (string, func(), error) {
+func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping, hostname string) (string, func(), error) {
 	p := filepath.Join(stateDir, "hosts")
-	if len(extraHosts) != 0 {
+	if len(extraHosts) != 0 || hostname != defaultHostname {
 		p += "." + identity.NewID()
 	}
 	_, err := os.Stat(p)
@@ -47,8 +45,7 @@
 	}
 
 	b := &bytes.Buffer{}
-
-	if _, err := b.Write([]byte(hostsContent)); err != nil {
+	if _, err := b.Write([]byte(initHostsFile(hostname))); err != nil {
 		return "", nil, err
 	}
 
@@ -77,3 +74,14 @@
 		os.RemoveAll(p)
 	}, nil
 }
+
+func initHostsFile(hostname string) string {
+	var hosts string
+	if hostname != "" {
+		hosts = fmt.Sprintf("127.0.0.1	localhost %s", hostname)
+	} else {
+		hosts = fmt.Sprintf("127.0.0.1	localhost %s", defaultHostname)
+	}
+	hosts = fmt.Sprintf("%s\n::1	localhost ip6-localhost ip6-loopback\n", hosts)
+	return hosts
+}
diff --git a/vendor/github.com/moby/buildkit/executor/oci/mounts.go b/vendor/github.com/moby/buildkit/executor/oci/mounts.go
index 62dbd38..62360f4 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/mounts.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/mounts.go
@@ -5,82 +5,57 @@
 	"path/filepath"
 	"strings"
 
+	"github.com/containerd/containerd/containers"
+	"github.com/containerd/containerd/oci"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
-	"github.com/pkg/errors"
 )
 
-// MountOpts sets oci spec specific info for mount points
-type MountOpts func([]specs.Mount) ([]specs.Mount, error)
-
-//GetMounts returns default required for buildkit
-// https://github.com/moby/buildkit/issues/429
-func GetMounts(ctx context.Context, mountOpts ...MountOpts) ([]specs.Mount, error) {
-	mounts := []specs.Mount{
-		{
-			Destination: "/proc",
-			Type:        "proc",
-			Source:      "proc",
-		},
-		{
-			Destination: "/dev",
-			Type:        "tmpfs",
-			Source:      "tmpfs",
-			Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
-		},
-		{
-			Destination: "/dev/pts",
-			Type:        "devpts",
-			Source:      "devpts",
-			Options:     []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
-		},
-		{
-			Destination: "/dev/shm",
-			Type:        "tmpfs",
-			Source:      "shm",
-			Options:     []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
-		},
-		{
-			Destination: "/dev/mqueue",
-			Type:        "mqueue",
-			Source:      "mqueue",
-			Options:     []string{"nosuid", "noexec", "nodev"},
-		},
-		{
-			Destination: "/sys",
-			Type:        "sysfs",
-			Source:      "sysfs",
-			Options:     []string{"nosuid", "noexec", "nodev", "ro"},
-		},
-	}
-	var err error
-	for _, o := range mountOpts {
-		mounts, err = o(mounts)
-		if err != nil {
-			return nil, err
+func withRemovedMount(destination string) oci.SpecOpts {
+	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
+		newMounts := []specs.Mount{}
+		for _, o := range s.Mounts {
+			if o.Destination != destination {
+				newMounts = append(newMounts, o)
+			}
 		}
+		s.Mounts = newMounts
+
+		return nil
 	}
-	return mounts, nil
 }
 
-func withROBind(src, dest string) func(m []specs.Mount) ([]specs.Mount, error) {
-	return func(m []specs.Mount) ([]specs.Mount, error) {
-		m = append(m, specs.Mount{
+func withROBind(src, dest string) oci.SpecOpts {
+	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
+		s.Mounts = append(s.Mounts, specs.Mount{
 			Destination: dest,
 			Type:        "bind",
 			Source:      src,
 			Options:     []string{"nosuid", "noexec", "nodev", "rbind", "ro"},
 		})
-		return m, nil
+		return nil
 	}
 }
 
+func withCGroup() oci.SpecOpts {
+	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
+		s.Mounts = append(s.Mounts, specs.Mount{
+			Destination: "/sys/fs/cgroup",
+			Type:        "cgroup",
+			Source:      "cgroup",
+			Options:     []string{"ro", "nosuid", "noexec", "nodev"},
+		})
+		return nil
+	}
+
+}
+
 func hasPrefix(p, prefixDir string) bool {
 	prefixDir = filepath.Clean(prefixDir)
-	if prefixDir == "/" {
+	if filepath.Base(prefixDir) == string(filepath.Separator) {
 		return true
 	}
 	p = filepath.Clean(p)
-	return p == prefixDir || strings.HasPrefix(p, prefixDir+"/")
+	return p == prefixDir || strings.HasPrefix(p, prefixDir+string(filepath.Separator))
 }
 
 func removeMountsWithPrefix(mounts []specs.Mount, prefixDir string) []specs.Mount {
@@ -93,25 +68,35 @@
 	return ret
 }
 
-func withProcessMode(processMode ProcessMode) func([]specs.Mount) ([]specs.Mount, error) {
-	return func(m []specs.Mount) ([]specs.Mount, error) {
-		switch processMode {
-		case ProcessSandbox:
-			// keep the default
-		case NoProcessSandbox:
-			m = removeMountsWithPrefix(m, "/proc")
-			procMount := specs.Mount{
-				Destination: "/proc",
-				Type:        "bind",
-				Source:      "/proc",
-				// NOTE: "rbind"+"ro" does not make /proc read-only recursively.
-				// So we keep maskedPath and readonlyPaths (although not mandatory for rootless mode)
-				Options: []string{"rbind"},
-			}
-			m = append([]specs.Mount{procMount}, m...)
-		default:
-			return nil, errors.Errorf("unknown process mode: %v", processMode)
+func withBoundProc() oci.SpecOpts {
+	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
+		s.Mounts = removeMountsWithPrefix(s.Mounts, "/proc")
+		procMount := specs.Mount{
+			Destination: "/proc",
+			Type:        "bind",
+			Source:      "/proc",
+			// NOTE: "rbind"+"ro" does not make /proc read-only recursively.
+			// So we keep maskedPath and readonlyPaths (although not mandatory for rootless mode)
+			Options: []string{"rbind"},
 		}
-		return m, nil
+		s.Mounts = append([]specs.Mount{procMount}, s.Mounts...)
+
+		var maskedPaths []string
+		for _, s := range s.Linux.MaskedPaths {
+			if !hasPrefix(s, "/proc") {
+				maskedPaths = append(maskedPaths, s)
+			}
+		}
+		s.Linux.MaskedPaths = maskedPaths
+
+		var readonlyPaths []string
+		for _, s := range s.Linux.ReadonlyPaths {
+			if !hasPrefix(s, "/proc") {
+				readonlyPaths = append(readonlyPaths, s)
+			}
+		}
+		s.Linux.ReadonlyPaths = readonlyPaths
+
+		return nil
 	}
 }
diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec.go b/vendor/github.com/moby/buildkit/executor/oci/spec.go
index 9329fa9..44ad95e 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/spec.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/spec.go
@@ -1,6 +1,25 @@
 package oci
 
-// ProcMode configures PID namespaces
+import (
+	"context"
+	"path"
+	"sync"
+
+	"github.com/containerd/containerd/containers"
+	"github.com/containerd/containerd/mount"
+	"github.com/containerd/containerd/namespaces"
+	"github.com/containerd/containerd/oci"
+	"github.com/containerd/continuity/fs"
+	"github.com/docker/docker/pkg/idtools"
+	"github.com/mitchellh/hashstructure"
+	"github.com/moby/buildkit/executor"
+	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/util/network"
+	specs "github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
+)
+
+// ProcessMode configures PID namespaces
 type ProcessMode int
 
 const (
@@ -11,3 +30,203 @@
 	// NoProcessSandbox should be enabled only when the BuildKit is running in a container as an unprivileged user.
 	NoProcessSandbox
 )
+
+// Ideally we don't have to import whole containerd just for the default spec
+
+// GenerateSpec generates spec using containerd functionality.
+// opts are ignored for s.Process, s.Hostname, and s.Mounts .
+func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, idmap *idtools.IdentityMapping, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
+	c := &containers.Container{
+		ID: id,
+	}
+
+	// containerd/oci.GenerateSpec requires a namespace, which
+	// will be used to namespace specs.Linux.CgroupsPath if generated
+	if _, ok := namespaces.Namespace(ctx); !ok {
+		ctx = namespaces.WithNamespace(ctx, "buildkit")
+	}
+
+	if mountOpts, err := generateMountOpts(resolvConf, hostsFile); err == nil {
+		opts = append(opts, mountOpts...)
+	} else {
+		return nil, nil, err
+	}
+
+	if securityOpts, err := generateSecurityOpts(meta.SecurityMode); err == nil {
+		opts = append(opts, securityOpts...)
+	} else {
+		return nil, nil, err
+	}
+
+	if processModeOpts, err := generateProcessModeOpts(processMode); err == nil {
+		opts = append(opts, processModeOpts...)
+	} else {
+		return nil, nil, err
+	}
+
+	if idmapOpts, err := generateIDmapOpts(idmap); err == nil {
+		opts = append(opts, idmapOpts...)
+	} else {
+		return nil, nil, err
+	}
+
+	hostname := defaultHostname
+	if meta.Hostname != "" {
+		hostname = meta.Hostname
+	}
+
+	opts = append(opts,
+		oci.WithProcessArgs(meta.Args...),
+		oci.WithEnv(meta.Env),
+		oci.WithProcessCwd(meta.Cwd),
+		oci.WithNewPrivileges,
+		oci.WithHostname(hostname),
+	)
+
+	s, err := oci.GenerateSpec(ctx, nil, c, opts...)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// set the networking information on the spec
+	if err := namespace.Set(s); err != nil {
+		return nil, nil, err
+	}
+
+	s.Process.Rlimits = nil // reset open files limit
+
+	sm := &submounts{}
+
+	var releasers []func() error
+	releaseAll := func() {
+		sm.cleanup()
+		for _, f := range releasers {
+			f()
+		}
+	}
+
+	for _, m := range mounts {
+		if m.Src == nil {
+			return nil, nil, errors.Errorf("mount %s has no source", m.Dest)
+		}
+		mountable, err := m.Src.Mount(ctx, m.Readonly)
+		if err != nil {
+			releaseAll()
+			return nil, nil, errors.Wrapf(err, "failed to mount %s", m.Dest)
+		}
+		mounts, release, err := mountable.Mount()
+		if err != nil {
+			releaseAll()
+			return nil, nil, errors.WithStack(err)
+		}
+		releasers = append(releasers, release)
+		for _, mount := range mounts {
+			mount, err = sm.subMount(mount, m.Selector)
+			if err != nil {
+				releaseAll()
+				return nil, nil, err
+			}
+			s.Mounts = append(s.Mounts, specs.Mount{
+				Destination: m.Dest,
+				Type:        mount.Type,
+				Source:      mount.Source,
+				Options:     mount.Options,
+			})
+		}
+	}
+
+	return s, releaseAll, nil
+}
+
+type mountRef struct {
+	mount   mount.Mount
+	unmount func() error
+}
+
+type submounts struct {
+	m map[uint64]mountRef
+}
+
+func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error) {
+	if path.Join("/", subPath) == "/" {
+		return m, nil
+	}
+	if s.m == nil {
+		s.m = map[uint64]mountRef{}
+	}
+	h, err := hashstructure.Hash(m, nil)
+	if err != nil {
+		return mount.Mount{}, nil
+	}
+	if mr, ok := s.m[h]; ok {
+		sm, err := sub(mr.mount, subPath)
+		if err != nil {
+			return mount.Mount{}, nil
+		}
+		return sm, nil
+	}
+
+	lm := snapshot.LocalMounterWithMounts([]mount.Mount{m})
+
+	mp, err := lm.Mount()
+	if err != nil {
+		return mount.Mount{}, err
+	}
+
+	opts := []string{"rbind"}
+	for _, opt := range m.Options {
+		if opt == "ro" {
+			opts = append(opts, opt)
+		}
+	}
+
+	s.m[h] = mountRef{
+		mount: mount.Mount{
+			Source:  mp,
+			Type:    "bind",
+			Options: opts,
+		},
+		unmount: lm.Unmount,
+	}
+
+	sm, err := sub(s.m[h].mount, subPath)
+	if err != nil {
+		return mount.Mount{}, err
+	}
+	return sm, nil
+}
+
+func (s *submounts) cleanup() {
+	var wg sync.WaitGroup
+	wg.Add(len(s.m))
+	for _, m := range s.m {
+		func(m mountRef) {
+			go func() {
+				m.unmount()
+				wg.Done()
+			}()
+		}(m)
+	}
+	wg.Wait()
+}
+
+func sub(m mount.Mount, subPath string) (mount.Mount, error) {
+	src, err := fs.RootPath(m.Source, subPath)
+	if err != nil {
+		return mount.Mount{}, err
+	}
+	m.Source = src
+	return m, nil
+}
+
+func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping {
+	var ids []specs.LinuxIDMapping
+	for _, item := range s {
+		ids = append(ids, specs.LinuxIDMapping{
+			HostID:      uint32(item.HostID),
+			ContainerID: uint32(item.ContainerID),
+			Size:        uint32(item.Size),
+		})
+	}
+	return ids
+}
diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go b/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
index 8ab4fb4..5c3f4c5 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/spec_unix.go
@@ -4,251 +4,68 @@
 
 import (
 	"context"
-	"path"
-	"sync"
 
 	"github.com/containerd/containerd/containers"
-	"github.com/containerd/containerd/contrib/seccomp"
-	"github.com/containerd/containerd/mount"
-	"github.com/containerd/containerd/namespaces"
 	"github.com/containerd/containerd/oci"
-	"github.com/containerd/continuity/fs"
 	"github.com/docker/docker/pkg/idtools"
-	"github.com/mitchellh/hashstructure"
-	"github.com/moby/buildkit/executor"
-	"github.com/moby/buildkit/snapshot"
+	"github.com/docker/docker/profiles/seccomp"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/entitlements/security"
-	"github.com/moby/buildkit/util/network"
 	"github.com/moby/buildkit/util/system"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
-	"github.com/pkg/errors"
 )
 
-// Ideally we don't have to import whole containerd just for the default spec
-
-// GenerateSpec generates spec using containerd functionality.
-// opts are ignored for s.Process, s.Hostname, and s.Mounts .
-func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, idmap *idtools.IdentityMapping, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
-	c := &containers.Container{
-		ID: id,
-	}
-	_, ok := namespaces.Namespace(ctx)
-	if !ok {
-		ctx = namespaces.WithNamespace(ctx, "buildkit")
-	}
-	if meta.SecurityMode == pb.SecurityMode_INSECURE {
-		opts = append(opts, security.WithInsecureSpec())
-	} else if system.SeccompSupported() && meta.SecurityMode == pb.SecurityMode_SANDBOX {
-		opts = append(opts, seccomp.WithDefaultProfile())
-	}
-
-	switch processMode {
-	case NoProcessSandbox:
-		// Mount for /proc is replaced in GetMounts()
-		opts = append(opts,
-			oci.WithHostNamespace(specs.PIDNamespace))
-		// TODO(AkihiroSuda): Configure seccomp to disable ptrace (and prctl?) explicitly
-	}
-
-	// Note that containerd.GenerateSpec is namespaced so as to make
-	// specs.Linux.CgroupsPath namespaced
-	s, err := oci.GenerateSpec(ctx, nil, c, opts...)
-	if err != nil {
-		return nil, nil, err
-	}
-	// set the networking information on the spec
-	namespace.Set(s)
-
-	s.Process.Args = meta.Args
-	s.Process.Env = meta.Env
-	s.Process.Cwd = meta.Cwd
-	s.Process.Rlimits = nil           // reset open files limit
-	s.Process.NoNewPrivileges = false // reset nonewprivileges
-	s.Hostname = "buildkitsandbox"
-
-	s.Mounts, err = GetMounts(ctx,
-		withProcessMode(processMode),
+func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
+	return []oci.SpecOpts{
+		// https://github.com/moby/buildkit/issues/429
+		withRemovedMount("/run"),
 		withROBind(resolvConf, "/etc/resolv.conf"),
 		withROBind(hostsFile, "/etc/hosts"),
-	)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	s.Mounts = append(s.Mounts, specs.Mount{
-		Destination: "/sys/fs/cgroup",
-		Type:        "cgroup",
-		Source:      "cgroup",
-		Options:     []string{"ro", "nosuid", "noexec", "nodev"},
-	})
-
-	if processMode == NoProcessSandbox {
-		var maskedPaths []string
-		for _, s := range s.Linux.MaskedPaths {
-			if !hasPrefix(s, "/proc") {
-				maskedPaths = append(maskedPaths, s)
-			}
-		}
-		s.Linux.MaskedPaths = maskedPaths
-		var readonlyPaths []string
-		for _, s := range s.Linux.ReadonlyPaths {
-			if !hasPrefix(s, "/proc") {
-				readonlyPaths = append(readonlyPaths, s)
-			}
-		}
-		s.Linux.ReadonlyPaths = readonlyPaths
-	}
-
-	if meta.SecurityMode == pb.SecurityMode_INSECURE {
-		if err = oci.WithWriteableCgroupfs(ctx, nil, c, s); err != nil {
-			return nil, nil, err
-		}
-		if err = oci.WithWriteableSysfs(ctx, nil, c, s); err != nil {
-			return nil, nil, err
-		}
-	}
-
-	if idmap != nil {
-		s.Linux.Namespaces = append(s.Linux.Namespaces, specs.LinuxNamespace{
-			Type: specs.UserNamespace,
-		})
-		s.Linux.UIDMappings = specMapping(idmap.UIDs())
-		s.Linux.GIDMappings = specMapping(idmap.GIDs())
-	}
-
-	sm := &submounts{}
-
-	var releasers []func() error
-	releaseAll := func() {
-		sm.cleanup()
-		for _, f := range releasers {
-			f()
-		}
-	}
-
-	for _, m := range mounts {
-		if m.Src == nil {
-			return nil, nil, errors.Errorf("mount %s has no source", m.Dest)
-		}
-		mountable, err := m.Src.Mount(ctx, m.Readonly)
-		if err != nil {
-			releaseAll()
-			return nil, nil, errors.Wrapf(err, "failed to mount %s", m.Dest)
-		}
-		mounts, release, err := mountable.Mount()
-		if err != nil {
-			releaseAll()
-			return nil, nil, errors.WithStack(err)
-		}
-		releasers = append(releasers, release)
-		for _, mount := range mounts {
-			mount, err = sm.subMount(mount, m.Selector)
-			if err != nil {
-				releaseAll()
-				return nil, nil, err
-			}
-			s.Mounts = append(s.Mounts, specs.Mount{
-				Destination: m.Dest,
-				Type:        mount.Type,
-				Source:      mount.Source,
-				Options:     mount.Options,
-			})
-		}
-	}
-
-	return s, releaseAll, nil
+		withCGroup(),
+	}, nil
 }
 
-type mountRef struct {
-	mount   mount.Mount
-	unmount func() error
+// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
+func generateSecurityOpts(mode pb.SecurityMode) ([]oci.SpecOpts, error) {
+	if mode == pb.SecurityMode_INSECURE {
+		return []oci.SpecOpts{
+			security.WithInsecureSpec(),
+			oci.WithWriteableCgroupfs,
+			oci.WithWriteableSysfs,
+		}, nil
+	} else if system.SeccompSupported() && mode == pb.SecurityMode_SANDBOX {
+		return []oci.SpecOpts{withDefaultProfile()}, nil
+	}
+	return nil, nil
 }
 
-type submounts struct {
-	m map[uint64]mountRef
+// generateProcessModeOpts may affect mounts, so must be called after generateMountOpts
+func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
+	if mode == NoProcessSandbox {
+		return []oci.SpecOpts{
+			oci.WithHostNamespace(specs.PIDNamespace),
+			withBoundProc(),
+		}, nil
+		// TODO(AkihiroSuda): Configure seccomp to disable ptrace (and prctl?) explicitly
+	}
+	return nil, nil
 }
 
-func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error) {
-	if path.Join("/", subPath) == "/" {
-		return m, nil
+func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
+	if idmap == nil {
+		return nil, nil
 	}
-	if s.m == nil {
-		s.m = map[uint64]mountRef{}
-	}
-	h, err := hashstructure.Hash(m, nil)
-	if err != nil {
-		return mount.Mount{}, nil
-	}
-	if mr, ok := s.m[h]; ok {
-		sm, err := sub(mr.mount, subPath)
-		if err != nil {
-			return mount.Mount{}, nil
-		}
-		return sm, nil
-	}
-
-	lm := snapshot.LocalMounterWithMounts([]mount.Mount{m})
-
-	mp, err := lm.Mount()
-	if err != nil {
-		return mount.Mount{}, err
-	}
-
-	opts := []string{"rbind"}
-	for _, opt := range m.Options {
-		if opt == "ro" {
-			opts = append(opts, opt)
-		}
-	}
-
-	s.m[h] = mountRef{
-		mount: mount.Mount{
-			Source:  mp,
-			Type:    "bind",
-			Options: opts,
-		},
-		unmount: lm.Unmount,
-	}
-
-	sm, err := sub(s.m[h].mount, subPath)
-	if err != nil {
-		return mount.Mount{}, err
-	}
-	return sm, nil
+	return []oci.SpecOpts{
+		oci.WithUserNamespace(specMapping(idmap.UIDs()), specMapping(idmap.GIDs())),
+	}, nil
 }
 
-func (s *submounts) cleanup() {
-	var wg sync.WaitGroup
-	wg.Add(len(s.m))
-	for _, m := range s.m {
-		func(m mountRef) {
-			go func() {
-				m.unmount()
-				wg.Done()
-			}()
-		}(m)
+// withDefaultProfile sets the default seccomp profile to the spec.
+// Note: must follow the setting of process capabilities
+func withDefaultProfile() oci.SpecOpts {
+	return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
+		var err error
+		s.Linux.Seccomp, err = seccomp.GetDefaultProfile(s)
+		return err
 	}
-	wg.Wait()
-}
-
-func sub(m mount.Mount, subPath string) (mount.Mount, error) {
-	src, err := fs.RootPath(m.Source, subPath)
-	if err != nil {
-		return mount.Mount{}, err
-	}
-	m.Source = src
-	return m, nil
-}
-
-func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping {
-	var ids []specs.LinuxIDMapping
-	for _, item := range s {
-		ids = append(ids, specs.LinuxIDMapping{
-			HostID:      uint32(item.HostID),
-			ContainerID: uint32(item.ContainerID),
-			Size:        uint32(item.Size),
-		})
-	}
-	return ids
 }
diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go b/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go
new file mode 100644
index 0000000..850a3b8
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go
@@ -0,0 +1,37 @@
+// +build windows
+
+package oci
+
+import (
+	"github.com/containerd/containerd/oci"
+	"github.com/docker/docker/pkg/idtools"
+	"github.com/moby/buildkit/solver/pb"
+	"github.com/pkg/errors"
+)
+
+func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
+	return nil, nil
+}
+
+// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
+func generateSecurityOpts(mode pb.SecurityMode) ([]oci.SpecOpts, error) {
+	if mode == pb.SecurityMode_INSECURE {
+		return nil, errors.New("no support for running in insecure mode on Windows")
+	}
+	return nil, nil
+}
+
+// generateProcessModeOpts may affect mounts, so must be called after generateMountOpts
+func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) {
+	if mode == NoProcessSandbox {
+		return nil, errors.New("no support for NoProcessSandbox on Windows")
+	}
+	return nil, nil
+}
+
+func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) {
+	if idmap == nil {
+		return nil, nil
+	}
+	return nil, errors.New("no support for IdentityMapping on Windows")
+}
diff --git a/vendor/github.com/moby/buildkit/executor/oci/user.go b/vendor/github.com/moby/buildkit/executor/oci/user.go
index 4f7cb10..e49eb8e 100644
--- a/vendor/github.com/moby/buildkit/executor/oci/user.go
+++ b/vendor/github.com/moby/buildkit/executor/oci/user.go
@@ -14,7 +14,7 @@
 	"github.com/pkg/errors"
 )
 
-func GetUser(ctx context.Context, root, username string) (uint32, uint32, []uint32, error) {
+func GetUser(root, username string) (uint32, uint32, []uint32, error) {
 	// fast path from uid/gid
 	if uid, gid, err := ParseUIDGID(username); err == nil {
 		return uid, gid, nil, nil
diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
index 068929c..62c2891 100644
--- a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
+++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go
@@ -17,10 +17,10 @@
 	"github.com/containerd/continuity/fs"
 	runc "github.com/containerd/go-runc"
 	"github.com/docker/docker/pkg/idtools"
-	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/executor"
 	"github.com/moby/buildkit/executor/oci"
 	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/solver/errdefs"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/network"
 	rootlessspecconv "github.com/moby/buildkit/util/rootless/specconv"
@@ -52,7 +52,6 @@
 type runcExecutor struct {
 	runc             *runc.Runc
 	root             string
-	cmd              string
 	cgroupParent     string
 	rootless         bool
 	networkProviders map[pb.NetMode]network.Provider
@@ -103,15 +102,16 @@
 	os.RemoveAll(filepath.Join(root, "resolv.conf"))
 
 	runtime := &runc.Runc{
-		Command:      cmd,
-		Log:          filepath.Join(root, "runc-log.json"),
-		LogFormat:    runc.JSON,
-		PdeathSignal: syscall.SIGKILL, // this can still leak the process
-		Setpgid:      true,
+		Command:   cmd,
+		Log:       filepath.Join(root, "runc-log.json"),
+		LogFormat: runc.JSON,
+		Setpgid:   true,
 		// we don't execute runc with --rootless=(true|false) explicitly,
 		// so as to support non-runc runtimes
 	}
 
+	updateRuncFieldsForHostOS(runtime)
+
 	w := &runcExecutor{
 		runc:             runtime,
 		root:             root,
@@ -128,7 +128,7 @@
 	return w, nil
 }
 
-func (w *runcExecutor) Run(ctx context.Context, id string, root cache.Mountable, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
+func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
 	meta := process.Meta
 
 	startedOnce := sync.Once{}
@@ -168,7 +168,7 @@
 		return err
 	}
 
-	hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap)
+	hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap, meta.Hostname)
 	if err != nil {
 		return err
 	}
@@ -176,7 +176,7 @@
 		defer clean()
 	}
 
-	mountable, err := root.Mount(ctx, false)
+	mountable, err := root.Src.Mount(ctx, false)
 	if err != nil {
 		return err
 	}
@@ -213,7 +213,9 @@
 	}
 	defer mount.Unmount(rootFSPath, 0)
 
-	uid, gid, sgids, err := oci.GetUser(ctx, rootFSPath, meta.User)
+	defer executor.MountStubsCleaner(rootFSPath, mounts)()
+
+	uid, gid, sgids, err := oci.GetUser(rootFSPath, meta.User)
 	if err != nil {
 		return err
 	}
@@ -258,7 +260,7 @@
 	defer cleanup()
 
 	spec.Root.Path = rootFSPath
-	if _, ok := root.(cache.ImmutableRef); ok { // TODO: pass in with mount, not ref type
+	if root.Readonly {
 		spec.Root.Readonly = true
 	}
 
@@ -323,28 +325,37 @@
 			close(started)
 		})
 	}
-	status, err := w.runc.Run(runCtx, id, bundle, &runc.CreateOpts{
-		IO:      &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
-		NoPivot: w.noPivot,
-	})
-	close(ended)
 
-	if status != 0 || err != nil {
-		if err == nil {
-			err = errors.Errorf("exit code: %d", status)
+	err = w.run(runCtx, id, bundle, process)
+	close(ended)
+	return exitError(ctx, err)
+}
+
+func exitError(ctx context.Context, err error) error {
+	if err != nil {
+		exitErr := &errdefs.ExitError{
+			ExitCode: errdefs.ContainerdUnknownExitStatus,
+			Err:      err,
+		}
+		var runcExitError *runc.ExitError
+		if errors.As(err, &runcExitError) {
+			exitErr = &errdefs.ExitError{
+				ExitCode: uint32(runcExitError.Status),
+			}
 		}
 		select {
 		case <-ctx.Done():
-			return errors.Wrapf(ctx.Err(), err.Error())
+			exitErr.Err = errors.Wrapf(ctx.Err(), exitErr.Error())
+			return exitErr
 		default:
-			return stack.Enable(err)
+			return stack.Enable(exitErr)
 		}
 	}
 
 	return nil
 }
 
-func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.ProcessInfo) error {
+func (w *runcExecutor) Exec(ctx context.Context, id string, process executor.ProcessInfo) (err error) {
 	// first verify the container is running, if we get an error assume the container
 	// is in the process of being created and check again every 100ms or until
 	// context is canceled.
@@ -386,7 +397,7 @@
 	}
 
 	if process.Meta.User != "" {
-		uid, gid, sgids, err := oci.GetUser(ctx, state.Rootfs, process.Meta.User)
+		uid, gid, sgids, err := oci.GetUser(state.Rootfs, process.Meta.User)
 		if err != nil {
 			return err
 		}
@@ -407,9 +418,8 @@
 		spec.Process.Env = process.Meta.Env
 	}
 
-	return w.runc.Exec(ctx, id, *spec.Process, &runc.ExecOpts{
-		IO: &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
-	})
+	err = w.exec(ctx, id, state.Bundle, spec.Process, process)
+	return exitError(ctx, err)
 }
 
 type forwardIO struct {
diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor_common.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor_common.go
new file mode 100644
index 0000000..3751b90
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor_common.go
@@ -0,0 +1,36 @@
+// +build !linux
+
+package runcexecutor
+
+import (
+	"context"
+
+	runc "github.com/containerd/go-runc"
+	"github.com/moby/buildkit/executor"
+	"github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
+)
+
+var unsupportedConsoleError = errors.New("tty for runc is only supported on linux")
+
+func updateRuncFieldsForHostOS(runtime *runc.Runc) {}
+
+func (w *runcExecutor) run(ctx context.Context, id, bundle string, process executor.ProcessInfo) error {
+	if process.Meta.Tty {
+		return unsupportedConsoleError
+	}
+	_, err := w.runc.Run(ctx, id, bundle, &runc.CreateOpts{
+		IO:      &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
+		NoPivot: w.noPivot,
+	})
+	return err
+}
+
+func (w *runcExecutor) exec(ctx context.Context, id, bundle string, specsProcess *specs.Process, process executor.ProcessInfo) error {
+	if process.Meta.Tty {
+		return unsupportedConsoleError
+	}
+	return w.runc.Exec(ctx, id, *specsProcess, &runc.ExecOpts{
+		IO: &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr},
+	})
+}
diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor_linux.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor_linux.go
new file mode 100644
index 0000000..b01040c
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor_linux.go
@@ -0,0 +1,160 @@
+package runcexecutor
+
+import (
+	"context"
+	"io"
+	"os"
+	"syscall"
+	"time"
+
+	"github.com/containerd/console"
+	runc "github.com/containerd/go-runc"
+	"github.com/docker/docker/pkg/signal"
+	"github.com/moby/buildkit/executor"
+	"github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"golang.org/x/sync/errgroup"
+)
+
+func updateRuncFieldsForHostOS(runtime *runc.Runc) {
+	// PdeathSignal only supported on unix platforms
+	runtime.PdeathSignal = syscall.SIGKILL // this can still leak the process
+}
+
+func (w *runcExecutor) run(ctx context.Context, id, bundle string, process executor.ProcessInfo) error {
+	return w.callWithIO(ctx, id, bundle, process, func(ctx context.Context, started chan<- int, io runc.IO) error {
+		_, err := w.runc.Run(ctx, id, bundle, &runc.CreateOpts{
+			NoPivot: w.noPivot,
+			Started: started,
+			IO:      io,
+		})
+		return err
+	})
+}
+
+func (w *runcExecutor) exec(ctx context.Context, id, bundle string, specsProcess *specs.Process, process executor.ProcessInfo) error {
+	return w.callWithIO(ctx, id, bundle, process, func(ctx context.Context, started chan<- int, io runc.IO) error {
+		return w.runc.Exec(ctx, id, *specsProcess, &runc.ExecOpts{
+			Started: started,
+			IO:      io,
+		})
+	})
+}
+
+type runcCall func(ctx context.Context, started chan<- int, io runc.IO) error
+
+func (w *runcExecutor) callWithIO(ctx context.Context, id, bundle string, process executor.ProcessInfo, call runcCall) error {
+	ctx, cancel := context.WithCancel(ctx)
+	defer cancel()
+
+	if !process.Meta.Tty {
+		return call(ctx, nil, &forwardIO{stdin: process.Stdin, stdout: process.Stdout, stderr: process.Stderr})
+	}
+
+	ptm, ptsName, err := console.NewPty()
+	if err != nil {
+		return err
+	}
+
+	pts, err := os.OpenFile(ptsName, os.O_RDWR|syscall.O_NOCTTY, 0)
+	if err != nil {
+		ptm.Close()
+		return err
+	}
+
+	eg, ctx := errgroup.WithContext(ctx)
+
+	defer func() {
+		if process.Stdin != nil {
+			process.Stdin.Close()
+		}
+		pts.Close()
+		ptm.Close()
+		cancel() // this will shutdown resize loop
+		err := eg.Wait()
+		if err != nil {
+			logrus.Warningf("error while shutting down tty io: %s", err)
+		}
+	}()
+
+	if process.Stdin != nil {
+		eg.Go(func() error {
+			_, err := io.Copy(ptm, process.Stdin)
+			// stdin might be a pipe, so this is like EOF
+			if errors.Is(err, io.ErrClosedPipe) {
+				return nil
+			}
+			return err
+		})
+	}
+
+	if process.Stdout != nil {
+		eg.Go(func() error {
+			_, err := io.Copy(process.Stdout, ptm)
+			// ignore `read /dev/ptmx: input/output error` when ptm is closed
+			var ptmClosedError *os.PathError
+			if errors.As(err, &ptmClosedError) {
+				if ptmClosedError.Op == "read" &&
+					ptmClosedError.Path == "/dev/ptmx" &&
+					ptmClosedError.Err == syscall.EIO {
+					return nil
+				}
+			}
+			return err
+		})
+	}
+
+	started := make(chan int, 1)
+
+	eg.Go(func() error {
+		startedCtx, timeout := context.WithTimeout(ctx, 10*time.Second)
+		defer timeout()
+		var runcProcess *os.Process
+		select {
+		case <-startedCtx.Done():
+			return errors.New("runc started message never received")
+		case pid, ok := <-started:
+			if !ok {
+				return errors.New("runc process failed to send pid")
+			}
+			runcProcess, err = os.FindProcess(pid)
+			if err != nil {
+				return errors.Wrapf(err, "unable to find runc process for pid %d", pid)
+			}
+			defer runcProcess.Release()
+		}
+
+		for {
+			select {
+			case <-ctx.Done():
+				return nil
+			case resize := <-process.Resize:
+				err = ptm.Resize(console.WinSize{
+					Height: uint16(resize.Rows),
+					Width:  uint16(resize.Cols),
+				})
+				if err != nil {
+					logrus.Errorf("failed to resize ptm: %s", err)
+				}
+				err = runcProcess.Signal(signal.SIGWINCH)
+				if err != nil {
+					logrus.Errorf("failed to send SIGWINCH to process: %s", err)
+				}
+			}
+		}
+	})
+
+	runcIO := &forwardIO{}
+	if process.Stdin != nil {
+		runcIO.stdin = pts
+	}
+	if process.Stdout != nil {
+		runcIO.stdout = pts
+	}
+	if process.Stderr != nil {
+		runcIO.stderr = pts
+	}
+
+	return call(ctx, started, runcIO)
+}
diff --git a/vendor/github.com/moby/buildkit/executor/stubs.go b/vendor/github.com/moby/buildkit/executor/stubs.go
new file mode 100644
index 0000000..2c13b13
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/executor/stubs.go
@@ -0,0 +1,49 @@
+package executor
+
+import (
+	"errors"
+	"os"
+	"path/filepath"
+	"syscall"
+
+	"github.com/containerd/continuity/fs"
+)
+
+func MountStubsCleaner(dir string, mounts []Mount) func() {
+	names := []string{"/etc/resolv.conf", "/etc/hosts"}
+
+	for _, m := range mounts {
+		names = append(names, m.Dest)
+	}
+
+	paths := make([]string, 0, len(names))
+
+	for _, p := range names {
+		p = filepath.Join("/", p)
+		if p == "/" {
+			continue
+		}
+		realPath, err := fs.RootPath(dir, p)
+		if err != nil {
+			continue
+		}
+
+		_, err = os.Lstat(realPath)
+		if errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
+			paths = append(paths, realPath)
+		}
+	}
+
+	return func() {
+		for _, p := range paths {
+			st, err := os.Lstat(p)
+			if err != nil {
+				continue
+			}
+			if st.Size() != 0 {
+				continue
+			}
+			os.Remove(p)
+		}
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
index 02e34eb..b428afd 100644
--- a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
+++ b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
@@ -1,11 +1,16 @@
 package exptypes
 
-import specs "github.com/opencontainers/image-spec/specs-go/v1"
+import (
+	"github.com/opencontainers/go-digest"
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
+)
 
 const ExporterImageConfigKey = "containerimage.config"
 const ExporterInlineCache = "containerimage.inlinecache"
 const ExporterPlatformsKey = "refs.platforms"
 
+const EmptyGZLayer = digest.Digest("sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1")
+
 type Platforms struct {
 	Platforms []Platform
 }
diff --git a/vendor/github.com/moby/buildkit/exporter/local/export.go b/vendor/github.com/moby/buildkit/exporter/local/export.go
index 28e3220..d772776 100644
--- a/vendor/github.com/moby/buildkit/exporter/local/export.go
+++ b/vendor/github.com/moby/buildkit/exporter/local/export.go
@@ -51,7 +51,7 @@
 	timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
 	defer cancel()
 
-	caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID)
+	caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID, false)
 	if err != nil {
 		return nil, err
 	}
@@ -70,7 +70,7 @@
 				}
 				defer os.RemoveAll(src)
 			} else {
-				mount, err := ref.Mount(ctx, true)
+				mount, err := ref.Mount(ctx, true, session.NewGroup(sessionID))
 				if err != nil {
 					return err
 				}
diff --git a/vendor/github.com/moby/buildkit/exporter/tar/export.go b/vendor/github.com/moby/buildkit/exporter/tar/export.go
index 0f635fc..79e98cd 100644
--- a/vendor/github.com/moby/buildkit/exporter/tar/export.go
+++ b/vendor/github.com/moby/buildkit/exporter/tar/export.go
@@ -65,7 +65,7 @@
 			}
 			defers = append(defers, func() { os.RemoveAll(src) })
 		} else {
-			mount, err := ref.Mount(ctx, true)
+			mount, err := ref.Mount(ctx, true, session.NewGroup(sessionID))
 			if err != nil {
 				return nil, err
 			}
@@ -135,7 +135,7 @@
 	timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
 	defer cancel()
 
-	caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID)
+	caller, err := e.opt.SessionManager.Get(timeoutCtx, sessionID, false)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
index 6d959d9..345e789 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go
@@ -14,11 +14,11 @@
 	"strings"
 
 	"github.com/containerd/containerd/platforms"
-	"github.com/docker/docker/builder/dockerignore"
 	controlapi "github.com/moby/buildkit/api/services/control"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/exporter/containerimage/exptypes"
 	"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
+	"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
 	"github.com/moby/buildkit/frontend/dockerfile/parser"
 	"github.com/moby/buildkit/frontend/gateway/client"
 	gwpb "github.com/moby/buildkit/frontend/gateway/pb"
@@ -53,16 +53,23 @@
 	keyNameDockerfile          = "dockerfilekey"
 	keyContextSubDir           = "contextsubdir"
 	keyContextKeepGitDir       = "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR"
+	keySyntax                  = "build-arg:BUILDKIT_SYNTAX"
+	keyHostname                = "hostname"
 )
 
 var httpPrefix = regexp.MustCompile(`^https?://`)
-var gitUrlPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
+var gitURLPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
 
 func Build(ctx context.Context, c client.Client) (*client.Result, error) {
 	opts := c.BuildOpts().Opts
 	caps := c.BuildOpts().LLBCaps
 	gwcaps := c.BuildOpts().Caps
 
+	allowForward, capsError := validateCaps(opts["frontend.caps"])
+	if !allowForward && capsError != nil {
+		return nil, capsError
+	}
+
 	marshalOpts := []llb.ConstraintsOpt{llb.WithCaps(caps)}
 
 	localNameContext := DefaultLocalNameContext
@@ -123,8 +130,15 @@
 
 	name := "load build definition from " + filename
 
+	filenames := []string{filename, filename + ".dockerignore"}
+
+	// dockerfile is also supported casing moby/moby#10858
+	if path.Base(filename) == defaultDockerfileName {
+		filenames = append(filenames, path.Join(path.Dir(filename), strings.ToLower(defaultDockerfileName)))
+	}
+
 	src := llb.Local(localNameDockerfile,
-		llb.FollowPaths([]string{filename, filename + ".dockerignore"}),
+		llb.FollowPaths(filenames),
 		llb.SessionID(c.BuildOpts().SessionID),
 		llb.SharedKeyHint(localNameDockerfile),
 		dockerfile2llb.WithInternalName(name),
@@ -251,7 +265,19 @@
 			Filename: filename,
 		})
 		if err != nil {
-			return errors.Wrapf(err, "failed to read dockerfile")
+			fallback := false
+			if path.Base(filename) == defaultDockerfileName {
+				var err1 error
+				dtDockerfile, err1 = ref.ReadFile(ctx2, client.ReadRequest{
+					Filename: path.Join(path.Dir(filename), strings.ToLower(defaultDockerfileName)),
+				})
+				if err1 == nil {
+					fallback = true
+				}
+			}
+			if !fallback {
+				return errors.Wrapf(err, "failed to read dockerfile")
+			}
 		}
 
 		sourceMap = llb.NewSourceMap(&src, filename, dtDockerfile)
@@ -317,8 +343,14 @@
 	}
 
 	if _, ok := opts["cmdline"]; !ok {
-		ref, cmdline, loc, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile))
-		if ok {
+		if cmdline, ok := opts[keySyntax]; ok {
+			p := strings.SplitN(strings.TrimSpace(cmdline), " ", 2)
+			res, err := forwardGateway(ctx, c, p[0], cmdline)
+			if err != nil && len(errdefs.Sources(err)) == 0 {
+				return nil, errors.Wrapf(err, "failed with %s = %s", keySyntax, cmdline)
+			}
+			return res, err
+		} else if ref, cmdline, loc, ok := dockerfile2llb.DetectSyntax(bytes.NewBuffer(dtDockerfile)); ok {
 			res, err := forwardGateway(ctx, c, ref, cmdline)
 			if err != nil && len(errdefs.Sources(err)) == 0 {
 				return nil, wrapSource(err, sourceMap, loc)
@@ -327,6 +359,14 @@
 		}
 	}
 
+	if capsError != nil {
+		return nil, capsError
+	}
+
+	if res, ok, err := checkSubRequest(ctx, opts); ok {
+		return res, err
+	}
+
 	exportMap := len(targetPlatforms) > 1
 
 	if v := opts[keyMultiPlatform]; v != "" {
@@ -375,6 +415,7 @@
 					OverrideCopyImage: opts[keyOverrideCopyImage],
 					LLBCaps:           &caps,
 					SourceMap:         sourceMap,
+					Hostname:          opts[keyHostname],
 				})
 
 				if err != nil {
@@ -512,7 +553,7 @@
 
 func detectGitContext(ref, gitContext string) (*llb.State, bool) {
 	found := false
-	if httpPrefix.MatchString(ref) && gitUrlPathWithFragmentSuffix.MatchString(ref) {
+	if httpPrefix.MatchString(ref) && gitURLPathWithFragmentSuffix.MatchString(ref) {
 		found = true
 	}
 
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/caps.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/caps.go
new file mode 100644
index 0000000..2797011
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/caps.go
@@ -0,0 +1,34 @@
+package builder
+
+import (
+	"strings"
+
+	"github.com/moby/buildkit/solver/errdefs"
+	"github.com/moby/buildkit/util/grpcerrors"
+	"github.com/moby/buildkit/util/stack"
+	"google.golang.org/grpc/codes"
+)
+
+var enabledCaps = map[string]struct{}{
+	"moby.buildkit.frontend.inputs":      {},
+	"moby.buildkit.frontend.subrequests": {},
+}
+
+func validateCaps(req string) (forward bool, err error) {
+	if req == "" {
+		return
+	}
+	caps := strings.Split(req, ",")
+	for _, c := range caps {
+		parts := strings.SplitN(c, "+", 2)
+		if _, ok := enabledCaps[parts[0]]; !ok {
+			err = stack.Enable(grpcerrors.WrapCode(errdefs.NewUnsupportedFrontendCapError(parts[0]), codes.Unimplemented))
+			if strings.Contains(c, "+forward") {
+				forward = true
+			} else {
+				return false, err
+			}
+		}
+	}
+	return
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/subrequests.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/subrequests.go
new file mode 100644
index 0000000..6d30b7b
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/subrequests.go
@@ -0,0 +1,39 @@
+package builder
+
+import (
+	"context"
+	"encoding/json"
+
+	"github.com/moby/buildkit/frontend/gateway/client"
+	"github.com/moby/buildkit/frontend/subrequests"
+	"github.com/moby/buildkit/solver/errdefs"
+)
+
+func checkSubRequest(ctx context.Context, opts map[string]string) (*client.Result, bool, error) {
+	req, ok := opts["requestid"]
+	if !ok {
+		return nil, false, nil
+	}
+	switch req {
+	case subrequests.RequestSubrequestsDescribe:
+		res, err := describe()
+		return res, true, err
+	default:
+		return nil, true, errdefs.NewUnsupportedSubrequestError(req)
+	}
+}
+
+func describe() (*client.Result, error) {
+	all := []subrequests.Request{
+		subrequests.SubrequestsDescribeDefinition,
+	}
+	dt, err := json.MarshalIndent(all, "  ", "")
+	if err != nil {
+		return nil, err
+	}
+	res := client.NewResult()
+	res.Metadata = map[string][]byte{
+		"result.json": dt,
+	}
+	return res, nil
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
index 28c7efc..7c749a7 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
@@ -62,6 +62,7 @@
 	LLBCaps           *apicaps.CapSet
 	ContextLocalName  string
 	SourceMap         *llb.SourceMap
+	Hostname          string
 }
 
 func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error) {
@@ -94,11 +95,13 @@
 
 	shlex := shell.NewLex(dockerfile.EscapeToken)
 
-	for _, metaArg := range metaArgs {
-		if metaArg.Value != nil {
-			*metaArg.Value, _ = shlex.ProcessWordWithMap(*metaArg.Value, metaArgsToMap(optMetaArgs))
+	for _, cmd := range metaArgs {
+		for _, metaArg := range cmd.Args {
+			if metaArg.Value != nil {
+				*metaArg.Value, _ = shlex.ProcessWordWithMap(*metaArg.Value, metaArgsToMap(optMetaArgs))
+			}
+			optMetaArgs = append(optMetaArgs, setKVValue(metaArg, opt.BuildArgs))
 		}
-		optMetaArgs = append(optMetaArgs, setKVValue(metaArg.KeyValuePairOptional, opt.BuildArgs))
 	}
 
 	metaResolver := opt.MetaResolver
@@ -246,33 +249,34 @@
 							ResolveMode: opt.ImageResolveMode.String(),
 							LogName:     fmt.Sprintf("%s load metadata for %s", prefix, d.stage.BaseName),
 						})
-						if err == nil { // handle the error while builder is actually running
-							var img Image
-							if err := json.Unmarshal(dt, &img); err != nil {
+						if err != nil {
+							return err
+						}
+						var img Image
+						if err := json.Unmarshal(dt, &img); err != nil {
+							return err
+						}
+						img.Created = nil
+						// if there is no explicit target platform, try to match based on image config
+						if d.platform == nil && platformOpt.implicitTarget {
+							p := autoDetectPlatform(img, *platform, platformOpt.buildPlatforms)
+							platform = &p
+						}
+						d.image = img
+						if dgst != "" {
+							ref, err = reference.WithDigest(ref, dgst)
+							if err != nil {
 								return err
 							}
-							img.Created = nil
-							// if there is no explicit target platform, try to match based on image config
-							if d.platform == nil && platformOpt.implicitTarget {
-								p := autoDetectPlatform(img, *platform, platformOpt.buildPlatforms)
-								platform = &p
-							}
-							d.image = img
-							if dgst != "" {
-								ref, err = reference.WithDigest(ref, dgst)
-								if err != nil {
-									return err
-								}
-							}
-							d.stage.BaseName = ref.String()
-							if len(img.RootFS.DiffIDs) == 0 {
-								isScratch = true
-								// schema1 images can't return diffIDs so double check :(
-								for _, h := range img.History {
-									if !h.EmptyLayer {
-										isScratch = false
-										break
-									}
+						}
+						d.stage.BaseName = ref.String()
+						if len(img.RootFS.DiffIDs) == 0 {
+							isScratch = true
+							// schema1 images can't return diffIDs so double check :(
+							for _, h := range img.History {
+								if !h.EmptyLayer {
+									isScratch = false
+									break
 								}
 							}
 						}
@@ -314,7 +318,11 @@
 
 		// make sure that PATH is always set
 		if _, ok := shell.BuildEnvs(d.image.Config.Env)["PATH"]; !ok {
-			d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv)
+			var os string
+			if d.platform != nil {
+				os = d.platform.OS
+			}
+			d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv(os))
 		}
 
 		// initialize base metadata from image conf
@@ -322,6 +330,9 @@
 			k, v := parseKeyValue(env)
 			d.state = d.state.AddEnv(k, v)
 		}
+		if opt.Hostname != "" {
+			d.state = d.state.Hostname(opt.Hostname)
+		}
 		if d.image.Config.WorkingDir != "" {
 			if err = dispatchWorkdir(d, &instructions.WorkdirCommand{Path: d.image.Config.WorkingDir}, false, nil); err != nil {
 				return nil, nil, parser.WithLocation(err, d.stage.Location)
@@ -1072,26 +1083,30 @@
 }
 
 func dispatchArg(d *dispatchState, c *instructions.ArgCommand, metaArgs []instructions.KeyValuePairOptional, buildArgValues map[string]string) error {
-	commitStr := "ARG " + c.Key
-	buildArg := setKVValue(c.KeyValuePairOptional, buildArgValues)
+	commitStrs := make([]string, 0, len(c.Args))
+	for _, arg := range c.Args {
+		buildArg := setKVValue(arg, buildArgValues)
 
-	if c.Value != nil {
-		commitStr += "=" + *c.Value
-	}
-	if buildArg.Value == nil {
-		for _, ma := range metaArgs {
-			if ma.Key == buildArg.Key {
-				buildArg.Value = ma.Value
+		commitStr := arg.Key
+		if arg.Value != nil {
+			commitStr += "=" + *arg.Value
+		}
+		commitStrs = append(commitStrs, commitStr)
+		if buildArg.Value == nil {
+			for _, ma := range metaArgs {
+				if ma.Key == buildArg.Key {
+					buildArg.Value = ma.Value
+				}
 			}
 		}
-	}
 
-	if buildArg.Value != nil {
-		d.state = d.state.AddEnv(buildArg.Key, *buildArg.Value)
-	}
+		if buildArg.Value != nil {
+			d.state = d.state.AddEnv(buildArg.Key, *buildArg.Value)
+		}
 
-	d.buildArgs = append(d.buildArgs, buildArg)
-	return commitToHistory(&d.image, commitStr, false, nil)
+		d.buildArgs = append(d.buildArgs, buildArg)
+	}
+	return commitToHistory(&d.image, "ARG "+strings.Join(commitStrs, " "), false, nil)
 }
 
 func pathRelativeToWorkingDir(s llb.State, p string) (string, error) {
@@ -1308,15 +1323,15 @@
 	isNil := true
 	for k, v := range args {
 		if strings.EqualFold(k, "http_proxy") {
-			pe.HttpProxy = v
+			pe.HTTPProxy = v
 			isNil = false
 		}
 		if strings.EqualFold(k, "https_proxy") {
-			pe.HttpsProxy = v
+			pe.HTTPSProxy = v
 			isNil = false
 		}
 		if strings.EqualFold(k, "ftp_proxy") {
-			pe.FtpProxy = v
+			pe.FTPProxy = v
 			isNil = false
 		}
 		if strings.EqualFold(k, "no_proxy") {
@@ -1339,7 +1354,7 @@
 	if len(img.Config.Shell) > 0 {
 		shell = append([]string{}, img.Config.Shell...)
 	} else {
-		shell = defaultShell()
+		shell = defaultShell(img.OS)
 	}
 	return append(shell, strings.Join(args, " "))
 }
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_norunmount.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_norunmount.go
deleted file mode 100644
index 5f0cd08..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_norunmount.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// +build !dfrunmount
-
-package dockerfile2llb
-
-import (
-	"github.com/moby/buildkit/client/llb"
-	"github.com/moby/buildkit/frontend/dockerfile/instructions"
-)
-
-func detectRunMount(cmd *command, allDispatchStates *dispatchStates) bool {
-	return false
-}
-
-func dispatchRunMounts(d *dispatchState, c *instructions.RunCommand, sources []*dispatchState, opt dispatchOpt) ([]llb.RunOption, error) {
-	return nil, nil
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nosecrets.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nosecrets.go
deleted file mode 100644
index d754702..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nosecrets.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build dfrunmount,!dfsecrets
-
-package dockerfile2llb
-
-import (
-	"github.com/moby/buildkit/client/llb"
-	"github.com/moby/buildkit/frontend/dockerfile/instructions"
-	"github.com/pkg/errors"
-)
-
-func dispatchSecret(m *instructions.Mount) (llb.RunOption, error) {
-	return nil, errors.Errorf("secret mounts not allowed")
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go
deleted file mode 100644
index 8b8afdc..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_nossh.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build dfrunmount,!dfssh
-
-package dockerfile2llb
-
-import (
-	"github.com/moby/buildkit/client/llb"
-	"github.com/moby/buildkit/frontend/dockerfile/instructions"
-	"github.com/pkg/errors"
-)
-
-func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) {
-	return nil, errors.Errorf("ssh mounts not allowed")
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
index 1be4849..8cd928b 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go
@@ -1,5 +1,3 @@
-// +build dfrunmount
-
 package dockerfile2llb
 
 import (
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_secrets.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_secrets.go
index 59c055a..2c88a5e 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_secrets.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_secrets.go
@@ -1,5 +1,3 @@
-// +build dfsecrets
-
 package dockerfile2llb
 
 import (
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
index a29b535..b55659d 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_ssh.go
@@ -1,5 +1,3 @@
-// +build dfssh
-
 package dockerfile2llb
 
 import (
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell.go
new file mode 100644
index 0000000..58b1737
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell.go
@@ -0,0 +1,8 @@
+package dockerfile2llb
+
+func defaultShell(os string) []string {
+	if os == "windows" {
+		return []string{"cmd", "/S", "/C"}
+	}
+	return []string{"/bin/sh", "-c"}
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell_unix.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell_unix.go
deleted file mode 100644
index b5d541d..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell_unix.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build !windows
-
-package dockerfile2llb
-
-func defaultShell() []string {
-	return []string{"/bin/sh", "-c"}
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell_windows.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell_windows.go
deleted file mode 100644
index 7693e05..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/defaultshell_windows.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build windows
-
-package dockerfile2llb
-
-func defaultShell() []string {
-	return []string{"cmd", "/S", "/C"}
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go
index 55e9add..6eb4cf6 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go
@@ -74,6 +74,6 @@
 	}
 	img.RootFS.Type = "layers"
 	img.Config.WorkingDir = "/"
-	img.Config.Env = []string{"PATH=" + system.DefaultPathEnv}
+	img.Config.Env = []string{"PATH=" + system.DefaultPathEnv(platform.OS)}
 	return img
 }
diff --git a/builder/dockerignore/dockerignore.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerignore/dockerignore.go
similarity index 94%
rename from builder/dockerignore/dockerignore.go
rename to vendor/github.com/moby/buildkit/frontend/dockerfile/dockerignore/dockerignore.go
index 57f224a..cc22381 100644
--- a/builder/dockerignore/dockerignore.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerignore/dockerignore.go
@@ -1,4 +1,4 @@
-package dockerignore // import "github.com/docker/docker/builder/dockerignore"
+package dockerignore
 
 import (
 	"bufio"
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands.go
index 4a4146a..e602744 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands.go
@@ -21,8 +21,9 @@
 
 // KeyValuePairOptional is the same as KeyValuePair but Value is optional
 type KeyValuePairOptional struct {
-	Key   string
-	Value *string
+	Key     string
+	Value   *string
+	Comment string
 }
 
 func (kvpo *KeyValuePairOptional) ValueString() string {
@@ -380,22 +381,25 @@
 // Dockerfile author may optionally set a default value of this variable.
 type ArgCommand struct {
 	withNameAndCode
-	KeyValuePairOptional
+	Args []KeyValuePairOptional
 }
 
 // Expand variables
 func (c *ArgCommand) Expand(expander SingleWordExpander) error {
-	p, err := expander(c.Key)
-	if err != nil {
-		return err
-	}
-	c.Key = p
-	if c.Value != nil {
-		p, err = expander(*c.Value)
+	for i, v := range c.Args {
+		p, err := expander(v.Key)
 		if err != nil {
 			return err
 		}
-		c.Value = &p
+		v.Key = p
+		if v.Value != nil {
+			p, err = expander(*v.Value)
+			if err != nil {
+				return err
+			}
+			v.Value = &p
+		}
+		c.Args[i] = v
 	}
 	return nil
 }
@@ -416,6 +420,7 @@
 	SourceCode string
 	Platform   string
 	Location   []parser.Range
+	Comment    string
 }
 
 // AddCommand to the stage
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go
deleted file mode 100644
index 5878064..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nosecrets.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build !dfsecrets
-
-package instructions
-
-func isSecretMountsSupported() bool {
-	return false
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go
deleted file mode 100644
index a131a27..0000000
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_nossh.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build !dfssh
-
-package instructions
-
-func isSSHMountsSupported() bool {
-	return false
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go
index 442877d..b0b0f01 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_runmount.go
@@ -1,5 +1,3 @@
-// +build dfrunmount
-
 package instructions
 
 import (
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_secrets.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_secrets.go
index 6cce119..2b4140b 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_secrets.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_secrets.go
@@ -1,5 +1,3 @@
-// +build dfsecrets
-
 package instructions
 
 func isSecretMountsSupported() bool {
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go
index 0b94a56..0e4e5f3 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/commands_ssh.go
@@ -1,5 +1,3 @@
-// +build dfssh
-
 package instructions
 
 func isSSHMountsSupported() bool {
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/parse.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/parse.go
index 1be9d7b..83cab66 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/parse.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/instructions/parse.go
@@ -22,6 +22,7 @@
 	flags      *BFlags
 	original   string
 	location   []parser.Range
+	comments   []string
 }
 
 var parseRunPreHooks []func(*RunCommand, parseRequest) error
@@ -50,6 +51,7 @@
 		original:   node.Original,
 		flags:      NewBFlagsWithArgs(node.Flags),
 		location:   node.Location(),
+		comments:   node.PrevComment,
 	}
 }
 
@@ -289,6 +291,7 @@
 		Commands:   []Command{},
 		Platform:   flPlatform.Value,
 		Location:   req.location,
+		Comment:    getComment(req.comments, stageName),
 	}, nil
 
 }
@@ -579,33 +582,38 @@
 }
 
 func parseArg(req parseRequest) (*ArgCommand, error) {
-	if len(req.args) != 1 {
-		return nil, errExactlyOneArgument("ARG")
+	if len(req.args) < 1 {
+		return nil, errAtLeastOneArgument("ARG")
 	}
 
-	kvpo := KeyValuePairOptional{}
+	pairs := make([]KeyValuePairOptional, len(req.args))
 
-	arg := req.args[0]
-	// 'arg' can just be a name or name-value pair. Note that this is different
-	// from 'env' that handles the split of name and value at the parser level.
-	// The reason for doing it differently for 'arg' is that we support just
-	// defining an arg and not assign it a value (while 'env' always expects a
-	// name-value pair). If possible, it will be good to harmonize the two.
-	if strings.Contains(arg, "=") {
-		parts := strings.SplitN(arg, "=", 2)
-		if len(parts[0]) == 0 {
-			return nil, errBlankCommandNames("ARG")
+	for i, arg := range req.args {
+		kvpo := KeyValuePairOptional{}
+
+		// 'arg' can just be a name or name-value pair. Note that this is different
+		// from 'env' that handles the split of name and value at the parser level.
+		// The reason for doing it differently for 'arg' is that we support just
+		// defining an arg and not assign it a value (while 'env' always expects a
+		// name-value pair). If possible, it will be good to harmonize the two.
+		if strings.Contains(arg, "=") {
+			parts := strings.SplitN(arg, "=", 2)
+			if len(parts[0]) == 0 {
+				return nil, errBlankCommandNames("ARG")
+			}
+
+			kvpo.Key = parts[0]
+			kvpo.Value = &parts[1]
+		} else {
+			kvpo.Key = arg
 		}
-
-		kvpo.Key = parts[0]
-		kvpo.Value = &parts[1]
-	} else {
-		kvpo.Key = arg
+		kvpo.Comment = getComment(req.comments, kvpo.Key)
+		pairs[i] = kvpo
 	}
 
 	return &ArgCommand{
-		KeyValuePairOptional: kvpo,
-		withNameAndCode:      newWithNameAndCode(req),
+		Args:            pairs,
+		withNameAndCode: newWithNameAndCode(req),
 	}, nil
 }
 
@@ -650,3 +658,15 @@
 func errTooManyArguments(command string) error {
 	return errors.Errorf("Bad input to %s, too many arguments", command)
 }
+
+func getComment(comments []string, name string) string {
+	if name == "" {
+		return ""
+	}
+	for _, line := range comments {
+		if strings.HasPrefix(line, name+" ") {
+			return strings.TrimPrefix(line, name+" ")
+		}
+	}
+	return ""
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/line_parsers.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/line_parsers.go
index 441824c..c0d0a55 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/line_parsers.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/line_parsers.go
@@ -40,7 +40,7 @@
 		return nil, nil, nil
 	}
 
-	child, err := newNodeFromLine(rest, d)
+	child, err := newNodeFromLine(rest, d, nil)
 	if err != nil {
 		return nil, nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
index dc6d178..1e30e20 100644
--- a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
+++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
@@ -28,14 +28,15 @@
 // works a little more effectively than a "proper" parse tree for our needs.
 //
 type Node struct {
-	Value      string          // actual content
-	Next       *Node           // the next item in the current sexp
-	Children   []*Node         // the children of this sexp
-	Attributes map[string]bool // special attributes for this node
-	Original   string          // original line used before parsing
-	Flags      []string        // only top Node should have this set
-	StartLine  int             // the line in the original dockerfile where the node begins
-	EndLine    int             // the line in the original dockerfile where the node ends
+	Value       string          // actual content
+	Next        *Node           // the next item in the current sexp
+	Children    []*Node         // the children of this sexp
+	Attributes  map[string]bool // special attributes for this node
+	Original    string          // original line used before parsing
+	Flags       []string        // only top Node should have this set
+	StartLine   int             // the line in the original dockerfile where the node begins
+	EndLine     int             // the line in the original dockerfile where the node ends
+	PrevComment []string
 }
 
 // Location return the location of node in source code
@@ -107,13 +108,25 @@
 	seen                  map[string]struct{} // Whether the escape directive has been seen
 }
 
-// setEscapeToken sets the default token for escaping characters in a Dockerfile.
+// setEscapeToken sets the default token for escaping characters and as line-
+// continuation token in a Dockerfile. Only ` (backtick) and \ (backslash) are
+// allowed as token.
 func (d *directives) setEscapeToken(s string) error {
-	if s != "`" && s != "\\" {
+	if s != "`" && s != `\` {
 		return errors.Errorf("invalid escape token '%s' does not match ` or \\", s)
 	}
 	d.escapeToken = rune(s[0])
-	d.lineContinuationRegex = regexp.MustCompile(`\` + s + `[ \t]*$`)
+	// The escape token is used both to escape characters in a line and as line
+	// continuation token. If it's the last non-whitespace token, it is used as
+	// line-continuation token, *unless* preceded by an escape-token.
+	//
+	// The second branch in the regular expression handles line-continuation
+	// tokens on their own line, which don't have any character preceding them.
+	//
+	// Due to Go lacking negative look-ahead matching, this regular expression
+	// does not currently handle a line-continuation token preceded by an *escaped*
+	// escape-token ("foo \\\").
+	d.lineContinuationRegex = regexp.MustCompile(`([^\` + s + `])\` + s + `[ \t]*$|^\` + s + `[ \t]*$`)
 	return nil
 }
 
@@ -191,7 +204,7 @@
 // newNodeFromLine splits the line into parts, and dispatches to a function
 // based on the command and command arguments. A Node is created from the
 // result of the dispatch.
-func newNodeFromLine(line string, d *directives) (*Node, error) {
+func newNodeFromLine(line string, d *directives, comments []string) (*Node, error) {
 	cmd, flags, args, err := splitCommand(line)
 	if err != nil {
 		return nil, err
@@ -208,11 +221,12 @@
 	}
 
 	return &Node{
-		Value:      cmd,
-		Original:   line,
-		Flags:      flags,
-		Next:       next,
-		Attributes: attrs,
+		Value:       cmd,
+		Original:    line,
+		Flags:       flags,
+		Next:        next,
+		Attributes:  attrs,
+		PrevComment: comments,
 	}, nil
 }
 
@@ -239,6 +253,7 @@
 	root := &Node{StartLine: -1}
 	scanner := bufio.NewScanner(rwc)
 	warnings := []string{}
+	var comments []string
 
 	var err error
 	for scanner.Scan() {
@@ -247,6 +262,14 @@
 			// First line, strip the byte-order-marker if present
 			bytesRead = bytes.TrimPrefix(bytesRead, utf8bom)
 		}
+		if isComment(bytesRead) {
+			comment := strings.TrimSpace(string(bytesRead[1:]))
+			if comment == "" {
+				comments = nil
+			} else {
+				comments = append(comments, comment)
+			}
+		}
 		bytesRead, err = processLine(d, bytesRead, true)
 		if err != nil {
 			return nil, withLocation(err, currentLine, 0)
@@ -285,10 +308,11 @@
 			warnings = append(warnings, "[WARNING]: Empty continuation line found in:\n    "+line)
 		}
 
-		child, err := newNodeFromLine(line, d)
+		child, err := newNodeFromLine(line, d, comments)
 		if err != nil {
 			return nil, withLocation(err, startLine, currentLine)
 		}
+		comments = nil
 		root.AddChild(child, startLine, currentLine)
 	}
 
@@ -327,7 +351,7 @@
 
 func trimContinuationCharacter(line string, d *directives) (string, bool) {
 	if d.lineContinuationRegex.MatchString(line) {
-		line = d.lineContinuationRegex.ReplaceAllString(line, "")
+		line = d.lineContinuationRegex.ReplaceAllString(line, "$1")
 		return line, false
 	}
 	return line, true
diff --git a/vendor/github.com/moby/buildkit/frontend/frontend.go b/vendor/github.com/moby/buildkit/frontend/frontend.go
index e55b6af..091813a 100644
--- a/vendor/github.com/moby/buildkit/frontend/frontend.go
+++ b/vendor/github.com/moby/buildkit/frontend/frontend.go
@@ -3,20 +3,18 @@
 import (
 	"context"
 
-	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/client/llb"
-	"github.com/moby/buildkit/executor"
 	gw "github.com/moby/buildkit/frontend/gateway/client"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver/pb"
 	digest "github.com/opencontainers/go-digest"
 )
 
 type Frontend interface {
-	Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string, inputs map[string]*pb.Definition, sid string) (*Result, error)
+	Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error)
 }
 
 type FrontendLLBBridge interface {
-	executor.Executor
 	Solve(ctx context.Context, req SolveRequest, sid string) (*Result, error)
 	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error)
 }
@@ -24,7 +22,3 @@
 type SolveRequest = gw.SolveRequest
 
 type CacheOptionsEntry = gw.CacheOptionsEntry
-
-type WorkerInfos interface {
-	WorkerInfos() []client.WorkerInfo
-}
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go b/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go
index bc7f96b..09d86ca 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/client/client.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"io"
 
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/solver/pb"
@@ -16,6 +17,64 @@
 	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error)
 	BuildOpts() BuildOpts
 	Inputs(ctx context.Context) (map[string]llb.State, error)
+	NewContainer(ctx context.Context, req NewContainerRequest) (Container, error)
+}
+
+// NewContainerRequest encapsulates the requirements for a client to define a
+// new container, without defining the initial process.
+type NewContainerRequest struct {
+	Mounts      []Mount
+	NetMode     pb.NetMode
+	Platform    *pb.Platform
+	Constraints *pb.WorkerConstraints
+}
+
+// Mount allows clients to specify a filesystem mount. A Reference to a
+// previously solved Result is required.
+type Mount struct {
+	Selector  string
+	Dest      string
+	ResultID  string
+	Ref       Reference
+	Readonly  bool
+	MountType pb.MountType
+	CacheOpt  *pb.CacheOpt
+	SecretOpt *pb.SecretOpt
+	SSHOpt    *pb.SSHOpt
+}
+
+// Container is used to start new processes inside a container and release the
+// container resources when done.
+type Container interface {
+	Start(context.Context, StartRequest) (ContainerProcess, error)
+	Release(context.Context) error
+}
+
+// StartRequest encapsulates the arguments to define a process within a
+// container.
+type StartRequest struct {
+	Args           []string
+	Env            []string
+	User           string
+	Cwd            string
+	Tty            bool
+	Stdin          io.ReadCloser
+	Stdout, Stderr io.WriteCloser
+	SecurityMode   pb.SecurityMode
+}
+
+// WinSize is same as executor.WinSize, copied here to prevent circular package
+// dependencies.
+type WinSize struct {
+	Rows uint32
+	Cols uint32
+}
+
+// ContainerProcess represents a process within a container.
+type ContainerProcess interface {
+	Wait() error
+	Resize(ctx context.Context, size WinSize) error
+	// TODO Signal(ctx context.Context, sig os.Signal)
 }
 
 type Reference interface {
@@ -46,6 +105,7 @@
 
 // SolveRequest is same as frontend.SolveRequest but avoiding dependency
 type SolveRequest struct {
+	Evaluate       bool
 	Definition     *pb.Definition
 	Frontend       string
 	FrontendOpt    map[string]string
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/container.go b/vendor/github.com/moby/buildkit/frontend/gateway/container.go
new file mode 100644
index 0000000..1f79bb6
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/container.go
@@ -0,0 +1,430 @@
+package gateway
+
+import (
+	"context"
+	"fmt"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+
+	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/executor"
+	"github.com/moby/buildkit/frontend/gateway/client"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/solver/llbsolver/mounts"
+	opspb "github.com/moby/buildkit/solver/pb"
+	"github.com/moby/buildkit/util/stack"
+	utilsystem "github.com/moby/buildkit/util/system"
+	"github.com/moby/buildkit/worker"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"golang.org/x/sync/errgroup"
+)
+
+type NewContainerRequest struct {
+	ContainerID string
+	NetMode     opspb.NetMode
+	Mounts      []Mount
+	Platform    *opspb.Platform
+	Constraints *opspb.WorkerConstraints
+}
+
+// Mount used for the gateway.Container is nearly identical to the client.Mount
+// except is has a RefProxy instead of Ref to allow for a common abstraction
+// between gateway clients.
+type Mount struct {
+	*opspb.Mount
+	WorkerRef *worker.WorkerRef
+}
+
+func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) {
+	ctx, cancel := context.WithCancel(ctx)
+	eg, ctx := errgroup.WithContext(ctx)
+	platform := opspb.Platform{
+		OS:           runtime.GOOS,
+		Architecture: runtime.GOARCH,
+	}
+	if req.Platform != nil {
+		platform = *req.Platform
+	}
+	ctr := &gatewayContainer{
+		id:       req.ContainerID,
+		netMode:  req.NetMode,
+		platform: platform,
+		executor: w.Executor(),
+		errGroup: eg,
+		ctx:      ctx,
+		cancel:   cancel,
+	}
+
+	var (
+		mnts []*opspb.Mount
+		refs []*worker.WorkerRef
+	)
+	for _, m := range req.Mounts {
+		mnts = append(mnts, m.Mount)
+		if m.WorkerRef != nil {
+			refs = append(refs, m.WorkerRef)
+			m.Mount.Input = opspb.InputIndex(len(refs) - 1)
+		} else {
+			m.Mount.Input = opspb.Empty
+		}
+	}
+
+	name := fmt.Sprintf("container %s", req.ContainerID)
+	mm := mounts.NewMountManager(name, w.CacheManager(), sm, w.MetadataStore())
+	p, err := PrepareMounts(ctx, mm, w.CacheManager(), g, mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) {
+		cm := w.CacheManager()
+		if m.Input != opspb.Empty {
+			cm = refs[m.Input].Worker.CacheManager()
+		}
+		return cm.New(ctx, ref, g)
+
+	})
+	if err != nil {
+		for i := len(p.Actives) - 1; i >= 0; i-- { // call in LIFO order
+			p.Actives[i].Ref.Release(context.TODO())
+		}
+		for _, o := range p.OutputRefs {
+			o.Ref.Release(context.TODO())
+		}
+		return nil, err
+	}
+	ctr.rootFS = p.Root
+	ctr.mounts = p.Mounts
+
+	for _, o := range p.OutputRefs {
+		o := o
+		ctr.cleanup = append(ctr.cleanup, func() error {
+			return o.Ref.Release(context.TODO())
+		})
+	}
+	for _, active := range p.Actives {
+		active := active
+		ctr.cleanup = append(ctr.cleanup, func() error {
+			return active.Ref.Release(context.TODO())
+		})
+	}
+
+	return ctr, nil
+}
+
+type PreparedMounts struct {
+	Root           executor.Mount
+	ReadonlyRootFS bool
+	Mounts         []executor.Mount
+	OutputRefs     []MountRef
+	Actives        []MountMutableRef
+}
+
+type MountRef struct {
+	Ref        cache.Ref
+	MountIndex int
+}
+
+type MountMutableRef struct {
+	Ref        cache.MutableRef
+	MountIndex int
+}
+
+type MakeMutable func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error)
+
+func PrepareMounts(ctx context.Context, mm *mounts.MountManager, cm cache.Manager, g session.Group, mnts []*opspb.Mount, refs []*worker.WorkerRef, makeMutable MakeMutable) (p PreparedMounts, err error) {
+	// loop over all mounts, fill in mounts, root and outputs
+	for i, m := range mnts {
+		var (
+			mountable cache.Mountable
+			ref       cache.ImmutableRef
+		)
+
+		if m.Dest == opspb.RootMount && m.MountType != opspb.MountType_BIND {
+			return p, errors.Errorf("invalid mount type %s for %s", m.MountType.String(), m.Dest)
+		}
+
+		// if mount is based on input validate and load it
+		if m.Input != opspb.Empty {
+			if int(m.Input) >= len(refs) {
+				return p, errors.Errorf("missing input %d", m.Input)
+			}
+			ref = refs[int(m.Input)].ImmutableRef
+			mountable = ref
+		}
+
+		switch m.MountType {
+		case opspb.MountType_BIND:
+			// if mount creates an output
+			if m.Output != opspb.SkipOutput {
+				// if it is readonly and not root then output is the input
+				if m.Readonly && ref != nil && m.Dest != opspb.RootMount {
+					p.OutputRefs = append(p.OutputRefs, MountRef{
+						MountIndex: i,
+						Ref:        ref.Clone(),
+					})
+				} else {
+					// otherwise output and mount is the mutable child
+					active, err := makeMutable(m, ref)
+					if err != nil {
+						return p, err
+					}
+					mountable = active
+					p.OutputRefs = append(p.OutputRefs, MountRef{
+						MountIndex: i,
+						Ref:        active,
+					})
+				}
+			} else if (!m.Readonly || ref == nil) && m.Dest != opspb.RootMount {
+				// this case is empty readonly scratch without output that is not really useful for anything but don't error
+				active, err := makeMutable(m, ref)
+				if err != nil {
+					return p, err
+				}
+				p.Actives = append(p.Actives, MountMutableRef{
+					MountIndex: i,
+					Ref:        active,
+				})
+				mountable = active
+			}
+
+		case opspb.MountType_CACHE:
+			active, err := mm.MountableCache(ctx, m, ref, g)
+			if err != nil {
+				return p, err
+			}
+			mountable = active
+			p.Actives = append(p.Actives, MountMutableRef{
+				MountIndex: i,
+				Ref:        active,
+			})
+			if m.Output != opspb.SkipOutput && ref != nil {
+				p.OutputRefs = append(p.OutputRefs, MountRef{
+					MountIndex: i,
+					Ref:        ref.Clone(),
+				})
+			}
+
+		case opspb.MountType_TMPFS:
+			mountable = mm.MountableTmpFS()
+		case opspb.MountType_SECRET:
+			var err error
+			mountable, err = mm.MountableSecret(ctx, m, g)
+			if err != nil {
+				return p, err
+			}
+			if mountable == nil {
+				continue
+			}
+		case opspb.MountType_SSH:
+			var err error
+			mountable, err = mm.MountableSSH(ctx, m, g)
+			if err != nil {
+				return p, err
+			}
+			if mountable == nil {
+				continue
+			}
+
+		default:
+			return p, errors.Errorf("mount type %s not implemented", m.MountType)
+		}
+
+		// validate that there is a mount
+		if mountable == nil {
+			return p, errors.Errorf("mount %s has no input", m.Dest)
+		}
+
+		// if dest is root we need mutable ref even if there is no output
+		if m.Dest == opspb.RootMount {
+			root := mountable
+			p.ReadonlyRootFS = m.Readonly
+			if m.Output == opspb.SkipOutput && p.ReadonlyRootFS {
+				active, err := makeMutable(m, ref)
+				if err != nil {
+					return p, err
+				}
+				p.Actives = append(p.Actives, MountMutableRef{
+					MountIndex: i,
+					Ref:        active,
+				})
+				root = active
+			}
+			p.Root = mountWithSession(root, g)
+		} else {
+			mws := mountWithSession(mountable, g)
+			mws.Dest = m.Dest
+			mws.Readonly = m.Readonly
+			mws.Selector = m.Selector
+			p.Mounts = append(p.Mounts, mws)
+		}
+	}
+
+	// sort mounts so parents are mounted first
+	sort.Slice(p.Mounts, func(i, j int) bool {
+		return p.Mounts[i].Dest < p.Mounts[j].Dest
+	})
+
+	return p, nil
+}
+
+type gatewayContainer struct {
+	id       string
+	netMode  opspb.NetMode
+	platform opspb.Platform
+	rootFS   executor.Mount
+	mounts   []executor.Mount
+	executor executor.Executor
+	started  bool
+	errGroup *errgroup.Group
+	mu       sync.Mutex
+	cleanup  []func() error
+	ctx      context.Context
+	cancel   func()
+}
+
+func (gwCtr *gatewayContainer) Start(ctx context.Context, req client.StartRequest) (client.ContainerProcess, error) {
+	resize := make(chan executor.WinSize)
+	procInfo := executor.ProcessInfo{
+		Meta: executor.Meta{
+			Args:         req.Args,
+			Env:          req.Env,
+			User:         req.User,
+			Cwd:          req.Cwd,
+			Tty:          req.Tty,
+			NetMode:      gwCtr.netMode,
+			SecurityMode: req.SecurityMode,
+		},
+		Stdin:  req.Stdin,
+		Stdout: req.Stdout,
+		Stderr: req.Stderr,
+		Resize: resize,
+	}
+	if procInfo.Meta.Cwd == "" {
+		procInfo.Meta.Cwd = "/"
+	}
+	procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "PATH", utilsystem.DefaultPathEnv(gwCtr.platform.OS))
+	if req.Tty {
+		procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "TERM", "xterm")
+	}
+
+	// mark that we have started on the first call to execProcess for this
+	// container, so that future calls will call Exec rather than Run
+	gwCtr.mu.Lock()
+	started := gwCtr.started
+	gwCtr.started = true
+	gwCtr.mu.Unlock()
+
+	eg, ctx := errgroup.WithContext(gwCtr.ctx)
+	gwProc := &gatewayContainerProcess{
+		resize:   resize,
+		errGroup: eg,
+		groupCtx: ctx,
+	}
+
+	if !started {
+		startedCh := make(chan struct{})
+		gwProc.errGroup.Go(func() error {
+			logrus.Debugf("Starting new container for %s with args: %q", gwCtr.id, procInfo.Meta.Args)
+			err := gwCtr.executor.Run(ctx, gwCtr.id, gwCtr.rootFS, gwCtr.mounts, procInfo, startedCh)
+			return stack.Enable(err)
+		})
+		select {
+		case <-ctx.Done():
+		case <-startedCh:
+		}
+	} else {
+		gwProc.errGroup.Go(func() error {
+			logrus.Debugf("Execing into container %s with args: %q", gwCtr.id, procInfo.Meta.Args)
+			err := gwCtr.executor.Exec(ctx, gwCtr.id, procInfo)
+			return stack.Enable(err)
+		})
+	}
+
+	gwCtr.errGroup.Go(gwProc.errGroup.Wait)
+
+	return gwProc, nil
+}
+
+func (gwCtr *gatewayContainer) Release(ctx context.Context) error {
+	gwCtr.cancel()
+	err1 := gwCtr.errGroup.Wait()
+
+	var err2 error
+	for i := len(gwCtr.cleanup) - 1; i >= 0; i-- { // call in LIFO order
+		err := gwCtr.cleanup[i]()
+		if err2 == nil {
+			err2 = err
+		}
+	}
+
+	if err1 != nil {
+		return stack.Enable(err1)
+	}
+	return stack.Enable(err2)
+}
+
+type gatewayContainerProcess struct {
+	errGroup *errgroup.Group
+	groupCtx context.Context
+	resize   chan<- executor.WinSize
+	mu       sync.Mutex
+}
+
+func (gwProc *gatewayContainerProcess) Wait() error {
+	err := stack.Enable(gwProc.errGroup.Wait())
+	gwProc.mu.Lock()
+	defer gwProc.mu.Unlock()
+	close(gwProc.resize)
+	return err
+}
+
+func (gwProc *gatewayContainerProcess) Resize(ctx context.Context, size client.WinSize) error {
+	gwProc.mu.Lock()
+	defer gwProc.mu.Unlock()
+
+	//  is the container done or should we proceed with sending event?
+	select {
+	case <-gwProc.groupCtx.Done():
+		return nil
+	case <-ctx.Done():
+		return nil
+	default:
+	}
+
+	// now we select on contexts again in case p.resize blocks b/c
+	// container no longer reading from it.  In that case when
+	// the errgroup finishes we want to unblock on the write
+	// and exit
+	select {
+	case <-gwProc.groupCtx.Done():
+	case <-ctx.Done():
+	case gwProc.resize <- executor.WinSize{Cols: size.Cols, Rows: size.Rows}:
+	}
+	return nil
+}
+
+func addDefaultEnvvar(env []string, k, v string) []string {
+	for _, e := range env {
+		if strings.HasPrefix(e, k+"=") {
+			return env
+		}
+	}
+	return append(env, k+"="+v)
+}
+
+func mountWithSession(m cache.Mountable, g session.Group) executor.Mount {
+	_, readonly := m.(cache.ImmutableRef)
+	return executor.Mount{
+		Src:      &mountable{m: m, g: g},
+		Readonly: readonly,
+	}
+}
+
+type mountable struct {
+	m cache.Mountable
+	g session.Group
+}
+
+func (m *mountable) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
+	return m.m.Mount(ctx, readonly, m.g)
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go
index 241be88..1476ae6 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/forward.go
@@ -4,46 +4,55 @@
 	"context"
 	"sync"
 
-	"github.com/moby/buildkit/cache"
 	cacheutil "github.com/moby/buildkit/cache/util"
-	clienttypes "github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/frontend"
+	"github.com/moby/buildkit/frontend/gateway"
 	"github.com/moby/buildkit/frontend/gateway/client"
 	gwpb "github.com/moby/buildkit/frontend/gateway/pb"
+	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/solver/errdefs"
+	llberrdefs "github.com/moby/buildkit/solver/llbsolver/errdefs"
 	opspb "github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/apicaps"
 	"github.com/moby/buildkit/worker"
 	"github.com/pkg/errors"
 	fstypes "github.com/tonistiigi/fsutil/types"
+	"golang.org/x/sync/errgroup"
 )
 
-func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, workerInfos []clienttypes.WorkerInfo, sid string) (*bridgeClient, error) {
+func llbBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, w worker.Infos, sid string, sm *session.Manager) (*bridgeClient, error) {
 	return &bridgeClient{
 		opts:              opts,
 		inputs:            inputs,
 		FrontendLLBBridge: llbBridge,
 		sid:               sid,
-		workerInfos:       workerInfos,
+		sm:                sm,
+		workers:           w,
 		final:             map[*ref]struct{}{},
+		workerRefByID:     make(map[string]*worker.WorkerRef),
 	}, nil
 }
 
 type bridgeClient struct {
 	frontend.FrontendLLBBridge
-	mu           sync.Mutex
-	opts         map[string]string
-	inputs       map[string]*opspb.Definition
-	final        map[*ref]struct{}
-	sid          string
-	exporterAttr map[string][]byte
-	refs         []*ref
-	workerInfos  []clienttypes.WorkerInfo
+	mu            sync.Mutex
+	opts          map[string]string
+	inputs        map[string]*opspb.Definition
+	final         map[*ref]struct{}
+	sid           string
+	sm            *session.Manager
+	refs          []*ref
+	workers       worker.Infos
+	workerRefByID map[string]*worker.WorkerRef
 }
 
 func (c *bridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) {
 	res, err := c.FrontendLLBBridge.Solve(ctx, frontend.SolveRequest{
+		Evaluate:       req.Evaluate,
 		Definition:     req.Definition,
 		Frontend:       req.Frontend,
 		FrontendOpt:    req.FrontendOpt,
@@ -51,13 +60,13 @@
 		CacheImports:   req.CacheImports,
 	}, c.sid)
 	if err != nil {
-		return nil, err
+		return nil, c.wrapSolveError(err)
 	}
 
 	cRes := &client.Result{}
 	c.mu.Lock()
 	for k, r := range res.Refs {
-		rr, err := newRef(r)
+		rr, err := c.newRef(r, session.NewGroup(c.sid))
 		if err != nil {
 			return nil, err
 		}
@@ -65,7 +74,7 @@
 		cRes.AddRef(k, rr)
 	}
 	if r := res.Ref; r != nil {
-		rr, err := newRef(r)
+		rr, err := c.newRef(r, session.NewGroup(c.sid))
 		if err != nil {
 			return nil, err
 		}
@@ -78,8 +87,8 @@
 	return cRes, nil
 }
 func (c *bridgeClient) BuildOpts() client.BuildOpts {
-	workers := make([]client.WorkerInfo, 0, len(c.workerInfos))
-	for _, w := range c.workerInfos {
+	workers := make([]client.WorkerInfo, 0, len(c.workers.WorkerInfos()))
+	for _, w := range c.workers.WorkerInfos() {
 		workers = append(workers, client.WorkerInfo{
 			ID:        w.ID,
 			Labels:    w.Labels,
@@ -109,6 +118,59 @@
 	return inputs, nil
 }
 
+func (c *bridgeClient) wrapSolveError(solveErr error) error {
+	var (
+		ee       *llberrdefs.ExecError
+		fae      *llberrdefs.FileActionError
+		sce      *solver.SlowCacheError
+		inputIDs []string
+		mountIDs []string
+		subject  errdefs.IsSolve_Subject
+	)
+	if errors.As(solveErr, &ee) {
+		var err error
+		inputIDs, err = c.registerResultIDs(ee.Inputs...)
+		if err != nil {
+			return err
+		}
+		mountIDs, err = c.registerResultIDs(ee.Mounts...)
+		if err != nil {
+			return err
+		}
+	}
+	if errors.As(solveErr, &fae) {
+		subject = fae.ToSubject()
+	}
+	if errors.As(solveErr, &sce) {
+		var err error
+		inputIDs, err = c.registerResultIDs(sce.Result)
+		if err != nil {
+			return err
+		}
+		subject = sce.ToSubject()
+	}
+	return errdefs.WithSolveError(solveErr, subject, inputIDs, mountIDs)
+}
+
+func (c *bridgeClient) registerResultIDs(results ...solver.Result) (ids []string, err error) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	ids = make([]string, len(results))
+	for i, res := range results {
+		if res == nil {
+			continue
+		}
+		workerRef, ok := res.Sys().(*worker.WorkerRef)
+		if !ok {
+			return ids, errors.Errorf("unexpected type for result, got %T", res.Sys())
+		}
+		ids[i] = workerRef.ID()
+		c.workerRefByID[workerRef.ID()] = workerRef
+	}
+	return ids, nil
+}
+
 func (c *bridgeClient) toFrontendResult(r *client.Result) (*frontend.Result, error) {
 	if r == nil {
 		return nil, nil
@@ -141,6 +203,10 @@
 }
 
 func (c *bridgeClient) discard(err error) {
+	for id, workerRef := range c.workerRefByID {
+		workerRef.ImmutableRef.Release(context.TODO())
+		delete(c.workerRefByID, id)
+	}
 	for _, r := range c.refs {
 		if r != nil {
 			if _, ok := c.final[r]; !ok || err != nil {
@@ -150,12 +216,83 @@
 	}
 }
 
-type ref struct {
-	solver.ResultProxy
+func (c *bridgeClient) NewContainer(ctx context.Context, req client.NewContainerRequest) (client.Container, error) {
+	ctrReq := gateway.NewContainerRequest{
+		ContainerID: identity.NewID(),
+		NetMode:     req.NetMode,
+		Mounts:      make([]gateway.Mount, len(req.Mounts)),
+	}
+
+	eg, ctx := errgroup.WithContext(ctx)
+
+	for i, m := range req.Mounts {
+		i, m := i, m
+		eg.Go(func() error {
+			var workerRef *worker.WorkerRef
+			if m.Ref != nil {
+				refProxy, ok := m.Ref.(*ref)
+				if !ok {
+					return errors.Errorf("unexpected Ref type: %T", m.Ref)
+				}
+
+				res, err := refProxy.Result(ctx)
+				if err != nil {
+					return err
+				}
+
+				workerRef, ok = res.Sys().(*worker.WorkerRef)
+				if !ok {
+					return errors.Errorf("invalid ref: %T", res.Sys())
+				}
+			} else if m.ResultID != "" {
+				var ok bool
+				workerRef, ok = c.workerRefByID[m.ResultID]
+				if !ok {
+					return errors.Errorf("failed to find ref %s for %q mount", m.ResultID, m.Dest)
+				}
+			}
+			ctrReq.Mounts[i] = gateway.Mount{
+				WorkerRef: workerRef,
+				Mount: &opspb.Mount{
+					Dest:      m.Dest,
+					Selector:  m.Selector,
+					Readonly:  m.Readonly,
+					MountType: m.MountType,
+					CacheOpt:  m.CacheOpt,
+					SecretOpt: m.SecretOpt,
+					SSHOpt:    m.SSHOpt,
+				},
+			}
+			return nil
+		})
+	}
+
+	err := eg.Wait()
+	if err != nil {
+		return nil, err
+	}
+
+	w, err := c.workers.GetDefault()
+	if err != nil {
+		return nil, err
+	}
+
+	group := session.NewGroup(c.sid)
+	ctr, err := gateway.NewContainer(ctx, w, c.sm, group, ctrReq)
+	if err != nil {
+		return nil, err
+	}
+	return ctr, nil
 }
 
-func newRef(r solver.ResultProxy) (*ref, error) {
-	return &ref{ResultProxy: r}, nil
+type ref struct {
+	solver.ResultProxy
+	session session.Group
+	c       *bridgeClient
+}
+
+func (c *bridgeClient) newRef(r solver.ResultProxy, s session.Group) (*ref, error) {
+	return &ref{ResultProxy: r, session: s, c: c}, nil
 }
 
 func (r *ref) ToState() (st llb.State, err error) {
@@ -167,7 +304,7 @@
 }
 
 func (r *ref) ReadFile(ctx context.Context, req client.ReadRequest) ([]byte, error) {
-	ref, err := r.getImmutableRef(ctx)
+	m, err := r.getMountable(ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -180,11 +317,11 @@
 			Length: r.Length,
 		}
 	}
-	return cacheutil.ReadFile(ctx, ref, newReq)
+	return cacheutil.ReadFile(ctx, m, newReq)
 }
 
 func (r *ref) ReadDir(ctx context.Context, req client.ReadDirRequest) ([]*fstypes.Stat, error) {
-	ref, err := r.getImmutableRef(ctx)
+	m, err := r.getMountable(ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -192,25 +329,25 @@
 		Path:           req.Path,
 		IncludePattern: req.IncludePattern,
 	}
-	return cacheutil.ReadDir(ctx, ref, newReq)
+	return cacheutil.ReadDir(ctx, m, newReq)
 }
 
 func (r *ref) StatFile(ctx context.Context, req client.StatRequest) (*fstypes.Stat, error) {
-	ref, err := r.getImmutableRef(ctx)
+	m, err := r.getMountable(ctx)
 	if err != nil {
 		return nil, err
 	}
-	return cacheutil.StatFile(ctx, ref, req.Path)
+	return cacheutil.StatFile(ctx, m, req.Path)
 }
 
-func (r *ref) getImmutableRef(ctx context.Context) (cache.ImmutableRef, error) {
+func (r *ref) getMountable(ctx context.Context) (snapshot.Mountable, error) {
 	rr, err := r.ResultProxy.Result(ctx)
 	if err != nil {
-		return nil, err
+		return nil, r.c.wrapSolveError(err)
 	}
 	ref, ok := rr.Sys().(*worker.WorkerRef)
 	if !ok {
 		return nil, errors.Errorf("invalid ref: %T", rr.Sys())
 	}
-	return ref.ImmutableRef, nil
+	return ref.ImmutableRef.Mount(ctx, true, r.session)
 }
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go
index 571aff8..7cd25a0 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/forwarder/frontend.go
@@ -5,10 +5,12 @@
 
 	"github.com/moby/buildkit/frontend"
 	"github.com/moby/buildkit/frontend/gateway/client"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver/pb"
+	"github.com/moby/buildkit/worker"
 )
 
-func NewGatewayForwarder(w frontend.WorkerInfos, f client.BuildFunc) frontend.Frontend {
+func NewGatewayForwarder(w worker.Infos, f client.BuildFunc) frontend.Frontend {
 	return &GatewayForwarder{
 		workers: w,
 		f:       f,
@@ -16,12 +18,12 @@
 }
 
 type GatewayForwarder struct {
-	workers frontend.WorkerInfos
+	workers worker.Infos
 	f       client.BuildFunc
 }
 
-func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*pb.Definition, sid string) (retRes *frontend.Result, retErr error) {
-	c, err := llbBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers.WorkerInfos(), sid)
+func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (retRes *frontend.Result, retErr error) {
+	c, err := llbBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers, sid, sm)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
index f2305e0..029468b 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go
@@ -13,6 +13,7 @@
 	"time"
 
 	"github.com/docker/distribution/reference"
+	"github.com/gogo/googleapis/google/rpc"
 	gogotypes "github.com/gogo/protobuf/types"
 	"github.com/golang/protobuf/ptypes/any"
 	apitypes "github.com/moby/buildkit/api/types"
@@ -23,20 +24,28 @@
 	"github.com/moby/buildkit/executor"
 	"github.com/moby/buildkit/exporter/containerimage/exptypes"
 	"github.com/moby/buildkit/frontend"
+	gwclient "github.com/moby/buildkit/frontend/gateway/client"
 	pb "github.com/moby/buildkit/frontend/gateway/pb"
 	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/solver/errdefs"
+	llberrdefs "github.com/moby/buildkit/solver/llbsolver/errdefs"
 	opspb "github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/apicaps"
 	"github.com/moby/buildkit/util/grpcerrors"
+	"github.com/moby/buildkit/util/stack"
 	"github.com/moby/buildkit/util/tracing"
 	"github.com/moby/buildkit/worker"
+	"github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/net/http2"
+	"golang.org/x/sync/errgroup"
 	spb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/health"
 	"google.golang.org/grpc/health/grpc_health_v1"
 	"google.golang.org/grpc/status"
@@ -47,14 +56,14 @@
 	keyDevel  = "gateway-devel"
 )
 
-func NewGatewayFrontend(w frontend.WorkerInfos) frontend.Frontend {
+func NewGatewayFrontend(w worker.Infos) frontend.Frontend {
 	return &gatewayFrontend{
 		workers: w,
 	}
 }
 
 type gatewayFrontend struct {
-	workers frontend.WorkerInfos
+	workers worker.Infos
 }
 
 func filterPrefix(opts map[string]string, pfx string) map[string]string {
@@ -67,7 +76,7 @@
 	return m
 }
 
-func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, sid string) (*frontend.Result, error) {
+func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, opts map[string]string, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*frontend.Result, error) {
 	source, ok := opts[keySource]
 	if !ok {
 		return nil, errors.Errorf("no source specified for gateway")
@@ -75,6 +84,7 @@
 
 	_, isDevel := opts[keyDevel]
 	var img specs.Image
+	var mfstDigest digest.Digest
 	var rootFS cache.MutableRef
 	var readonly bool // TODO: try to switch to read-only by default.
 
@@ -105,7 +115,7 @@
 			return nil, errors.Errorf("invalid ref: %T", res.Sys())
 		}
 
-		rootFS, err = workerRef.Worker.CacheManager().New(ctx, workerRef.ImmutableRef)
+		rootFS, err = workerRef.Worker.CacheManager().New(ctx, workerRef.ImmutableRef, session.NewGroup(sid))
 		if err != nil {
 			return nil, err
 		}
@@ -126,6 +136,7 @@
 		if err != nil {
 			return nil, err
 		}
+		mfstDigest = dgst
 
 		if err := json.Unmarshal(config, &img); err != nil {
 			return nil, err
@@ -168,19 +179,13 @@
 		if !ok {
 			return nil, errors.Errorf("invalid ref: %T", r.Sys())
 		}
-		rootFS, err = workerRef.Worker.CacheManager().New(ctx, workerRef.ImmutableRef)
+		rootFS, err = workerRef.Worker.CacheManager().New(ctx, workerRef.ImmutableRef, session.NewGroup(sid))
 		if err != nil {
 			return nil, err
 		}
 		defer rootFS.Release(context.TODO())
 	}
 
-	lbf, ctx, err := newLLBBridgeForwarder(ctx, llbBridge, gf.workers, inputs, sid)
-	defer lbf.conn.Close()
-	if err != nil {
-		return nil, err
-	}
-
 	args := []string{"/run"}
 	env := []string{}
 	cwd := "/"
@@ -207,8 +212,6 @@
 	}
 	env = append(env, "BUILDKIT_WORKERS="+string(dt))
 
-	defer lbf.Discard()
-
 	env = append(env, "BUILDKIT_EXPORTEDPRODUCT="+apicaps.ExportedProduct)
 
 	meta := executor.Meta{
@@ -224,10 +227,35 @@
 		}
 	}
 
-	err = llbBridge.Run(ctx, "", rootFS, nil, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil)
+	curCaps := getCaps(img.Config.Labels["moby.buildkit.frontend.caps"])
+	addCapsForKnownFrontends(curCaps, mfstDigest)
+	reqCaps := getCaps(opts["frontend.caps"])
+	if len(inputs) > 0 {
+		reqCaps["moby.buildkit.frontend.inputs"] = struct{}{}
+	}
+
+	for c := range reqCaps {
+		if _, ok := curCaps[c]; !ok {
+			return nil, stack.Enable(grpcerrors.WrapCode(errdefs.NewUnsupportedFrontendCapError(c), codes.Unimplemented))
+		}
+	}
+
+	lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, gf.workers, inputs, sid, sm)
+	defer lbf.conn.Close() //nolint
+	if err != nil {
+		return nil, err
+	}
+	defer lbf.Discard()
+
+	w, err := gf.workers.GetDefault()
+	if err != nil {
+		return nil, err
+	}
+
+	err = w.Executor().Run(ctx, "", mountWithSession(rootFS, session.NewGroup(sid)), nil, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil)
 
 	if err != nil {
-		if errors.Is(err, context.Canceled) && lbf.isErrServerClosed {
+		if errdefs.IsCanceled(err) && lbf.isErrServerClosed {
 			err = errors.Errorf("frontend grpc server closed unexpectedly")
 		}
 		// An existing error (set via Return rpc) takes
@@ -247,6 +275,10 @@
 func (lbf *llbBridgeForwarder) Discard() {
 	lbf.mu.Lock()
 	defer lbf.mu.Unlock()
+	for id, workerRef := range lbf.workerRefByID {
+		workerRef.ImmutableRef.Release(context.TODO())
+		delete(lbf.workerRefByID, id)
+	}
 	for id, r := range lbf.refs {
 		if lbf.err == nil && lbf.result != nil {
 			keep := false
@@ -302,23 +334,30 @@
 	return lbf.result, nil
 }
 
-func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos, inputs map[string]*opspb.Definition, sid string) *llbBridgeForwarder {
+func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder {
+	return newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm)
+}
+
+func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder {
 	lbf := &llbBridgeForwarder{
-		callCtx:   ctx,
-		llbBridge: llbBridge,
-		refs:      map[string]solver.ResultProxy{},
-		doneCh:    make(chan struct{}),
-		pipe:      newPipe(),
-		workers:   workers,
-		inputs:    inputs,
-		sid:       sid,
+		callCtx:       ctx,
+		llbBridge:     llbBridge,
+		refs:          map[string]solver.ResultProxy{},
+		workerRefByID: map[string]*worker.WorkerRef{},
+		doneCh:        make(chan struct{}),
+		pipe:          newPipe(),
+		workers:       workers,
+		inputs:        inputs,
+		sid:           sid,
+		sm:            sm,
+		ctrs:          map[string]gwclient.Container{},
 	}
 	return lbf
 }
 
-func newLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers frontend.WorkerInfos, inputs map[string]*opspb.Definition, sid string) (*llbBridgeForwarder, context.Context, error) {
+func serveLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*llbBridgeForwarder, context.Context, error) {
 	ctx, cancel := context.WithCancel(ctx)
-	lbf := NewBridgeForwarder(ctx, llbBridge, workers, inputs, sid)
+	lbf := newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm)
 	server := grpc.NewServer(grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor), grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor))
 	grpc_health_v1.RegisterHealthServer(server, health.NewServer())
 	pb.RegisterLLBBridgeServer(server, lbf)
@@ -393,25 +432,29 @@
 	pb.LLBBridgeServer
 	Done() <-chan struct{}
 	Result() (*frontend.Result, error)
+	Discard()
 }
 
 type llbBridgeForwarder struct {
-	mu        sync.Mutex
-	callCtx   context.Context
-	llbBridge frontend.FrontendLLBBridge
-	refs      map[string]solver.ResultProxy
+	mu            sync.Mutex
+	callCtx       context.Context
+	llbBridge     frontend.FrontendLLBBridge
+	refs          map[string]solver.ResultProxy
+	workerRefByID map[string]*worker.WorkerRef
 	// lastRef      solver.CachedResult
 	// lastRefs     map[string]solver.CachedResult
 	// err          error
 	doneCh            chan struct{} // closed when result or err become valid through a call to a Return
 	result            *frontend.Result
 	err               error
-	exporterAttr      map[string][]byte
-	workers           frontend.WorkerInfos
+	workers           worker.Infos
 	inputs            map[string]*opspb.Definition
 	isErrServerClosed bool
 	sid               string
+	sm                *session.Manager
 	*pipe
+	ctrs   map[string]gwclient.Container
+	ctrsMu sync.Mutex
 }
 
 func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.ResolveImageConfigRequest) (*pb.ResolveImageConfigResponse, error) {
@@ -454,6 +497,59 @@
 	return nil
 }
 
+func (lbf *llbBridgeForwarder) wrapSolveError(solveErr error) error {
+	var (
+		ee       *llberrdefs.ExecError
+		fae      *llberrdefs.FileActionError
+		sce      *solver.SlowCacheError
+		inputIDs []string
+		mountIDs []string
+		subject  errdefs.IsSolve_Subject
+	)
+	if errors.As(solveErr, &ee) {
+		var err error
+		inputIDs, err = lbf.registerResultIDs(ee.Inputs...)
+		if err != nil {
+			return err
+		}
+		mountIDs, err = lbf.registerResultIDs(ee.Mounts...)
+		if err != nil {
+			return err
+		}
+	}
+	if errors.As(solveErr, &fae) {
+		subject = fae.ToSubject()
+	}
+	if errors.As(solveErr, &sce) {
+		var err error
+		inputIDs, err = lbf.registerResultIDs(sce.Result)
+		if err != nil {
+			return err
+		}
+		subject = sce.ToSubject()
+	}
+	return errdefs.WithSolveError(solveErr, subject, inputIDs, mountIDs)
+}
+
+func (lbf *llbBridgeForwarder) registerResultIDs(results ...solver.Result) (ids []string, err error) {
+	lbf.mu.Lock()
+	defer lbf.mu.Unlock()
+
+	ids = make([]string, len(results))
+	for i, res := range results {
+		if res == nil {
+			continue
+		}
+		workerRef, ok := res.Sys().(*worker.WorkerRef)
+		if !ok {
+			return ids, errors.Errorf("unexpected type for result, got %T", res.Sys())
+		}
+		ids[i] = workerRef.ID()
+		lbf.workerRefByID[workerRef.ID()] = workerRef
+	}
+	return ids, nil
+}
+
 func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest) (*pb.SolveResponse, error) {
 	if err := translateLegacySolveRequest(req); err != nil {
 		return nil, err
@@ -468,6 +564,7 @@
 
 	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
 	res, err := lbf.llbBridge.Solve(ctx, frontend.SolveRequest{
+		Evaluate:       req.Evaluate,
 		Definition:     req.Definition,
 		Frontend:       req.Frontend,
 		FrontendOpt:    req.FrontendOpt,
@@ -475,7 +572,7 @@
 		CacheImports:   cacheImports,
 	}, lbf.sid)
 	if err != nil {
-		return nil, err
+		return nil, lbf.wrapSolveError(err)
 	}
 
 	if len(res.Refs) > 0 && !req.AllowResultReturn {
@@ -562,26 +659,39 @@
 
 	return resp, nil
 }
-func (lbf *llbBridgeForwarder) ReadFile(ctx context.Context, req *pb.ReadFileRequest) (*pb.ReadFileResponse, error) {
-	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
+
+func (lbf *llbBridgeForwarder) getImmutableRef(ctx context.Context, id, path string) (cache.ImmutableRef, error) {
 	lbf.mu.Lock()
-	ref, ok := lbf.refs[req.Ref]
+	ref, ok := lbf.refs[id]
 	lbf.mu.Unlock()
 	if !ok {
-		return nil, errors.Errorf("no such ref: %v", req.Ref)
+		return nil, errors.Errorf("no such ref: %v", id)
 	}
 	if ref == nil {
-		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.FilePath)
+		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", path)
 	}
+
 	r, err := ref.Result(ctx)
 	if err != nil {
-		return nil, err
+		return nil, lbf.wrapSolveError(err)
 	}
+
 	workerRef, ok := r.Sys().(*worker.WorkerRef)
 	if !ok {
 		return nil, errors.Errorf("invalid ref: %T", r.Sys())
 	}
 
+	return workerRef.ImmutableRef, nil
+}
+
+func (lbf *llbBridgeForwarder) ReadFile(ctx context.Context, req *pb.ReadFileRequest) (*pb.ReadFileResponse, error) {
+	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
+
+	ref, err := lbf.getImmutableRef(ctx, req.Ref, req.FilePath)
+	if err != nil {
+		return nil, err
+	}
+
 	newReq := cacheutil.ReadRequest{
 		Filename: req.FilePath,
 	}
@@ -592,67 +702,55 @@
 		}
 	}
 
-	dt, err := cacheutil.ReadFile(ctx, workerRef.ImmutableRef, newReq)
+	m, err := ref.Mount(ctx, true, session.NewGroup(lbf.sid))
 	if err != nil {
 		return nil, err
 	}
 
+	dt, err := cacheutil.ReadFile(ctx, m, newReq)
+	if err != nil {
+		return nil, lbf.wrapSolveError(err)
+	}
+
 	return &pb.ReadFileResponse{Data: dt}, nil
 }
 
 func (lbf *llbBridgeForwarder) ReadDir(ctx context.Context, req *pb.ReadDirRequest) (*pb.ReadDirResponse, error) {
 	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
-	lbf.mu.Lock()
-	ref, ok := lbf.refs[req.Ref]
-	lbf.mu.Unlock()
-	if !ok {
-		return nil, errors.Errorf("no such ref: %v", req.Ref)
-	}
-	if ref == nil {
-		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.DirPath)
-	}
-	r, err := ref.Result(ctx)
+
+	ref, err := lbf.getImmutableRef(ctx, req.Ref, req.DirPath)
 	if err != nil {
 		return nil, err
 	}
-	workerRef, ok := r.Sys().(*worker.WorkerRef)
-	if !ok {
-		return nil, errors.Errorf("invalid ref: %T", r.Sys())
-	}
 
 	newReq := cacheutil.ReadDirRequest{
 		Path:           req.DirPath,
 		IncludePattern: req.IncludePattern,
 	}
-	entries, err := cacheutil.ReadDir(ctx, workerRef.ImmutableRef, newReq)
+	m, err := ref.Mount(ctx, true, session.NewGroup(lbf.sid))
 	if err != nil {
 		return nil, err
 	}
+	entries, err := cacheutil.ReadDir(ctx, m, newReq)
+	if err != nil {
+		return nil, lbf.wrapSolveError(err)
+	}
 
 	return &pb.ReadDirResponse{Entries: entries}, nil
 }
 
 func (lbf *llbBridgeForwarder) StatFile(ctx context.Context, req *pb.StatFileRequest) (*pb.StatFileResponse, error) {
 	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
-	lbf.mu.Lock()
-	ref, ok := lbf.refs[req.Ref]
-	lbf.mu.Unlock()
-	if !ok {
-		return nil, errors.Errorf("no such ref: %v", req.Ref)
-	}
-	if ref == nil {
-		return nil, errors.Wrapf(os.ErrNotExist, "%s not found", req.Path)
-	}
-	r, err := ref.Result(ctx)
+
+	ref, err := lbf.getImmutableRef(ctx, req.Ref, req.Path)
 	if err != nil {
 		return nil, err
 	}
-	workerRef, ok := r.Sys().(*worker.WorkerRef)
-	if !ok {
-		return nil, errors.Errorf("invalid ref: %T", r.Sys())
+	m, err := ref.Mount(ctx, true, session.NewGroup(lbf.sid))
+	if err != nil {
+		return nil, err
 	}
-
-	st, err := cacheutil.StatFile(ctx, workerRef.ImmutableRef, req.Path)
+	st, err := cacheutil.StatFile(ctx, m, req.Path)
 	if err != nil {
 		return nil, err
 	}
@@ -686,47 +784,46 @@
 			Message: in.Error.Message,
 			Details: convertGogoAny(in.Error.Details),
 		})))
-	} else {
-		r := &frontend.Result{
-			Metadata: in.Result.Metadata,
-		}
-
-		switch res := in.Result.Result.(type) {
-		case *pb.Result_RefDeprecated:
-			ref, err := lbf.convertRef(res.RefDeprecated)
-			if err != nil {
-				return nil, err
-			}
-			r.Ref = ref
-		case *pb.Result_RefsDeprecated:
-			m := map[string]solver.ResultProxy{}
-			for k, id := range res.RefsDeprecated.Refs {
-				ref, err := lbf.convertRef(id)
-				if err != nil {
-					return nil, err
-				}
-				m[k] = ref
-			}
-			r.Refs = m
-		case *pb.Result_Ref:
-			ref, err := lbf.convertRef(res.Ref.Id)
-			if err != nil {
-				return nil, err
-			}
-			r.Ref = ref
-		case *pb.Result_Refs:
-			m := map[string]solver.ResultProxy{}
-			for k, ref := range res.Refs.Refs {
-				ref, err := lbf.convertRef(ref.Id)
-				if err != nil {
-					return nil, err
-				}
-				m[k] = ref
-			}
-			r.Refs = m
-		}
-		return lbf.setResult(r, nil)
 	}
+	r := &frontend.Result{
+		Metadata: in.Result.Metadata,
+	}
+
+	switch res := in.Result.Result.(type) {
+	case *pb.Result_RefDeprecated:
+		ref, err := lbf.convertRef(res.RefDeprecated)
+		if err != nil {
+			return nil, err
+		}
+		r.Ref = ref
+	case *pb.Result_RefsDeprecated:
+		m := map[string]solver.ResultProxy{}
+		for k, id := range res.RefsDeprecated.Refs {
+			ref, err := lbf.convertRef(id)
+			if err != nil {
+				return nil, err
+			}
+			m[k] = ref
+		}
+		r.Refs = m
+	case *pb.Result_Ref:
+		ref, err := lbf.convertRef(res.Ref.Id)
+		if err != nil {
+			return nil, err
+		}
+		r.Ref = ref
+	case *pb.Result_Refs:
+		m := map[string]solver.ResultProxy{}
+		for k, ref := range res.Refs.Refs {
+			ref, err := lbf.convertRef(ref.Id)
+			if err != nil {
+				return nil, err
+			}
+			m[k] = ref
+		}
+		r.Refs = m
+	}
+	return lbf.setResult(r, nil)
 }
 
 func (lbf *llbBridgeForwarder) Inputs(ctx context.Context, in *pb.InputsRequest) (*pb.InputsResponse, error) {
@@ -735,6 +832,440 @@
 	}, nil
 }
 
+func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewContainerRequest) (_ *pb.NewContainerResponse, err error) {
+	logrus.Debugf("|<--- NewContainer %s", in.ContainerID)
+	ctrReq := NewContainerRequest{
+		ContainerID: in.ContainerID,
+		NetMode:     in.Network,
+		Platform:    in.Platform,
+		Constraints: in.Constraints,
+	}
+
+	for _, m := range in.Mounts {
+		var workerRef *worker.WorkerRef
+		if m.ResultID != "" {
+			var ok bool
+			workerRef, ok = lbf.workerRefByID[m.ResultID]
+			if !ok {
+				refProxy, err := lbf.convertRef(m.ResultID)
+				if err != nil {
+					return nil, errors.Wrapf(err, "failed to find ref %s for %q mount", m.ResultID, m.Dest)
+				}
+
+				res, err := refProxy.Result(ctx)
+				if err != nil {
+					return nil, stack.Enable(err)
+				}
+
+				workerRef, ok = res.Sys().(*worker.WorkerRef)
+				if !ok {
+					return nil, errors.Errorf("invalid reference %T", res.Sys())
+				}
+			}
+
+		}
+		ctrReq.Mounts = append(ctrReq.Mounts, Mount{
+			WorkerRef: workerRef,
+			Mount: &opspb.Mount{
+				Dest:      m.Dest,
+				Selector:  m.Selector,
+				Readonly:  m.Readonly,
+				MountType: m.MountType,
+				CacheOpt:  m.CacheOpt,
+				SecretOpt: m.SecretOpt,
+				SSHOpt:    m.SSHOpt,
+			},
+		})
+	}
+
+	// Not using `ctx` here because it will get cancelled as soon as NewContainer returns
+	// and we want the context to live for the duration of the container.
+	group := session.NewGroup(lbf.sid)
+
+	w, err := lbf.workers.GetDefault()
+	if err != nil {
+		return nil, stack.Enable(err)
+	}
+
+	ctr, err := NewContainer(context.Background(), w, lbf.sm, group, ctrReq)
+	if err != nil {
+		return nil, stack.Enable(err)
+	}
+	defer func() {
+		if err != nil {
+			ctr.Release(ctx) // ensure release on error
+		}
+	}()
+
+	lbf.ctrsMu.Lock()
+	defer lbf.ctrsMu.Unlock()
+	// ensure we are not clobbering a dup container id request
+	if _, ok := lbf.ctrs[in.ContainerID]; ok {
+		return nil, stack.Enable(status.Errorf(codes.AlreadyExists, "Container %s already exists", in.ContainerID))
+	}
+	lbf.ctrs[in.ContainerID] = ctr
+	return &pb.NewContainerResponse{}, nil
+}
+
+func (lbf *llbBridgeForwarder) ReleaseContainer(ctx context.Context, in *pb.ReleaseContainerRequest) (*pb.ReleaseContainerResponse, error) {
+	logrus.Debugf("|<--- ReleaseContainer %s", in.ContainerID)
+	lbf.ctrsMu.Lock()
+	ctr, ok := lbf.ctrs[in.ContainerID]
+	delete(lbf.ctrs, in.ContainerID)
+	lbf.ctrsMu.Unlock()
+	if !ok {
+		return nil, errors.Errorf("container details for %s not found", in.ContainerID)
+	}
+	err := ctr.Release(ctx)
+	return &pb.ReleaseContainerResponse{}, stack.Enable(err)
+}
+
+type processIO struct {
+	id       string
+	mu       sync.Mutex
+	resize   func(context.Context, gwclient.WinSize) error
+	done     chan struct{}
+	doneOnce sync.Once
+	// these track the process side of the io pipe for
+	// read (fd=0) and write (fd=1, fd=2)
+	processReaders map[uint32]io.ReadCloser
+	processWriters map[uint32]io.WriteCloser
+	// these track the server side of the io pipe, so
+	// when we receive an EOF over grpc, we will close
+	// this end
+	serverWriters map[uint32]io.WriteCloser
+	serverReaders map[uint32]io.ReadCloser
+}
+
+func newProcessIO(id string, openFds []uint32) *processIO {
+	pio := &processIO{
+		id:             id,
+		processReaders: map[uint32]io.ReadCloser{},
+		processWriters: map[uint32]io.WriteCloser{},
+		serverReaders:  map[uint32]io.ReadCloser{},
+		serverWriters:  map[uint32]io.WriteCloser{},
+		done:           make(chan struct{}),
+	}
+
+	for _, fd := range openFds {
+		// TODO do we know which way to pipe each fd?  For now assume fd0 is for
+		// reading, and the rest are for writing
+		r, w := io.Pipe()
+		if fd == 0 {
+			pio.processReaders[fd] = r
+			pio.serverWriters[fd] = w
+		} else {
+			pio.processWriters[fd] = w
+			pio.serverReaders[fd] = r
+		}
+	}
+
+	return pio
+}
+
+func (pio *processIO) Close() (err error) {
+	pio.mu.Lock()
+	defer pio.mu.Unlock()
+	for fd, r := range pio.processReaders {
+		delete(pio.processReaders, fd)
+		err1 := r.Close()
+		if err1 != nil && err == nil {
+			err = stack.Enable(err1)
+		}
+	}
+	for fd, w := range pio.serverReaders {
+		delete(pio.serverReaders, fd)
+		err1 := w.Close()
+		if err1 != nil && err == nil {
+			err = stack.Enable(err1)
+		}
+	}
+	pio.Done()
+	return err
+}
+
+func (pio *processIO) Done() {
+	stillOpen := len(pio.processReaders) + len(pio.processWriters) + len(pio.serverReaders) + len(pio.serverWriters)
+	if stillOpen == 0 {
+		pio.doneOnce.Do(func() {
+			close(pio.done)
+		})
+	}
+}
+
+func (pio *processIO) Write(f *pb.FdMessage) (err error) {
+	pio.mu.Lock()
+	writer := pio.serverWriters[f.Fd]
+	pio.mu.Unlock()
+	if writer == nil {
+		return status.Errorf(codes.OutOfRange, "fd %d unavailable to write", f.Fd)
+	}
+	defer func() {
+		if err != nil || f.EOF {
+			writer.Close()
+			pio.mu.Lock()
+			defer pio.mu.Unlock()
+			delete(pio.serverWriters, f.Fd)
+			pio.Done()
+		}
+	}()
+	if len(f.Data) > 0 {
+		_, err = writer.Write(f.Data)
+		return stack.Enable(err)
+	}
+	return nil
+}
+
+type outputWriter struct {
+	stream    pb.LLBBridge_ExecProcessServer
+	fd        uint32
+	processID string
+}
+
+func (w *outputWriter) Write(msg []byte) (int, error) {
+	logrus.Debugf("|---> File Message %s, fd=%d, %d bytes", w.processID, w.fd, len(msg))
+	err := w.stream.Send(&pb.ExecMessage{
+		ProcessID: w.processID,
+		Input: &pb.ExecMessage_File{
+			File: &pb.FdMessage{
+				Fd:   w.fd,
+				Data: msg,
+			},
+		},
+	})
+	return len(msg), stack.Enable(err)
+}
+
+func (lbf *llbBridgeForwarder) ExecProcess(srv pb.LLBBridge_ExecProcessServer) error {
+	eg, ctx := errgroup.WithContext(srv.Context())
+
+	msgs := make(chan *pb.ExecMessage)
+
+	eg.Go(func() error {
+		defer close(msgs)
+		for {
+			execMsg, err := srv.Recv()
+			if err != nil {
+				if errors.Is(err, io.EOF) {
+					return nil
+				}
+				return stack.Enable(err)
+			}
+			switch m := execMsg.GetInput().(type) {
+			case *pb.ExecMessage_Init:
+				logrus.Debugf("|<--- Init Message %s", execMsg.ProcessID)
+			case *pb.ExecMessage_File:
+				if m.File.EOF {
+					logrus.Debugf("|<--- File Message %s, fd=%d, EOF", execMsg.ProcessID, m.File.Fd)
+				} else {
+					logrus.Debugf("|<--- File Message %s, fd=%d, %d bytes", execMsg.ProcessID, m.File.Fd, len(m.File.Data))
+				}
+			case *pb.ExecMessage_Resize:
+				logrus.Debugf("|<--- Resize Message %s", execMsg.ProcessID)
+			}
+			select {
+			case <-ctx.Done():
+			case msgs <- execMsg:
+			}
+		}
+	})
+
+	eg.Go(func() error {
+		pios := make(map[string]*processIO)
+		// close any stray pios on exit to make sure
+		// all the associated resources get cleaned up
+		defer func() {
+			for _, pio := range pios {
+				pio.Close()
+			}
+		}()
+
+		for {
+			var execMsg *pb.ExecMessage
+			select {
+			case <-ctx.Done():
+				return nil
+			case execMsg = <-msgs:
+			}
+			if execMsg == nil {
+				return nil
+			}
+
+			pid := execMsg.ProcessID
+			if pid == "" {
+				return stack.Enable(status.Errorf(codes.InvalidArgument, "ProcessID required"))
+			}
+
+			pio, pioFound := pios[pid]
+
+			if data := execMsg.GetFile(); data != nil {
+				if !pioFound {
+					return stack.Enable(status.Errorf(codes.NotFound, "IO for process %q not found", pid))
+				}
+				err := pio.Write(data)
+				if err != nil {
+					return stack.Enable(err)
+				}
+			} else if resize := execMsg.GetResize(); resize != nil {
+				if !pioFound {
+					return stack.Enable(status.Errorf(codes.NotFound, "IO for process %q not found", pid))
+				}
+				pio.resize(ctx, gwclient.WinSize{
+					Cols: resize.Cols,
+					Rows: resize.Rows,
+				})
+			} else if init := execMsg.GetInit(); init != nil {
+				if pioFound {
+					return stack.Enable(status.Errorf(codes.AlreadyExists, "Process %s already exists", pid))
+				}
+				id := init.ContainerID
+				lbf.ctrsMu.Lock()
+				ctr, ok := lbf.ctrs[id]
+				lbf.ctrsMu.Unlock()
+				if !ok {
+					return stack.Enable(status.Errorf(codes.NotFound, "container %q previously released or not created", id))
+				}
+
+				initCtx, initCancel := context.WithCancel(context.Background())
+				defer initCancel()
+
+				pio := newProcessIO(pid, init.Fds)
+				pios[pid] = pio
+
+				proc, err := ctr.Start(initCtx, gwclient.StartRequest{
+					Args:   init.Meta.Args,
+					Env:    init.Meta.Env,
+					User:   init.Meta.User,
+					Cwd:    init.Meta.Cwd,
+					Tty:    init.Tty,
+					Stdin:  pio.processReaders[0],
+					Stdout: pio.processWriters[1],
+					Stderr: pio.processWriters[2],
+				})
+				if err != nil {
+					return stack.Enable(err)
+				}
+				pio.resize = proc.Resize
+
+				eg.Go(func() error {
+					<-pio.done
+					logrus.Debugf("|---> Done Message %s", pid)
+					err := srv.Send(&pb.ExecMessage{
+						ProcessID: pid,
+						Input: &pb.ExecMessage_Done{
+							Done: &pb.DoneMessage{},
+						},
+					})
+					return stack.Enable(err)
+				})
+
+				eg.Go(func() error {
+					defer func() {
+						pio.Close()
+					}()
+					err := proc.Wait()
+
+					var statusCode uint32
+					var exitError *errdefs.ExitError
+					var statusError *rpc.Status
+					if err != nil {
+						statusCode = errdefs.ContainerdUnknownExitStatus
+						st, _ := status.FromError(grpcerrors.ToGRPC(err))
+						stp := st.Proto()
+						statusError = &rpc.Status{
+							Code:    stp.Code,
+							Message: stp.Message,
+							Details: convertToGogoAny(stp.Details),
+						}
+					}
+					if errors.As(err, &exitError) {
+						statusCode = exitError.ExitCode
+					}
+					logrus.Debugf("|---> Exit Message %s, code=%d, error=%s", pid, statusCode, err)
+					sendErr := srv.Send(&pb.ExecMessage{
+						ProcessID: pid,
+						Input: &pb.ExecMessage_Exit{
+							Exit: &pb.ExitMessage{
+								Code:  statusCode,
+								Error: statusError,
+							},
+						},
+					})
+
+					if sendErr != nil && err != nil {
+						return errors.Wrap(sendErr, err.Error())
+					} else if sendErr != nil {
+						return stack.Enable(sendErr)
+					}
+
+					if err != nil && statusCode != 0 {
+						// this was a container exit error which is "normal" so
+						// don't return this error from the errgroup
+						return nil
+					}
+					return stack.Enable(err)
+				})
+
+				logrus.Debugf("|---> Started Message %s", pid)
+				err = srv.Send(&pb.ExecMessage{
+					ProcessID: pid,
+					Input: &pb.ExecMessage_Started{
+						Started: &pb.StartedMessage{},
+					},
+				})
+				if err != nil {
+					return stack.Enable(err)
+				}
+
+				// start sending Fd output back to client, this is done after
+				// StartedMessage so that Fd output will not potentially arrive
+				// to the client before "Started" as the container starts up.
+				for fd, file := range pio.serverReaders {
+					fd, file := fd, file
+					eg.Go(func() error {
+						defer func() {
+							file.Close()
+							pio.mu.Lock()
+							defer pio.mu.Unlock()
+							w := pio.processWriters[fd]
+							if w != nil {
+								w.Close()
+							}
+							delete(pio.processWriters, fd)
+							pio.Done()
+						}()
+						dest := &outputWriter{
+							stream:    srv,
+							fd:        uint32(fd),
+							processID: pid,
+						}
+						_, err := io.Copy(dest, file)
+						// ignore ErrClosedPipe, it is EOF for our usage.
+						if err != nil && !errors.Is(err, io.ErrClosedPipe) {
+							return stack.Enable(err)
+						}
+						// no error so must be EOF
+						logrus.Debugf("|---> File Message %s, fd=%d, EOF", pid, fd)
+						err = srv.Send(&pb.ExecMessage{
+							ProcessID: pid,
+							Input: &pb.ExecMessage_File{
+								File: &pb.FdMessage{
+									Fd:  uint32(fd),
+									EOF: true,
+								},
+							},
+						})
+						return stack.Enable(err)
+					})
+				}
+			}
+		}
+	})
+
+	err := eg.Wait()
+	return stack.Enable(err)
+}
+
 func (lbf *llbBridgeForwarder) convertRef(id string) (solver.ResultProxy, error) {
 	if id == "" {
 		return nil, nil
@@ -773,3 +1304,39 @@
 	}
 	return out
 }
+
+func convertToGogoAny(in []*any.Any) []*gogotypes.Any {
+	out := make([]*gogotypes.Any, len(in))
+	for i := range in {
+		out[i] = &gogotypes.Any{TypeUrl: in[i].TypeUrl, Value: in[i].Value}
+	}
+	return out
+}
+
+func getCaps(label string) map[string]struct{} {
+	if label == "" {
+		return make(map[string]struct{})
+	}
+	caps := strings.Split(label, ",")
+	out := make(map[string]struct{}, len(caps))
+	for _, c := range caps {
+		name := strings.SplitN(c, "+", 2)
+		if name[0] != "" {
+			out[name[0]] = struct{}{}
+		}
+	}
+	return out
+}
+
+func addCapsForKnownFrontends(caps map[string]struct{}, dgst digest.Digest) {
+	// these frontends were built without caps detection but do support inputs
+	defaults := map[digest.Digest]struct{}{
+		"sha256:9ac1c43a60e31dca741a6fe8314130a9cd4c4db0311fbbc636ff992ef60ae76d": {}, // docker/dockerfile:1.1.6
+		"sha256:080bd74d8778f83e7b670de193362d8c593c8b14f5c8fb919d28ee8feda0d069": {}, // docker/dockerfile:1.1.7
+		"sha256:60543a9d92b92af5088fb2938fb09b2072684af8384399e153e137fe081f8ab4": {}, // docker/dockerfile:1.1.6-experimental
+		"sha256:de85b2f3a3e8a2f7fe48e8e84a65f6fdd5cd5183afa6412fff9caa6871649c44": {}, // docker/dockerfile:1.1.7-experimental
+	}
+	if _, ok := defaults[dgst]; ok {
+		caps["moby.buildkit.frontend.inputs"] = struct{}{}
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go b/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
index 5fe33a1..84a2767 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/grpcclient/client.go
@@ -3,10 +3,12 @@
 import (
 	"context"
 	"encoding/json"
+	"fmt"
 	"io"
 	"net"
 	"os"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/gogo/googleapis/google/rpc"
@@ -15,26 +17,33 @@
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/frontend/gateway/client"
 	pb "github.com/moby/buildkit/frontend/gateway/pb"
+	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/solver/errdefs"
 	opspb "github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/apicaps"
 	"github.com/moby/buildkit/util/grpcerrors"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
 	fstypes "github.com/tonistiigi/fsutil/types"
+	"golang.org/x/sync/errgroup"
+	spb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 )
 
 const frontendPrefix = "BUILDKIT_FRONTEND_OPT_"
 
 type GrpcClient interface {
+	client.Client
 	Run(context.Context, client.BuildFunc) error
 }
 
 func New(ctx context.Context, opts map[string]string, session, product string, c pb.LLBBridgeClient, w []client.WorkerInfo) (GrpcClient, error) {
-	ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
-	defer cancel()
-	resp, err := c.Ping(ctx, &pb.PingRequest{})
+	pingCtx, pingCancel := context.WithTimeout(ctx, 15*time.Second)
+	defer pingCancel()
+	resp, err := c.Ping(pingCtx, &pb.PingRequest{})
 	if err != nil {
 		return nil, err
 	}
@@ -56,6 +65,7 @@
 		caps:      pb.Caps.CapSet(resp.FrontendAPICaps),
 		llbCaps:   opspb.Caps.CapSet(resp.LLBCaps),
 		requests:  map[string]*pb.SolveRequest{},
+		execMsgs:  newMessageForwarder(ctx, c),
 	}, nil
 }
 
@@ -167,10 +177,21 @@
 		}()
 	}
 
+	defer func() {
+		err = c.execMsgs.Release()
+		if err != nil && retError != nil {
+			retError = err
+		}
+	}()
+
 	if res, err = f(ctx, c); err != nil {
 		return err
 	}
 
+	if res == nil {
+		return nil
+	}
+
 	if err := c.caps.Supports(pb.CapReturnMap); len(res.Refs) > 1 && err != nil {
 		return err
 	}
@@ -253,6 +274,7 @@
 	caps      apicaps.CapSet
 	llbCaps   apicaps.CapSet
 	requests  map[string]*pb.SolveRequest
+	execMsgs  *messageForwarder
 }
 
 func (c *grpcClient) requestForRef(ref client.Reference) (*pb.SolveRequest, error) {
@@ -276,7 +298,7 @@
 	return req, nil
 }
 
-func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (*client.Result, error) {
+func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (res *client.Result, err error) {
 	if creq.Definition != nil {
 		for _, md := range creq.Definition.Metadata {
 			for cap := range md.Caps {
@@ -322,13 +344,45 @@
 		req.ExporterAttr = []byte("{}")
 	}
 
+	if creq.Evaluate {
+		if c.caps.Supports(pb.CapGatewayEvaluateSolve) == nil {
+			req.Evaluate = creq.Evaluate
+		} else {
+			// If evaluate is not supported, fallback to running Stat(".") in order to
+			// trigger an evaluation of the result.
+			defer func() {
+				if res == nil {
+					return
+				}
+
+				var (
+					id  string
+					ref client.Reference
+				)
+				ref, err = res.SingleRef()
+				if err != nil {
+					for refID := range res.Refs {
+						id = refID
+						break
+					}
+				} else {
+					id = ref.(*reference).id
+				}
+
+				_, err = c.client.StatFile(ctx, &pb.StatFileRequest{
+					Ref:  id,
+					Path: ".",
+				})
+			}()
+		}
+	}
+
 	resp, err := c.client.Solve(ctx, req)
 	if err != nil {
 		return nil, err
 	}
 
-	res := &client.Result{}
-
+	res = &client.Result{}
 	if resp.Result == nil {
 		if id := resp.Ref; id != "" {
 			c.requests[id] = req
@@ -423,14 +477,460 @@
 		inputs[key] = llb.NewState(op)
 	}
 	return inputs, nil
+}
 
+// procMessageForwarder is created per container process to act as the
+// communication channel between the process and the ExecProcess message
+// stream.
+type procMessageForwarder struct {
+	done      chan struct{}
+	closeOnce sync.Once
+	msgs      chan *pb.ExecMessage
+}
+
+func newProcMessageForwarder() *procMessageForwarder {
+	return &procMessageForwarder{
+		done: make(chan struct{}),
+		msgs: make(chan *pb.ExecMessage),
+	}
+}
+
+func (b *procMessageForwarder) Send(ctx context.Context, m *pb.ExecMessage) {
+	select {
+	case <-ctx.Done():
+	case <-b.done:
+		b.closeOnce.Do(func() {
+			close(b.msgs)
+		})
+	case b.msgs <- m:
+	}
+}
+
+func (b *procMessageForwarder) Recv(ctx context.Context) (m *pb.ExecMessage, ok bool) {
+	select {
+	case <-ctx.Done():
+		return nil, true
+	case <-b.done:
+		return nil, false
+	case m = <-b.msgs:
+		return m, true
+	}
+}
+
+func (b *procMessageForwarder) Close() {
+	close(b.done)
+	b.Recv(context.Background())      // flush any messages in queue
+	b.Send(context.Background(), nil) // ensure channel is closed
+}
+
+// messageForwarder manages a single grpc stream for ExecProcess to facilitate
+// a pub/sub message channel for each new process started from the client
+// connection.
+type messageForwarder struct {
+	client pb.LLBBridgeClient
+	ctx    context.Context
+	cancel func()
+	eg     *errgroup.Group
+	mu     sync.Mutex
+	pids   map[string]*procMessageForwarder
+	stream pb.LLBBridge_ExecProcessClient
+	// startOnce used to only start the exec message forwarder once,
+	// so we only have one exec stream per client
+	startOnce sync.Once
+	// startErr tracks the error when initializing the stream, it will
+	// be returned on subsequent calls to Start
+	startErr error
+}
+
+func newMessageForwarder(ctx context.Context, client pb.LLBBridgeClient) *messageForwarder {
+	ctx, cancel := context.WithCancel(ctx)
+	eg, ctx := errgroup.WithContext(ctx)
+	return &messageForwarder{
+		client: client,
+		pids:   map[string]*procMessageForwarder{},
+		ctx:    ctx,
+		cancel: cancel,
+		eg:     eg,
+	}
+}
+
+func (m *messageForwarder) Start() (err error) {
+	defer func() {
+		if err != nil {
+			m.startErr = err
+		}
+	}()
+
+	if m.startErr != nil {
+		return m.startErr
+	}
+
+	m.startOnce.Do(func() {
+		m.stream, err = m.client.ExecProcess(m.ctx)
+		if err != nil {
+			return
+		}
+		m.eg.Go(func() error {
+			for {
+				msg, err := m.stream.Recv()
+				if errors.Is(err, io.EOF) || grpcerrors.Code(err) == codes.Canceled {
+					return nil
+				}
+				logrus.Debugf("|<--- %s", debugMessage(msg))
+
+				if err != nil {
+					return err
+				}
+
+				m.mu.Lock()
+				msgs, ok := m.pids[msg.ProcessID]
+				m.mu.Unlock()
+
+				if !ok {
+					logrus.Debugf("Received exec message for unregistered process: %s", msg.String())
+					continue
+				}
+				msgs.Send(m.ctx, msg)
+			}
+		})
+	})
+	return err
+}
+
+func debugMessage(msg *pb.ExecMessage) string {
+	switch m := msg.GetInput().(type) {
+	case *pb.ExecMessage_Init:
+		return fmt.Sprintf("Init Message %s", msg.ProcessID)
+	case *pb.ExecMessage_File:
+		if m.File.EOF {
+			return fmt.Sprintf("File Message %s, fd=%d, EOF", msg.ProcessID, m.File.Fd)
+		}
+		return fmt.Sprintf("File Message %s, fd=%d, %d bytes", msg.ProcessID, m.File.Fd, len(m.File.Data))
+	case *pb.ExecMessage_Resize:
+		return fmt.Sprintf("Resize Message %s", msg.ProcessID)
+	case *pb.ExecMessage_Started:
+		return fmt.Sprintf("Started Message %s", msg.ProcessID)
+	case *pb.ExecMessage_Exit:
+		return fmt.Sprintf("Exit Message %s, code=%d, err=%s", msg.ProcessID, m.Exit.Code, m.Exit.Error)
+	case *pb.ExecMessage_Done:
+		return fmt.Sprintf("Done Message %s", msg.ProcessID)
+	}
+	return fmt.Sprintf("Unknown Message %s", msg.String())
+}
+
+func (m *messageForwarder) Send(msg *pb.ExecMessage) error {
+	m.mu.Lock()
+	_, ok := m.pids[msg.ProcessID]
+	defer m.mu.Unlock()
+	if !ok {
+		return errors.Errorf("process %s has ended, not sending message %#v", msg.ProcessID, msg.Input)
+	}
+	logrus.Debugf("|---> %s", debugMessage(msg))
+	return m.stream.Send(msg)
+}
+
+func (m *messageForwarder) Release() error {
+	m.cancel()
+	return m.eg.Wait()
+}
+
+func (m *messageForwarder) Register(pid string) *procMessageForwarder {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	sender := newProcMessageForwarder()
+	m.pids[pid] = sender
+	return sender
+}
+
+func (m *messageForwarder) Deregister(pid string) {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	sender, ok := m.pids[pid]
+	if !ok {
+		return
+	}
+	delete(m.pids, pid)
+	sender.Close()
+}
+
+type msgWriter struct {
+	mux       *messageForwarder
+	fd        uint32
+	processID string
+}
+
+func (w *msgWriter) Write(msg []byte) (int, error) {
+	err := w.mux.Send(&pb.ExecMessage{
+		ProcessID: w.processID,
+		Input: &pb.ExecMessage_File{
+			File: &pb.FdMessage{
+				Fd:   w.fd,
+				Data: msg,
+			},
+		},
+	})
+	if err != nil {
+		return 0, err
+	}
+	return len(msg), nil
+}
+
+func (c *grpcClient) NewContainer(ctx context.Context, req client.NewContainerRequest) (client.Container, error) {
+	err := c.caps.Supports(pb.CapGatewayExec)
+	if err != nil {
+		return nil, err
+	}
+	id := identity.NewID()
+	var mounts []*opspb.Mount
+	for _, m := range req.Mounts {
+		resultID := m.ResultID
+		if m.Ref != nil {
+			ref, ok := m.Ref.(*reference)
+			if !ok {
+				return nil, errors.Errorf("unexpected type for reference, got %T", m.Ref)
+			}
+			resultID = ref.id
+		}
+		mounts = append(mounts, &opspb.Mount{
+			Dest:      m.Dest,
+			Selector:  m.Selector,
+			Readonly:  m.Readonly,
+			MountType: m.MountType,
+			ResultID:  resultID,
+			CacheOpt:  m.CacheOpt,
+			SecretOpt: m.SecretOpt,
+			SSHOpt:    m.SSHOpt,
+		})
+	}
+
+	logrus.Debugf("|---> NewContainer %s", id)
+	_, err = c.client.NewContainer(ctx, &pb.NewContainerRequest{
+		ContainerID: id,
+		Mounts:      mounts,
+		Platform:    req.Platform,
+		Constraints: req.Constraints,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	// ensure message forwarder is started, only sets up stream first time called
+	err = c.execMsgs.Start()
+	if err != nil {
+		return nil, err
+	}
+
+	return &container{
+		client:   c.client,
+		id:       id,
+		execMsgs: c.execMsgs,
+	}, nil
+}
+
+type container struct {
+	client   pb.LLBBridgeClient
+	id       string
+	execMsgs *messageForwarder
+}
+
+func (ctr *container) Start(ctx context.Context, req client.StartRequest) (client.ContainerProcess, error) {
+	pid := fmt.Sprintf("%s:%s", ctr.id, identity.NewID())
+	msgs := ctr.execMsgs.Register(pid)
+
+	init := &pb.InitMessage{
+		ContainerID: ctr.id,
+		Meta: &opspb.Meta{
+			Args: req.Args,
+			Env:  req.Env,
+			Cwd:  req.Cwd,
+			User: req.User,
+		},
+		Tty:      req.Tty,
+		Security: req.SecurityMode,
+	}
+	if req.Stdin != nil {
+		init.Fds = append(init.Fds, 0)
+	}
+	if req.Stdout != nil {
+		init.Fds = append(init.Fds, 1)
+	}
+	if req.Stderr != nil {
+		init.Fds = append(init.Fds, 2)
+	}
+
+	err := ctr.execMsgs.Send(&pb.ExecMessage{
+		ProcessID: pid,
+		Input: &pb.ExecMessage_Init{
+			Init: init,
+		},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	msg, _ := msgs.Recv(ctx)
+	if msg == nil {
+		return nil, errors.Errorf("failed to receive started message")
+	}
+	started := msg.GetStarted()
+	if started == nil {
+		return nil, errors.Errorf("expecting started message, got %T", msg.GetInput())
+	}
+
+	eg, ctx := errgroup.WithContext(ctx)
+	done := make(chan struct{})
+
+	ctrProc := &containerProcess{
+		execMsgs: ctr.execMsgs,
+		id:       pid,
+		eg:       eg,
+	}
+
+	var stdinReader *io.PipeReader
+	ctrProc.eg.Go(func() error {
+		<-done
+		if stdinReader != nil {
+			return stdinReader.Close()
+		}
+		return nil
+	})
+
+	if req.Stdin != nil {
+		var stdinWriter io.WriteCloser
+		stdinReader, stdinWriter = io.Pipe()
+		// This go routine is intentionally not part of the errgroup because
+		// if os.Stdin is used for req.Stdin then this will block until
+		// the user closes the input, which will likely be after we are done
+		// with the container, so we can't Wait on it.
+		go func() {
+			io.Copy(stdinWriter, req.Stdin)
+			stdinWriter.Close()
+		}()
+
+		ctrProc.eg.Go(func() error {
+			m := &msgWriter{
+				mux:       ctr.execMsgs,
+				processID: pid,
+				fd:        0,
+			}
+			_, err := io.Copy(m, stdinReader)
+			// ignore ErrClosedPipe, it is EOF for our usage.
+			if err != nil && !errors.Is(err, io.ErrClosedPipe) {
+				return err
+			}
+			// not an error so must be eof
+			return ctr.execMsgs.Send(&pb.ExecMessage{
+				ProcessID: pid,
+				Input: &pb.ExecMessage_File{
+					File: &pb.FdMessage{
+						Fd:  0,
+						EOF: true,
+					},
+				},
+			})
+		})
+	}
+
+	ctrProc.eg.Go(func() error {
+		var closeDoneOnce sync.Once
+		var exitError error
+		for {
+			msg, ok := msgs.Recv(ctx)
+			if !ok {
+				// no more messages, return
+				return exitError
+			}
+
+			if msg == nil {
+				// empty message from ctx cancel, so just start shutting down
+				// input, but continue processing more exit/done messages
+				closeDoneOnce.Do(func() {
+					close(done)
+				})
+				continue
+			}
+
+			if file := msg.GetFile(); file != nil {
+				var out io.WriteCloser
+				switch file.Fd {
+				case 1:
+					out = req.Stdout
+				case 2:
+					out = req.Stderr
+				}
+				if out == nil {
+					// if things are plumbed correctly this should never happen
+					return errors.Errorf("missing writer for output fd %d", file.Fd)
+				}
+				if len(file.Data) > 0 {
+					_, err := out.Write(file.Data)
+					if err != nil {
+						return err
+					}
+				}
+			} else if exit := msg.GetExit(); exit != nil {
+				// capture exit message to exitError so we can return it after
+				// the server sends the Done message
+				closeDoneOnce.Do(func() {
+					close(done)
+				})
+				if exit.Code == 0 {
+					continue
+				}
+				exitError = grpcerrors.FromGRPC(status.ErrorProto(&spb.Status{
+					Code:    exit.Error.Code,
+					Message: exit.Error.Message,
+					Details: convertGogoAny(exit.Error.Details),
+				}))
+				if exit.Code != errdefs.ContainerdUnknownExitStatus {
+					exitError = &errdefs.ExitError{ExitCode: exit.Code, Err: exitError}
+				}
+			} else if serverDone := msg.GetDone(); serverDone != nil {
+				return exitError
+			} else {
+				return errors.Errorf("unexpected Exec Message for pid %s: %T", pid, msg.GetInput())
+			}
+		}
+	})
+
+	return ctrProc, nil
+}
+
+func (ctr *container) Release(ctx context.Context) error {
+	logrus.Debugf("|---> ReleaseContainer %s", ctr.id)
+	_, err := ctr.client.ReleaseContainer(ctx, &pb.ReleaseContainerRequest{
+		ContainerID: ctr.id,
+	})
+	return err
+}
+
+type containerProcess struct {
+	execMsgs *messageForwarder
+	id       string
+	eg       *errgroup.Group
+}
+
+func (ctrProc *containerProcess) Wait() error {
+	defer ctrProc.execMsgs.Deregister(ctrProc.id)
+	return ctrProc.eg.Wait()
+}
+
+func (ctrProc *containerProcess) Resize(_ context.Context, size client.WinSize) error {
+	return ctrProc.execMsgs.Send(&pb.ExecMessage{
+		ProcessID: ctrProc.id,
+		Input: &pb.ExecMessage_Resize{
+			Resize: &pb.ResizeMessage{
+				Cols: size.Cols,
+				Rows: size.Rows,
+			},
+		},
+	})
 }
 
 type reference struct {
-	c      *grpcClient
-	id     string
-	def    *opspb.Definition
-	output llb.Output
+	c   *grpcClient
+	id  string
+	def *opspb.Definition
 }
 
 func newReference(c *grpcClient, ref *pb.Ref) (*reference, error) {
@@ -502,11 +1002,11 @@
 }
 
 func grpcClientConn(ctx context.Context) (context.Context, *grpc.ClientConn, error) {
-	dialOpt := grpc.WithDialer(func(addr string, d time.Duration) (net.Conn, error) {
+	dialOpt := grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
 		return stdioConn(), nil
 	})
 
-	cc, err := grpc.DialContext(ctx, "", dialOpt, grpc.WithInsecure(), grpc.WithUnaryInterceptor(grpcerrors.UnaryClientInterceptor), grpc.WithStreamInterceptor(grpcerrors.StreamClientInterceptor))
+	cc, err := grpc.DialContext(ctx, "localhost", dialOpt, grpc.WithInsecure(), grpc.WithUnaryInterceptor(grpcerrors.UnaryClientInterceptor), grpc.WithStreamInterceptor(grpcerrors.StreamClientInterceptor))
 	if err != nil {
 		return nil, nil, errors.Wrap(err, "failed to create grpc client")
 	}
@@ -593,6 +1093,14 @@
 	return os.Getenv("BUILDKIT_EXPORTEDPRODUCT")
 }
 
+func convertGogoAny(in []*gogotypes.Any) []*any.Any {
+	out := make([]*any.Any, len(in))
+	for i := range in {
+		out[i] = &any.Any{TypeUrl: in[i].TypeUrl, Value: in[i].Value}
+	}
+	return out
+}
+
 func convertToGogoAny(in []*any.Any) []*gogotypes.Any {
 	out := make([]*gogotypes.Any, len(in))
 	for i := range in {
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go b/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go
index afb51cf..efddd74 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/caps.go
@@ -1,4 +1,4 @@
-package moby_buildkit_v1_frontend
+package moby_buildkit_v1_frontend //nolint:golint
 
 import "github.com/moby/buildkit/util/apicaps"
 
@@ -35,6 +35,18 @@
 
 	// CapGatewaySolveMetadata can be used to check if solve calls from gateway reliably return metadata
 	CapGatewaySolveMetadata apicaps.CapID = "gateway.solve.metadata"
+
+	// CapGatewayExec is the capability to create and interact with new
+	// containers directly through the gateway
+	CapGatewayExec apicaps.CapID = "gateway.exec"
+
+	// CapFrontendCaps can be used to check that frontends define support for certain capabilities
+	CapFrontendCaps apicaps.CapID = "frontend.caps"
+
+	// CapGatewayEvaluateSolve is a capability to immediately unlazy solve
+	// results. This is generally used by the client to return and handle solve
+	// errors.
+	CapGatewayEvaluateSolve apicaps.CapID = "gateway.solve.evaluate"
 )
 
 func init() {
@@ -136,4 +148,25 @@
 		Enabled: true,
 		Status:  apicaps.CapStatusExperimental,
 	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapGatewayExec,
+		Name:    "gateway exec",
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapFrontendCaps,
+		Name:    "frontend capabilities",
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapGatewayEvaluateSolve,
+		Name:    "gateway evaluate solve",
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
 }
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go
index a155367..a700d48 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go
@@ -622,6 +622,7 @@
 	CacheImports []*CacheOptionsEntry `protobuf:"bytes,12,rep,name=CacheImports,proto3" json:"CacheImports,omitempty"`
 	// apicaps:CapFrontendInputs
 	FrontendInputs       map[string]*pb.Definition `protobuf:"bytes,13,rep,name=FrontendInputs,proto3" json:"FrontendInputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Evaluate             bool                      `protobuf:"varint,14,opt,name=Evaluate,proto3" json:"Evaluate,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}                  `json:"-"`
 	XXX_unrecognized     []byte                    `json:"-"`
 	XXX_sizecache        int32                     `json:"-"`
@@ -730,6 +731,13 @@
 	return nil
 }
 
+func (m *SolveRequest) GetEvaluate() bool {
+	if m != nil {
+		return m.Evaluate
+	}
+	return false
+}
+
 // CacheOptionsEntry corresponds to the control.CacheOptionsEntry
 type CacheOptionsEntry struct {
 	Type                 string            `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
@@ -1322,6 +1330,689 @@
 	return nil
 }
 
+type NewContainerRequest struct {
+	ContainerID string `protobuf:"bytes,1,opt,name=ContainerID,proto3" json:"ContainerID,omitempty"`
+	// For mount input values we can use random identifiers passed with ref
+	Mounts               []*pb.Mount           `protobuf:"bytes,2,rep,name=Mounts,proto3" json:"Mounts,omitempty"`
+	Network              pb.NetMode            `protobuf:"varint,3,opt,name=Network,proto3,enum=pb.NetMode" json:"Network,omitempty"`
+	Platform             *pb.Platform          `protobuf:"bytes,4,opt,name=platform,proto3" json:"platform,omitempty"`
+	Constraints          *pb.WorkerConstraints `protobuf:"bytes,5,opt,name=constraints,proto3" json:"constraints,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
+	XXX_unrecognized     []byte                `json:"-"`
+	XXX_sizecache        int32                 `json:"-"`
+}
+
+func (m *NewContainerRequest) Reset()         { *m = NewContainerRequest{} }
+func (m *NewContainerRequest) String() string { return proto.CompactTextString(m) }
+func (*NewContainerRequest) ProtoMessage()    {}
+func (*NewContainerRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{22}
+}
+func (m *NewContainerRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *NewContainerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_NewContainerRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *NewContainerRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NewContainerRequest.Merge(m, src)
+}
+func (m *NewContainerRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *NewContainerRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_NewContainerRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_NewContainerRequest proto.InternalMessageInfo
+
+func (m *NewContainerRequest) GetContainerID() string {
+	if m != nil {
+		return m.ContainerID
+	}
+	return ""
+}
+
+func (m *NewContainerRequest) GetMounts() []*pb.Mount {
+	if m != nil {
+		return m.Mounts
+	}
+	return nil
+}
+
+func (m *NewContainerRequest) GetNetwork() pb.NetMode {
+	if m != nil {
+		return m.Network
+	}
+	return pb.NetMode_UNSET
+}
+
+func (m *NewContainerRequest) GetPlatform() *pb.Platform {
+	if m != nil {
+		return m.Platform
+	}
+	return nil
+}
+
+func (m *NewContainerRequest) GetConstraints() *pb.WorkerConstraints {
+	if m != nil {
+		return m.Constraints
+	}
+	return nil
+}
+
+type NewContainerResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *NewContainerResponse) Reset()         { *m = NewContainerResponse{} }
+func (m *NewContainerResponse) String() string { return proto.CompactTextString(m) }
+func (*NewContainerResponse) ProtoMessage()    {}
+func (*NewContainerResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{23}
+}
+func (m *NewContainerResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *NewContainerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_NewContainerResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *NewContainerResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_NewContainerResponse.Merge(m, src)
+}
+func (m *NewContainerResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *NewContainerResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_NewContainerResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_NewContainerResponse proto.InternalMessageInfo
+
+type ReleaseContainerRequest struct {
+	ContainerID          string   `protobuf:"bytes,1,opt,name=ContainerID,proto3" json:"ContainerID,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ReleaseContainerRequest) Reset()         { *m = ReleaseContainerRequest{} }
+func (m *ReleaseContainerRequest) String() string { return proto.CompactTextString(m) }
+func (*ReleaseContainerRequest) ProtoMessage()    {}
+func (*ReleaseContainerRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{24}
+}
+func (m *ReleaseContainerRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ReleaseContainerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ReleaseContainerRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *ReleaseContainerRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ReleaseContainerRequest.Merge(m, src)
+}
+func (m *ReleaseContainerRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *ReleaseContainerRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ReleaseContainerRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ReleaseContainerRequest proto.InternalMessageInfo
+
+func (m *ReleaseContainerRequest) GetContainerID() string {
+	if m != nil {
+		return m.ContainerID
+	}
+	return ""
+}
+
+type ReleaseContainerResponse struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ReleaseContainerResponse) Reset()         { *m = ReleaseContainerResponse{} }
+func (m *ReleaseContainerResponse) String() string { return proto.CompactTextString(m) }
+func (*ReleaseContainerResponse) ProtoMessage()    {}
+func (*ReleaseContainerResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{25}
+}
+func (m *ReleaseContainerResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ReleaseContainerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ReleaseContainerResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *ReleaseContainerResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ReleaseContainerResponse.Merge(m, src)
+}
+func (m *ReleaseContainerResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *ReleaseContainerResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_ReleaseContainerResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ReleaseContainerResponse proto.InternalMessageInfo
+
+type ExecMessage struct {
+	ProcessID string `protobuf:"bytes,1,opt,name=ProcessID,proto3" json:"ProcessID,omitempty"`
+	// Types that are valid to be assigned to Input:
+	//	*ExecMessage_Init
+	//	*ExecMessage_File
+	//	*ExecMessage_Resize
+	//	*ExecMessage_Started
+	//	*ExecMessage_Exit
+	//	*ExecMessage_Done
+	Input                isExecMessage_Input `protobuf_oneof:"Input"`
+	XXX_NoUnkeyedLiteral struct{}            `json:"-"`
+	XXX_unrecognized     []byte              `json:"-"`
+	XXX_sizecache        int32               `json:"-"`
+}
+
+func (m *ExecMessage) Reset()         { *m = ExecMessage{} }
+func (m *ExecMessage) String() string { return proto.CompactTextString(m) }
+func (*ExecMessage) ProtoMessage()    {}
+func (*ExecMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{26}
+}
+func (m *ExecMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ExecMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ExecMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *ExecMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ExecMessage.Merge(m, src)
+}
+func (m *ExecMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *ExecMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_ExecMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExecMessage proto.InternalMessageInfo
+
+type isExecMessage_Input interface {
+	isExecMessage_Input()
+	MarshalTo([]byte) (int, error)
+	Size() int
+}
+
+type ExecMessage_Init struct {
+	Init *InitMessage `protobuf:"bytes,2,opt,name=Init,proto3,oneof" json:"Init,omitempty"`
+}
+type ExecMessage_File struct {
+	File *FdMessage `protobuf:"bytes,3,opt,name=File,proto3,oneof" json:"File,omitempty"`
+}
+type ExecMessage_Resize struct {
+	Resize *ResizeMessage `protobuf:"bytes,4,opt,name=Resize,proto3,oneof" json:"Resize,omitempty"`
+}
+type ExecMessage_Started struct {
+	Started *StartedMessage `protobuf:"bytes,5,opt,name=Started,proto3,oneof" json:"Started,omitempty"`
+}
+type ExecMessage_Exit struct {
+	Exit *ExitMessage `protobuf:"bytes,6,opt,name=Exit,proto3,oneof" json:"Exit,omitempty"`
+}
+type ExecMessage_Done struct {
+	Done *DoneMessage `protobuf:"bytes,7,opt,name=Done,proto3,oneof" json:"Done,omitempty"`
+}
+
+func (*ExecMessage_Init) isExecMessage_Input()    {}
+func (*ExecMessage_File) isExecMessage_Input()    {}
+func (*ExecMessage_Resize) isExecMessage_Input()  {}
+func (*ExecMessage_Started) isExecMessage_Input() {}
+func (*ExecMessage_Exit) isExecMessage_Input()    {}
+func (*ExecMessage_Done) isExecMessage_Input()    {}
+
+func (m *ExecMessage) GetInput() isExecMessage_Input {
+	if m != nil {
+		return m.Input
+	}
+	return nil
+}
+
+func (m *ExecMessage) GetProcessID() string {
+	if m != nil {
+		return m.ProcessID
+	}
+	return ""
+}
+
+func (m *ExecMessage) GetInit() *InitMessage {
+	if x, ok := m.GetInput().(*ExecMessage_Init); ok {
+		return x.Init
+	}
+	return nil
+}
+
+func (m *ExecMessage) GetFile() *FdMessage {
+	if x, ok := m.GetInput().(*ExecMessage_File); ok {
+		return x.File
+	}
+	return nil
+}
+
+func (m *ExecMessage) GetResize() *ResizeMessage {
+	if x, ok := m.GetInput().(*ExecMessage_Resize); ok {
+		return x.Resize
+	}
+	return nil
+}
+
+func (m *ExecMessage) GetStarted() *StartedMessage {
+	if x, ok := m.GetInput().(*ExecMessage_Started); ok {
+		return x.Started
+	}
+	return nil
+}
+
+func (m *ExecMessage) GetExit() *ExitMessage {
+	if x, ok := m.GetInput().(*ExecMessage_Exit); ok {
+		return x.Exit
+	}
+	return nil
+}
+
+func (m *ExecMessage) GetDone() *DoneMessage {
+	if x, ok := m.GetInput().(*ExecMessage_Done); ok {
+		return x.Done
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*ExecMessage) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*ExecMessage_Init)(nil),
+		(*ExecMessage_File)(nil),
+		(*ExecMessage_Resize)(nil),
+		(*ExecMessage_Started)(nil),
+		(*ExecMessage_Exit)(nil),
+		(*ExecMessage_Done)(nil),
+	}
+}
+
+type InitMessage struct {
+	ContainerID          string          `protobuf:"bytes,1,opt,name=ContainerID,proto3" json:"ContainerID,omitempty"`
+	Meta                 *pb.Meta        `protobuf:"bytes,2,opt,name=Meta,proto3" json:"Meta,omitempty"`
+	Fds                  []uint32        `protobuf:"varint,3,rep,packed,name=Fds,proto3" json:"Fds,omitempty"`
+	Tty                  bool            `protobuf:"varint,4,opt,name=Tty,proto3" json:"Tty,omitempty"`
+	Security             pb.SecurityMode `protobuf:"varint,5,opt,name=Security,proto3,enum=pb.SecurityMode" json:"Security,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *InitMessage) Reset()         { *m = InitMessage{} }
+func (m *InitMessage) String() string { return proto.CompactTextString(m) }
+func (*InitMessage) ProtoMessage()    {}
+func (*InitMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{27}
+}
+func (m *InitMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *InitMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_InitMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *InitMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_InitMessage.Merge(m, src)
+}
+func (m *InitMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *InitMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_InitMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_InitMessage proto.InternalMessageInfo
+
+func (m *InitMessage) GetContainerID() string {
+	if m != nil {
+		return m.ContainerID
+	}
+	return ""
+}
+
+func (m *InitMessage) GetMeta() *pb.Meta {
+	if m != nil {
+		return m.Meta
+	}
+	return nil
+}
+
+func (m *InitMessage) GetFds() []uint32 {
+	if m != nil {
+		return m.Fds
+	}
+	return nil
+}
+
+func (m *InitMessage) GetTty() bool {
+	if m != nil {
+		return m.Tty
+	}
+	return false
+}
+
+func (m *InitMessage) GetSecurity() pb.SecurityMode {
+	if m != nil {
+		return m.Security
+	}
+	return pb.SecurityMode_SANDBOX
+}
+
+type ExitMessage struct {
+	Code                 uint32      `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
+	Error                *rpc.Status `protobuf:"bytes,2,opt,name=Error,proto3" json:"Error,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
+	XXX_unrecognized     []byte      `json:"-"`
+	XXX_sizecache        int32       `json:"-"`
+}
+
+func (m *ExitMessage) Reset()         { *m = ExitMessage{} }
+func (m *ExitMessage) String() string { return proto.CompactTextString(m) }
+func (*ExitMessage) ProtoMessage()    {}
+func (*ExitMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{28}
+}
+func (m *ExitMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ExitMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ExitMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *ExitMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ExitMessage.Merge(m, src)
+}
+func (m *ExitMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *ExitMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_ExitMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ExitMessage proto.InternalMessageInfo
+
+func (m *ExitMessage) GetCode() uint32 {
+	if m != nil {
+		return m.Code
+	}
+	return 0
+}
+
+func (m *ExitMessage) GetError() *rpc.Status {
+	if m != nil {
+		return m.Error
+	}
+	return nil
+}
+
+type StartedMessage struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *StartedMessage) Reset()         { *m = StartedMessage{} }
+func (m *StartedMessage) String() string { return proto.CompactTextString(m) }
+func (*StartedMessage) ProtoMessage()    {}
+func (*StartedMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{29}
+}
+func (m *StartedMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *StartedMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_StartedMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *StartedMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_StartedMessage.Merge(m, src)
+}
+func (m *StartedMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *StartedMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_StartedMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StartedMessage proto.InternalMessageInfo
+
+type DoneMessage struct {
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DoneMessage) Reset()         { *m = DoneMessage{} }
+func (m *DoneMessage) String() string { return proto.CompactTextString(m) }
+func (*DoneMessage) ProtoMessage()    {}
+func (*DoneMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{30}
+}
+func (m *DoneMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *DoneMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_DoneMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *DoneMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DoneMessage.Merge(m, src)
+}
+func (m *DoneMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *DoneMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_DoneMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DoneMessage proto.InternalMessageInfo
+
+type FdMessage struct {
+	Fd                   uint32   `protobuf:"varint,1,opt,name=Fd,proto3" json:"Fd,omitempty"`
+	EOF                  bool     `protobuf:"varint,2,opt,name=EOF,proto3" json:"EOF,omitempty"`
+	Data                 []byte   `protobuf:"bytes,3,opt,name=Data,proto3" json:"Data,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *FdMessage) Reset()         { *m = FdMessage{} }
+func (m *FdMessage) String() string { return proto.CompactTextString(m) }
+func (*FdMessage) ProtoMessage()    {}
+func (*FdMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{31}
+}
+func (m *FdMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *FdMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_FdMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *FdMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FdMessage.Merge(m, src)
+}
+func (m *FdMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *FdMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_FdMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FdMessage proto.InternalMessageInfo
+
+func (m *FdMessage) GetFd() uint32 {
+	if m != nil {
+		return m.Fd
+	}
+	return 0
+}
+
+func (m *FdMessage) GetEOF() bool {
+	if m != nil {
+		return m.EOF
+	}
+	return false
+}
+
+func (m *FdMessage) GetData() []byte {
+	if m != nil {
+		return m.Data
+	}
+	return nil
+}
+
+type ResizeMessage struct {
+	Rows                 uint32   `protobuf:"varint,1,opt,name=Rows,proto3" json:"Rows,omitempty"`
+	Cols                 uint32   `protobuf:"varint,2,opt,name=Cols,proto3" json:"Cols,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ResizeMessage) Reset()         { *m = ResizeMessage{} }
+func (m *ResizeMessage) String() string { return proto.CompactTextString(m) }
+func (*ResizeMessage) ProtoMessage()    {}
+func (*ResizeMessage) Descriptor() ([]byte, []int) {
+	return fileDescriptor_f1a937782ebbded5, []int{32}
+}
+func (m *ResizeMessage) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *ResizeMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_ResizeMessage.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *ResizeMessage) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ResizeMessage.Merge(m, src)
+}
+func (m *ResizeMessage) XXX_Size() int {
+	return m.Size()
+}
+func (m *ResizeMessage) XXX_DiscardUnknown() {
+	xxx_messageInfo_ResizeMessage.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ResizeMessage proto.InternalMessageInfo
+
+func (m *ResizeMessage) GetRows() uint32 {
+	if m != nil {
+		return m.Rows
+	}
+	return 0
+}
+
+func (m *ResizeMessage) GetCols() uint32 {
+	if m != nil {
+		return m.Cols
+	}
+	return 0
+}
+
 func init() {
 	proto.RegisterType((*Result)(nil), "moby.buildkit.v1.frontend.Result")
 	proto.RegisterMapType((map[string][]byte)(nil), "moby.buildkit.v1.frontend.Result.MetadataEntry")
@@ -1352,102 +2043,143 @@
 	proto.RegisterType((*StatFileResponse)(nil), "moby.buildkit.v1.frontend.StatFileResponse")
 	proto.RegisterType((*PingRequest)(nil), "moby.buildkit.v1.frontend.PingRequest")
 	proto.RegisterType((*PongResponse)(nil), "moby.buildkit.v1.frontend.PongResponse")
+	proto.RegisterType((*NewContainerRequest)(nil), "moby.buildkit.v1.frontend.NewContainerRequest")
+	proto.RegisterType((*NewContainerResponse)(nil), "moby.buildkit.v1.frontend.NewContainerResponse")
+	proto.RegisterType((*ReleaseContainerRequest)(nil), "moby.buildkit.v1.frontend.ReleaseContainerRequest")
+	proto.RegisterType((*ReleaseContainerResponse)(nil), "moby.buildkit.v1.frontend.ReleaseContainerResponse")
+	proto.RegisterType((*ExecMessage)(nil), "moby.buildkit.v1.frontend.ExecMessage")
+	proto.RegisterType((*InitMessage)(nil), "moby.buildkit.v1.frontend.InitMessage")
+	proto.RegisterType((*ExitMessage)(nil), "moby.buildkit.v1.frontend.ExitMessage")
+	proto.RegisterType((*StartedMessage)(nil), "moby.buildkit.v1.frontend.StartedMessage")
+	proto.RegisterType((*DoneMessage)(nil), "moby.buildkit.v1.frontend.DoneMessage")
+	proto.RegisterType((*FdMessage)(nil), "moby.buildkit.v1.frontend.FdMessage")
+	proto.RegisterType((*ResizeMessage)(nil), "moby.buildkit.v1.frontend.ResizeMessage")
 }
 
 func init() { proto.RegisterFile("gateway.proto", fileDescriptor_f1a937782ebbded5) }
 
 var fileDescriptor_f1a937782ebbded5 = []byte{
-	// 1436 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x57, 0xcd, 0x6e, 0xdb, 0xc6,
-	0x16, 0x36, 0xad, 0x1f, 0x5b, 0x47, 0x92, 0xad, 0x4c, 0x2e, 0x2e, 0x14, 0x2e, 0x1c, 0x5d, 0x22,
-	0xf0, 0x55, 0x12, 0x87, 0x6a, 0x9d, 0x04, 0x4e, 0x9d, 0x22, 0x69, 0x14, 0x27, 0xb0, 0x5b, 0x3b,
-	0x51, 0x27, 0x2d, 0x02, 0x04, 0x29, 0x50, 0x4a, 0x1c, 0x32, 0x44, 0x24, 0x0e, 0x3b, 0x1c, 0x25,
-	0x15, 0xba, 0x69, 0x77, 0xdd, 0x17, 0xe8, 0x03, 0xf4, 0x01, 0x8a, 0x3e, 0x41, 0xd7, 0x59, 0x76,
-	0x59, 0x74, 0x11, 0x14, 0x7e, 0x92, 0x62, 0x7e, 0x68, 0x51, 0xb2, 0x4c, 0x59, 0xe8, 0x4a, 0x33,
-	0x87, 0xe7, 0x3b, 0x73, 0xce, 0x37, 0xe7, 0x67, 0x04, 0x55, 0xdf, 0xe1, 0xe4, 0xad, 0x33, 0xb2,
-	0x23, 0x46, 0x39, 0x45, 0x97, 0x06, 0xb4, 0x3b, 0xb2, 0xbb, 0xc3, 0xa0, 0xef, 0xbe, 0x0e, 0xb8,
-	0xfd, 0xe6, 0x43, 0xdb, 0x63, 0x34, 0xe4, 0x24, 0x74, 0xcd, 0x1b, 0x7e, 0xc0, 0x5f, 0x0d, 0xbb,
-	0x76, 0x8f, 0x0e, 0x5a, 0x3e, 0xf5, 0x69, 0x4b, 0x22, 0xba, 0x43, 0x4f, 0xee, 0xe4, 0x46, 0xae,
-	0x94, 0x25, 0x73, 0x7b, 0x5a, 0xdd, 0xa7, 0xd4, 0xef, 0x13, 0x27, 0x0a, 0x62, 0xbd, 0x6c, 0xb1,
-	0xa8, 0xd7, 0x8a, 0xb9, 0xc3, 0x87, 0xb1, 0xc6, 0x6c, 0xa5, 0x30, 0xc2, 0x91, 0x56, 0xe2, 0x48,
-	0x2b, 0xa6, 0xfd, 0x37, 0x84, 0xb5, 0xa2, 0x6e, 0x8b, 0x46, 0x89, 0x76, 0xeb, 0x4c, 0x6d, 0x27,
-	0x0a, 0x5a, 0x7c, 0x14, 0x91, 0xb8, 0xf5, 0x96, 0xb2, 0xd7, 0x84, 0x69, 0xc0, 0xcd, 0x33, 0x01,
-	0x43, 0x1e, 0xf4, 0x05, 0xaa, 0xe7, 0x44, 0xb1, 0x38, 0x44, 0xfc, 0x6a, 0x50, 0x3a, 0x6c, 0x4e,
-	0xc3, 0x20, 0xe6, 0x41, 0xe0, 0x07, 0x2d, 0x2f, 0x96, 0x18, 0x75, 0x8a, 0x08, 0x42, 0xa9, 0x5b,
-	0x3f, 0xe6, 0xa0, 0x88, 0x49, 0x3c, 0xec, 0x73, 0xb4, 0x09, 0x55, 0x46, 0xbc, 0x3d, 0x12, 0x31,
-	0xd2, 0x73, 0x38, 0x71, 0xeb, 0x46, 0xc3, 0x68, 0x96, 0xf6, 0x97, 0xf0, 0xa4, 0x18, 0x7d, 0x09,
-	0x6b, 0x8c, 0x78, 0x71, 0x4a, 0x71, 0xb9, 0x61, 0x34, 0xcb, 0xdb, 0xd7, 0xed, 0x33, 0x2f, 0xc3,
-	0xc6, 0xc4, 0x3b, 0x72, 0xa2, 0x31, 0x64, 0x7f, 0x09, 0x4f, 0x19, 0x41, 0xdb, 0x90, 0x63, 0xc4,
-	0xab, 0xe7, 0xa4, 0xad, 0x8d, 0x6c, 0x5b, 0xfb, 0x4b, 0x58, 0x28, 0xa3, 0x1d, 0xc8, 0x0b, 0x2b,
-	0xf5, 0xbc, 0x04, 0xfd, 0x6f, 0xae, 0x03, 0xfb, 0x4b, 0x58, 0x02, 0xd0, 0x67, 0xb0, 0x3a, 0x20,
-	0xdc, 0x71, 0x1d, 0xee, 0xd4, 0xa1, 0x91, 0x6b, 0x96, 0xb7, 0x5b, 0x99, 0x60, 0x41, 0x90, 0x7d,
-	0xa4, 0x11, 0x8f, 0x42, 0xce, 0x46, 0xf8, 0xc4, 0x80, 0x79, 0x17, 0xaa, 0x13, 0x9f, 0x50, 0x0d,
-	0x72, 0xaf, 0xc9, 0x48, 0xf1, 0x87, 0xc5, 0x12, 0xfd, 0x07, 0x0a, 0x6f, 0x9c, 0xfe, 0x90, 0x48,
-	0xaa, 0x2a, 0x58, 0x6d, 0x76, 0x97, 0xef, 0x18, 0xed, 0x55, 0x28, 0x32, 0x69, 0xde, 0xfa, 0xd9,
-	0x80, 0xda, 0x34, 0x4f, 0xe8, 0x40, 0x47, 0x68, 0x48, 0x27, 0x6f, 0x2f, 0x40, 0xb1, 0x10, 0xc4,
-	0xca, 0x55, 0x69, 0xc2, 0xdc, 0x81, 0xd2, 0x89, 0x68, 0x9e, 0x8b, 0xa5, 0x94, 0x8b, 0xd6, 0x0e,
-	0xe4, 0x30, 0xf1, 0xd0, 0x1a, 0x2c, 0x07, 0x3a, 0x29, 0xf0, 0x72, 0xe0, 0xa2, 0x06, 0xe4, 0x5c,
-	0xe2, 0xe9, 0xcb, 0x5f, 0xb3, 0xa3, 0xae, 0xbd, 0x47, 0xbc, 0x20, 0x0c, 0x78, 0x40, 0x43, 0x2c,
-	0x3e, 0x59, 0xbf, 0x18, 0x22, 0xb9, 0x84, 0x5b, 0xe8, 0xfe, 0x44, 0x1c, 0xf3, 0x53, 0xe5, 0x94,
-	0xf7, 0xcf, 0xb3, 0xbd, 0xbf, 0x95, 0xf6, 0x7e, 0x6e, 0xfe, 0xa4, 0xa3, 0xe3, 0x50, 0xc5, 0x84,
-	0x0f, 0x59, 0x88, 0xc9, 0x37, 0x43, 0x12, 0x73, 0xf4, 0x51, 0x72, 0x23, 0xd2, 0xfe, 0xbc, 0xb4,
-	0x12, 0x8a, 0x58, 0x03, 0x50, 0x13, 0x0a, 0x84, 0x31, 0xca, 0xb4, 0x17, 0xc8, 0x56, 0x9d, 0xc3,
-	0x66, 0x51, 0xcf, 0x7e, 0x26, 0x3b, 0x07, 0x56, 0x0a, 0x56, 0x0d, 0xd6, 0x92, 0x53, 0xe3, 0x88,
-	0x86, 0x31, 0xb1, 0xd6, 0xa1, 0x7a, 0x10, 0x46, 0x43, 0x1e, 0x6b, 0x3f, 0xac, 0xdf, 0x0d, 0x58,
-	0x4b, 0x24, 0x4a, 0x07, 0xbd, 0x84, 0xf2, 0x98, 0xe3, 0x84, 0xcc, 0xdd, 0x0c, 0xff, 0x26, 0xf1,
-	0xa9, 0x0b, 0xd2, 0xdc, 0xa6, 0xcd, 0x99, 0x4f, 0xa0, 0x36, 0xad, 0x30, 0x83, 0xe9, 0x2b, 0x93,
-	0x4c, 0x4f, 0x5f, 0x7c, 0x8a, 0xd9, 0x9f, 0x0c, 0xb8, 0x84, 0x89, 0x6c, 0x85, 0x07, 0x03, 0xc7,
-	0x27, 0x0f, 0x69, 0xe8, 0x05, 0x7e, 0x42, 0x73, 0x4d, 0x66, 0x55, 0x62, 0x59, 0x24, 0x58, 0x13,
-	0x56, 0x3b, 0x7d, 0x87, 0x7b, 0x94, 0x0d, 0xb4, 0xf1, 0x8a, 0x30, 0x9e, 0xc8, 0xf0, 0xc9, 0x57,
-	0xd4, 0x80, 0xb2, 0x36, 0x7c, 0x44, 0x5d, 0x22, 0x7b, 0x46, 0x09, 0xa7, 0x45, 0xa8, 0x0e, 0x2b,
-	0x87, 0xd4, 0x7f, 0xe2, 0x0c, 0x88, 0x6c, 0x0e, 0x25, 0x9c, 0x6c, 0xad, 0xef, 0x0d, 0x30, 0x67,
-	0x79, 0xa5, 0x29, 0xfe, 0x14, 0x8a, 0x7b, 0x81, 0x4f, 0x62, 0x75, 0xfb, 0xa5, 0xf6, 0xf6, 0xbb,
-	0xf7, 0x97, 0x97, 0xfe, 0x7a, 0x7f, 0xf9, 0x5a, 0xaa, 0xaf, 0xd2, 0x88, 0x84, 0x3d, 0x1a, 0x72,
-	0x27, 0x08, 0x09, 0x13, 0xe3, 0xe1, 0x86, 0x2b, 0x21, 0xb6, 0x42, 0x62, 0x6d, 0x01, 0xfd, 0x17,
-	0x8a, 0xca, 0xba, 0x2e, 0x7b, 0xbd, 0xb3, 0xfe, 0x2c, 0x40, 0xe5, 0x99, 0x70, 0x20, 0xe1, 0xc2,
-	0x06, 0x18, 0x53, 0xa8, 0xd3, 0x6e, 0x9a, 0xd8, 0x94, 0x06, 0x32, 0x61, 0xf5, 0xb1, 0xbe, 0x62,
-	0x5d, 0xae, 0x27, 0x7b, 0xf4, 0x02, 0xca, 0xc9, 0xfa, 0x69, 0xc4, 0xeb, 0x39, 0x99, 0x23, 0x77,
-	0x32, 0x72, 0x24, 0xed, 0x89, 0x9d, 0x82, 0xea, 0x0c, 0x49, 0x49, 0xd0, 0xc7, 0x70, 0xe9, 0x60,
-	0x10, 0x51, 0xc6, 0x1f, 0x3a, 0xbd, 0x57, 0x04, 0x4f, 0x4e, 0x81, 0x7c, 0x23, 0xd7, 0x2c, 0xe1,
-	0xb3, 0x15, 0xd0, 0x16, 0x5c, 0x70, 0xfa, 0x7d, 0xfa, 0x56, 0x17, 0x8d, 0x4c, 0xff, 0x7a, 0xa1,
-	0x61, 0x34, 0x57, 0xf1, 0xe9, 0x0f, 0xe8, 0x03, 0xb8, 0x98, 0x12, 0x3e, 0x60, 0xcc, 0x19, 0x89,
-	0x7c, 0x29, 0x4a, 0xfd, 0x59, 0x9f, 0x44, 0x07, 0x7b, 0x1c, 0x84, 0x4e, 0xbf, 0x0e, 0x52, 0x47,
-	0x6d, 0x90, 0x05, 0x95, 0x47, 0xdf, 0x0a, 0x97, 0x08, 0x7b, 0xc0, 0x39, 0xab, 0x97, 0xe5, 0x55,
-	0x4c, 0xc8, 0x50, 0x07, 0x2a, 0xd2, 0x61, 0xe5, 0x7b, 0x5c, 0xaf, 0x48, 0xd2, 0xb6, 0x32, 0x48,
-	0x93, 0xea, 0x4f, 0xa3, 0x54, 0x29, 0x4d, 0x58, 0x40, 0x3d, 0x58, 0x4b, 0x88, 0x53, 0x35, 0x58,
-	0xaf, 0x4a, 0x9b, 0x77, 0x17, 0xbd, 0x08, 0x85, 0x56, 0x47, 0x4c, 0x99, 0x34, 0xef, 0x41, 0x6d,
-	0xfa, 0xbe, 0x16, 0x69, 0xec, 0xe6, 0xe7, 0x70, 0x71, 0xc6, 0x31, 0xff, 0xaa, 0xe6, 0x7f, 0x33,
-	0xe0, 0xc2, 0x29, 0x6e, 0x10, 0x82, 0xfc, 0x17, 0xa3, 0x88, 0x68, 0x93, 0x72, 0x8d, 0x8e, 0xa0,
-	0x20, 0xb8, 0x8f, 0xeb, 0xcb, 0x92, 0x98, 0x9d, 0x45, 0xc8, 0xb6, 0x25, 0x52, 0x91, 0xa2, 0xac,
-	0x98, 0x77, 0x00, 0xc6, 0xc2, 0x85, 0xc6, 0xdb, 0x4b, 0xa8, 0x6a, 0xe6, 0x75, 0x0b, 0xa8, 0xa9,
-	0x97, 0x88, 0x06, 0x8b, 0x77, 0xc6, 0x78, 0x24, 0xe4, 0x16, 0x1c, 0x09, 0xd6, 0x77, 0xb0, 0x8e,
-	0x89, 0xe3, 0x3e, 0x0e, 0xfa, 0xe4, 0xec, 0xce, 0x27, 0xea, 0x39, 0xe8, 0x93, 0x8e, 0xc3, 0x5f,
-	0x9d, 0xd4, 0xb3, 0xde, 0xa3, 0x5d, 0x28, 0x60, 0x27, 0xf4, 0x89, 0x3e, 0xfa, 0x4a, 0xc6, 0xd1,
-	0xf2, 0x10, 0xa1, 0x8b, 0x15, 0xc4, 0xba, 0x0b, 0xa5, 0x13, 0x99, 0xe8, 0x46, 0x4f, 0x3d, 0x2f,
-	0x26, 0xaa, 0xb3, 0xe5, 0xb0, 0xde, 0x09, 0xf9, 0x21, 0x09, 0x7d, 0x7d, 0x74, 0x0e, 0xeb, 0x9d,
-	0xb5, 0x29, 0x9e, 0x23, 0x89, 0xe7, 0x9a, 0x1a, 0x04, 0xf9, 0x3d, 0xf1, 0x66, 0x32, 0x64, 0x11,
-	0xc9, 0xb5, 0xe5, 0x8a, 0x51, 0xe6, 0xb8, 0x7b, 0x01, 0x3b, 0x3b, 0xc0, 0x3a, 0xac, 0xec, 0x05,
-	0x2c, 0x15, 0x5f, 0xb2, 0x45, 0x9b, 0x62, 0xc8, 0xf5, 0xfa, 0x43, 0x57, 0x44, 0xcb, 0x09, 0x0b,
-	0x75, 0x37, 0x9f, 0x92, 0x5a, 0xf7, 0x15, 0x8f, 0xf2, 0x14, 0xed, 0xcc, 0x16, 0xac, 0x90, 0x90,
-	0xb3, 0x80, 0x24, 0x93, 0x10, 0xd9, 0xea, 0x99, 0x6b, 0xcb, 0x67, 0xae, 0x9c, 0xb8, 0x38, 0x51,
-	0xb1, 0x76, 0x60, 0x5d, 0x08, 0xb2, 0x2f, 0x02, 0x41, 0x3e, 0xe5, 0xa4, 0x5c, 0x5b, 0xbb, 0x50,
-	0x1b, 0x03, 0xf5, 0xd1, 0x9b, 0x90, 0x17, 0x8f, 0x68, 0xdd, 0xaa, 0x67, 0x9d, 0x2b, 0xbf, 0x5b,
-	0x55, 0x28, 0x77, 0x82, 0x30, 0x99, 0x79, 0xd6, 0xb1, 0x01, 0x95, 0x0e, 0x0d, 0xc7, 0xd3, 0xa6,
-	0x03, 0xeb, 0x49, 0x05, 0x3e, 0xe8, 0x1c, 0x3c, 0x74, 0xa2, 0x24, 0x94, 0xc6, 0xe9, 0x6b, 0xd6,
-	0xef, 0x7d, 0x5b, 0x29, 0xb6, 0xf3, 0x62, 0x30, 0xe1, 0x69, 0x38, 0xfa, 0x04, 0x56, 0x0e, 0x0f,
-	0xdb, 0xd2, 0xd2, 0xf2, 0x42, 0x96, 0x12, 0x18, 0xba, 0x07, 0x2b, 0xcf, 0xe5, 0xdf, 0x90, 0x58,
-	0x0f, 0x8f, 0x19, 0x29, 0xa7, 0x02, 0x55, 0x6a, 0x98, 0xf4, 0x28, 0x73, 0x71, 0x02, 0xda, 0xfe,
-	0xb5, 0x08, 0xa5, 0xc3, 0xc3, 0x76, 0x9b, 0x05, 0xae, 0x4f, 0xd0, 0x0f, 0x06, 0xa0, 0xd3, 0xe3,
-	0x16, 0xdd, 0xca, 0xae, 0xa0, 0xd9, 0x6f, 0x06, 0xf3, 0xf6, 0x82, 0x28, 0xcd, 0xf2, 0x0b, 0x28,
-	0xc8, 0x0a, 0x47, 0xff, 0x3f, 0x67, 0xf7, 0x35, 0x9b, 0xf3, 0x15, 0xb5, 0xed, 0x1e, 0xac, 0x26,
-	0x55, 0x82, 0xae, 0x65, 0xba, 0x37, 0xd1, 0x04, 0xcc, 0xeb, 0xe7, 0xd2, 0xd5, 0x87, 0x7c, 0x0d,
-	0x2b, 0x3a, 0xf9, 0xd1, 0xd5, 0x39, 0xb8, 0x71, 0x19, 0x9a, 0xd7, 0xce, 0xa3, 0x3a, 0x0e, 0x23,
-	0x49, 0xf2, 0xcc, 0x30, 0xa6, 0x4a, 0x28, 0x33, 0x8c, 0x53, 0x55, 0xf3, 0x1c, 0xf2, 0xa2, 0x1a,
-	0xd0, 0x66, 0x06, 0x28, 0x55, 0x2e, 0x66, 0xd6, 0x75, 0x4d, 0x94, 0xd1, 0x57, 0xe2, 0x7f, 0x86,
-	0x7c, 0x35, 0x34, 0x33, 0x63, 0x4e, 0x3d, 0xf3, 0xcd, 0xab, 0xe7, 0xd0, 0x1c, 0x9b, 0x57, 0xf3,
-	0x31, 0xd3, 0xfc, 0xc4, 0xeb, 0x3d, 0xd3, 0xfc, 0xe4, 0xab, 0xbc, 0x5d, 0x79, 0x77, 0xbc, 0x61,
-	0xfc, 0x71, 0xbc, 0x61, 0xfc, 0x7d, 0xbc, 0x61, 0x74, 0x8b, 0xf2, 0x8f, 0xf9, 0xcd, 0x7f, 0x02,
-	0x00, 0x00, 0xff, 0xff, 0xa9, 0x05, 0x0f, 0x9d, 0xea, 0x10, 0x00, 0x00,
+	// 1909 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x4f, 0x6f, 0x1b, 0xc7,
+	0x15, 0xd7, 0x8a, 0xa4, 0x48, 0x3e, 0xfe, 0x31, 0x33, 0x4e, 0x53, 0x7a, 0x11, 0x38, 0xcc, 0x22,
+	0x55, 0x69, 0x47, 0x59, 0xa6, 0x74, 0x02, 0xb9, 0x72, 0x90, 0xd4, 0x94, 0x28, 0x58, 0x8d, 0x24,
+	0xab, 0xe3, 0x14, 0x06, 0x82, 0x14, 0xe8, 0x8a, 0x3b, 0xa4, 0x17, 0xa6, 0x76, 0xb7, 0xb3, 0x43,
+	0xcb, 0x4c, 0x2e, 0xed, 0xad, 0xf7, 0x02, 0xbd, 0x16, 0xe8, 0x27, 0xe8, 0xa5, 0xd7, 0x9e, 0x73,
+	0xec, 0xb9, 0x07, 0xa3, 0x10, 0xfa, 0x11, 0x7a, 0x6f, 0xf1, 0x66, 0x67, 0xc8, 0x25, 0x45, 0x2d,
+	0x49, 0xe4, 0xc4, 0x99, 0xb7, 0xef, 0xf7, 0xe6, 0xfd, 0x9b, 0xf7, 0xde, 0x10, 0x2a, 0x03, 0x47,
+	0xb0, 0x4b, 0x67, 0x6c, 0x87, 0x3c, 0x10, 0x01, 0xb9, 0x73, 0x11, 0x9c, 0x8f, 0xed, 0xf3, 0x91,
+	0x37, 0x74, 0x5f, 0x7a, 0xc2, 0x7e, 0xf5, 0x33, 0xbb, 0xcf, 0x03, 0x5f, 0x30, 0xdf, 0x35, 0x3f,
+	0x1a, 0x78, 0xe2, 0xc5, 0xe8, 0xdc, 0xee, 0x05, 0x17, 0xad, 0x41, 0x30, 0x08, 0x5a, 0x12, 0x71,
+	0x3e, 0xea, 0xcb, 0x9d, 0xdc, 0xc8, 0x55, 0x2c, 0xc9, 0x6c, 0xcf, 0xb3, 0x0f, 0x82, 0x60, 0x30,
+	0x64, 0x4e, 0xe8, 0x45, 0x6a, 0xd9, 0xe2, 0x61, 0xaf, 0x15, 0x09, 0x47, 0x8c, 0x22, 0x85, 0xd9,
+	0x49, 0x60, 0x50, 0x91, 0x96, 0x56, 0xa4, 0x15, 0x05, 0xc3, 0x57, 0x8c, 0xb7, 0xc2, 0xf3, 0x56,
+	0x10, 0x6a, 0xee, 0xd6, 0x8d, 0xdc, 0x4e, 0xe8, 0xb5, 0xc4, 0x38, 0x64, 0x51, 0xeb, 0x32, 0xe0,
+	0x2f, 0x19, 0x57, 0x80, 0x07, 0x37, 0x02, 0x46, 0xc2, 0x1b, 0x22, 0xaa, 0xe7, 0x84, 0x11, 0x1e,
+	0x82, 0xbf, 0x0a, 0x94, 0x34, 0x5b, 0x04, 0xbe, 0x17, 0x09, 0xcf, 0x1b, 0x78, 0xad, 0x7e, 0x24,
+	0x31, 0xf1, 0x29, 0x68, 0x44, 0xcc, 0x6e, 0xfd, 0x31, 0x03, 0x5b, 0x94, 0x45, 0xa3, 0xa1, 0x20,
+	0xdb, 0x50, 0xe1, 0xac, 0x7f, 0xc0, 0x42, 0xce, 0x7a, 0x8e, 0x60, 0x6e, 0xdd, 0x68, 0x18, 0xcd,
+	0xe2, 0x93, 0x0d, 0x3a, 0x4b, 0x26, 0xbf, 0x86, 0x2a, 0x67, 0xfd, 0x28, 0xc1, 0xb8, 0xd9, 0x30,
+	0x9a, 0xa5, 0xf6, 0x87, 0xf6, 0x8d, 0xc1, 0xb0, 0x29, 0xeb, 0x9f, 0x38, 0xe1, 0x14, 0xf2, 0x64,
+	0x83, 0xce, 0x09, 0x21, 0x6d, 0xc8, 0x70, 0xd6, 0xaf, 0x67, 0xa4, 0xac, 0xbb, 0xe9, 0xb2, 0x9e,
+	0x6c, 0x50, 0x64, 0x26, 0xbb, 0x90, 0x45, 0x29, 0xf5, 0xac, 0x04, 0xbd, 0xbf, 0x54, 0x81, 0x27,
+	0x1b, 0x54, 0x02, 0xc8, 0x97, 0x50, 0xb8, 0x60, 0xc2, 0x71, 0x1d, 0xe1, 0xd4, 0xa1, 0x91, 0x69,
+	0x96, 0xda, 0xad, 0x54, 0x30, 0x3a, 0xc8, 0x3e, 0x51, 0x88, 0xae, 0x2f, 0xf8, 0x98, 0x4e, 0x04,
+	0x98, 0x8f, 0xa0, 0x32, 0xf3, 0x89, 0xd4, 0x20, 0xf3, 0x92, 0x8d, 0x63, 0xff, 0x51, 0x5c, 0x92,
+	0xb7, 0x21, 0xf7, 0xca, 0x19, 0x8e, 0x98, 0x74, 0x55, 0x99, 0xc6, 0x9b, 0xbd, 0xcd, 0x87, 0x46,
+	0xa7, 0x00, 0x5b, 0x5c, 0x8a, 0xb7, 0xfe, 0x6c, 0x40, 0x6d, 0xde, 0x4f, 0xe4, 0x48, 0x59, 0x68,
+	0x48, 0x25, 0x3f, 0x5d, 0xc3, 0xc5, 0x48, 0x88, 0x62, 0x55, 0xa5, 0x08, 0x73, 0x17, 0x8a, 0x13,
+	0xd2, 0x32, 0x15, 0x8b, 0x09, 0x15, 0xad, 0x5d, 0xc8, 0x50, 0xd6, 0x27, 0x55, 0xd8, 0xf4, 0x54,
+	0x52, 0xd0, 0x4d, 0xcf, 0x25, 0x0d, 0xc8, 0xb8, 0xac, 0xaf, 0x82, 0x5f, 0xb5, 0xc3, 0x73, 0xfb,
+	0x80, 0xf5, 0x3d, 0xdf, 0x13, 0x5e, 0xe0, 0x53, 0xfc, 0x64, 0xfd, 0xd5, 0xc0, 0xe4, 0x42, 0xb5,
+	0xc8, 0x17, 0x33, 0x76, 0x2c, 0x4f, 0x95, 0x6b, 0xda, 0x3f, 0x4f, 0xd7, 0xfe, 0x93, 0xa4, 0xf6,
+	0x4b, 0xf3, 0x27, 0x69, 0x9d, 0x80, 0x0a, 0x65, 0x62, 0xc4, 0x7d, 0xca, 0x7e, 0x37, 0x62, 0x91,
+	0x20, 0x3f, 0xd7, 0x11, 0x91, 0xf2, 0x97, 0xa5, 0x15, 0x32, 0x52, 0x05, 0x20, 0x4d, 0xc8, 0x31,
+	0xce, 0x03, 0xae, 0xb4, 0x20, 0x76, 0x5c, 0x39, 0x6c, 0x1e, 0xf6, 0xec, 0x67, 0xb2, 0x72, 0xd0,
+	0x98, 0xc1, 0xaa, 0x41, 0x55, 0x9f, 0x1a, 0x85, 0x81, 0x1f, 0x31, 0xeb, 0x16, 0x54, 0x8e, 0xfc,
+	0x70, 0x24, 0x22, 0xa5, 0x87, 0xf5, 0x0f, 0x03, 0xaa, 0x9a, 0x12, 0xf3, 0x90, 0x6f, 0xa0, 0x34,
+	0xf5, 0xb1, 0x76, 0xe6, 0x5e, 0x8a, 0x7e, 0xb3, 0xf8, 0x44, 0x80, 0x94, 0x6f, 0x93, 0xe2, 0xcc,
+	0x53, 0xa8, 0xcd, 0x33, 0x2c, 0xf0, 0xf4, 0x07, 0xb3, 0x9e, 0x9e, 0x0f, 0x7c, 0xc2, 0xb3, 0x7f,
+	0x32, 0xe0, 0x0e, 0x65, 0xb2, 0x14, 0x1e, 0x5d, 0x38, 0x03, 0xb6, 0x1f, 0xf8, 0x7d, 0x6f, 0xa0,
+	0xdd, 0x5c, 0x93, 0x59, 0xa5, 0x25, 0x63, 0x82, 0x35, 0xa1, 0x70, 0x36, 0x74, 0x44, 0x3f, 0xe0,
+	0x17, 0x4a, 0x78, 0x19, 0x85, 0x6b, 0x1a, 0x9d, 0x7c, 0x25, 0x0d, 0x28, 0x29, 0xc1, 0x27, 0x81,
+	0xcb, 0x64, 0xcd, 0x28, 0xd2, 0x24, 0x89, 0xd4, 0x21, 0x7f, 0x1c, 0x0c, 0x4e, 0x9d, 0x0b, 0x26,
+	0x8b, 0x43, 0x91, 0xea, 0xad, 0xf5, 0x7b, 0x03, 0xcc, 0x45, 0x5a, 0x29, 0x17, 0xff, 0x12, 0xb6,
+	0x0e, 0xbc, 0x01, 0x8b, 0xe2, 0xe8, 0x17, 0x3b, 0xed, 0xef, 0xdf, 0xbc, 0xb7, 0xf1, 0xaf, 0x37,
+	0xef, 0xdd, 0x4f, 0xd4, 0xd5, 0x20, 0x64, 0x7e, 0x2f, 0xf0, 0x85, 0xe3, 0xf9, 0x8c, 0x63, 0x7b,
+	0xf8, 0xc8, 0x95, 0x10, 0x3b, 0x46, 0x52, 0x25, 0x81, 0xbc, 0x03, 0x5b, 0xb1, 0x74, 0x75, 0xed,
+	0xd5, 0xce, 0xfa, 0x6f, 0x0e, 0xca, 0xcf, 0x50, 0x01, 0xed, 0x0b, 0x1b, 0x60, 0xea, 0x42, 0x95,
+	0x76, 0xf3, 0x8e, 0x4d, 0x70, 0x10, 0x13, 0x0a, 0x87, 0x2a, 0xc4, 0xea, 0xba, 0x4e, 0xf6, 0xe4,
+	0x6b, 0x28, 0xe9, 0xf5, 0xd3, 0x50, 0xd4, 0x33, 0x32, 0x47, 0x1e, 0xa6, 0xe4, 0x48, 0x52, 0x13,
+	0x3b, 0x01, 0x55, 0x19, 0x92, 0xa0, 0x90, 0xcf, 0xe0, 0xce, 0xd1, 0x45, 0x18, 0x70, 0xb1, 0xef,
+	0xf4, 0x5e, 0x30, 0x3a, 0xdb, 0x05, 0xb2, 0x8d, 0x4c, 0xb3, 0x48, 0x6f, 0x66, 0x20, 0x3b, 0xf0,
+	0x96, 0x33, 0x1c, 0x06, 0x97, 0xea, 0xd2, 0xc8, 0xf4, 0xaf, 0xe7, 0x1a, 0x46, 0xb3, 0x40, 0xaf,
+	0x7f, 0x20, 0x1f, 0xc3, 0xed, 0x04, 0xf1, 0x31, 0xe7, 0xce, 0x18, 0xf3, 0x65, 0x4b, 0xf2, 0x2f,
+	0xfa, 0x84, 0x15, 0xec, 0xd0, 0xf3, 0x9d, 0x61, 0x1d, 0x24, 0x4f, 0xbc, 0x21, 0x16, 0x94, 0xbb,
+	0xaf, 0x51, 0x25, 0xc6, 0x1f, 0x0b, 0xc1, 0xeb, 0x25, 0x19, 0x8a, 0x19, 0x1a, 0x39, 0x83, 0xb2,
+	0x54, 0x38, 0xd6, 0x3d, 0xaa, 0x97, 0xa5, 0xd3, 0x76, 0x52, 0x9c, 0x26, 0xd9, 0x9f, 0x86, 0x89,
+	0xab, 0x34, 0x23, 0x81, 0xf4, 0xa0, 0xaa, 0x1d, 0x17, 0xdf, 0xc1, 0x7a, 0x45, 0xca, 0x7c, 0xb4,
+	0x6e, 0x20, 0x62, 0x74, 0x7c, 0xc4, 0x9c, 0x48, 0x4c, 0x83, 0x2e, 0x5e, 0x37, 0x47, 0xb0, 0x7a,
+	0x55, 0xda, 0x3c, 0xd9, 0x9b, 0x9f, 0x43, 0x6d, 0x3e, 0x96, 0xeb, 0x14, 0x7d, 0xf3, 0x57, 0x70,
+	0x7b, 0x81, 0x0a, 0x3f, 0xa8, 0x1e, 0xfc, 0xcd, 0x80, 0xb7, 0xae, 0xf9, 0x8d, 0x10, 0xc8, 0x7e,
+	0x35, 0x0e, 0x99, 0x12, 0x29, 0xd7, 0xe4, 0x04, 0x72, 0x18, 0x97, 0xa8, 0xbe, 0x29, 0x9d, 0xb6,
+	0xbb, 0x4e, 0x20, 0x6c, 0x89, 0x8c, 0x1d, 0x16, 0x4b, 0x31, 0x1f, 0x02, 0x4c, 0x89, 0x6b, 0xb5,
+	0xbe, 0x6f, 0xa0, 0xa2, 0xa2, 0xa2, 0xca, 0x43, 0x2d, 0x9e, 0x52, 0x14, 0x18, 0x67, 0x90, 0x69,
+	0xbb, 0xc8, 0xac, 0xd9, 0x2e, 0xac, 0xef, 0xe0, 0x16, 0x65, 0x8e, 0x7b, 0xe8, 0x0d, 0xd9, 0xcd,
+	0x55, 0x11, 0xef, 0xba, 0x37, 0x64, 0x67, 0x8e, 0x78, 0x31, 0xb9, 0xeb, 0x6a, 0x4f, 0xf6, 0x20,
+	0x47, 0x1d, 0x7f, 0xc0, 0xd4, 0xd1, 0x1f, 0xa4, 0x1c, 0x2d, 0x0f, 0x41, 0x5e, 0x1a, 0x43, 0xac,
+	0x47, 0x50, 0x9c, 0xd0, 0xb0, 0x52, 0x3d, 0xed, 0xf7, 0x23, 0x16, 0x57, 0xbd, 0x0c, 0x55, 0x3b,
+	0xa4, 0x1f, 0x33, 0x7f, 0xa0, 0x8e, 0xce, 0x50, 0xb5, 0xb3, 0xb6, 0x71, 0x54, 0xd1, 0x9a, 0x2b,
+	0xd7, 0x10, 0xc8, 0x1e, 0xe0, 0x3c, 0x65, 0xc8, 0x0b, 0x26, 0xd7, 0x96, 0x8b, 0x6d, 0xce, 0x71,
+	0x0f, 0x3c, 0x7e, 0xb3, 0x81, 0x75, 0xc8, 0x1f, 0x78, 0x3c, 0x61, 0x9f, 0xde, 0x92, 0x6d, 0x6c,
+	0x80, 0xbd, 0xe1, 0xc8, 0x45, 0x6b, 0x05, 0xe3, 0xbe, 0xaa, 0xf4, 0x73, 0x54, 0xeb, 0x8b, 0xd8,
+	0x8f, 0xf2, 0x14, 0xa5, 0xcc, 0x0e, 0xe4, 0x99, 0x2f, 0xb8, 0xc7, 0x74, 0x97, 0x24, 0x76, 0x3c,
+	0x02, 0xdb, 0x72, 0x04, 0x96, 0xdd, 0x98, 0x6a, 0x16, 0x6b, 0x17, 0x6e, 0x21, 0x21, 0x3d, 0x10,
+	0x04, 0xb2, 0x09, 0x25, 0xe5, 0xda, 0xda, 0x83, 0xda, 0x14, 0xa8, 0x8e, 0xde, 0x86, 0x2c, 0x0e,
+	0xd8, 0xaa, 0x8c, 0x2f, 0x3a, 0x57, 0x7e, 0xb7, 0x2a, 0x50, 0x3a, 0xf3, 0x7c, 0xdd, 0x0f, 0xad,
+	0x2b, 0x03, 0xca, 0x67, 0x81, 0x3f, 0xed, 0x44, 0x67, 0x70, 0x4b, 0xdf, 0xc0, 0xc7, 0x67, 0x47,
+	0xfb, 0x4e, 0xa8, 0x4d, 0x69, 0x5c, 0x0f, 0xb3, 0x7a, 0x0b, 0xd8, 0x31, 0x63, 0x27, 0x8b, 0x4d,
+	0x8b, 0xce, 0xc3, 0xc9, 0x2f, 0x20, 0x7f, 0x7c, 0xdc, 0x91, 0x92, 0x36, 0xd7, 0x92, 0xa4, 0x61,
+	0xe4, 0x73, 0xc8, 0x3f, 0x97, 0x4f, 0x94, 0x48, 0x35, 0x96, 0x05, 0x29, 0x17, 0x1b, 0x1a, 0xb3,
+	0x51, 0xd6, 0x0b, 0xb8, 0x4b, 0x35, 0xc8, 0xfa, 0x8f, 0x01, 0xb7, 0x4f, 0xd9, 0xe5, 0xbe, 0x6e,
+	0x9e, 0xda, 0xdb, 0x0d, 0x28, 0x4d, 0x68, 0x47, 0x07, 0xca, 0xeb, 0x49, 0x12, 0x79, 0x1f, 0xb6,
+	0x4e, 0x82, 0x91, 0x2f, 0xb4, 0xea, 0x45, 0xac, 0x33, 0x92, 0x42, 0xd5, 0x07, 0xf2, 0x13, 0xc8,
+	0x9f, 0x32, 0x81, 0x4f, 0x28, 0x99, 0x27, 0xd5, 0x76, 0x09, 0x79, 0x4e, 0x99, 0xc0, 0x89, 0x80,
+	0xea, 0x6f, 0x38, 0x66, 0x84, 0x7a, 0xcc, 0xc8, 0x2e, 0x1a, 0x33, 0xf4, 0x57, 0xb2, 0x0b, 0xa5,
+	0x5e, 0xe0, 0x47, 0x82, 0x3b, 0x1e, 0x1e, 0x9c, 0x93, 0xcc, 0x3f, 0x42, 0xe6, 0xd8, 0x9e, 0xfd,
+	0xe9, 0x47, 0x9a, 0xe4, 0xb4, 0xde, 0x81, 0xb7, 0x67, 0xad, 0x54, 0x33, 0xde, 0x23, 0xf8, 0x31,
+	0x65, 0x43, 0xe6, 0x44, 0x6c, 0x7d, 0x0f, 0x58, 0x26, 0xd4, 0xaf, 0x83, 0x95, 0xe0, 0xbf, 0x67,
+	0xa0, 0xd4, 0x7d, 0xcd, 0x7a, 0x27, 0x2c, 0x8a, 0x9c, 0x01, 0x23, 0xef, 0x42, 0xf1, 0x8c, 0x07,
+	0x3d, 0x16, 0x45, 0x13, 0x59, 0x53, 0x02, 0xf9, 0x0c, 0xb2, 0x47, 0xbe, 0x27, 0x54, 0xc5, 0xde,
+	0x4e, 0x9d, 0x1f, 0x3d, 0xa1, 0x64, 0xe2, 0xdb, 0x09, 0xb7, 0x64, 0x0f, 0xb2, 0x98, 0xef, 0xab,
+	0xd4, 0x1c, 0x37, 0x81, 0x45, 0x0c, 0xe9, 0xc8, 0xd7, 0xa6, 0xf7, 0x2d, 0x53, 0x9e, 0x6f, 0xa6,
+	0x17, 0x4b, 0xef, 0x5b, 0x36, 0x95, 0xa0, 0x90, 0xa4, 0x0b, 0xf9, 0x67, 0xc2, 0xe1, 0x38, 0x72,
+	0xc4, 0x11, 0xb9, 0x97, 0xd6, 0x53, 0x63, 0xce, 0xa9, 0x14, 0x8d, 0x45, 0x27, 0x74, 0x5f, 0x7b,
+	0x42, 0x0e, 0x14, 0xe9, 0x4e, 0x40, 0xb6, 0x84, 0x21, 0xb8, 0x45, 0xf4, 0x41, 0xe0, 0xb3, 0x7a,
+	0x7e, 0x29, 0x1a, 0xd9, 0x12, 0x68, 0xdc, 0x76, 0xf2, 0x90, 0x93, 0x4d, 0xd5, 0xfa, 0x8b, 0x01,
+	0xa5, 0x84, 0x8f, 0x57, 0xb8, 0x07, 0xef, 0x42, 0x16, 0x1f, 0x9b, 0x2a, 0x76, 0x05, 0x79, 0x0b,
+	0x98, 0x70, 0xa8, 0xa4, 0x62, 0xd5, 0x3a, 0x74, 0xe3, 0xbb, 0x59, 0xa1, 0xb8, 0x44, 0xca, 0x57,
+	0x62, 0x2c, 0xdd, 0x5d, 0xa0, 0xb8, 0x24, 0x3b, 0x50, 0x78, 0xc6, 0x7a, 0x23, 0xee, 0x89, 0xb1,
+	0x74, 0x60, 0xb5, 0x5d, 0x43, 0x29, 0x9a, 0x26, 0x2f, 0xcb, 0x84, 0xc3, 0xfa, 0x12, 0x13, 0x6b,
+	0xaa, 0x20, 0x81, 0xec, 0x3e, 0x8e, 0xdc, 0xa8, 0x59, 0x85, 0xca, 0x35, 0xbe, 0x7a, 0xba, 0xcb,
+	0x5e, 0x3d, 0x5d, 0xfd, 0xea, 0x99, 0x0d, 0x08, 0x16, 0xc1, 0x84, 0x83, 0xac, 0xc7, 0x50, 0x9c,
+	0x24, 0x0d, 0x3e, 0x38, 0x0f, 0x5d, 0x75, 0xd2, 0xe6, 0xa1, 0x8b, 0xa6, 0x74, 0x9f, 0x1e, 0xca,
+	0x53, 0x0a, 0x14, 0x97, 0x93, 0x96, 0x93, 0x49, 0xb4, 0x9c, 0x5d, 0x7c, 0xcf, 0x25, 0x32, 0x07,
+	0x99, 0x68, 0x70, 0x19, 0x69, 0x95, 0x71, 0x1d, 0x9b, 0x31, 0x8c, 0xa4, 0x2c, 0x69, 0xc6, 0x30,
+	0x6a, 0xff, 0xaf, 0x00, 0xc5, 0xe3, 0xe3, 0x4e, 0x87, 0x7b, 0xee, 0x80, 0x91, 0x3f, 0x18, 0x40,
+	0xae, 0x3f, 0x13, 0xc8, 0x27, 0xe9, 0x09, 0xbb, 0xf8, 0xad, 0x63, 0x7e, 0xba, 0x26, 0x4a, 0x75,
+	0x80, 0xaf, 0x21, 0x27, 0xa7, 0x0f, 0xf2, 0xd3, 0x15, 0xa7, 0x46, 0xb3, 0xb9, 0x9c, 0x51, 0xc9,
+	0xee, 0x41, 0x41, 0x77, 0x70, 0x72, 0x3f, 0x55, 0xbd, 0x99, 0x01, 0xc5, 0xfc, 0x70, 0x25, 0x5e,
+	0x75, 0xc8, 0x6f, 0x21, 0xaf, 0x1a, 0x33, 0xb9, 0xb7, 0x04, 0x37, 0x1d, 0x11, 0xcc, 0xfb, 0xab,
+	0xb0, 0x4e, 0xcd, 0xd0, 0x0d, 0x38, 0xd5, 0x8c, 0xb9, 0xf6, 0x9e, 0x6a, 0xc6, 0xb5, 0x8e, 0xfe,
+	0x1c, 0xb2, 0xd8, 0xa9, 0x49, 0xda, 0x35, 0x4f, 0xb4, 0x72, 0x33, 0x2d, 0x5c, 0x33, 0x2d, 0xfe,
+	0x37, 0x58, 0x0e, 0xe5, 0x6b, 0x27, 0xbd, 0x10, 0x26, 0xfe, 0x9e, 0x30, 0xef, 0xad, 0xc0, 0x39,
+	0x15, 0xaf, 0x5e, 0x0a, 0xcd, 0x15, 0xfe, 0x23, 0x58, 0x2e, 0x7e, 0xee, 0xdf, 0x88, 0x00, 0xca,
+	0xc9, 0x2e, 0x47, 0xec, 0x14, 0xe8, 0x82, 0xa6, 0x6f, 0xb6, 0x56, 0xe6, 0x57, 0x07, 0x7e, 0x87,
+	0x53, 0xe7, 0x6c, 0x07, 0x24, 0xed, 0x54, 0x77, 0x2c, 0xec, 0xb5, 0xe6, 0x83, 0xb5, 0x30, 0xea,
+	0x70, 0x27, 0xee, 0xb0, 0xaa, 0x8b, 0x92, 0xf4, 0x86, 0x31, 0xe9, 0xc4, 0xe6, 0x8a, 0x7c, 0x4d,
+	0xe3, 0x63, 0xa3, 0x53, 0xfe, 0xfe, 0xea, 0xae, 0xf1, 0xcf, 0xab, 0xbb, 0xc6, 0xbf, 0xaf, 0xee,
+	0x1a, 0xe7, 0x5b, 0xf2, 0x1f, 0xda, 0x07, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x9d, 0x1a,
+	0x7c, 0xf3, 0x16, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -1476,6 +2208,9 @@
 	Return(ctx context.Context, in *ReturnRequest, opts ...grpc.CallOption) (*ReturnResponse, error)
 	// apicaps:CapFrontendInputs
 	Inputs(ctx context.Context, in *InputsRequest, opts ...grpc.CallOption) (*InputsResponse, error)
+	NewContainer(ctx context.Context, in *NewContainerRequest, opts ...grpc.CallOption) (*NewContainerResponse, error)
+	ReleaseContainer(ctx context.Context, in *ReleaseContainerRequest, opts ...grpc.CallOption) (*ReleaseContainerResponse, error)
+	ExecProcess(ctx context.Context, opts ...grpc.CallOption) (LLBBridge_ExecProcessClient, error)
 }
 
 type lLBBridgeClient struct {
@@ -1558,6 +2293,55 @@
 	return out, nil
 }
 
+func (c *lLBBridgeClient) NewContainer(ctx context.Context, in *NewContainerRequest, opts ...grpc.CallOption) (*NewContainerResponse, error) {
+	out := new(NewContainerResponse)
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/NewContainer", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *lLBBridgeClient) ReleaseContainer(ctx context.Context, in *ReleaseContainerRequest, opts ...grpc.CallOption) (*ReleaseContainerResponse, error) {
+	out := new(ReleaseContainerResponse)
+	err := c.cc.Invoke(ctx, "/moby.buildkit.v1.frontend.LLBBridge/ReleaseContainer", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *lLBBridgeClient) ExecProcess(ctx context.Context, opts ...grpc.CallOption) (LLBBridge_ExecProcessClient, error) {
+	stream, err := c.cc.NewStream(ctx, &_LLBBridge_serviceDesc.Streams[0], "/moby.buildkit.v1.frontend.LLBBridge/ExecProcess", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &lLBBridgeExecProcessClient{stream}
+	return x, nil
+}
+
+type LLBBridge_ExecProcessClient interface {
+	Send(*ExecMessage) error
+	Recv() (*ExecMessage, error)
+	grpc.ClientStream
+}
+
+type lLBBridgeExecProcessClient struct {
+	grpc.ClientStream
+}
+
+func (x *lLBBridgeExecProcessClient) Send(m *ExecMessage) error {
+	return x.ClientStream.SendMsg(m)
+}
+
+func (x *lLBBridgeExecProcessClient) Recv() (*ExecMessage, error) {
+	m := new(ExecMessage)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
 // LLBBridgeServer is the server API for LLBBridge service.
 type LLBBridgeServer interface {
 	// apicaps:CapResolveImage
@@ -1574,6 +2358,9 @@
 	Return(context.Context, *ReturnRequest) (*ReturnResponse, error)
 	// apicaps:CapFrontendInputs
 	Inputs(context.Context, *InputsRequest) (*InputsResponse, error)
+	NewContainer(context.Context, *NewContainerRequest) (*NewContainerResponse, error)
+	ReleaseContainer(context.Context, *ReleaseContainerRequest) (*ReleaseContainerResponse, error)
+	ExecProcess(LLBBridge_ExecProcessServer) error
 }
 
 // UnimplementedLLBBridgeServer can be embedded to have forward compatible implementations.
@@ -1604,6 +2391,15 @@
 func (*UnimplementedLLBBridgeServer) Inputs(ctx context.Context, req *InputsRequest) (*InputsResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method Inputs not implemented")
 }
+func (*UnimplementedLLBBridgeServer) NewContainer(ctx context.Context, req *NewContainerRequest) (*NewContainerResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method NewContainer not implemented")
+}
+func (*UnimplementedLLBBridgeServer) ReleaseContainer(ctx context.Context, req *ReleaseContainerRequest) (*ReleaseContainerResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ReleaseContainer not implemented")
+}
+func (*UnimplementedLLBBridgeServer) ExecProcess(srv LLBBridge_ExecProcessServer) error {
+	return status.Errorf(codes.Unimplemented, "method ExecProcess not implemented")
+}
 
 func RegisterLLBBridgeServer(s *grpc.Server, srv LLBBridgeServer) {
 	s.RegisterService(&_LLBBridge_serviceDesc, srv)
@@ -1753,6 +2549,68 @@
 	return interceptor(ctx, in, info, handler)
 }
 
+func _LLBBridge_NewContainer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(NewContainerRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(LLBBridgeServer).NewContainer(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.buildkit.v1.frontend.LLBBridge/NewContainer",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(LLBBridgeServer).NewContainer(ctx, req.(*NewContainerRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _LLBBridge_ReleaseContainer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ReleaseContainerRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(LLBBridgeServer).ReleaseContainer(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.buildkit.v1.frontend.LLBBridge/ReleaseContainer",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(LLBBridgeServer).ReleaseContainer(ctx, req.(*ReleaseContainerRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _LLBBridge_ExecProcess_Handler(srv interface{}, stream grpc.ServerStream) error {
+	return srv.(LLBBridgeServer).ExecProcess(&lLBBridgeExecProcessServer{stream})
+}
+
+type LLBBridge_ExecProcessServer interface {
+	Send(*ExecMessage) error
+	Recv() (*ExecMessage, error)
+	grpc.ServerStream
+}
+
+type lLBBridgeExecProcessServer struct {
+	grpc.ServerStream
+}
+
+func (x *lLBBridgeExecProcessServer) Send(m *ExecMessage) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func (x *lLBBridgeExecProcessServer) Recv() (*ExecMessage, error) {
+	m := new(ExecMessage)
+	if err := x.ServerStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
 var _LLBBridge_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "moby.buildkit.v1.frontend.LLBBridge",
 	HandlerType: (*LLBBridgeServer)(nil),
@@ -1789,8 +2647,23 @@
 			MethodName: "Inputs",
 			Handler:    _LLBBridge_Inputs_Handler,
 		},
+		{
+			MethodName: "NewContainer",
+			Handler:    _LLBBridge_NewContainer_Handler,
+		},
+		{
+			MethodName: "ReleaseContainer",
+			Handler:    _LLBBridge_ReleaseContainer_Handler,
+		},
 	},
-	Streams:  []grpc.StreamDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "ExecProcess",
+			Handler:       _LLBBridge_ExecProcess_Handler,
+			ServerStreams: true,
+			ClientStreams: true,
+		},
+	},
 	Metadata: "gateway.proto",
 }
 
@@ -2356,6 +3229,16 @@
 		i -= len(m.XXX_unrecognized)
 		copy(dAtA[i:], m.XXX_unrecognized)
 	}
+	if m.Evaluate {
+		i--
+		if m.Evaluate {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x70
+	}
 	if len(m.FrontendInputs) > 0 {
 		for k := range m.FrontendInputs {
 			v := m.FrontendInputs[k]
@@ -2971,6 +3854,603 @@
 	return len(dAtA) - i, nil
 }
 
+func (m *NewContainerRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *NewContainerRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *NewContainerRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Constraints != nil {
+		{
+			size, err := m.Constraints.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x2a
+	}
+	if m.Platform != nil {
+		{
+			size, err := m.Platform.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x22
+	}
+	if m.Network != 0 {
+		i = encodeVarintGateway(dAtA, i, uint64(m.Network))
+		i--
+		dAtA[i] = 0x18
+	}
+	if len(m.Mounts) > 0 {
+		for iNdEx := len(m.Mounts) - 1; iNdEx >= 0; iNdEx-- {
+			{
+				size, err := m.Mounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
+				if err != nil {
+					return 0, err
+				}
+				i -= size
+				i = encodeVarintGateway(dAtA, i, uint64(size))
+			}
+			i--
+			dAtA[i] = 0x12
+		}
+	}
+	if len(m.ContainerID) > 0 {
+		i -= len(m.ContainerID)
+		copy(dAtA[i:], m.ContainerID)
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.ContainerID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *NewContainerResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *NewContainerResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *NewContainerResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ReleaseContainerRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ReleaseContainerRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ReleaseContainerRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.ContainerID) > 0 {
+		i -= len(m.ContainerID)
+		copy(dAtA[i:], m.ContainerID)
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.ContainerID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ReleaseContainerResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ReleaseContainerResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ReleaseContainerResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ExecMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ExecMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Input != nil {
+		{
+			size := m.Input.Size()
+			i -= size
+			if _, err := m.Input.MarshalTo(dAtA[i:]); err != nil {
+				return 0, err
+			}
+		}
+	}
+	if len(m.ProcessID) > 0 {
+		i -= len(m.ProcessID)
+		copy(dAtA[i:], m.ProcessID)
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.ProcessID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ExecMessage_Init) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage_Init) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Init != nil {
+		{
+			size, err := m.Init.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	return len(dAtA) - i, nil
+}
+func (m *ExecMessage_File) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage_File) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.File != nil {
+		{
+			size, err := m.File.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x1a
+	}
+	return len(dAtA) - i, nil
+}
+func (m *ExecMessage_Resize) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage_Resize) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Resize != nil {
+		{
+			size, err := m.Resize.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x22
+	}
+	return len(dAtA) - i, nil
+}
+func (m *ExecMessage_Started) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage_Started) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Started != nil {
+		{
+			size, err := m.Started.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x2a
+	}
+	return len(dAtA) - i, nil
+}
+func (m *ExecMessage_Exit) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage_Exit) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Exit != nil {
+		{
+			size, err := m.Exit.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x32
+	}
+	return len(dAtA) - i, nil
+}
+func (m *ExecMessage_Done) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExecMessage_Done) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	if m.Done != nil {
+		{
+			size, err := m.Done.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x3a
+	}
+	return len(dAtA) - i, nil
+}
+func (m *InitMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *InitMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *InitMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Security != 0 {
+		i = encodeVarintGateway(dAtA, i, uint64(m.Security))
+		i--
+		dAtA[i] = 0x28
+	}
+	if m.Tty {
+		i--
+		if m.Tty {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x20
+	}
+	if len(m.Fds) > 0 {
+		dAtA24 := make([]byte, len(m.Fds)*10)
+		var j23 int
+		for _, num := range m.Fds {
+			for num >= 1<<7 {
+				dAtA24[j23] = uint8(uint64(num)&0x7f | 0x80)
+				num >>= 7
+				j23++
+			}
+			dAtA24[j23] = uint8(num)
+			j23++
+		}
+		i -= j23
+		copy(dAtA[i:], dAtA24[:j23])
+		i = encodeVarintGateway(dAtA, i, uint64(j23))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if m.Meta != nil {
+		{
+			size, err := m.Meta.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.ContainerID) > 0 {
+		i -= len(m.ContainerID)
+		copy(dAtA[i:], m.ContainerID)
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.ContainerID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ExitMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ExitMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ExitMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Error != nil {
+		{
+			size, err := m.Error.MarshalToSizedBuffer(dAtA[:i])
+			if err != nil {
+				return 0, err
+			}
+			i -= size
+			i = encodeVarintGateway(dAtA, i, uint64(size))
+		}
+		i--
+		dAtA[i] = 0x12
+	}
+	if m.Code != 0 {
+		i = encodeVarintGateway(dAtA, i, uint64(m.Code))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *StartedMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *StartedMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *StartedMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *DoneMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *DoneMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *DoneMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *FdMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *FdMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *FdMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if len(m.Data) > 0 {
+		i -= len(m.Data)
+		copy(dAtA[i:], m.Data)
+		i = encodeVarintGateway(dAtA, i, uint64(len(m.Data)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if m.EOF {
+		i--
+		if m.EOF {
+			dAtA[i] = 1
+		} else {
+			dAtA[i] = 0
+		}
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Fd != 0 {
+		i = encodeVarintGateway(dAtA, i, uint64(m.Fd))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *ResizeMessage) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *ResizeMessage) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *ResizeMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		i -= len(m.XXX_unrecognized)
+		copy(dAtA[i:], m.XXX_unrecognized)
+	}
+	if m.Cols != 0 {
+		i = encodeVarintGateway(dAtA, i, uint64(m.Cols))
+		i--
+		dAtA[i] = 0x10
+	}
+	if m.Rows != 0 {
+		i = encodeVarintGateway(dAtA, i, uint64(m.Rows))
+		i--
+		dAtA[i] = 0x8
+	}
+	return len(dAtA) - i, nil
+}
+
 func encodeVarintGateway(dAtA []byte, offset int, v uint64) int {
 	offset -= sovGateway(v)
 	base := offset
@@ -3297,6 +4777,9 @@
 			n += mapEntrySize + 1 + sovGateway(uint64(mapEntrySize))
 		}
 	}
+	if m.Evaluate {
+		n += 2
+	}
 	if m.XXX_unrecognized != nil {
 		n += len(m.XXX_unrecognized)
 	}
@@ -3525,6 +5008,286 @@
 	return n
 }
 
+func (m *NewContainerRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ContainerID)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if len(m.Mounts) > 0 {
+		for _, e := range m.Mounts {
+			l = e.Size()
+			n += 1 + l + sovGateway(uint64(l))
+		}
+	}
+	if m.Network != 0 {
+		n += 1 + sovGateway(uint64(m.Network))
+	}
+	if m.Platform != nil {
+		l = m.Platform.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.Constraints != nil {
+		l = m.Constraints.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *NewContainerResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ReleaseContainerRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ContainerID)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ReleaseContainerResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ExecMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ProcessID)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.Input != nil {
+		n += m.Input.Size()
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ExecMessage_Init) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Init != nil {
+		l = m.Init.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+func (m *ExecMessage_File) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.File != nil {
+		l = m.File.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+func (m *ExecMessage_Resize) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Resize != nil {
+		l = m.Resize.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+func (m *ExecMessage_Started) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Started != nil {
+		l = m.Started.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+func (m *ExecMessage_Exit) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Exit != nil {
+		l = m.Exit.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+func (m *ExecMessage_Done) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Done != nil {
+		l = m.Done.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	return n
+}
+func (m *InitMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ContainerID)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.Meta != nil {
+		l = m.Meta.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if len(m.Fds) > 0 {
+		l = 0
+		for _, e := range m.Fds {
+			l += sovGateway(uint64(e))
+		}
+		n += 1 + sovGateway(uint64(l)) + l
+	}
+	if m.Tty {
+		n += 2
+	}
+	if m.Security != 0 {
+		n += 1 + sovGateway(uint64(m.Security))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ExitMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Code != 0 {
+		n += 1 + sovGateway(uint64(m.Code))
+	}
+	if m.Error != nil {
+		l = m.Error.Size()
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *StartedMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *DoneMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *FdMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Fd != 0 {
+		n += 1 + sovGateway(uint64(m.Fd))
+	}
+	if m.EOF {
+		n += 2
+	}
+	l = len(m.Data)
+	if l > 0 {
+		n += 1 + l + sovGateway(uint64(l))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
+func (m *ResizeMessage) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	if m.Rows != 0 {
+		n += 1 + sovGateway(uint64(m.Rows))
+	}
+	if m.Cols != 0 {
+		n += 1 + sovGateway(uint64(m.Cols))
+	}
+	if m.XXX_unrecognized != nil {
+		n += len(m.XXX_unrecognized)
+	}
+	return n
+}
+
 func sovGateway(x uint64) (n int) {
 	return (math_bits.Len64(x|1) + 6) / 7
 }
@@ -5572,6 +7335,26 @@
 			}
 			m.FrontendInputs[mapkey] = mapvalue
 			iNdEx = postIndex
+		case 14:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Evaluate", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.Evaluate = bool(v != 0)
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGateway(dAtA[iNdEx:])
@@ -6922,6 +8705,1380 @@
 	}
 	return nil
 }
+func (m *NewContainerRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: NewContainerRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: NewContainerRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ContainerID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ContainerID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Mounts", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Mounts = append(m.Mounts, &pb.Mount{})
+			if err := m.Mounts[len(m.Mounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Network", wireType)
+			}
+			m.Network = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Network |= pb.NetMode(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Platform", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Platform == nil {
+				m.Platform = &pb.Platform{}
+			}
+			if err := m.Platform.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Constraints", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Constraints == nil {
+				m.Constraints = &pb.WorkerConstraints{}
+			}
+			if err := m.Constraints.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *NewContainerResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: NewContainerResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: NewContainerResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ReleaseContainerRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ReleaseContainerRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ReleaseContainerRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ContainerID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ContainerID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ReleaseContainerResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ReleaseContainerResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ReleaseContainerResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ExecMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ExecMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ExecMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ProcessID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ProcessID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Init", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &InitMessage{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Input = &ExecMessage_Init{v}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field File", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &FdMessage{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Input = &ExecMessage_File{v}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Resize", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &ResizeMessage{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Input = &ExecMessage_Resize{v}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Started", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &StartedMessage{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Input = &ExecMessage_Started{v}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Exit", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &ExitMessage{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Input = &ExecMessage_Exit{v}
+			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Done", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			v := &DoneMessage{}
+			if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			m.Input = &ExecMessage_Done{v}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *InitMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: InitMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: InitMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ContainerID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ContainerID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Meta", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Meta == nil {
+				m.Meta = &pb.Meta{}
+			}
+			if err := m.Meta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType == 0 {
+				var v uint32
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return ErrIntOverflowGateway
+					}
+					if iNdEx >= l {
+						return io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					v |= uint32(b&0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				m.Fds = append(m.Fds, v)
+			} else if wireType == 2 {
+				var packedLen int
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return ErrIntOverflowGateway
+					}
+					if iNdEx >= l {
+						return io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					packedLen |= int(b&0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				if packedLen < 0 {
+					return ErrInvalidLengthGateway
+				}
+				postIndex := iNdEx + packedLen
+				if postIndex < 0 {
+					return ErrInvalidLengthGateway
+				}
+				if postIndex > l {
+					return io.ErrUnexpectedEOF
+				}
+				var elementCount int
+				var count int
+				for _, integer := range dAtA[iNdEx:postIndex] {
+					if integer < 128 {
+						count++
+					}
+				}
+				elementCount = count
+				if elementCount != 0 && len(m.Fds) == 0 {
+					m.Fds = make([]uint32, 0, elementCount)
+				}
+				for iNdEx < postIndex {
+					var v uint32
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowGateway
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						v |= uint32(b&0x7F) << shift
+						if b < 0x80 {
+							break
+						}
+					}
+					m.Fds = append(m.Fds, v)
+				}
+			} else {
+				return fmt.Errorf("proto: wrong wireType = %d for field Fds", wireType)
+			}
+		case 4:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Tty", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.Tty = bool(v != 0)
+		case 5:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Security", wireType)
+			}
+			m.Security = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Security |= pb.SecurityMode(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ExitMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ExitMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ExitMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
+			}
+			m.Code = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Code |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + msglen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Error == nil {
+				m.Error = &rpc.Status{}
+			}
+			if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *StartedMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: StartedMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: StartedMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *DoneMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: DoneMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: DoneMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *FdMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: FdMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: FdMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Fd", wireType)
+			}
+			m.Fd = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Fd |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field EOF", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.EOF = bool(v != 0)
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthGateway
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
+			if m.Data == nil {
+				m.Data = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *ResizeMessage) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGateway
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: ResizeMessage: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: ResizeMessage: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rows", wireType)
+			}
+			m.Rows = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Rows |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Cols", wireType)
+			}
+			m.Cols = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGateway
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.Cols |= uint32(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGateway(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthGateway
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func skipGateway(dAtA []byte) (n int, err error) {
 	l := len(dAtA)
 	iNdEx := 0
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto
index 8b4725e..5fc8a02 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.proto
@@ -28,6 +28,10 @@
 	rpc Return(ReturnRequest) returns (ReturnResponse);
 	// apicaps:CapFrontendInputs
 	rpc Inputs(InputsRequest) returns (InputsResponse);
+
+	rpc NewContainer(NewContainerRequest) returns (NewContainerResponse);
+	rpc ReleaseContainer(ReleaseContainerRequest) returns (ReleaseContainerResponse);
+	rpc ExecProcess(stream ExecMessage) returns (stream ExecMessage);  
 }
 
 message Result {
@@ -103,6 +107,8 @@
 
 	// apicaps:CapFrontendInputs
 	map<string, pb.Definition> FrontendInputs = 13;
+
+	bool Evaluate = 14;
 }
 
 // CacheOptionsEntry corresponds to the control.CacheOptionsEntry
@@ -162,3 +168,71 @@
 	repeated moby.buildkit.v1.apicaps.APICap LLBCaps = 2 [(gogoproto.nullable) = false];
 	repeated moby.buildkit.v1.types.WorkerRecord Workers = 3;
 }
+
+message NewContainerRequest {
+	string ContainerID = 1;
+	// For mount input values we can use random identifiers passed with ref
+	repeated pb.Mount Mounts = 2;
+	pb.NetMode Network = 3;
+	pb.Platform platform = 4;
+	pb.WorkerConstraints constraints = 5;
+}
+
+message NewContainerResponse{}
+
+message ReleaseContainerRequest {
+	string ContainerID = 1;
+}
+
+message ReleaseContainerResponse{}
+
+message ExecMessage {
+	string ProcessID = 1;
+	oneof Input {
+		// InitMessage sent from client to server will start a new process in a
+		// container
+		InitMessage Init = 2;
+		// FdMessage used from client to server for input (stdin) and 
+		// from server to client for output (stdout, stderr)
+		FdMessage File = 3;
+		// ResizeMessage used from client to server for terminal resize events
+		ResizeMessage Resize = 4;
+		// StartedMessage sent from server to client after InitMessage to
+		// indicate the process has started.
+		StartedMessage Started = 5;
+		// ExitMessage sent from server to client will contain the exit code
+		// when the process ends.
+		ExitMessage Exit = 6;
+		// DoneMessage from server to client will be the last message for any
+		// process.  Note that FdMessage might be sent after ExitMessage.
+		DoneMessage Done = 7;
+	}
+}
+
+message InitMessage{
+	string ContainerID = 1;
+	pb.Meta Meta = 2;
+	repeated uint32 Fds = 3;
+	bool Tty = 4;
+	pb.SecurityMode Security = 5;
+}
+
+message ExitMessage {
+	uint32 Code = 1;
+	google.rpc.Status Error = 2;
+}
+
+message StartedMessage{}
+
+message DoneMessage{}
+
+message FdMessage{
+	uint32 Fd = 1; // what fd the data was from
+	bool EOF = 2;  // true if eof was reached
+	bytes Data = 3;
+}
+
+message ResizeMessage{
+	uint32 Rows = 1;
+	uint32 Cols = 2;
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/generate.go b/vendor/github.com/moby/buildkit/frontend/gateway/pb/generate.go
index 4ab07c6..e17b9da 100644
--- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/generate.go
+++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/generate.go
@@ -1,3 +1,3 @@
-package moby_buildkit_v1_frontend
+package moby_buildkit_v1_frontend //nolint:golint
 
 //go:generate protoc -I=. -I=../../../vendor/ -I=../../../../../../ --gogo_out=plugins=grpc:. gateway.proto
diff --git a/vendor/github.com/moby/buildkit/frontend/subrequests/describe.go b/vendor/github.com/moby/buildkit/frontend/subrequests/describe.go
new file mode 100644
index 0000000..cc8053e
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/subrequests/describe.go
@@ -0,0 +1,63 @@
+package subrequests
+
+import (
+	"context"
+	"encoding/json"
+
+	"github.com/moby/buildkit/frontend/gateway/client"
+	gwpb "github.com/moby/buildkit/frontend/gateway/pb"
+	"github.com/moby/buildkit/solver/errdefs"
+	"github.com/pkg/errors"
+)
+
+const RequestSubrequestsDescribe = "frontend.subrequests.describe"
+
+var SubrequestsDescribeDefinition = Request{
+	Name:        RequestSubrequestsDescribe,
+	Version:     "1.0.0",
+	Type:        TypeRPC,
+	Description: "List available subrequest types",
+	Metadata: []Named{
+		{
+			Name: "result.json",
+		},
+	},
+}
+
+func Describe(ctx context.Context, c client.Client) ([]Request, error) {
+	gwcaps := c.BuildOpts().Caps
+
+	if err := (&gwcaps).Supports(gwpb.CapFrontendCaps); err != nil {
+		return nil, errdefs.NewUnsupportedSubrequestError(RequestSubrequestsDescribe)
+	}
+
+	res, err := c.Solve(ctx, client.SolveRequest{
+		FrontendOpt: map[string]string{
+			"requestid":     RequestSubrequestsDescribe,
+			"frontend.caps": "moby.buildkit.frontend.subrequests",
+		},
+		Frontend: "dockerfile.v0",
+	})
+	if err != nil {
+		var reqErr *errdefs.UnsupportedSubrequestError
+		if errors.As(err, &reqErr) {
+			return nil, err
+		}
+		var capErr *errdefs.UnsupportedFrontendCapError
+		if errors.As(err, &capErr) {
+			return nil, errdefs.NewUnsupportedSubrequestError(RequestSubrequestsDescribe)
+		}
+		return nil, err
+	}
+
+	dt, ok := res.Metadata["result.json"]
+	if !ok {
+		return nil, errors.Errorf("no result.json metadata in response")
+	}
+
+	var reqs []Request
+	if err := json.Unmarshal(dt, &reqs); err != nil {
+		return nil, errors.Wrap(err, "failed to parse describe result")
+	}
+	return reqs, nil
+}
diff --git a/vendor/github.com/moby/buildkit/frontend/subrequests/types.go b/vendor/github.com/moby/buildkit/frontend/subrequests/types.go
new file mode 100644
index 0000000..db62afe
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/frontend/subrequests/types.go
@@ -0,0 +1,21 @@
+package subrequests
+
+type Request struct {
+	Name        string      `json:"name"`
+	Version     string      `json:"version"`
+	Type        RequestType `json:"type"`
+	Description string      `json:"description"`
+	Opts        []Named     `json:"opts"`
+	Inputs      []Named     `json:"inputs"`
+	Metadata    []Named     `json:"metadata"`
+	Refs        []Named     `json:"refs"`
+}
+
+type Named struct {
+	Name        string `json:"name"`
+	Description string `json:"description"`
+}
+
+type RequestType string
+
+const TypeRPC RequestType = "rpc"
diff --git a/vendor/github.com/moby/buildkit/go.mod b/vendor/github.com/moby/buildkit/go.mod
index f92a2b7..07d7129 100644
--- a/vendor/github.com/moby/buildkit/go.mod
+++ b/vendor/github.com/moby/buildkit/go.mod
@@ -3,76 +3,77 @@
 go 1.13
 
 require (
-	github.com/AkihiroSuda/containerd-fuse-overlayfs v0.0.0-20200512015515-32086ef23a5a
-	github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
+	github.com/AkihiroSuda/containerd-fuse-overlayfs v1.0.0
 	github.com/BurntSushi/toml v0.3.1
-	github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5
-	github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect
+	github.com/Microsoft/go-winio v0.4.15
+	github.com/Microsoft/hcsshim v0.8.10
 	github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 // indirect
-	github.com/containerd/cgroups v0.0.0-20200327175542-b44481373989 // indirect
-	github.com/containerd/console v1.0.0
-	github.com/containerd/containerd v1.4.0-0
-	github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb
-	github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b // indirect
-	github.com/containerd/go-cni v0.0.0-20200107172653-c154a49e2c75
-	github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328
-	github.com/coreos/go-systemd/v22 v22.0.0
-	github.com/docker/cli v0.0.0-20200227165822-2298e6a3fe24
+	github.com/containerd/console v1.0.1
+	github.com/containerd/containerd v1.4.1-0.20201117152358-0edc412565dc
+	github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe
+	github.com/containerd/go-cni v1.0.1
+	github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0
+	github.com/containerd/stargz-snapshotter v0.0.0-20201027054423-3a04e4c2c116
+	github.com/containerd/typeurl v1.0.1
+	github.com/coreos/go-systemd/v22 v22.1.0
+	github.com/docker/cli v20.10.0-beta1.0.20201029214301-1d20b15adc38+incompatible
 	github.com/docker/distribution v2.7.1+incompatible
-	github.com/docker/docker v0.0.0
-	github.com/docker/docker-credential-helpers v0.6.0 // indirect
-	github.com/docker/go-connections v0.3.0
-	github.com/docker/libnetwork v0.8.0-dev.2.0.20200226230617-d8334ccdb9be
-	github.com/gofrs/flock v0.7.0
+	github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible
+	github.com/docker/go-connections v0.4.0
+	github.com/docker/libnetwork v0.8.0-dev.2.0.20200917202933-d0951081b35f
+	github.com/gofrs/flock v0.7.3
 	github.com/gogo/googleapis v1.3.2
 	github.com/gogo/protobuf v1.3.1
-	github.com/golang/protobuf v1.3.3
-	github.com/google/go-cmp v0.4.0
-	github.com/google/shlex v0.0.0-20150127133951-6f45313302b9
-	github.com/google/uuid v1.1.1 // indirect
-	github.com/gorilla/mux v1.7.4 // indirect
+	// protobuf: the actual version is replaced in replace()
+	github.com/golang/protobuf v1.4.2
+	github.com/google/go-cmp v0.4.1
+	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
+	github.com/gorilla/mux v1.8.0 // indirect
 	github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
 	github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
 	github.com/hashicorp/go-immutable-radix v1.0.0
-	github.com/hashicorp/golang-lru v0.5.1
+	github.com/hashicorp/golang-lru v0.5.3
 	github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c // indirect
-	github.com/imdario/mergo v0.3.9 // indirect
 	github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 // indirect
 	github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea
 	github.com/mitchellh/hashstructure v1.0.0
-	github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c
+	github.com/moby/locker v1.0.1
+	github.com/moby/sys/mount v0.1.1 // indirect; force more current version of sys/mount than go mod selects automatically
+	github.com/moby/sys/mountinfo v0.4.0 // indirect; force more current version of sys/mountinfo than go mod selects automatically
+	github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2 // indirect
+	github.com/morikuni/aec v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/image-spec v1.0.1
-	github.com/opencontainers/runc v1.0.0-rc10
-	github.com/opencontainers/runtime-spec v1.0.2
-	github.com/opencontainers/selinux v1.5.1 // indirect
-	github.com/opentracing-contrib/go-stdlib v0.0.0-20171029140428-b1a47cfbdd75
-	github.com/opentracing/opentracing-go v1.1.0
+	github.com/opencontainers/runc v1.0.0-rc92
+	github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6
+	github.com/opentracing-contrib/go-stdlib v1.0.0
+	github.com/opentracing/opentracing-go v1.2.0
 	github.com/pkg/errors v0.9.1
-	github.com/pkg/profile v1.2.1
+	github.com/pkg/profile v1.5.0
 	github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002
-	github.com/sirupsen/logrus v1.4.2
+	github.com/sirupsen/logrus v1.7.0
 	github.com/stretchr/testify v1.5.1
-	github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
-	github.com/tonistiigi/fsutil v0.0.0-20200512175118-ae3a8d753069
+	github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85
 	github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
-	github.com/uber/jaeger-client-go v2.11.2+incompatible
-	github.com/uber/jaeger-lib v1.2.1 // indirect
+	github.com/uber/jaeger-client-go v2.25.0+incompatible
+	github.com/uber/jaeger-lib v2.2.0+incompatible // indirect
 	github.com/urfave/cli v1.22.2
-	github.com/vishvananda/netlink v1.1.0 // indirect
-	go.etcd.io/bbolt v1.3.3
-	golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d
-	golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
-	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
-	golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527
-	golang.org/x/time v0.0.0-20191024005414-555d28b269f0
-	google.golang.org/genproto v0.0.0-20200227132054-3f1135a288c9
-	google.golang.org/grpc v1.27.1
+	go.etcd.io/bbolt v1.3.5
+	golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
+	golang.org/x/net v0.0.0-20200707034311-ab3426394381
+	golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
+	golang.org/x/sys v0.0.0-20201013081832-0aaa2718063a
+	golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
+	// genproto: the actual version is replaced in replace()
+	google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece
+	google.golang.org/grpc v1.29.1
 )
 
 replace (
-	github.com/containerd/containerd => github.com/containerd/containerd v1.3.1-0.20200512144102-f13ba8f2f2fd
-	github.com/docker/docker => github.com/docker/docker v17.12.0-ce-rc1.0.20200310163718-4634ce647cf2+incompatible
+	// protobuf: corresponds to containerd
+	github.com/golang/protobuf => github.com/golang/protobuf v1.3.5
 	github.com/hashicorp/go-immutable-radix => github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe
 	github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305
+	// genproto: corresponds to containerd
+	google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
 )
diff --git a/vendor/github.com/moby/buildkit/session/auth/auth.go b/vendor/github.com/moby/buildkit/session/auth/auth.go
index 6a65eb8..864ed5d 100644
--- a/vendor/github.com/moby/buildkit/session/auth/auth.go
+++ b/vendor/github.com/moby/buildkit/session/auth/auth.go
@@ -2,16 +2,33 @@
 
 import (
 	"context"
+	"crypto/subtle"
+	"math/rand"
+	"sync"
 
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/util/grpcerrors"
+	"github.com/pkg/errors"
+	"golang.org/x/crypto/nacl/sign"
 	"google.golang.org/grpc/codes"
 )
 
-func CredentialsFunc(sm *session.Manager, g session.Group) func(string) (string, string, error) {
-	return func(host string) (string, string, error) {
-		var user, secret string
-		err := sm.Any(context.TODO(), g, func(ctx context.Context, _ string, c session.Caller) error {
+var salt []byte
+var saltOnce sync.Once
+
+// getSalt returns unique component per daemon restart to avoid persistent keys
+func getSalt() []byte {
+	saltOnce.Do(func() {
+		salt = make([]byte, 32)
+		rand.Read(salt)
+	})
+	return salt
+}
+
+func CredentialsFunc(sm *session.Manager, g session.Group) func(string) (session, username, secret string, err error) {
+	return func(host string) (string, string, string, error) {
+		var sessionID, user, secret string
+		err := sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
 			client := NewAuthClient(c.Conn())
 
 			resp, err := client.Credentials(ctx, &CredentialsRequest{
@@ -23,13 +40,91 @@
 				}
 				return err
 			}
+			sessionID = id
 			user = resp.Username
 			secret = resp.Secret
 			return nil
 		})
 		if err != nil {
-			return "", "", err
+			return "", "", "", err
 		}
-		return user, secret, nil
+		return sessionID, user, secret, nil
 	}
 }
+
+func FetchToken(req *FetchTokenRequest, sm *session.Manager, g session.Group) (resp *FetchTokenResponse, err error) {
+	err = sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
+		client := NewAuthClient(c.Conn())
+
+		resp, err = client.FetchToken(ctx, req)
+		if err != nil {
+			return err
+		}
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
+func VerifyTokenAuthority(host string, pubKey *[32]byte, sm *session.Manager, g session.Group) (sessionID string, ok bool, err error) {
+	var verified bool
+	err = sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
+		client := NewAuthClient(c.Conn())
+
+		payload := make([]byte, 32)
+		rand.Read(payload)
+		resp, err := client.VerifyTokenAuthority(ctx, &VerifyTokenAuthorityRequest{
+			Host:    host,
+			Salt:    getSalt(),
+			Payload: payload,
+		})
+		if err != nil {
+			if grpcerrors.Code(err) == codes.Unimplemented {
+				return nil
+			}
+			return err
+		}
+		var dt []byte
+		dt, ok = sign.Open(nil, resp.Signed, pubKey)
+		if ok && subtle.ConstantTimeCompare(dt, payload) == 1 {
+			verified = true
+		}
+		sessionID = id
+		return nil
+	})
+	if err != nil {
+		return "", false, err
+	}
+	return sessionID, verified, nil
+}
+
+func GetTokenAuthority(host string, sm *session.Manager, g session.Group) (sessionID string, pubKey *[32]byte, err error) {
+	err = sm.Any(context.TODO(), g, func(ctx context.Context, id string, c session.Caller) error {
+		client := NewAuthClient(c.Conn())
+
+		resp, err := client.GetTokenAuthority(ctx, &GetTokenAuthorityRequest{
+			Host: host,
+			Salt: getSalt(),
+		})
+		if err != nil {
+			if grpcerrors.Code(err) == codes.Unimplemented || grpcerrors.Code(err) == codes.Unavailable {
+				return nil
+			}
+			return err
+		}
+		if len(resp.PublicKey) != 32 {
+			return errors.Errorf("invalid pubkey length %d", len(pubKey))
+		}
+
+		sessionID = id
+		pubKey = new([32]byte)
+		copy((*pubKey)[:], resp.PublicKey)
+		return nil
+	})
+	if err != nil {
+		return "", nil, err
+	}
+	return sessionID, pubKey, nil
+}
diff --git a/vendor/github.com/moby/buildkit/session/auth/auth.pb.go b/vendor/github.com/moby/buildkit/session/auth/auth.pb.go
index 04afb3d..ffe60e9 100644
--- a/vendor/github.com/moby/buildkit/session/auth/auth.pb.go
+++ b/vendor/github.com/moby/buildkit/session/auth/auth.pb.go
@@ -4,6 +4,7 @@
 package auth
 
 import (
+	bytes "bytes"
 	context "context"
 	fmt "fmt"
 	proto "github.com/gogo/protobuf/proto"
@@ -122,30 +123,384 @@
 	return ""
 }
 
+type FetchTokenRequest struct {
+	ClientID string   `protobuf:"bytes,1,opt,name=ClientID,proto3" json:"ClientID,omitempty"`
+	Host     string   `protobuf:"bytes,2,opt,name=Host,proto3" json:"Host,omitempty"`
+	Realm    string   `protobuf:"bytes,3,opt,name=Realm,proto3" json:"Realm,omitempty"`
+	Service  string   `protobuf:"bytes,4,opt,name=Service,proto3" json:"Service,omitempty"`
+	Scopes   []string `protobuf:"bytes,5,rep,name=Scopes,proto3" json:"Scopes,omitempty"`
+}
+
+func (m *FetchTokenRequest) Reset()      { *m = FetchTokenRequest{} }
+func (*FetchTokenRequest) ProtoMessage() {}
+func (*FetchTokenRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_8bbd6f3875b0e874, []int{2}
+}
+func (m *FetchTokenRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *FetchTokenRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_FetchTokenRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *FetchTokenRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FetchTokenRequest.Merge(m, src)
+}
+func (m *FetchTokenRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *FetchTokenRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_FetchTokenRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FetchTokenRequest proto.InternalMessageInfo
+
+func (m *FetchTokenRequest) GetClientID() string {
+	if m != nil {
+		return m.ClientID
+	}
+	return ""
+}
+
+func (m *FetchTokenRequest) GetHost() string {
+	if m != nil {
+		return m.Host
+	}
+	return ""
+}
+
+func (m *FetchTokenRequest) GetRealm() string {
+	if m != nil {
+		return m.Realm
+	}
+	return ""
+}
+
+func (m *FetchTokenRequest) GetService() string {
+	if m != nil {
+		return m.Service
+	}
+	return ""
+}
+
+func (m *FetchTokenRequest) GetScopes() []string {
+	if m != nil {
+		return m.Scopes
+	}
+	return nil
+}
+
+type FetchTokenResponse struct {
+	Token     string `protobuf:"bytes,1,opt,name=Token,proto3" json:"Token,omitempty"`
+	ExpiresIn int64  `protobuf:"varint,2,opt,name=ExpiresIn,proto3" json:"ExpiresIn,omitempty"`
+	IssuedAt  int64  `protobuf:"varint,3,opt,name=IssuedAt,proto3" json:"IssuedAt,omitempty"`
+}
+
+func (m *FetchTokenResponse) Reset()      { *m = FetchTokenResponse{} }
+func (*FetchTokenResponse) ProtoMessage() {}
+func (*FetchTokenResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_8bbd6f3875b0e874, []int{3}
+}
+func (m *FetchTokenResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *FetchTokenResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_FetchTokenResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *FetchTokenResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FetchTokenResponse.Merge(m, src)
+}
+func (m *FetchTokenResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *FetchTokenResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_FetchTokenResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FetchTokenResponse proto.InternalMessageInfo
+
+func (m *FetchTokenResponse) GetToken() string {
+	if m != nil {
+		return m.Token
+	}
+	return ""
+}
+
+func (m *FetchTokenResponse) GetExpiresIn() int64 {
+	if m != nil {
+		return m.ExpiresIn
+	}
+	return 0
+}
+
+func (m *FetchTokenResponse) GetIssuedAt() int64 {
+	if m != nil {
+		return m.IssuedAt
+	}
+	return 0
+}
+
+type GetTokenAuthorityRequest struct {
+	Host string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"`
+	Salt []byte `protobuf:"bytes,2,opt,name=Salt,proto3" json:"Salt,omitempty"`
+}
+
+func (m *GetTokenAuthorityRequest) Reset()      { *m = GetTokenAuthorityRequest{} }
+func (*GetTokenAuthorityRequest) ProtoMessage() {}
+func (*GetTokenAuthorityRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_8bbd6f3875b0e874, []int{4}
+}
+func (m *GetTokenAuthorityRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetTokenAuthorityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_GetTokenAuthorityRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *GetTokenAuthorityRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetTokenAuthorityRequest.Merge(m, src)
+}
+func (m *GetTokenAuthorityRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetTokenAuthorityRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetTokenAuthorityRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetTokenAuthorityRequest proto.InternalMessageInfo
+
+func (m *GetTokenAuthorityRequest) GetHost() string {
+	if m != nil {
+		return m.Host
+	}
+	return ""
+}
+
+func (m *GetTokenAuthorityRequest) GetSalt() []byte {
+	if m != nil {
+		return m.Salt
+	}
+	return nil
+}
+
+type GetTokenAuthorityResponse struct {
+	PublicKey []byte `protobuf:"bytes,1,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"`
+}
+
+func (m *GetTokenAuthorityResponse) Reset()      { *m = GetTokenAuthorityResponse{} }
+func (*GetTokenAuthorityResponse) ProtoMessage() {}
+func (*GetTokenAuthorityResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_8bbd6f3875b0e874, []int{5}
+}
+func (m *GetTokenAuthorityResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *GetTokenAuthorityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_GetTokenAuthorityResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *GetTokenAuthorityResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_GetTokenAuthorityResponse.Merge(m, src)
+}
+func (m *GetTokenAuthorityResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *GetTokenAuthorityResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_GetTokenAuthorityResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetTokenAuthorityResponse proto.InternalMessageInfo
+
+func (m *GetTokenAuthorityResponse) GetPublicKey() []byte {
+	if m != nil {
+		return m.PublicKey
+	}
+	return nil
+}
+
+type VerifyTokenAuthorityRequest struct {
+	Host    string `protobuf:"bytes,1,opt,name=Host,proto3" json:"Host,omitempty"`
+	Payload []byte `protobuf:"bytes,2,opt,name=Payload,proto3" json:"Payload,omitempty"`
+	Salt    []byte `protobuf:"bytes,3,opt,name=Salt,proto3" json:"Salt,omitempty"`
+}
+
+func (m *VerifyTokenAuthorityRequest) Reset()      { *m = VerifyTokenAuthorityRequest{} }
+func (*VerifyTokenAuthorityRequest) ProtoMessage() {}
+func (*VerifyTokenAuthorityRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_8bbd6f3875b0e874, []int{6}
+}
+func (m *VerifyTokenAuthorityRequest) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *VerifyTokenAuthorityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_VerifyTokenAuthorityRequest.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *VerifyTokenAuthorityRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VerifyTokenAuthorityRequest.Merge(m, src)
+}
+func (m *VerifyTokenAuthorityRequest) XXX_Size() int {
+	return m.Size()
+}
+func (m *VerifyTokenAuthorityRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_VerifyTokenAuthorityRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_VerifyTokenAuthorityRequest proto.InternalMessageInfo
+
+func (m *VerifyTokenAuthorityRequest) GetHost() string {
+	if m != nil {
+		return m.Host
+	}
+	return ""
+}
+
+func (m *VerifyTokenAuthorityRequest) GetPayload() []byte {
+	if m != nil {
+		return m.Payload
+	}
+	return nil
+}
+
+func (m *VerifyTokenAuthorityRequest) GetSalt() []byte {
+	if m != nil {
+		return m.Salt
+	}
+	return nil
+}
+
+type VerifyTokenAuthorityResponse struct {
+	Signed []byte `protobuf:"bytes,1,opt,name=Signed,proto3" json:"Signed,omitempty"`
+}
+
+func (m *VerifyTokenAuthorityResponse) Reset()      { *m = VerifyTokenAuthorityResponse{} }
+func (*VerifyTokenAuthorityResponse) ProtoMessage() {}
+func (*VerifyTokenAuthorityResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_8bbd6f3875b0e874, []int{7}
+}
+func (m *VerifyTokenAuthorityResponse) XXX_Unmarshal(b []byte) error {
+	return m.Unmarshal(b)
+}
+func (m *VerifyTokenAuthorityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	if deterministic {
+		return xxx_messageInfo_VerifyTokenAuthorityResponse.Marshal(b, m, deterministic)
+	} else {
+		b = b[:cap(b)]
+		n, err := m.MarshalToSizedBuffer(b)
+		if err != nil {
+			return nil, err
+		}
+		return b[:n], nil
+	}
+}
+func (m *VerifyTokenAuthorityResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_VerifyTokenAuthorityResponse.Merge(m, src)
+}
+func (m *VerifyTokenAuthorityResponse) XXX_Size() int {
+	return m.Size()
+}
+func (m *VerifyTokenAuthorityResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_VerifyTokenAuthorityResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_VerifyTokenAuthorityResponse proto.InternalMessageInfo
+
+func (m *VerifyTokenAuthorityResponse) GetSigned() []byte {
+	if m != nil {
+		return m.Signed
+	}
+	return nil
+}
+
 func init() {
 	proto.RegisterType((*CredentialsRequest)(nil), "moby.filesync.v1.CredentialsRequest")
 	proto.RegisterType((*CredentialsResponse)(nil), "moby.filesync.v1.CredentialsResponse")
+	proto.RegisterType((*FetchTokenRequest)(nil), "moby.filesync.v1.FetchTokenRequest")
+	proto.RegisterType((*FetchTokenResponse)(nil), "moby.filesync.v1.FetchTokenResponse")
+	proto.RegisterType((*GetTokenAuthorityRequest)(nil), "moby.filesync.v1.GetTokenAuthorityRequest")
+	proto.RegisterType((*GetTokenAuthorityResponse)(nil), "moby.filesync.v1.GetTokenAuthorityResponse")
+	proto.RegisterType((*VerifyTokenAuthorityRequest)(nil), "moby.filesync.v1.VerifyTokenAuthorityRequest")
+	proto.RegisterType((*VerifyTokenAuthorityResponse)(nil), "moby.filesync.v1.VerifyTokenAuthorityResponse")
 }
 
 func init() { proto.RegisterFile("auth.proto", fileDescriptor_8bbd6f3875b0e874) }
 
 var fileDescriptor_8bbd6f3875b0e874 = []byte{
-	// 233 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0x2c, 0x2d, 0xc9,
-	0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xc8, 0xcd, 0x4f, 0xaa, 0xd4, 0x4b, 0xcb, 0xcc,
-	0x49, 0x2d, 0xae, 0xcc, 0x4b, 0xd6, 0x2b, 0x33, 0x54, 0xd2, 0xe0, 0x12, 0x72, 0x2e, 0x4a, 0x4d,
-	0x49, 0xcd, 0x2b, 0xc9, 0x4c, 0xcc, 0x29, 0x0e, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12,
-	0xe2, 0x62, 0xf1, 0xc8, 0x2f, 0x2e, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x95,
-	0x3c, 0xb9, 0x84, 0x51, 0x54, 0x16, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x0a, 0x49, 0x71, 0x71, 0x84,
-	0x16, 0xa7, 0x16, 0xe5, 0x25, 0xe6, 0xa6, 0x42, 0x95, 0xc3, 0xf9, 0x42, 0x62, 0x5c, 0x6c, 0xc1,
-	0xa9, 0xc9, 0x45, 0xa9, 0x25, 0x12, 0x4c, 0x60, 0x19, 0x28, 0xcf, 0x28, 0x89, 0x8b, 0xc5, 0xb1,
-	0xb4, 0x24, 0x43, 0x28, 0x8a, 0x8b, 0x1b, 0xc9, 0x48, 0x21, 0x15, 0x3d, 0x74, 0xe7, 0xe9, 0x61,
-	0xba, 0x4d, 0x4a, 0x95, 0x80, 0x2a, 0x88, 0xbb, 0x9c, 0xac, 0x2e, 0x3c, 0x94, 0x63, 0xb8, 0xf1,
-	0x50, 0x8e, 0xe1, 0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31, 0x9e,
-	0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9, 0x31,
-	0x7c, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb,
-	0x31, 0x44, 0xb1, 0x80, 0x02, 0x2b, 0x89, 0x0d, 0x1c, 0x5a, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
-	0xff, 0x64, 0x61, 0x71, 0x59, 0x3b, 0x01, 0x00, 0x00,
+	// 513 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0xcd, 0x6e, 0xd3, 0x40,
+	0x10, 0xc7, 0xbd, 0x75, 0xd2, 0x36, 0x43, 0x0f, 0x74, 0x89, 0x90, 0x31, 0xd1, 0xaa, 0x32, 0x45,
+	0xaa, 0x40, 0x58, 0x02, 0x24, 0x24, 0xb8, 0xb5, 0xe5, 0x2b, 0xe2, 0x52, 0x39, 0x7c, 0x48, 0xbd,
+	0x20, 0xc7, 0x9e, 0x12, 0x0b, 0xc7, 0x0e, 0xde, 0x75, 0x85, 0x6f, 0xdc, 0xb9, 0xf0, 0x08, 0x1c,
+	0x79, 0x14, 0x8e, 0x39, 0xf6, 0x48, 0x9c, 0x0b, 0xc7, 0x3c, 0x02, 0xf2, 0x66, 0x9d, 0x04, 0x1c,
+	0xd2, 0xdc, 0xfc, 0x1f, 0xff, 0x77, 0xe6, 0xb7, 0x33, 0xa3, 0x05, 0x70, 0x53, 0xd1, 0xb3, 0x07,
+	0x49, 0x2c, 0x62, 0x7a, 0xb5, 0x1f, 0x77, 0x33, 0xfb, 0x2c, 0x08, 0x91, 0x67, 0x91, 0x67, 0x9f,
+	0xdf, 0xb7, 0x0e, 0x80, 0x1e, 0x27, 0xe8, 0x63, 0x24, 0x02, 0x37, 0xe4, 0x0e, 0x7e, 0x4a, 0x91,
+	0x0b, 0x4a, 0xa1, 0xf6, 0x32, 0xe6, 0xc2, 0x20, 0x7b, 0xe4, 0xa0, 0xe1, 0xc8, 0x6f, 0xab, 0x0d,
+	0xd7, 0xfe, 0x72, 0xf2, 0x41, 0x1c, 0x71, 0xa4, 0x26, 0x6c, 0xbf, 0xe1, 0x98, 0x44, 0x6e, 0x1f,
+	0x95, 0x7d, 0xa6, 0xe9, 0x75, 0xd8, 0xec, 0xa0, 0x97, 0xa0, 0x30, 0x36, 0xe4, 0x1f, 0xa5, 0xac,
+	0xaf, 0x04, 0x76, 0x9f, 0xa3, 0xf0, 0x7a, 0xaf, 0xe3, 0x8f, 0x18, 0x95, 0x45, 0x4d, 0xd8, 0x3e,
+	0x0e, 0x03, 0x8c, 0x44, 0xfb, 0x69, 0x99, 0xa9, 0xd4, 0x33, 0xa0, 0x8d, 0x39, 0x10, 0x6d, 0x42,
+	0xdd, 0x41, 0x37, 0xec, 0x1b, 0xba, 0x0c, 0x4e, 0x05, 0x35, 0x60, 0xab, 0x83, 0xc9, 0x79, 0xe0,
+	0xa1, 0x51, 0x93, 0xf1, 0x52, 0x4a, 0x1a, 0x2f, 0x1e, 0x20, 0x37, 0xea, 0x7b, 0xba, 0xa4, 0x91,
+	0xca, 0xf2, 0x81, 0x2e, 0xc2, 0xa8, 0x7b, 0x35, 0xa1, 0x2e, 0x03, 0x0a, 0x65, 0x2a, 0x68, 0x0b,
+	0x1a, 0xcf, 0x3e, 0x0f, 0x82, 0x04, 0x79, 0x3b, 0x92, 0x30, 0xba, 0x33, 0x0f, 0x14, 0x37, 0x68,
+	0x73, 0x9e, 0xa2, 0x7f, 0x28, 0x24, 0x94, 0xee, 0xcc, 0xb4, 0x75, 0x04, 0xc6, 0x0b, 0x14, 0x32,
+	0xcb, 0x61, 0x2a, 0x7a, 0x71, 0x12, 0x88, 0x6c, 0x45, 0xbb, 0x8b, 0x58, 0xc7, 0x0d, 0xa7, 0x37,
+	0xde, 0x71, 0xe4, 0xb7, 0xf5, 0x18, 0x6e, 0x2c, 0xc9, 0xa1, 0x80, 0x5b, 0xd0, 0x38, 0x49, 0xbb,
+	0x61, 0xe0, 0xbd, 0xc2, 0x4c, 0x66, 0xda, 0x71, 0xe6, 0x01, 0xeb, 0x3d, 0xdc, 0x7c, 0x8b, 0x49,
+	0x70, 0x96, 0xad, 0x4f, 0x60, 0xc0, 0xd6, 0x89, 0x9b, 0x85, 0xb1, 0xeb, 0x2b, 0x88, 0x52, 0xce,
+	0xd8, 0xf4, 0x05, 0xb6, 0x47, 0xd0, 0x5a, 0x5e, 0x40, 0xe1, 0x15, 0xdd, 0x0f, 0x3e, 0x44, 0xe8,
+	0x2b, 0x36, 0xa5, 0x1e, 0x7c, 0xd7, 0xa1, 0x56, 0xb8, 0xe9, 0x29, 0x5c, 0x59, 0xd8, 0x2f, 0xba,
+	0x6f, 0xff, 0xbb, 0xab, 0x76, 0x75, 0x51, 0xcd, 0xdb, 0x97, 0xb8, 0x54, 0xf1, 0x77, 0x00, 0xf3,
+	0x11, 0xd3, 0x5b, 0xd5, 0x43, 0x95, 0x6d, 0x34, 0xf7, 0x57, 0x9b, 0x54, 0xe2, 0x10, 0x76, 0x2b,
+	0x13, 0xa1, 0x77, 0xaa, 0x47, 0xff, 0x37, 0x7a, 0xf3, 0xee, 0x5a, 0x5e, 0x55, 0x2d, 0x85, 0xe6,
+	0xb2, 0x1e, 0xd3, 0x7b, 0xd5, 0x24, 0x2b, 0x86, 0x6d, 0xda, 0xeb, 0xda, 0xa7, 0x65, 0x8f, 0x9e,
+	0x0c, 0x47, 0x4c, 0xbb, 0x18, 0x31, 0x6d, 0x32, 0x62, 0xe4, 0x4b, 0xce, 0xc8, 0x8f, 0x9c, 0x91,
+	0x9f, 0x39, 0x23, 0xc3, 0x9c, 0x91, 0x5f, 0x39, 0x23, 0xbf, 0x73, 0xa6, 0x4d, 0x72, 0x46, 0xbe,
+	0x8d, 0x99, 0x36, 0x1c, 0x33, 0xed, 0x62, 0xcc, 0xb4, 0xd3, 0x5a, 0xf1, 0xee, 0x74, 0x37, 0xe5,
+	0xc3, 0xf3, 0xf0, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xba, 0xb3, 0x18, 0x70, 0x86, 0x04, 0x00,
+	0x00,
 }
 
 func (this *CredentialsRequest) Equal(that interface{}) bool {
@@ -199,6 +554,182 @@
 	}
 	return true
 }
+func (this *FetchTokenRequest) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*FetchTokenRequest)
+	if !ok {
+		that2, ok := that.(FetchTokenRequest)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if this.ClientID != that1.ClientID {
+		return false
+	}
+	if this.Host != that1.Host {
+		return false
+	}
+	if this.Realm != that1.Realm {
+		return false
+	}
+	if this.Service != that1.Service {
+		return false
+	}
+	if len(this.Scopes) != len(that1.Scopes) {
+		return false
+	}
+	for i := range this.Scopes {
+		if this.Scopes[i] != that1.Scopes[i] {
+			return false
+		}
+	}
+	return true
+}
+func (this *FetchTokenResponse) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*FetchTokenResponse)
+	if !ok {
+		that2, ok := that.(FetchTokenResponse)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if this.Token != that1.Token {
+		return false
+	}
+	if this.ExpiresIn != that1.ExpiresIn {
+		return false
+	}
+	if this.IssuedAt != that1.IssuedAt {
+		return false
+	}
+	return true
+}
+func (this *GetTokenAuthorityRequest) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*GetTokenAuthorityRequest)
+	if !ok {
+		that2, ok := that.(GetTokenAuthorityRequest)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if this.Host != that1.Host {
+		return false
+	}
+	if !bytes.Equal(this.Salt, that1.Salt) {
+		return false
+	}
+	return true
+}
+func (this *GetTokenAuthorityResponse) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*GetTokenAuthorityResponse)
+	if !ok {
+		that2, ok := that.(GetTokenAuthorityResponse)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if !bytes.Equal(this.PublicKey, that1.PublicKey) {
+		return false
+	}
+	return true
+}
+func (this *VerifyTokenAuthorityRequest) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*VerifyTokenAuthorityRequest)
+	if !ok {
+		that2, ok := that.(VerifyTokenAuthorityRequest)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if this.Host != that1.Host {
+		return false
+	}
+	if !bytes.Equal(this.Payload, that1.Payload) {
+		return false
+	}
+	if !bytes.Equal(this.Salt, that1.Salt) {
+		return false
+	}
+	return true
+}
+func (this *VerifyTokenAuthorityResponse) Equal(that interface{}) bool {
+	if that == nil {
+		return this == nil
+	}
+
+	that1, ok := that.(*VerifyTokenAuthorityResponse)
+	if !ok {
+		that2, ok := that.(VerifyTokenAuthorityResponse)
+		if ok {
+			that1 = &that2
+		} else {
+			return false
+		}
+	}
+	if that1 == nil {
+		return this == nil
+	} else if this == nil {
+		return false
+	}
+	if !bytes.Equal(this.Signed, that1.Signed) {
+		return false
+	}
+	return true
+}
 func (this *CredentialsRequest) GoString() string {
 	if this == nil {
 		return "nil"
@@ -220,6 +751,75 @@
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
+func (this *FetchTokenRequest) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 9)
+	s = append(s, "&auth.FetchTokenRequest{")
+	s = append(s, "ClientID: "+fmt.Sprintf("%#v", this.ClientID)+",\n")
+	s = append(s, "Host: "+fmt.Sprintf("%#v", this.Host)+",\n")
+	s = append(s, "Realm: "+fmt.Sprintf("%#v", this.Realm)+",\n")
+	s = append(s, "Service: "+fmt.Sprintf("%#v", this.Service)+",\n")
+	s = append(s, "Scopes: "+fmt.Sprintf("%#v", this.Scopes)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *FetchTokenResponse) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 7)
+	s = append(s, "&auth.FetchTokenResponse{")
+	s = append(s, "Token: "+fmt.Sprintf("%#v", this.Token)+",\n")
+	s = append(s, "ExpiresIn: "+fmt.Sprintf("%#v", this.ExpiresIn)+",\n")
+	s = append(s, "IssuedAt: "+fmt.Sprintf("%#v", this.IssuedAt)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *GetTokenAuthorityRequest) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 6)
+	s = append(s, "&auth.GetTokenAuthorityRequest{")
+	s = append(s, "Host: "+fmt.Sprintf("%#v", this.Host)+",\n")
+	s = append(s, "Salt: "+fmt.Sprintf("%#v", this.Salt)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *GetTokenAuthorityResponse) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 5)
+	s = append(s, "&auth.GetTokenAuthorityResponse{")
+	s = append(s, "PublicKey: "+fmt.Sprintf("%#v", this.PublicKey)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *VerifyTokenAuthorityRequest) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 7)
+	s = append(s, "&auth.VerifyTokenAuthorityRequest{")
+	s = append(s, "Host: "+fmt.Sprintf("%#v", this.Host)+",\n")
+	s = append(s, "Payload: "+fmt.Sprintf("%#v", this.Payload)+",\n")
+	s = append(s, "Salt: "+fmt.Sprintf("%#v", this.Salt)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
+func (this *VerifyTokenAuthorityResponse) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 5)
+	s = append(s, "&auth.VerifyTokenAuthorityResponse{")
+	s = append(s, "Signed: "+fmt.Sprintf("%#v", this.Signed)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func valueToGoStringAuth(v interface{}, typ string) string {
 	rv := reflect.ValueOf(v)
 	if rv.IsNil() {
@@ -242,6 +842,9 @@
 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
 type AuthClient interface {
 	Credentials(ctx context.Context, in *CredentialsRequest, opts ...grpc.CallOption) (*CredentialsResponse, error)
+	FetchToken(ctx context.Context, in *FetchTokenRequest, opts ...grpc.CallOption) (*FetchTokenResponse, error)
+	GetTokenAuthority(ctx context.Context, in *GetTokenAuthorityRequest, opts ...grpc.CallOption) (*GetTokenAuthorityResponse, error)
+	VerifyTokenAuthority(ctx context.Context, in *VerifyTokenAuthorityRequest, opts ...grpc.CallOption) (*VerifyTokenAuthorityResponse, error)
 }
 
 type authClient struct {
@@ -261,9 +864,39 @@
 	return out, nil
 }
 
+func (c *authClient) FetchToken(ctx context.Context, in *FetchTokenRequest, opts ...grpc.CallOption) (*FetchTokenResponse, error) {
+	out := new(FetchTokenResponse)
+	err := c.cc.Invoke(ctx, "/moby.filesync.v1.Auth/FetchToken", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *authClient) GetTokenAuthority(ctx context.Context, in *GetTokenAuthorityRequest, opts ...grpc.CallOption) (*GetTokenAuthorityResponse, error) {
+	out := new(GetTokenAuthorityResponse)
+	err := c.cc.Invoke(ctx, "/moby.filesync.v1.Auth/GetTokenAuthority", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *authClient) VerifyTokenAuthority(ctx context.Context, in *VerifyTokenAuthorityRequest, opts ...grpc.CallOption) (*VerifyTokenAuthorityResponse, error) {
+	out := new(VerifyTokenAuthorityResponse)
+	err := c.cc.Invoke(ctx, "/moby.filesync.v1.Auth/VerifyTokenAuthority", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // AuthServer is the server API for Auth service.
 type AuthServer interface {
 	Credentials(context.Context, *CredentialsRequest) (*CredentialsResponse, error)
+	FetchToken(context.Context, *FetchTokenRequest) (*FetchTokenResponse, error)
+	GetTokenAuthority(context.Context, *GetTokenAuthorityRequest) (*GetTokenAuthorityResponse, error)
+	VerifyTokenAuthority(context.Context, *VerifyTokenAuthorityRequest) (*VerifyTokenAuthorityResponse, error)
 }
 
 // UnimplementedAuthServer can be embedded to have forward compatible implementations.
@@ -273,6 +906,15 @@
 func (*UnimplementedAuthServer) Credentials(ctx context.Context, req *CredentialsRequest) (*CredentialsResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method Credentials not implemented")
 }
+func (*UnimplementedAuthServer) FetchToken(ctx context.Context, req *FetchTokenRequest) (*FetchTokenResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method FetchToken not implemented")
+}
+func (*UnimplementedAuthServer) GetTokenAuthority(ctx context.Context, req *GetTokenAuthorityRequest) (*GetTokenAuthorityResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetTokenAuthority not implemented")
+}
+func (*UnimplementedAuthServer) VerifyTokenAuthority(ctx context.Context, req *VerifyTokenAuthorityRequest) (*VerifyTokenAuthorityResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method VerifyTokenAuthority not implemented")
+}
 
 func RegisterAuthServer(s *grpc.Server, srv AuthServer) {
 	s.RegisterService(&_Auth_serviceDesc, srv)
@@ -296,6 +938,60 @@
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Auth_FetchToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(FetchTokenRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AuthServer).FetchToken(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.filesync.v1.Auth/FetchToken",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AuthServer).FetchToken(ctx, req.(*FetchTokenRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_GetTokenAuthority_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetTokenAuthorityRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AuthServer).GetTokenAuthority(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.filesync.v1.Auth/GetTokenAuthority",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AuthServer).GetTokenAuthority(ctx, req.(*GetTokenAuthorityRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Auth_VerifyTokenAuthority_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(VerifyTokenAuthorityRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(AuthServer).VerifyTokenAuthority(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/moby.filesync.v1.Auth/VerifyTokenAuthority",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(AuthServer).VerifyTokenAuthority(ctx, req.(*VerifyTokenAuthorityRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 var _Auth_serviceDesc = grpc.ServiceDesc{
 	ServiceName: "moby.filesync.v1.Auth",
 	HandlerType: (*AuthServer)(nil),
@@ -304,6 +1000,18 @@
 			MethodName: "Credentials",
 			Handler:    _Auth_Credentials_Handler,
 		},
+		{
+			MethodName: "FetchToken",
+			Handler:    _Auth_FetchToken_Handler,
+		},
+		{
+			MethodName: "GetTokenAuthority",
+			Handler:    _Auth_GetTokenAuthority_Handler,
+		},
+		{
+			MethodName: "VerifyTokenAuthority",
+			Handler:    _Auth_VerifyTokenAuthority_Handler,
+		},
 	},
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "auth.proto",
@@ -376,6 +1084,247 @@
 	return len(dAtA) - i, nil
 }
 
+func (m *FetchTokenRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *FetchTokenRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *FetchTokenRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Scopes) > 0 {
+		for iNdEx := len(m.Scopes) - 1; iNdEx >= 0; iNdEx-- {
+			i -= len(m.Scopes[iNdEx])
+			copy(dAtA[i:], m.Scopes[iNdEx])
+			i = encodeVarintAuth(dAtA, i, uint64(len(m.Scopes[iNdEx])))
+			i--
+			dAtA[i] = 0x2a
+		}
+	}
+	if len(m.Service) > 0 {
+		i -= len(m.Service)
+		copy(dAtA[i:], m.Service)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Service)))
+		i--
+		dAtA[i] = 0x22
+	}
+	if len(m.Realm) > 0 {
+		i -= len(m.Realm)
+		copy(dAtA[i:], m.Realm)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Realm)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.Host) > 0 {
+		i -= len(m.Host)
+		copy(dAtA[i:], m.Host)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Host)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.ClientID) > 0 {
+		i -= len(m.ClientID)
+		copy(dAtA[i:], m.ClientID)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.ClientID)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *FetchTokenResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *FetchTokenResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *FetchTokenResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if m.IssuedAt != 0 {
+		i = encodeVarintAuth(dAtA, i, uint64(m.IssuedAt))
+		i--
+		dAtA[i] = 0x18
+	}
+	if m.ExpiresIn != 0 {
+		i = encodeVarintAuth(dAtA, i, uint64(m.ExpiresIn))
+		i--
+		dAtA[i] = 0x10
+	}
+	if len(m.Token) > 0 {
+		i -= len(m.Token)
+		copy(dAtA[i:], m.Token)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Token)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetTokenAuthorityRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetTokenAuthorityRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetTokenAuthorityRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Salt) > 0 {
+		i -= len(m.Salt)
+		copy(dAtA[i:], m.Salt)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Salt)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Host) > 0 {
+		i -= len(m.Host)
+		copy(dAtA[i:], m.Host)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Host)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *GetTokenAuthorityResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *GetTokenAuthorityResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *GetTokenAuthorityResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.PublicKey) > 0 {
+		i -= len(m.PublicKey)
+		copy(dAtA[i:], m.PublicKey)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.PublicKey)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *VerifyTokenAuthorityRequest) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *VerifyTokenAuthorityRequest) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *VerifyTokenAuthorityRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Salt) > 0 {
+		i -= len(m.Salt)
+		copy(dAtA[i:], m.Salt)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Salt)))
+		i--
+		dAtA[i] = 0x1a
+	}
+	if len(m.Payload) > 0 {
+		i -= len(m.Payload)
+		copy(dAtA[i:], m.Payload)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Payload)))
+		i--
+		dAtA[i] = 0x12
+	}
+	if len(m.Host) > 0 {
+		i -= len(m.Host)
+		copy(dAtA[i:], m.Host)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Host)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
+func (m *VerifyTokenAuthorityResponse) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalToSizedBuffer(dAtA[:size])
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *VerifyTokenAuthorityResponse) MarshalTo(dAtA []byte) (int, error) {
+	size := m.Size()
+	return m.MarshalToSizedBuffer(dAtA[:size])
+}
+
+func (m *VerifyTokenAuthorityResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
+	i := len(dAtA)
+	_ = i
+	var l int
+	_ = l
+	if len(m.Signed) > 0 {
+		i -= len(m.Signed)
+		copy(dAtA[i:], m.Signed)
+		i = encodeVarintAuth(dAtA, i, uint64(len(m.Signed)))
+		i--
+		dAtA[i] = 0xa
+	}
+	return len(dAtA) - i, nil
+}
+
 func encodeVarintAuth(dAtA []byte, offset int, v uint64) int {
 	offset -= sovAuth(v)
 	base := offset
@@ -417,6 +1366,120 @@
 	return n
 }
 
+func (m *FetchTokenRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.ClientID)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	l = len(m.Host)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	l = len(m.Realm)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	l = len(m.Service)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	if len(m.Scopes) > 0 {
+		for _, s := range m.Scopes {
+			l = len(s)
+			n += 1 + l + sovAuth(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *FetchTokenResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Token)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	if m.ExpiresIn != 0 {
+		n += 1 + sovAuth(uint64(m.ExpiresIn))
+	}
+	if m.IssuedAt != 0 {
+		n += 1 + sovAuth(uint64(m.IssuedAt))
+	}
+	return n
+}
+
+func (m *GetTokenAuthorityRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Host)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	l = len(m.Salt)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	return n
+}
+
+func (m *GetTokenAuthorityResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.PublicKey)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	return n
+}
+
+func (m *VerifyTokenAuthorityRequest) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Host)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	l = len(m.Payload)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	l = len(m.Salt)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	return n
+}
+
+func (m *VerifyTokenAuthorityResponse) Size() (n int) {
+	if m == nil {
+		return 0
+	}
+	var l int
+	_ = l
+	l = len(m.Signed)
+	if l > 0 {
+		n += 1 + l + sovAuth(uint64(l))
+	}
+	return n
+}
+
 func sovAuth(x uint64) (n int) {
 	return (math_bits.Len64(x|1) + 6) / 7
 }
@@ -444,6 +1507,75 @@
 	}, "")
 	return s
 }
+func (this *FetchTokenRequest) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&FetchTokenRequest{`,
+		`ClientID:` + fmt.Sprintf("%v", this.ClientID) + `,`,
+		`Host:` + fmt.Sprintf("%v", this.Host) + `,`,
+		`Realm:` + fmt.Sprintf("%v", this.Realm) + `,`,
+		`Service:` + fmt.Sprintf("%v", this.Service) + `,`,
+		`Scopes:` + fmt.Sprintf("%v", this.Scopes) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *FetchTokenResponse) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&FetchTokenResponse{`,
+		`Token:` + fmt.Sprintf("%v", this.Token) + `,`,
+		`ExpiresIn:` + fmt.Sprintf("%v", this.ExpiresIn) + `,`,
+		`IssuedAt:` + fmt.Sprintf("%v", this.IssuedAt) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *GetTokenAuthorityRequest) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&GetTokenAuthorityRequest{`,
+		`Host:` + fmt.Sprintf("%v", this.Host) + `,`,
+		`Salt:` + fmt.Sprintf("%v", this.Salt) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *GetTokenAuthorityResponse) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&GetTokenAuthorityResponse{`,
+		`PublicKey:` + fmt.Sprintf("%v", this.PublicKey) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *VerifyTokenAuthorityRequest) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&VerifyTokenAuthorityRequest{`,
+		`Host:` + fmt.Sprintf("%v", this.Host) + `,`,
+		`Payload:` + fmt.Sprintf("%v", this.Payload) + `,`,
+		`Salt:` + fmt.Sprintf("%v", this.Salt) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *VerifyTokenAuthorityResponse) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&VerifyTokenAuthorityResponse{`,
+		`Signed:` + fmt.Sprintf("%v", this.Signed) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func valueToStringAuth(v interface{}) string {
 	rv := reflect.ValueOf(v)
 	if rv.IsNil() {
@@ -654,6 +1786,788 @@
 	}
 	return nil
 }
+func (m *FetchTokenRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowAuth
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: FetchTokenRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: FetchTokenRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ClientID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ClientID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Host", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Host = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Realm", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Realm = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Service", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Service = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Scopes", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Scopes = append(m.Scopes, string(dAtA[iNdEx:postIndex]))
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAuth(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *FetchTokenResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowAuth
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: FetchTokenResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: FetchTokenResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Token = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ExpiresIn", wireType)
+			}
+			m.ExpiresIn = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.ExpiresIn |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field IssuedAt", wireType)
+			}
+			m.IssuedAt = 0
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				m.IssuedAt |= int64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAuth(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetTokenAuthorityRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowAuth
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetTokenAuthorityRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetTokenAuthorityRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Host", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Host = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Salt = append(m.Salt[:0], dAtA[iNdEx:postIndex]...)
+			if m.Salt == nil {
+				m.Salt = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAuth(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *GetTokenAuthorityResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowAuth
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: GetTokenAuthorityResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: GetTokenAuthorityResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.PublicKey = append(m.PublicKey[:0], dAtA[iNdEx:postIndex]...)
+			if m.PublicKey == nil {
+				m.PublicKey = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAuth(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *VerifyTokenAuthorityRequest) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowAuth
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: VerifyTokenAuthorityRequest: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: VerifyTokenAuthorityRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Host", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Host = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Payload", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Payload = append(m.Payload[:0], dAtA[iNdEx:postIndex]...)
+			if m.Payload == nil {
+				m.Payload = []byte{}
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Salt", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Salt = append(m.Salt[:0], dAtA[iNdEx:postIndex]...)
+			if m.Salt == nil {
+				m.Salt = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAuth(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *VerifyTokenAuthorityResponse) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowAuth
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= uint64(b&0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: VerifyTokenAuthorityResponse: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: VerifyTokenAuthorityResponse: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Signed", wireType)
+			}
+			var byteLen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowAuth
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				byteLen |= int(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if byteLen < 0 {
+				return ErrInvalidLengthAuth
+			}
+			postIndex := iNdEx + byteLen
+			if postIndex < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Signed = append(m.Signed[:0], dAtA[iNdEx:postIndex]...)
+			if m.Signed == nil {
+				m.Signed = []byte{}
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipAuth(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) < 0 {
+				return ErrInvalidLengthAuth
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func skipAuth(dAtA []byte) (n int, err error) {
 	l := len(dAtA)
 	iNdEx := 0
diff --git a/vendor/github.com/moby/buildkit/session/auth/auth.proto b/vendor/github.com/moby/buildkit/session/auth/auth.proto
index 5933127..139b0d0 100644
--- a/vendor/github.com/moby/buildkit/session/auth/auth.proto
+++ b/vendor/github.com/moby/buildkit/session/auth/auth.proto
@@ -6,9 +6,11 @@
 
 service Auth{
   rpc Credentials(CredentialsRequest) returns (CredentialsResponse);
+  rpc FetchToken(FetchTokenRequest) returns (FetchTokenResponse);
+  rpc GetTokenAuthority(GetTokenAuthorityRequest) returns (GetTokenAuthorityResponse);
+  rpc VerifyTokenAuthority(VerifyTokenAuthorityRequest) returns (VerifyTokenAuthorityResponse);
 }
 
-
 message CredentialsRequest {
 	string Host = 1;
 }
@@ -17,3 +19,36 @@
 	string Username = 1;
 	string Secret = 2;
 }
+
+message FetchTokenRequest {
+	string ClientID = 1;
+	string Host = 2;
+	string Realm = 3;
+	string Service = 4;
+	repeated string Scopes = 5;
+}
+
+message FetchTokenResponse {
+	string Token = 1;
+	int64 ExpiresIn = 2; // seconds
+	int64 IssuedAt = 3; // timestamp
+}
+
+message GetTokenAuthorityRequest {
+	string Host = 1;
+	bytes Salt = 2;
+}
+
+message GetTokenAuthorityResponse {
+	bytes PublicKey = 1;
+}
+
+message VerifyTokenAuthorityRequest {
+	string Host = 1;
+	bytes Payload = 2;
+	bytes Salt = 3;
+}
+
+message VerifyTokenAuthorityResponse {
+	bytes Signed = 1;
+}
diff --git a/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go b/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
index ac255e4..c3104db 100644
--- a/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
+++ b/vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
@@ -2,6 +2,7 @@
 
 import (
 	"bufio"
+	"context"
 	io "io"
 	"os"
 	"time"
@@ -13,7 +14,13 @@
 	"google.golang.org/grpc"
 )
 
-func sendDiffCopy(stream grpc.Stream, fs fsutil.FS, progress progressCb) error {
+type Stream interface {
+	Context() context.Context
+	SendMsg(m interface{}) error
+	RecvMsg(m interface{}) error
+}
+
+func sendDiffCopy(stream Stream, fs fsutil.FS, progress progressCb) error {
 	return errors.WithStack(fsutil.Send(stream.Context(), stream, fs, progress))
 }
 
@@ -63,7 +70,7 @@
 	return nil
 }
 
-func recvDiffCopy(ds grpc.Stream, dest string, cu CacheUpdater, progress progressCb, filter func(string, *fstypes.Stat) bool) error {
+func recvDiffCopy(ds grpc.ClientStream, dest string, cu CacheUpdater, progress progressCb, filter func(string, *fstypes.Stat) bool) error {
 	st := time.Now()
 	defer func() {
 		logrus.Debugf("diffcopy took: %v", time.Since(st))
@@ -83,7 +90,7 @@
 	}))
 }
 
-func syncTargetDiffCopy(ds grpc.Stream, dest string) error {
+func syncTargetDiffCopy(ds grpc.ServerStream, dest string) error {
 	if err := os.MkdirAll(dest, 0700); err != nil {
 		return errors.Wrapf(err, "failed to create synctarget dest dir %s", dest)
 	}
@@ -101,7 +108,7 @@
 	}))
 }
 
-func writeTargetFile(ds grpc.Stream, wc io.WriteCloser) error {
+func writeTargetFile(ds grpc.ServerStream, wc io.WriteCloser) error {
 	for {
 		bm := BytesMessage{}
 		if err := ds.RecvMsg(&bm); err != nil {
diff --git a/vendor/github.com/moby/buildkit/session/filesync/filesync.go b/vendor/github.com/moby/buildkit/session/filesync/filesync.go
index 51dd3c5..af62d1c 100644
--- a/vendor/github.com/moby/buildkit/session/filesync/filesync.go
+++ b/vendor/github.com/moby/buildkit/session/filesync/filesync.go
@@ -129,8 +129,8 @@
 
 type protocol struct {
 	name   string
-	sendFn func(stream grpc.Stream, fs fsutil.FS, progress progressCb) error
-	recvFn func(stream grpc.Stream, destDir string, cu CacheUpdater, progress progressCb, mapFunc func(string, *fstypes.Stat) bool) error
+	sendFn func(stream Stream, fs fsutil.FS, progress progressCb) error
+	recvFn func(stream grpc.ClientStream, destDir string, cu CacheUpdater, progress progressCb, mapFunc func(string, *fstypes.Stat) bool) error
 }
 
 func isProtoSupported(p string) bool {
diff --git a/vendor/github.com/moby/buildkit/session/group.go b/vendor/github.com/moby/buildkit/session/group.go
index 88409bf..4b9ba22 100644
--- a/vendor/github.com/moby/buildkit/session/group.go
+++ b/vendor/github.com/moby/buildkit/session/group.go
@@ -74,7 +74,7 @@
 
 		timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
 		defer cancel()
-		c, err := sm.Get(timeoutCtx, id)
+		c, err := sm.Get(timeoutCtx, id, false)
 		if err != nil {
 			lastErr = err
 			continue
diff --git a/vendor/github.com/moby/buildkit/session/grpc.go b/vendor/github.com/moby/buildkit/session/grpc.go
index 02870ca..728ea2e 100644
--- a/vendor/github.com/moby/buildkit/session/grpc.go
+++ b/vendor/github.com/moby/buildkit/session/grpc.go
@@ -31,7 +31,7 @@
 	var stream []grpc.StreamClientInterceptor
 
 	var dialCount int64
-	dialer := grpc.WithDialer(func(addr string, d time.Duration) (net.Conn, error) {
+	dialer := grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
 		if c := atomic.AddInt64(&dialCount, 1); c > 1 {
 			return nil, errors.Errorf("only one connection allowed")
 		}
@@ -64,7 +64,7 @@
 		dialOpts = append(dialOpts, grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(stream...)))
 	}
 
-	cc, err := grpc.DialContext(ctx, "", dialOpts...)
+	cc, err := grpc.DialContext(ctx, "localhost", dialOpts...)
 	if err != nil {
 		return nil, nil, errors.Wrap(err, "failed to create grpc client")
 	}
diff --git a/vendor/github.com/moby/buildkit/session/grpchijack/dial.go b/vendor/github.com/moby/buildkit/session/grpchijack/dial.go
index 2486563..5f0cf3d 100644
--- a/vendor/github.com/moby/buildkit/session/grpchijack/dial.go
+++ b/vendor/github.com/moby/buildkit/session/grpchijack/dial.go
@@ -33,21 +33,26 @@
 	}
 }
 
-func streamToConn(stream grpc.Stream) (net.Conn, <-chan struct{}) {
+type stream interface {
+	Context() context.Context
+	SendMsg(m interface{}) error
+	RecvMsg(m interface{}) error
+}
+
+func streamToConn(stream stream) (net.Conn, <-chan struct{}) {
 	closeCh := make(chan struct{})
 	c := &conn{stream: stream, buf: make([]byte, 32*1<<10), closeCh: closeCh}
 	return c, closeCh
 }
 
 type conn struct {
-	stream  grpc.Stream
+	stream  stream
 	buf     []byte
 	lastBuf []byte
 
 	closedOnce sync.Once
 	readMu     sync.Mutex
 	writeMu    sync.Mutex
-	err        error
 	closeCh    chan struct{}
 }
 
diff --git a/vendor/github.com/moby/buildkit/session/manager.go b/vendor/github.com/moby/buildkit/session/manager.go
index e01b047..edac930 100644
--- a/vendor/github.com/moby/buildkit/session/manager.go
+++ b/vendor/github.com/moby/buildkit/session/manager.go
@@ -149,7 +149,7 @@
 }
 
 // Get returns a session by ID
-func (sm *Manager) Get(ctx context.Context, id string) (Caller, error) {
+func (sm *Manager) Get(ctx context.Context, id string, noWait bool) (Caller, error) {
 	// session prefix is used to identify vertexes with different contexts so
 	// they would not collide, but for lookup we don't need the prefix
 	if p := strings.SplitN(id, ":", 2); len(p) == 2 && len(p[1]) > 0 {
@@ -180,7 +180,7 @@
 		}
 		var ok bool
 		c, ok = sm.sessions[id]
-		if !ok || c.closed() {
+		if (!ok || c.closed()) && !noWait {
 			sm.updateCondition.Wait()
 			continue
 		}
@@ -188,6 +188,10 @@
 		break
 	}
 
+	if c == nil {
+		return nil, nil
+	}
+
 	return c, nil
 }
 
diff --git a/vendor/github.com/moby/buildkit/session/sshforward/copy.go b/vendor/github.com/moby/buildkit/session/sshforward/copy.go
index 85366f1..6db4148 100644
--- a/vendor/github.com/moby/buildkit/session/sshforward/copy.go
+++ b/vendor/github.com/moby/buildkit/session/sshforward/copy.go
@@ -6,10 +6,14 @@
 	"github.com/pkg/errors"
 	context "golang.org/x/net/context"
 	"golang.org/x/sync/errgroup"
-	"google.golang.org/grpc"
 )
 
-func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream, closeStream func() error) error {
+type Stream interface {
+	SendMsg(m interface{}) error
+	RecvMsg(m interface{}) error
+}
+
+func Copy(ctx context.Context, conn io.ReadWriteCloser, stream Stream, closeStream func() error) error {
 	g, ctx := errgroup.WithContext(ctx)
 
 	g.Go(func() (retErr error) {
diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go b/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go
index a5cd1a2..df2e99b 100644
--- a/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go
+++ b/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go
@@ -25,12 +25,27 @@
 		return "", errors.Wrapf(errdefs.ErrNotImplemented, "request to mount %d layers, only 1 is supported", len(lm.mounts))
 	}
 
+	m := lm.mounts[0]
+
+	if m.Type == "bind" || m.Type == "rbind" {
+		ro := false
+		for _, opt := range m.Options {
+			if opt == "ro" {
+				ro = true
+				break
+			}
+		}
+		if !ro {
+			return m.Source, nil
+		}
+	}
+
 	// Windows mounts always activate in-place, so the target of the mount must be the source directory.
 	// See https://github.com/containerd/containerd/pull/2366
-	dir := lm.mounts[0].Source
+	dir := m.Source
 
-	if err := lm.mounts[0].Mount(dir); err != nil {
-		return "", errors.Wrapf(err, "failed to mount in-place: %v", lm.mounts[0])
+	if err := m.Mount(dir); err != nil {
+		return "", errors.Wrapf(err, "failed to mount in-place: %v", m)
 	}
 	lm.target = dir
 	return lm.target, nil
diff --git a/vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go b/vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go
index 1975581..515feff 100644
--- a/vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go
+++ b/vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go
@@ -233,12 +233,6 @@
 		}
 	}
 
-	links := tx.Bucket([]byte(resultBucket))
-	if results == nil {
-		return nil
-	}
-	links = links.Bucket([]byte(id))
-
 	return s.emptyBranchWithParents(tx, []byte(id))
 }
 
diff --git a/vendor/github.com/moby/buildkit/solver/cacheopts.go b/vendor/github.com/moby/buildkit/solver/cacheopts.go
new file mode 100644
index 0000000..7c58d82
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/cacheopts.go
@@ -0,0 +1,88 @@
+package solver
+
+import (
+	"context"
+
+	digest "github.com/opencontainers/go-digest"
+	"github.com/sirupsen/logrus"
+)
+
+type CacheOpts map[interface{}]interface{}
+
+type cacheOptGetterKey struct{}
+
+func CacheOptGetterOf(ctx context.Context) func(keys ...interface{}) map[interface{}]interface{} {
+	if v := ctx.Value(cacheOptGetterKey{}); v != nil {
+		if getter, ok := v.(func(keys ...interface{}) map[interface{}]interface{}); ok {
+			return getter
+		}
+	}
+	return nil
+}
+
+func withAncestorCacheOpts(ctx context.Context, start *state) context.Context {
+	return context.WithValue(ctx, cacheOptGetterKey{}, func(keys ...interface{}) map[interface{}]interface{} {
+		keySet := make(map[interface{}]struct{})
+		for _, k := range keys {
+			keySet[k] = struct{}{}
+		}
+		values := make(map[interface{}]interface{})
+		walkAncestors(start, func(st *state) bool {
+			if st.clientVertex.Error != "" {
+				// don't use values from cancelled or otherwise error'd vertexes
+				return false
+			}
+			for _, res := range st.op.cacheRes {
+				if res.Opts == nil {
+					continue
+				}
+				for k := range keySet {
+					if v, ok := res.Opts[k]; ok {
+						values[k] = v
+						delete(keySet, k)
+						if len(keySet) == 0 {
+							return true
+						}
+					}
+				}
+			}
+			return false
+		})
+		return values
+	})
+}
+
+func walkAncestors(start *state, f func(*state) bool) {
+	stack := [][]*state{{start}}
+	cache := make(map[digest.Digest]struct{})
+	for len(stack) > 0 {
+		sts := stack[len(stack)-1]
+		if len(sts) == 0 {
+			stack = stack[:len(stack)-1]
+			continue
+		}
+		st := sts[len(sts)-1]
+		stack[len(stack)-1] = sts[:len(sts)-1]
+		if st == nil {
+			continue
+		}
+		if _, ok := cache[st.origDigest]; ok {
+			continue
+		}
+		cache[st.origDigest] = struct{}{}
+		if shouldStop := f(st); shouldStop {
+			return
+		}
+		stack = append(stack, []*state{})
+		for _, parentDgst := range st.clientVertex.Inputs {
+			st.solver.mu.RLock()
+			parent := st.solver.actives[parentDgst]
+			st.solver.mu.RUnlock()
+			if parent == nil {
+				logrus.Warnf("parent %q not found in active job list during cache opt search", parentDgst)
+				continue
+			}
+			stack[len(stack)-1] = append(stack[len(stack)-1], parent)
+		}
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/solver/cachestorage.go b/vendor/github.com/moby/buildkit/solver/cachestorage.go
index cc1e211..1279722 100644
--- a/vendor/github.com/moby/buildkit/solver/cachestorage.go
+++ b/vendor/github.com/moby/buildkit/solver/cachestorage.go
@@ -4,6 +4,7 @@
 	"context"
 	"time"
 
+	"github.com/moby/buildkit/session"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 )
@@ -46,6 +47,6 @@
 type CacheResultStorage interface {
 	Save(Result, time.Time) (CacheResult, error)
 	Load(ctx context.Context, res CacheResult) (Result, error)
-	LoadRemote(ctx context.Context, res CacheResult) (*Remote, error)
+	LoadRemote(ctx context.Context, res CacheResult, s session.Group) (*Remote, error)
 	Exists(id string) bool
 }
diff --git a/vendor/github.com/moby/buildkit/solver/edge.go b/vendor/github.com/moby/buildkit/solver/edge.go
index 52613ad..125c55f 100644
--- a/vendor/github.com/moby/buildkit/solver/edge.go
+++ b/vendor/github.com/moby/buildkit/solver/edge.go
@@ -76,8 +76,6 @@
 	edgeState
 	index             Index
 	keyMap            map[string]*CacheKey
-	desiredState      edgeStatusType
-	e                 *edge
 	slowCacheReq      pipe.Receiver
 	slowCacheComplete bool
 	slowCacheFoundKey bool
@@ -119,7 +117,7 @@
 // incrementReferenceCount increases the number of times release needs to be
 // called to release the edge. Called on merging edges.
 func (e *edge) incrementReferenceCount() {
-	e.releaserCount += 1
+	e.releaserCount++
 }
 
 // release releases the edge resources
@@ -225,6 +223,14 @@
 	return e.cacheMap.Deps[int(dep.index)].ComputeDigestFunc
 }
 
+// preprocessFunc returns result based cache func
+func (e *edge) preprocessFunc(dep *dep) PreprocessFunc {
+	if e.cacheMap == nil {
+		return nil
+	}
+	return e.cacheMap.Deps[int(dep.index)].PreprocessFunc
+}
+
 // allDepsHaveKeys checks if all dependencies have at least one key. used for
 // determining if there is enough data for combining cache key for edge
 func (e *edge) allDepsHaveKeys(matching bool) bool {
@@ -353,6 +359,7 @@
 	if e.execReq == nil {
 		if added := e.createInputRequests(desiredState, f, false); !added && !e.hasActiveOutgoing && !cacheMapReq {
 			logrus.Errorf("buildkit scheluding error: leaving incoming open. forcing solve. Please report this with BUILDKIT_SCHEDULER_DEBUG=1")
+			debugSchedulerPreUnpark(e, incoming, updates, allPipes)
 			e.createInputRequests(desiredState, f, true)
 		}
 	}
@@ -489,17 +496,20 @@
 					e.err = upt.Status().Err
 				}
 			} else if !dep.slowCacheComplete {
-				k := NewCacheKey(upt.Status().Value.(digest.Digest), -1)
-				dep.slowCacheKey = &ExportableCacheKey{CacheKey: k, Exporter: &exporter{k: k}}
-				slowKeyExp := CacheKeyWithSelector{CacheKey: *dep.slowCacheKey}
-				defKeys := make([]CacheKeyWithSelector, 0, len(dep.result.CacheKeys()))
-				for _, dk := range dep.result.CacheKeys() {
-					defKeys = append(defKeys, CacheKeyWithSelector{CacheKey: dk, Selector: e.cacheMap.Deps[i].Selector})
-				}
-				dep.slowCacheFoundKey = e.probeCache(dep, []CacheKeyWithSelector{slowKeyExp})
+				dgst := upt.Status().Value.(digest.Digest)
+				if e.cacheMap.Deps[int(dep.index)].ComputeDigestFunc != nil && dgst != "" {
+					k := NewCacheKey(dgst, -1)
+					dep.slowCacheKey = &ExportableCacheKey{CacheKey: k, Exporter: &exporter{k: k}}
+					slowKeyExp := CacheKeyWithSelector{CacheKey: *dep.slowCacheKey}
+					defKeys := make([]CacheKeyWithSelector, 0, len(dep.result.CacheKeys()))
+					for _, dk := range dep.result.CacheKeys() {
+						defKeys = append(defKeys, CacheKeyWithSelector{CacheKey: dk, Selector: e.cacheMap.Deps[i].Selector})
+					}
+					dep.slowCacheFoundKey = e.probeCache(dep, []CacheKeyWithSelector{slowKeyExp})
 
-				// connect def key to slow key
-				e.op.Cache().Query(append(defKeys, slowKeyExp), dep.index, e.cacheMap.Digest, e.edge.Index)
+					// connect def key to slow key
+					e.op.Cache().Query(append(defKeys, slowKeyExp), dep.index, e.cacheMap.Digest, e.edge.Index)
+				}
 
 				dep.slowCacheComplete = true
 				e.keysDidChange = true
@@ -585,7 +595,7 @@
 	stHigh := edgeStatusCacheSlow // maximum possible state
 	if e.cacheMap != nil {
 		for _, dep := range e.deps {
-			isSlowIncomplete := e.slowCacheFunc(dep) != nil && (dep.state == edgeStatusCacheSlow || (dep.state == edgeStatusComplete && !dep.slowCacheComplete))
+			isSlowIncomplete := (e.slowCacheFunc(dep) != nil || e.preprocessFunc(dep) != nil) && (dep.state == edgeStatusCacheSlow || (dep.state == edgeStatusComplete && !dep.slowCacheComplete))
 
 			if dep.state > stLow && len(dep.keyMap) == 0 && !isSlowIncomplete {
 				stLow = dep.state
@@ -806,15 +816,16 @@
 			}
 		}
 		// initialize function to compute cache key based on dependency result
-		if dep.state == edgeStatusComplete && dep.slowCacheReq == nil && e.slowCacheFunc(dep) != nil && e.cacheMap != nil {
+		if dep.state == edgeStatusComplete && dep.slowCacheReq == nil && (e.slowCacheFunc(dep) != nil || e.preprocessFunc(dep) != nil) && e.cacheMap != nil {
+			pfn := e.preprocessFunc(dep)
 			fn := e.slowCacheFunc(dep)
 			res := dep.result
-			func(fn ResultBasedCacheFunc, res Result, index Index) {
+			func(pfn PreprocessFunc, fn ResultBasedCacheFunc, res Result, index Index) {
 				dep.slowCacheReq = f.NewFuncRequest(func(ctx context.Context) (interface{}, error) {
-					v, err := e.op.CalcSlowCache(ctx, index, fn, res)
+					v, err := e.op.CalcSlowCache(ctx, index, pfn, fn, res)
 					return v, errors.Wrap(err, "failed to compute cache key")
 				})
-			}(fn, res, dep.index)
+			}(pfn, fn, res, dep.index)
 			addedNew = true
 		}
 	}
@@ -867,6 +878,7 @@
 	logrus.Debugf("load cache for %s with %s", e.edge.Vertex.Name(), rec.ID)
 	res, err := e.op.LoadCache(ctx, rec)
 	if err != nil {
+		logrus.Debugf("load cache for %s err: %v", e.edge.Vertex.Name(), err)
 		return nil, errors.Wrap(err, "failed to load cache")
 	}
 
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/context.go b/vendor/github.com/moby/buildkit/solver/errdefs/context.go
new file mode 100644
index 0000000..ea6bdfb
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/context.go
@@ -0,0 +1,13 @@
+package errdefs
+
+import (
+	"context"
+	"errors"
+
+	"github.com/moby/buildkit/util/grpcerrors"
+	"google.golang.org/grpc/codes"
+)
+
+func IsCanceled(err error) bool {
+	return errors.Is(err, context.Canceled) || grpcerrors.Code(err) == codes.Canceled
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go b/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go
index f179e99..5da34b6 100644
--- a/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go
@@ -105,25 +105,295 @@
 	return nil
 }
 
+type FrontendCap struct {
+	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *FrontendCap) Reset()         { *m = FrontendCap{} }
+func (m *FrontendCap) String() string { return proto.CompactTextString(m) }
+func (*FrontendCap) ProtoMessage()    {}
+func (*FrontendCap) Descriptor() ([]byte, []int) {
+	return fileDescriptor_689dc58a5060aff5, []int{2}
+}
+func (m *FrontendCap) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FrontendCap.Unmarshal(m, b)
+}
+func (m *FrontendCap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FrontendCap.Marshal(b, m, deterministic)
+}
+func (m *FrontendCap) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FrontendCap.Merge(m, src)
+}
+func (m *FrontendCap) XXX_Size() int {
+	return xxx_messageInfo_FrontendCap.Size(m)
+}
+func (m *FrontendCap) XXX_DiscardUnknown() {
+	xxx_messageInfo_FrontendCap.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FrontendCap proto.InternalMessageInfo
+
+func (m *FrontendCap) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+type Subrequest struct {
+	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *Subrequest) Reset()         { *m = Subrequest{} }
+func (m *Subrequest) String() string { return proto.CompactTextString(m) }
+func (*Subrequest) ProtoMessage()    {}
+func (*Subrequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_689dc58a5060aff5, []int{3}
+}
+func (m *Subrequest) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Subrequest.Unmarshal(m, b)
+}
+func (m *Subrequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Subrequest.Marshal(b, m, deterministic)
+}
+func (m *Subrequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Subrequest.Merge(m, src)
+}
+func (m *Subrequest) XXX_Size() int {
+	return xxx_messageInfo_Subrequest.Size(m)
+}
+func (m *Subrequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_Subrequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Subrequest proto.InternalMessageInfo
+
+func (m *Subrequest) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
+type Solve struct {
+	InputIDs []string `protobuf:"bytes,1,rep,name=inputIDs,proto3" json:"inputIDs,omitempty"`
+	MountIDs []string `protobuf:"bytes,2,rep,name=mountIDs,proto3" json:"mountIDs,omitempty"`
+	Op       *pb.Op   `protobuf:"bytes,3,opt,name=op,proto3" json:"op,omitempty"`
+	// Types that are valid to be assigned to Subject:
+	//	*Solve_File
+	//	*Solve_Cache
+	Subject              isSolve_Subject `protobuf_oneof:"subject"`
+	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
+	XXX_unrecognized     []byte          `json:"-"`
+	XXX_sizecache        int32           `json:"-"`
+}
+
+func (m *Solve) Reset()         { *m = Solve{} }
+func (m *Solve) String() string { return proto.CompactTextString(m) }
+func (*Solve) ProtoMessage()    {}
+func (*Solve) Descriptor() ([]byte, []int) {
+	return fileDescriptor_689dc58a5060aff5, []int{4}
+}
+func (m *Solve) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_Solve.Unmarshal(m, b)
+}
+func (m *Solve) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_Solve.Marshal(b, m, deterministic)
+}
+func (m *Solve) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_Solve.Merge(m, src)
+}
+func (m *Solve) XXX_Size() int {
+	return xxx_messageInfo_Solve.Size(m)
+}
+func (m *Solve) XXX_DiscardUnknown() {
+	xxx_messageInfo_Solve.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Solve proto.InternalMessageInfo
+
+type isSolve_Subject interface {
+	isSolve_Subject()
+}
+
+type Solve_File struct {
+	File *FileAction `protobuf:"bytes,4,opt,name=file,proto3,oneof" json:"file,omitempty"`
+}
+type Solve_Cache struct {
+	Cache *ContentCache `protobuf:"bytes,5,opt,name=cache,proto3,oneof" json:"cache,omitempty"`
+}
+
+func (*Solve_File) isSolve_Subject()  {}
+func (*Solve_Cache) isSolve_Subject() {}
+
+func (m *Solve) GetSubject() isSolve_Subject {
+	if m != nil {
+		return m.Subject
+	}
+	return nil
+}
+
+func (m *Solve) GetInputIDs() []string {
+	if m != nil {
+		return m.InputIDs
+	}
+	return nil
+}
+
+func (m *Solve) GetMountIDs() []string {
+	if m != nil {
+		return m.MountIDs
+	}
+	return nil
+}
+
+func (m *Solve) GetOp() *pb.Op {
+	if m != nil {
+		return m.Op
+	}
+	return nil
+}
+
+func (m *Solve) GetFile() *FileAction {
+	if x, ok := m.GetSubject().(*Solve_File); ok {
+		return x.File
+	}
+	return nil
+}
+
+func (m *Solve) GetCache() *ContentCache {
+	if x, ok := m.GetSubject().(*Solve_Cache); ok {
+		return x.Cache
+	}
+	return nil
+}
+
+// XXX_OneofWrappers is for the internal use of the proto package.
+func (*Solve) XXX_OneofWrappers() []interface{} {
+	return []interface{}{
+		(*Solve_File)(nil),
+		(*Solve_Cache)(nil),
+	}
+}
+
+type FileAction struct {
+	// Index of the file action that failed the exec.
+	Index                int64    `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *FileAction) Reset()         { *m = FileAction{} }
+func (m *FileAction) String() string { return proto.CompactTextString(m) }
+func (*FileAction) ProtoMessage()    {}
+func (*FileAction) Descriptor() ([]byte, []int) {
+	return fileDescriptor_689dc58a5060aff5, []int{5}
+}
+func (m *FileAction) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_FileAction.Unmarshal(m, b)
+}
+func (m *FileAction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_FileAction.Marshal(b, m, deterministic)
+}
+func (m *FileAction) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_FileAction.Merge(m, src)
+}
+func (m *FileAction) XXX_Size() int {
+	return xxx_messageInfo_FileAction.Size(m)
+}
+func (m *FileAction) XXX_DiscardUnknown() {
+	xxx_messageInfo_FileAction.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FileAction proto.InternalMessageInfo
+
+func (m *FileAction) GetIndex() int64 {
+	if m != nil {
+		return m.Index
+	}
+	return 0
+}
+
+type ContentCache struct {
+	// Original index of result that failed the slow cache calculation.
+	Index                int64    `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *ContentCache) Reset()         { *m = ContentCache{} }
+func (m *ContentCache) String() string { return proto.CompactTextString(m) }
+func (*ContentCache) ProtoMessage()    {}
+func (*ContentCache) Descriptor() ([]byte, []int) {
+	return fileDescriptor_689dc58a5060aff5, []int{6}
+}
+func (m *ContentCache) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_ContentCache.Unmarshal(m, b)
+}
+func (m *ContentCache) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_ContentCache.Marshal(b, m, deterministic)
+}
+func (m *ContentCache) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ContentCache.Merge(m, src)
+}
+func (m *ContentCache) XXX_Size() int {
+	return xxx_messageInfo_ContentCache.Size(m)
+}
+func (m *ContentCache) XXX_DiscardUnknown() {
+	xxx_messageInfo_ContentCache.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ContentCache proto.InternalMessageInfo
+
+func (m *ContentCache) GetIndex() int64 {
+	if m != nil {
+		return m.Index
+	}
+	return 0
+}
+
 func init() {
 	proto.RegisterType((*Vertex)(nil), "errdefs.Vertex")
 	proto.RegisterType((*Source)(nil), "errdefs.Source")
+	proto.RegisterType((*FrontendCap)(nil), "errdefs.FrontendCap")
+	proto.RegisterType((*Subrequest)(nil), "errdefs.Subrequest")
+	proto.RegisterType((*Solve)(nil), "errdefs.Solve")
+	proto.RegisterType((*FileAction)(nil), "errdefs.FileAction")
+	proto.RegisterType((*ContentCache)(nil), "errdefs.ContentCache")
 }
 
 func init() { proto.RegisterFile("errdefs.proto", fileDescriptor_689dc58a5060aff5) }
 
 var fileDescriptor_689dc58a5060aff5 = []byte{
-	// 177 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x2c, 0xcd, 0xc1, 0x8a, 0x83, 0x30,
-	0x10, 0x80, 0x61, 0xdc, 0x5d, 0xb2, 0x18, 0xd9, 0x3d, 0xe4, 0x50, 0xa4, 0x27, 0xeb, 0xc9, 0x43,
-	0x49, 0xc0, 0x3e, 0x45, 0x4f, 0x85, 0x14, 0x7a, 0x6f, 0x74, 0xb4, 0xa1, 0xea, 0x84, 0x49, 0x2c,
-	0xed, 0xdb, 0x17, 0x6d, 0x8e, 0xff, 0x7c, 0x33, 0x0c, 0xff, 0x03, 0xa2, 0x16, 0x3a, 0x2f, 0x1d,
-	0x61, 0x40, 0xf1, 0x1b, 0x73, 0xbb, 0xef, 0x6d, 0xb8, 0xcd, 0x46, 0x36, 0x38, 0xaa, 0x11, 0xcd,
-	0x4b, 0x99, 0xd9, 0x0e, 0xed, 0xdd, 0x06, 0xe5, 0x71, 0x78, 0x00, 0x29, 0x67, 0x14, 0xba, 0x78,
-	0x56, 0x16, 0x9c, 0x5d, 0x80, 0x02, 0x3c, 0xc5, 0x86, 0xb3, 0xd6, 0xf6, 0xe0, 0x43, 0x9e, 0x14,
-	0x49, 0x95, 0xea, 0x58, 0xe5, 0x89, 0xb3, 0x33, 0xce, 0xd4, 0x80, 0x28, 0xf9, 0x8f, 0x9d, 0x3a,
-	0x5c, 0x3d, 0xab, 0xff, 0xa5, 0x33, 0xf2, 0x23, 0xc7, 0xa9, 0x43, 0xbd, 0x9a, 0xd8, 0x71, 0x46,
-	0xd7, 0xa9, 0x07, 0x9f, 0x7f, 0x15, 0xdf, 0x55, 0x56, 0xa7, 0xcb, 0x96, 0x5e, 0x26, 0x3a, 0x82,
-	0x61, 0xeb, 0xe7, 0xc3, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x93, 0xb5, 0x8b, 0x2a, 0xc1, 0x00, 0x00,
-	0x00,
+	// 348 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xcd, 0x8e, 0xd3, 0x30,
+	0x14, 0x85, 0x27, 0xbf, 0x43, 0x6e, 0x81, 0x85, 0x81, 0x51, 0x34, 0xab, 0x8c, 0xc5, 0xa2, 0x48,
+	0x90, 0x48, 0xc3, 0x13, 0x40, 0xd1, 0x68, 0x66, 0x55, 0xc9, 0x95, 0xd8, 0xc7, 0xc9, 0x4d, 0x6b,
+	0x48, 0x6c, 0xe3, 0xd8, 0xa8, 0xbc, 0x1b, 0x0f, 0x87, 0xe2, 0xa4, 0x65, 0x16, 0xdd, 0xe5, 0xe4,
+	0xfb, 0x7c, 0xed, 0x63, 0xc3, 0x2b, 0x34, 0xa6, 0xc5, 0x6e, 0x2c, 0xb5, 0x51, 0x56, 0x91, 0xeb,
+	0x25, 0xde, 0x7e, 0xdc, 0x0b, 0x7b, 0x70, 0xbc, 0x6c, 0xd4, 0x50, 0x0d, 0x8a, 0xff, 0xa9, 0xb8,
+	0x13, 0x7d, 0xfb, 0x53, 0xd8, 0x6a, 0x54, 0xfd, 0x6f, 0x34, 0x95, 0xe6, 0x95, 0xd2, 0xcb, 0x32,
+	0x5a, 0x40, 0xfa, 0x1d, 0x8d, 0xc5, 0x23, 0xb9, 0x81, 0xb4, 0x15, 0x7b, 0x1c, 0x6d, 0x1e, 0x14,
+	0xc1, 0x3a, 0x63, 0x4b, 0xa2, 0x5b, 0x48, 0x77, 0xca, 0x99, 0x06, 0x09, 0x85, 0x58, 0xc8, 0x4e,
+	0x79, 0xbe, 0xba, 0x7f, 0x5d, 0x6a, 0x5e, 0xce, 0xe4, 0x49, 0x76, 0x8a, 0x79, 0x46, 0xee, 0x20,
+	0x35, 0xb5, 0xdc, 0xe3, 0x98, 0x87, 0x45, 0xb4, 0x5e, 0xdd, 0x67, 0x93, 0xc5, 0xa6, 0x3f, 0x6c,
+	0x01, 0xf4, 0x0e, 0x56, 0x0f, 0x46, 0x49, 0x8b, 0xb2, 0xdd, 0xd4, 0x9a, 0x10, 0x88, 0x65, 0x3d,
+	0xe0, 0xb2, 0xab, 0xff, 0xa6, 0x05, 0xc0, 0xce, 0x71, 0x83, 0xbf, 0x1c, 0x8e, 0xf6, 0xa2, 0xf1,
+	0x37, 0x80, 0x64, 0x37, 0xf5, 0x21, 0xb7, 0xf0, 0x42, 0x48, 0xed, 0xec, 0xd3, 0xb7, 0x31, 0x0f,
+	0x8a, 0x68, 0x9d, 0xb1, 0x73, 0x9e, 0xd8, 0xa0, 0x9c, 0xf4, 0x2c, 0x9c, 0xd9, 0x29, 0x93, 0x1b,
+	0x08, 0x95, 0xce, 0x23, 0xdf, 0x25, 0x9d, 0x4e, 0xb9, 0xd5, 0x2c, 0x54, 0x9a, 0x7c, 0x80, 0xb8,
+	0x13, 0x3d, 0xe6, 0xb1, 0x27, 0x6f, 0xca, 0xd3, 0x35, 0x3f, 0x88, 0x1e, 0xbf, 0x34, 0x56, 0x28,
+	0xf9, 0x78, 0xc5, 0xbc, 0x42, 0x3e, 0x41, 0xd2, 0xd4, 0xcd, 0x01, 0xf3, 0xc4, 0xbb, 0xef, 0xce,
+	0xee, 0xc6, 0xd7, 0xb3, 0x9b, 0x09, 0x3e, 0x5e, 0xb1, 0xd9, 0xfa, 0x9a, 0xc1, 0xf5, 0xe8, 0xf8,
+	0x0f, 0x6c, 0x2c, 0xa5, 0x00, 0xff, 0xe7, 0x91, 0xb7, 0x90, 0x08, 0xd9, 0xe2, 0xd1, 0x37, 0x8c,
+	0xd8, 0x1c, 0xe8, 0x7b, 0x78, 0xf9, 0x7c, 0xce, 0x65, 0x8b, 0xa7, 0xfe, 0x1d, 0x3f, 0xff, 0x0b,
+	0x00, 0x00, 0xff, 0xff, 0x1e, 0xfa, 0x9c, 0x6f, 0x0f, 0x02, 0x00, 0x00,
 }
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.proto b/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.proto
index 7e808cb..d4b9177 100644
--- a/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.proto
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.proto
@@ -12,3 +12,32 @@
 	pb.SourceInfo info = 1;
 	repeated pb.Range ranges = 2;
 }
+
+message FrontendCap {
+	string name = 1;
+}
+
+message Subrequest {
+	string name = 1;
+}
+
+message Solve {
+	repeated string inputIDs = 1;
+	repeated string mountIDs = 2;
+	pb.Op op = 3;
+
+	oneof subject {
+		FileAction file = 4;
+		ContentCache cache = 5;
+	}
+}
+
+message FileAction {
+	// Index of the file action that failed the exec.
+	int64 index = 1;
+}
+
+message ContentCache {
+	// Original index of result that failed the slow cache calculation.
+	int64 index = 1;
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/exit.go b/vendor/github.com/moby/buildkit/solver/errdefs/exit.go
new file mode 100644
index 0000000..696fe25
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/exit.go
@@ -0,0 +1,34 @@
+package errdefs
+
+import "fmt"
+
+const (
+	// ContainerdUnknownExitStatus is returned when containerd is unable to
+	// determine the exit status of a process. This can happen if the process never starts
+	// or if an error was encountered when obtaining the exit status, it is set to 255.
+	//
+	// This const is defined here to prevent importing github.com/containerd/containerd
+	// and corresponds with https://github.com/containerd/containerd/blob/40b22ef0741028917761d8c5d5d29e0d19038836/task.go#L52-L55
+	ContainerdUnknownExitStatus = 255
+)
+
+// ExitError will be returned when the container process exits with a non-zero
+// exit code.
+type ExitError struct {
+	ExitCode uint32
+	Err      error
+}
+
+func (err *ExitError) Error() string {
+	if err.Err != nil {
+		return err.Err.Error()
+	}
+	return fmt.Sprintf("exit code: %d", err.ExitCode)
+}
+
+func (err *ExitError) Unwrap() error {
+	if err.Err == nil {
+		return fmt.Errorf("exit code: %d", err.ExitCode)
+	}
+	return err.Err
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/fronetendcap.go b/vendor/github.com/moby/buildkit/solver/errdefs/fronetendcap.go
new file mode 100644
index 0000000..e8af9ff
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/fronetendcap.go
@@ -0,0 +1,41 @@
+package errdefs
+
+import (
+	fmt "fmt"
+
+	"github.com/containerd/typeurl"
+	"github.com/moby/buildkit/util/grpcerrors"
+)
+
+func init() {
+	typeurl.Register((*FrontendCap)(nil), "github.com/moby/buildkit", "errdefs.FrontendCap+json")
+}
+
+type UnsupportedFrontendCapError struct {
+	FrontendCap
+	error
+}
+
+func (e *UnsupportedFrontendCapError) Error() string {
+	msg := fmt.Sprintf("unsupported frontend capability %s", e.FrontendCap.Name)
+	if e.error != nil {
+		msg += ": " + e.error.Error()
+	}
+	return msg
+}
+
+func (e *UnsupportedFrontendCapError) Unwrap() error {
+	return e.error
+}
+
+func (e *UnsupportedFrontendCapError) ToProto() grpcerrors.TypedErrorProto {
+	return &e.FrontendCap
+}
+
+func NewUnsupportedFrontendCapError(name string) error {
+	return &UnsupportedFrontendCapError{FrontendCap: FrontendCap{Name: name}}
+}
+
+func (v *FrontendCap) WrapError(err error) error {
+	return &UnsupportedFrontendCapError{error: err, FrontendCap: *v}
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/op.go b/vendor/github.com/moby/buildkit/solver/errdefs/op.go
new file mode 100644
index 0000000..61068b6
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/op.go
@@ -0,0 +1,20 @@
+package errdefs
+
+import "github.com/moby/buildkit/solver/pb"
+
+type OpError struct {
+	error
+	Op *pb.Op
+}
+
+func (e *OpError) Unwrap() error {
+	return e.error
+}
+
+func WithOp(err error, iface interface{}) error {
+	op, ok := iface.(*pb.Op)
+	if err == nil || !ok {
+		return err
+	}
+	return &OpError{error: err, Op: op}
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/solve.go b/vendor/github.com/moby/buildkit/solver/errdefs/solve.go
new file mode 100644
index 0000000..97ce5a3
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/solve.go
@@ -0,0 +1,74 @@
+package errdefs
+
+import (
+	"bytes"
+	"errors"
+
+	"github.com/containerd/typeurl"
+	"github.com/golang/protobuf/jsonpb"
+	"github.com/moby/buildkit/solver/pb"
+	"github.com/moby/buildkit/util/grpcerrors"
+)
+
+func init() {
+	typeurl.Register((*Solve)(nil), "github.com/moby/buildkit", "errdefs.Solve+json")
+}
+
+//nolint:golint
+type IsSolve_Subject isSolve_Subject
+
+// SolveError will be returned when an error is encountered during a solve that
+// has an exec op.
+type SolveError struct {
+	Solve
+	Err error
+}
+
+func (e *SolveError) Error() string {
+	return e.Err.Error()
+}
+
+func (e *SolveError) Unwrap() error {
+	return e.Err
+}
+
+func (e *SolveError) ToProto() grpcerrors.TypedErrorProto {
+	return &e.Solve
+}
+
+func WithSolveError(err error, subject IsSolve_Subject, inputIDs, mountIDs []string) error {
+	if err == nil {
+		return nil
+	}
+	var (
+		oe *OpError
+		op *pb.Op
+	)
+	if errors.As(err, &oe) {
+		op = oe.Op
+	}
+	return &SolveError{
+		Err: err,
+		Solve: Solve{
+			InputIDs: inputIDs,
+			MountIDs: mountIDs,
+			Op:       op,
+			Subject:  subject,
+		},
+	}
+}
+
+func (v *Solve) WrapError(err error) error {
+	return &SolveError{Err: err, Solve: *v}
+}
+
+func (v *Solve) MarshalJSON() ([]byte, error) {
+	m := jsonpb.Marshaler{}
+	buf := new(bytes.Buffer)
+	err := m.Marshal(buf, v)
+	return buf.Bytes(), err
+}
+
+func (v *Solve) UnmarshalJSON(b []byte) error {
+	return jsonpb.Unmarshal(bytes.NewReader(b), v)
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/subrequest.go b/vendor/github.com/moby/buildkit/solver/errdefs/subrequest.go
new file mode 100644
index 0000000..b30eab3
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/subrequest.go
@@ -0,0 +1,41 @@
+package errdefs
+
+import (
+	fmt "fmt"
+
+	"github.com/containerd/typeurl"
+	"github.com/moby/buildkit/util/grpcerrors"
+)
+
+func init() {
+	typeurl.Register((*Subrequest)(nil), "github.com/moby/buildkit", "errdefs.Subrequest+json")
+}
+
+type UnsupportedSubrequestError struct {
+	Subrequest
+	error
+}
+
+func (e *UnsupportedSubrequestError) Error() string {
+	msg := fmt.Sprintf("unsupported request %s", e.Subrequest.Name)
+	if e.error != nil {
+		msg += ": " + e.error.Error()
+	}
+	return msg
+}
+
+func (e *UnsupportedSubrequestError) Unwrap() error {
+	return e.error
+}
+
+func (e *UnsupportedSubrequestError) ToProto() grpcerrors.TypedErrorProto {
+	return &e.Subrequest
+}
+
+func NewUnsupportedSubrequestError(name string) error {
+	return &UnsupportedSubrequestError{Subrequest: Subrequest{Name: name}}
+}
+
+func (v *Subrequest) WrapError(err error) error {
+	return &UnsupportedSubrequestError{error: err, Subrequest: *v}
+}
diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/vertex.go b/vendor/github.com/moby/buildkit/solver/errdefs/vertex.go
index 71fdb6c..4ec3751 100644
--- a/vendor/github.com/moby/buildkit/solver/errdefs/vertex.go
+++ b/vendor/github.com/moby/buildkit/solver/errdefs/vertex.go
@@ -1,14 +1,14 @@
 package errdefs
 
 import (
-	proto "github.com/golang/protobuf/proto"
+	"github.com/containerd/typeurl"
 	"github.com/moby/buildkit/util/grpcerrors"
 	digest "github.com/opencontainers/go-digest"
 )
 
 func init() {
-	proto.RegisterType((*Vertex)(nil), "errdefs.Vertex")
-	proto.RegisterType((*Source)(nil), "errdefs.Source")
+	typeurl.Register((*Vertex)(nil), "github.com/moby/buildkit", "errdefs.Vertex+json")
+	typeurl.Register((*Source)(nil), "github.com/moby/buildkit", "errdefs.Source+json")
 }
 
 type VertexError struct {
diff --git a/vendor/github.com/moby/buildkit/solver/exporter.go b/vendor/github.com/moby/buildkit/solver/exporter.go
index 6a07396..26ca2fb 100644
--- a/vendor/github.com/moby/buildkit/solver/exporter.go
+++ b/vendor/github.com/moby/buildkit/solver/exporter.go
@@ -100,7 +100,7 @@
 			return nil, err
 		}
 
-		remote, err = cm.results.LoadRemote(ctx, res)
+		remote, err = cm.results.LoadRemote(ctx, res, opt.Session)
 		if err != nil {
 			return nil, err
 		}
diff --git a/vendor/github.com/moby/buildkit/solver/index.go b/vendor/github.com/moby/buildkit/solver/index.go
index 78a2cca..4a33066 100644
--- a/vendor/github.com/moby/buildkit/solver/index.go
+++ b/vendor/github.com/moby/buildkit/solver/index.go
@@ -121,14 +121,14 @@
 }
 
 // enforceLinked adds links from current ID to all dep keys
-func (er *edgeIndex) enforceLinked(id string, k *CacheKey) {
-	main, ok := er.items[id]
+func (ei *edgeIndex) enforceLinked(id string, k *CacheKey) {
+	main, ok := ei.items[id]
 	if !ok {
 		main = &indexItem{
 			links: map[CacheInfoLink]map[string]struct{}{},
 			deps:  map[string]struct{}{},
 		}
-		er.items[id] = main
+		ei.items[id] = main
 	}
 
 	deps := k.Deps()
@@ -136,10 +136,10 @@
 	for i, dd := range deps {
 		for _, d := range dd {
 			ck := d.CacheKey.CacheKey
-			er.enforceIndexID(ck)
+			ei.enforceIndexID(ck)
 			ll := CacheInfoLink{Input: Index(i), Digest: k.Digest(), Output: k.Output(), Selector: d.Selector}
 			for _, ckID := range ck.indexIDs {
-				if item, ok := er.items[ckID]; ok {
+				if item, ok := ei.items[ckID]; ok {
 					links, ok := item.links[ll]
 					if !ok {
 						links = map[string]struct{}{}
diff --git a/vendor/github.com/moby/buildkit/solver/jobs.go b/vendor/github.com/moby/buildkit/solver/jobs.go
index 182a6d0..67f1a30 100644
--- a/vendor/github.com/moby/buildkit/solver/jobs.go
+++ b/vendor/github.com/moby/buildkit/solver/jobs.go
@@ -230,6 +230,7 @@
 	pw     progress.Writer
 	span   opentracing.Span
 	values sync.Map
+	id     string
 
 	progressCloser func()
 	SessionID      string
@@ -267,6 +268,17 @@
 	st.setEdge(e.Index, newEdge)
 }
 
+func (jl *Solver) getState(e Edge) *state {
+	jl.mu.RLock()
+	defer jl.mu.RUnlock()
+
+	st, ok := jl.actives[e.Vertex.Digest()]
+	if !ok {
+		return nil
+	}
+	return st
+}
+
 func (jl *Solver) getEdge(e Edge) *edge {
 	jl.mu.RLock()
 	defer jl.mu.RUnlock()
@@ -429,6 +441,7 @@
 		pw:             pw,
 		progressCloser: progressCloser,
 		span:           (&opentracing.NoopTracer{}).StartSpan(""),
+		id:             id,
 	}
 	jl.jobs[id] = j
 
@@ -513,6 +526,8 @@
 		}
 		st.mu.Unlock()
 	}
+
+	delete(j.list.jobs, j.id)
 	return nil
 }
 
@@ -543,7 +558,7 @@
 	Exec(ctx context.Context, inputs []Result) (outputs []Result, exporters []ExportableCacheKey, err error)
 	IgnoreCache() bool
 	Cache() CacheManager
-	CalcSlowCache(context.Context, Index, ResultBasedCacheFunc, Result) (digest.Digest, error)
+	CalcSlowCache(context.Context, Index, PreprocessFunc, ResultBasedCacheFunc, Result) (digest.Digest, error)
 }
 
 func newSharedOp(resolver ResolveOpFunc, cacheManager CacheManager, st *state) *sharedOp {
@@ -596,20 +611,24 @@
 	// no cache hit. start evaluating the node
 	span, ctx := tracing.StartSpan(ctx, "load cache: "+s.st.vtx.Name())
 	notifyStarted(ctx, &s.st.clientVertex, true)
-	res, err := s.Cache().Load(ctx, rec)
+	res, err := s.Cache().Load(withAncestorCacheOpts(ctx, s.st), rec)
 	tracing.FinishWithError(span, err)
 	notifyCompleted(ctx, &s.st.clientVertex, err, true)
 	return res, err
 }
 
-func (s *sharedOp) CalcSlowCache(ctx context.Context, index Index, f ResultBasedCacheFunc, res Result) (dgst digest.Digest, err error) {
+// CalcSlowCache computes the digest of an input that is ready and has been
+// evaluated, hence "slow" cache.
+func (s *sharedOp) CalcSlowCache(ctx context.Context, index Index, p PreprocessFunc, f ResultBasedCacheFunc, res Result) (dgst digest.Digest, err error) {
 	defer func() {
+		err = WrapSlowCache(err, index, NewSharedResult(res).Clone())
+		err = errdefs.WithOp(err, s.st.vtx.Sys())
 		err = errdefs.WrapVertex(err, s.st.origDigest)
 	}()
 	key, err := s.g.Do(ctx, fmt.Sprintf("slow-compute-%d", index), func(ctx context.Context) (interface{}, error) {
 		s.slowMu.Lock()
 		// TODO: add helpers for these stored values
-		if res := s.slowCacheRes[index]; res != "" {
+		if res, ok := s.slowCacheRes[index]; ok {
 			s.slowMu.Unlock()
 			return res, nil
 		}
@@ -618,14 +637,29 @@
 			return err, nil
 		}
 		s.slowMu.Unlock()
-		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
-		key, err := f(ctx, res)
+
 		complete := true
+		if p != nil {
+			st := s.st.solver.getState(s.st.vtx.Inputs()[index])
+			ctx2 := opentracing.ContextWithSpan(progress.WithProgress(ctx, st.mpw), st.mspan)
+			err = p(ctx2, res, st)
+			if err != nil {
+				f = nil
+				ctx = ctx2
+			}
+		}
+
+		var key digest.Digest
+		if f != nil {
+			ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
+			key, err = f(withAncestorCacheOpts(ctx, s.st), res, s.st)
+		}
 		if err != nil {
 			select {
 			case <-ctx.Done():
 				if strings.Contains(err.Error(), context.Canceled.Error()) {
 					complete = false
+					releaseError(err)
 					err = errors.Wrap(ctx.Err(), err.Error())
 				}
 			default:
@@ -652,6 +686,7 @@
 
 func (s *sharedOp) CacheMap(ctx context.Context, index int) (resp *cacheMapResp, err error) {
 	defer func() {
+		err = errdefs.WithOp(err, s.st.vtx.Sys())
 		err = errdefs.WrapVertex(err, s.st.origDigest)
 	}()
 	op, err := s.getOp()
@@ -666,6 +701,7 @@
 			return nil, s.cacheErr
 		}
 		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
+		ctx = withAncestorCacheOpts(ctx, s.st)
 		if len(s.st.vtx.Inputs()) == 0 {
 			// no cache hit. start evaluating the node
 			span, ctx := tracing.StartSpan(ctx, "cache request: "+s.st.vtx.Name())
@@ -682,6 +718,7 @@
 			case <-ctx.Done():
 				if strings.Contains(err.Error(), context.Canceled.Error()) {
 					complete = false
+					releaseError(err)
 					err = errors.Wrap(ctx.Err(), err.Error())
 				}
 			default:
@@ -709,6 +746,7 @@
 
 func (s *sharedOp) Exec(ctx context.Context, inputs []Result) (outputs []Result, exporters []ExportableCacheKey, err error) {
 	defer func() {
+		err = errdefs.WithOp(err, s.st.vtx.Sys())
 		err = errdefs.WrapVertex(err, s.st.origDigest)
 	}()
 	op, err := s.getOp()
@@ -721,6 +759,7 @@
 		}
 
 		ctx = opentracing.ContextWithSpan(progress.WithProgress(ctx, s.st.mpw), s.st.mspan)
+		ctx = withAncestorCacheOpts(ctx, s.st)
 
 		// no cache hit. start evaluating the node
 		span, ctx := tracing.StartSpan(ctx, s.st.vtx.Name())
@@ -737,6 +776,7 @@
 			case <-ctx.Done():
 				if strings.Contains(err.Error(), context.Canceled.Error()) {
 					complete = false
+					releaseError(err)
 					err = errors.Wrap(ctx.Err(), err.Error())
 				}
 			default:
@@ -849,3 +889,40 @@
 	}
 	pw.Write(v.Digest.String(), *v)
 }
+
+type SlowCacheError struct {
+	error
+	Index  Index
+	Result Result
+}
+
+func (e *SlowCacheError) Unwrap() error {
+	return e.error
+}
+
+func (e *SlowCacheError) ToSubject() errdefs.IsSolve_Subject {
+	return &errdefs.Solve_Cache{
+		Cache: &errdefs.ContentCache{
+			Index: int64(e.Index),
+		},
+	}
+}
+
+func WrapSlowCache(err error, index Index, res Result) error {
+	if err == nil {
+		return nil
+	}
+	return &SlowCacheError{Index: index, Result: res, error: err}
+}
+
+func releaseError(err error) {
+	if err == nil {
+		return
+	}
+	if re, ok := err.(interface {
+		Release() error
+	}); ok {
+		re.Release()
+	}
+	releaseError(errors.Unwrap(err))
+}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go
index d08d061..e6a5850 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go
@@ -9,18 +9,16 @@
 
 	"github.com/containerd/containerd/platforms"
 	"github.com/mitchellh/hashstructure"
-	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/cache/remotecache"
 	"github.com/moby/buildkit/client/llb"
-	"github.com/moby/buildkit/executor"
 	"github.com/moby/buildkit/frontend"
 	gw "github.com/moby/buildkit/frontend/gateway/client"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/solver/errdefs"
+	llberrdefs "github.com/moby/buildkit/solver/llbsolver/errdefs"
 	"github.com/moby/buildkit/solver/pb"
 	"github.com/moby/buildkit/util/flightcontrol"
-	"github.com/moby/buildkit/util/tracing"
 	"github.com/moby/buildkit/worker"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
@@ -126,12 +124,16 @@
 
 	if req.Definition != nil && req.Definition.Def != nil {
 		res = &frontend.Result{Ref: newResultProxy(b, req)}
+		if req.Evaluate {
+			_, err := res.Ref.Result(ctx)
+			return res, err
+		}
 	} else if req.Frontend != "" {
 		f, ok := b.frontends[req.Frontend]
 		if !ok {
 			return nil, errors.Errorf("invalid frontend: %s", req.Frontend)
 		}
-		res, err = f.Solve(ctx, b, req.FrontendOpt, req.FrontendInputs, sid)
+		res, err = f.Solve(ctx, b, req.FrontendOpt, req.FrontendInputs, sid, b.sm)
 		if err != nil {
 			return nil, errors.Wrapf(err, "failed to solve with frontend %s", req.Frontend)
 		}
@@ -143,41 +145,60 @@
 }
 
 type resultProxy struct {
-	cb       func(context.Context) (solver.CachedResult, error)
-	def      *pb.Definition
-	g        flightcontrol.Group
-	mu       sync.Mutex
-	released bool
-	v        solver.CachedResult
-	err      error
+	cb         func(context.Context) (solver.CachedResult, error)
+	def        *pb.Definition
+	g          flightcontrol.Group
+	mu         sync.Mutex
+	released   bool
+	v          solver.CachedResult
+	err        error
+	errResults []solver.Result
 }
 
 func newResultProxy(b *llbBridge, req frontend.SolveRequest) *resultProxy {
-	return &resultProxy{
+	rp := &resultProxy{
 		def: req.Definition,
-		cb: func(ctx context.Context) (solver.CachedResult, error) {
-			return b.loadResult(ctx, req.Definition, req.CacheImports)
-		},
 	}
+	rp.cb = func(ctx context.Context) (solver.CachedResult, error) {
+		res, err := b.loadResult(ctx, req.Definition, req.CacheImports)
+		var ee *llberrdefs.ExecError
+		if errors.As(err, &ee) {
+			ee.EachRef(func(res solver.Result) error {
+				rp.errResults = append(rp.errResults, res)
+				return nil
+			})
+			// acquire ownership so ExecError finalizer doesn't attempt to release as well
+			ee.OwnerBorrowed = true
+		}
+		return res, err
+	}
+	return rp
 }
 
 func (rp *resultProxy) Definition() *pb.Definition {
 	return rp.def
 }
 
-func (rp *resultProxy) Release(ctx context.Context) error {
+func (rp *resultProxy) Release(ctx context.Context) (err error) {
 	rp.mu.Lock()
 	defer rp.mu.Unlock()
+	for _, res := range rp.errResults {
+		rerr := res.Release(ctx)
+		if rerr != nil {
+			err = rerr
+		}
+	}
 	if rp.v != nil {
 		if rp.released {
 			logrus.Warnf("release of already released result")
 		}
-		if err := rp.v.Release(ctx); err != nil {
-			return err
+		rerr := rp.v.Release(ctx)
+		if err != nil {
+			return rerr
 		}
 	}
 	rp.released = true
-	return nil
+	return
 }
 
 func (rp *resultProxy) wrapError(err error) error {
@@ -245,30 +266,8 @@
 	return nil, err
 }
 
-func (s *llbBridge) Run(ctx context.Context, id string, root cache.Mountable, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
-	w, err := s.resolveWorker()
-	if err != nil {
-		return err
-	}
-	span, ctx := tracing.StartSpan(ctx, strings.Join(process.Meta.Args, " "))
-	err = w.Executor().Run(ctx, id, root, mounts, process, started)
-	tracing.FinishWithError(span, err)
-	return err
-}
-
-func (s *llbBridge) Exec(ctx context.Context, id string, process executor.ProcessInfo) (err error) {
-	w, err := s.resolveWorker()
-	if err != nil {
-		return err
-	}
-	span, ctx := tracing.StartSpan(ctx, strings.Join(process.Meta.Args, " "))
-	err = w.Executor().Exec(ctx, id, process)
-	tracing.FinishWithError(span, err)
-	return err
-}
-
-func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (dgst digest.Digest, config []byte, err error) {
-	w, err := s.resolveWorker()
+func (b *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (dgst digest.Digest, config []byte, err error) {
+	w, err := b.resolveWorker()
 	if err != nil {
 		return "", nil, err
 	}
@@ -281,8 +280,8 @@
 	} else {
 		id += platforms.Format(*platform)
 	}
-	err = inBuilderContext(ctx, s.builder, opt.LogName, id, func(ctx context.Context, g session.Group) error {
-		dgst, config, err = w.ResolveImageConfig(ctx, ref, opt, s.sm, g)
+	err = inBuilderContext(ctx, b.builder, opt.LogName, id, func(ctx context.Context, g session.Group) error {
+		dgst, config, err = w.ResolveImageConfig(ctx, ref, opt, b.sm, g)
 		return err
 	})
 	return dgst, config, err
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/errdefs/exec.go b/vendor/github.com/moby/buildkit/solver/llbsolver/errdefs/exec.go
new file mode 100644
index 0000000..f607571
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/errdefs/exec.go
@@ -0,0 +1,74 @@
+package errdefs
+
+import (
+	"context"
+	"runtime"
+
+	"github.com/moby/buildkit/solver"
+	"github.com/sirupsen/logrus"
+)
+
+// ExecError will be returned when an error is encountered when evaluating an op.
+type ExecError struct {
+	error
+	Inputs        []solver.Result
+	Mounts        []solver.Result
+	OwnerBorrowed bool
+}
+
+func (e *ExecError) Unwrap() error {
+	return e.error
+}
+
+func (e *ExecError) EachRef(fn func(solver.Result) error) (err error) {
+	for _, res := range e.Inputs {
+		if res == nil {
+			continue
+		}
+		if err1 := fn(res); err1 != nil && err == nil {
+			err = err1
+		}
+	}
+	for _, res := range e.Mounts {
+		if res == nil {
+			continue
+		}
+		if err1 := fn(res); err1 != nil && err == nil {
+			err = err1
+		}
+	}
+	return err
+}
+
+func (e *ExecError) Release() error {
+	if e.OwnerBorrowed {
+		return nil
+	}
+	err := e.EachRef(func(r solver.Result) error {
+		r.Release(context.TODO())
+		return nil
+	})
+	e.OwnerBorrowed = true
+	return err
+}
+
+func WithExecError(err error, inputs, mounts []solver.Result) error {
+	if err == nil {
+		return nil
+	}
+	ee := &ExecError{
+		error:  err,
+		Inputs: inputs,
+		Mounts: mounts,
+	}
+	runtime.SetFinalizer(ee, func(e *ExecError) {
+		if !e.OwnerBorrowed {
+			e.EachRef(func(r solver.Result) error {
+				logrus.Warn("leaked execError detected and released")
+				r.Release(context.TODO())
+				return nil
+			})
+		}
+	})
+	return ee
+}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/errdefs/file.go b/vendor/github.com/moby/buildkit/solver/llbsolver/errdefs/file.go
new file mode 100644
index 0000000..cef5397
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/errdefs/file.go
@@ -0,0 +1,34 @@
+package errdefs
+
+import (
+	serrdefs "github.com/moby/buildkit/solver/errdefs"
+)
+
+// FileActionError will be returned when an error is encountered when solving
+// a fileop.
+type FileActionError struct {
+	error
+	Index int
+}
+
+func (e *FileActionError) Unwrap() error {
+	return e.error
+}
+
+func (e *FileActionError) ToSubject() serrdefs.IsSolve_Subject {
+	return &serrdefs.Solve_File{
+		File: &serrdefs.FileAction{
+			Index: int64(e.Index),
+		},
+	}
+}
+
+func WithFileActionError(err error, idx int) error {
+	if err == nil {
+		return nil
+	}
+	return &FileActionError{
+		error: err,
+		Index: idx,
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go b/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go
index a690012..8ecf648 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go
@@ -37,13 +37,13 @@
 				// non-nil old is already mapped
 				if idmap != nil {
 					identity, err := idmap.ToHost(idtools.Identity{
-						UID: old.Uid,
-						GID: old.Gid,
+						UID: old.UID,
+						GID: old.GID,
 					})
 					if err != nil {
 						return nil, err
 					}
-					return &copy.User{Uid: identity.UID, Gid: identity.GID}, nil
+					return &copy.User{UID: identity.UID, GID: identity.GID}, nil
 				}
 			}
 			return old, nil
@@ -52,14 +52,14 @@
 	u := *user
 	if idmap != nil {
 		identity, err := idmap.ToHost(idtools.Identity{
-			UID: user.Uid,
-			GID: user.Gid,
+			UID: user.UID,
+			GID: user.GID,
 		})
 		if err != nil {
 			return nil, err
 		}
-		u.Uid = identity.UID
-		u.Gid = identity.GID
+		u.UID = identity.UID
+		u.GID = identity.GID
 	}
 	return func(*copy.User) (*copy.User, error) {
 		return &u, nil
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/file/refmanager.go b/vendor/github.com/moby/buildkit/solver/llbsolver/file/refmanager.go
index faa4cdb..926c461 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/file/refmanager.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/file/refmanager.go
@@ -4,6 +4,7 @@
 	"context"
 
 	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes"
 	"github.com/pkg/errors"
@@ -17,29 +18,29 @@
 	cm cache.Manager
 }
 
-func (rm *RefManager) Prepare(ctx context.Context, ref fileoptypes.Ref, readonly bool) (fileoptypes.Mount, error) {
+func (rm *RefManager) Prepare(ctx context.Context, ref fileoptypes.Ref, readonly bool, g session.Group) (fileoptypes.Mount, error) {
 	ir, ok := ref.(cache.ImmutableRef)
 	if !ok && ref != nil {
 		return nil, errors.Errorf("invalid ref type: %T", ref)
 	}
 
 	if ir != nil && readonly {
-		m, err := ir.Mount(ctx, readonly)
+		m, err := ir.Mount(ctx, readonly, g)
 		if err != nil {
 			return nil, err
 		}
-		return &Mount{m: m}, nil
+		return &Mount{m: m, readonly: readonly}, nil
 	}
 
-	mr, err := rm.cm.New(ctx, ir, cache.WithDescription("fileop target"), cache.CachePolicyRetain)
+	mr, err := rm.cm.New(ctx, ir, g, cache.WithDescription("fileop target"), cache.CachePolicyRetain)
 	if err != nil {
 		return nil, err
 	}
-	m, err := mr.Mount(ctx, readonly)
+	m, err := mr.Mount(ctx, readonly, g)
 	if err != nil {
 		return nil, err
 	}
-	return &Mount{m: m, mr: mr}, nil
+	return &Mount{m: m, mr: mr, readonly: readonly}, nil
 }
 
 func (rm *RefManager) Commit(ctx context.Context, mount fileoptypes.Mount) (fileoptypes.Ref, error) {
@@ -57,8 +58,9 @@
 }
 
 type Mount struct {
-	m  snapshot.Mountable
-	mr cache.MutableRef
+	m        snapshot.Mountable
+	mr       cache.MutableRef
+	readonly bool
 }
 
 func (m *Mount) Release(ctx context.Context) error {
@@ -68,3 +70,7 @@
 	return nil
 }
 func (m *Mount) IsFileOpMount() {}
+
+func (m *Mount) Readonly() bool {
+	return m.readonly
+}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_linux.go b/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_linux.go
index 93b3236..8e4848c 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_linux.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_linux.go
@@ -58,12 +58,12 @@
 			}
 
 			if len(users) > 0 {
-				us.Uid = users[0].Uid
-				us.Gid = users[0].Gid
+				us.UID = users[0].Uid
+				us.GID = users[0].Gid
 			}
 		case *pb.UserOpt_ByID:
-			us.Uid = int(u.ByID)
-			us.Gid = int(u.ByID)
+			us.UID = int(u.ByID)
+			us.GID = int(u.ByID)
 		}
 	}
 
@@ -108,10 +108,10 @@
 			}
 
 			if len(groups) > 0 {
-				us.Gid = groups[0].Gid
+				us.GID = groups[0].Gid
 			}
 		case *pb.UserOpt_ByID:
-			us.Gid = int(u.ByID)
+			us.GID = int(u.ByID)
 		}
 	}
 
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_nolinux.go b/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_nolinux.go
index 780b559..246f187 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_nolinux.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/file/user_nolinux.go
@@ -10,5 +10,8 @@
 )
 
 func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.User, error) {
+	if chopt == nil {
+		return nil, nil
+	}
 	return nil, errors.New("only implemented in linux")
 }
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go b/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go
new file mode 100644
index 0000000..05703ac
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go
@@ -0,0 +1,519 @@
+package mounts
+
+import (
+	"context"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sync"
+	"time"
+
+	"github.com/containerd/containerd/mount"
+	"github.com/containerd/containerd/sys"
+	"github.com/docker/docker/pkg/idtools"
+	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/cache/metadata"
+	"github.com/moby/buildkit/client"
+	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/session/secrets"
+	"github.com/moby/buildkit/session/sshforward"
+	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/solver/pb"
+	"github.com/moby/buildkit/util/grpcerrors"
+	"github.com/moby/locker"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	bolt "go.etcd.io/bbolt"
+	"google.golang.org/grpc/codes"
+)
+
+func NewMountManager(name string, cm cache.Manager, sm *session.Manager, md *metadata.Store) *MountManager {
+	return &MountManager{
+		cm:          cm,
+		sm:          sm,
+		cacheMounts: map[string]*cacheRefShare{},
+		md:          md,
+		managerName: name,
+	}
+}
+
+type MountManager struct {
+	cm            cache.Manager
+	sm            *session.Manager
+	cacheMountsMu sync.Mutex
+	cacheMounts   map[string]*cacheRefShare
+	md            *metadata.Store
+	managerName   string
+}
+
+func (mm *MountManager) getRefCacheDir(ctx context.Context, ref cache.ImmutableRef, id string, m *pb.Mount, sharing pb.CacheSharingOpt, s session.Group) (mref cache.MutableRef, err error) {
+	g := &cacheRefGetter{
+		locker:          &mm.cacheMountsMu,
+		cacheMounts:     mm.cacheMounts,
+		cm:              mm.cm,
+		md:              mm.md,
+		globalCacheRefs: sharedCacheRefs,
+		name:            fmt.Sprintf("cached mount %s from %s", m.Dest, mm.managerName),
+		session:         s,
+	}
+	return g.getRefCacheDir(ctx, ref, id, sharing)
+}
+
+type cacheRefGetter struct {
+	locker          sync.Locker
+	cacheMounts     map[string]*cacheRefShare
+	cm              cache.Manager
+	md              *metadata.Store
+	globalCacheRefs *cacheRefs
+	name            string
+	session         session.Group
+}
+
+func (g *cacheRefGetter) getRefCacheDir(ctx context.Context, ref cache.ImmutableRef, id string, sharing pb.CacheSharingOpt) (mref cache.MutableRef, err error) {
+	key := "cache-dir:" + id
+	if ref != nil {
+		key += ":" + ref.ID()
+	}
+	mu := g.locker
+	mu.Lock()
+	defer mu.Unlock()
+
+	if ref, ok := g.cacheMounts[key]; ok {
+		return ref.clone(), nil
+	}
+	defer func() {
+		if err == nil {
+			share := &cacheRefShare{MutableRef: mref, refs: map[*cacheRef]struct{}{}}
+			g.cacheMounts[key] = share
+			mref = share.clone()
+		}
+	}()
+
+	switch sharing {
+	case pb.CacheSharingOpt_SHARED:
+		return g.globalCacheRefs.get(key, func() (cache.MutableRef, error) {
+			return g.getRefCacheDirNoCache(ctx, key, ref, id, false)
+		})
+	case pb.CacheSharingOpt_PRIVATE:
+		return g.getRefCacheDirNoCache(ctx, key, ref, id, false)
+	case pb.CacheSharingOpt_LOCKED:
+		return g.getRefCacheDirNoCache(ctx, key, ref, id, true)
+	default:
+		return nil, errors.Errorf("invalid cache sharing option: %s", sharing.String())
+	}
+}
+
+func (g *cacheRefGetter) getRefCacheDirNoCache(ctx context.Context, key string, ref cache.ImmutableRef, id string, block bool) (cache.MutableRef, error) {
+	makeMutable := func(ref cache.ImmutableRef) (cache.MutableRef, error) {
+		return g.cm.New(ctx, ref, g.session, cache.WithRecordType(client.UsageRecordTypeCacheMount), cache.WithDescription(g.name), cache.CachePolicyRetain)
+	}
+
+	cacheRefsLocker.Lock(key)
+	defer cacheRefsLocker.Unlock(key)
+	for {
+		sis, err := g.md.Search(key)
+		if err != nil {
+			return nil, err
+		}
+		locked := false
+		for _, si := range sis {
+			if mRef, err := g.cm.GetMutable(ctx, si.ID()); err == nil {
+				logrus.Debugf("reusing ref for cache dir: %s", mRef.ID())
+				return mRef, nil
+			} else if errors.Is(err, cache.ErrLocked) {
+				locked = true
+			}
+		}
+		if block && locked {
+			cacheRefsLocker.Unlock(key)
+			select {
+			case <-ctx.Done():
+				cacheRefsLocker.Lock(key)
+				return nil, ctx.Err()
+			case <-time.After(100 * time.Millisecond):
+				cacheRefsLocker.Lock(key)
+			}
+		} else {
+			break
+		}
+	}
+	mRef, err := makeMutable(ref)
+	if err != nil {
+		return nil, err
+	}
+
+	si, _ := g.md.Get(mRef.ID())
+	v, err := metadata.NewValue(key)
+	if err != nil {
+		mRef.Release(context.TODO())
+		return nil, err
+	}
+	v.Index = key
+	if err := si.Update(func(b *bolt.Bucket) error {
+		return si.SetValue(b, key, v)
+	}); err != nil {
+		mRef.Release(context.TODO())
+		return nil, err
+	}
+	return mRef, nil
+}
+
+func (mm *MountManager) getSSHMountable(ctx context.Context, m *pb.Mount, g session.Group) (cache.Mountable, error) {
+	var caller session.Caller
+	err := mm.sm.Any(ctx, g, func(ctx context.Context, _ string, c session.Caller) error {
+		if err := sshforward.CheckSSHID(ctx, c, m.SSHOpt.ID); err != nil {
+			if m.SSHOpt.Optional {
+				return nil
+			}
+			if grpcerrors.Code(err) == codes.Unimplemented {
+				return errors.Errorf("no SSH key %q forwarded from the client", m.SSHOpt.ID)
+			}
+			return err
+		}
+		caller = c
+		return nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	if caller == nil {
+		return nil, nil
+	}
+	// because ssh socket remains active, to actually handle session disconnecting ssh error
+	// should restart the whole exec with new session
+	return &sshMount{mount: m, caller: caller, idmap: mm.cm.IdentityMapping()}, nil
+}
+
+type sshMount struct {
+	mount  *pb.Mount
+	caller session.Caller
+	idmap  *idtools.IdentityMapping
+}
+
+func (sm *sshMount) Mount(ctx context.Context, readonly bool, g session.Group) (snapshot.Mountable, error) {
+	return &sshMountInstance{sm: sm, idmap: sm.idmap}, nil
+}
+
+type sshMountInstance struct {
+	sm    *sshMount
+	idmap *idtools.IdentityMapping
+}
+
+func (sm *sshMountInstance) Mount() ([]mount.Mount, func() error, error) {
+	ctx, cancel := context.WithCancel(context.TODO())
+
+	uid := int(sm.sm.mount.SSHOpt.Uid)
+	gid := int(sm.sm.mount.SSHOpt.Gid)
+
+	if sm.idmap != nil {
+		identity, err := sm.idmap.ToHost(idtools.Identity{
+			UID: uid,
+			GID: gid,
+		})
+		if err != nil {
+			cancel()
+			return nil, nil, err
+		}
+		uid = identity.UID
+		gid = identity.GID
+	}
+
+	sock, cleanup, err := sshforward.MountSSHSocket(ctx, sm.sm.caller, sshforward.SocketOpt{
+		ID:   sm.sm.mount.SSHOpt.ID,
+		UID:  uid,
+		GID:  gid,
+		Mode: int(sm.sm.mount.SSHOpt.Mode & 0777),
+	})
+	if err != nil {
+		cancel()
+		return nil, nil, err
+	}
+	release := func() error {
+		var err error
+		if cleanup != nil {
+			err = cleanup()
+		}
+		cancel()
+		return err
+	}
+
+	return []mount.Mount{{
+		Type:    "bind",
+		Source:  sock,
+		Options: []string{"rbind"},
+	}}, release, nil
+}
+
+func (sm *sshMountInstance) IdentityMapping() *idtools.IdentityMapping {
+	return sm.idmap
+}
+
+func (mm *MountManager) getSecretMountable(ctx context.Context, m *pb.Mount, g session.Group) (cache.Mountable, error) {
+	if m.SecretOpt == nil {
+		return nil, errors.Errorf("invalid secret mount options")
+	}
+	sopt := *m.SecretOpt
+
+	id := sopt.ID
+	if id == "" {
+		return nil, errors.Errorf("secret ID missing from mount options")
+	}
+	var dt []byte
+	var err error
+	err = mm.sm.Any(ctx, g, func(ctx context.Context, _ string, caller session.Caller) error {
+		dt, err = secrets.GetSecret(ctx, caller, id)
+		if err != nil {
+			if errors.Is(err, secrets.ErrNotFound) && m.SecretOpt.Optional {
+				return nil
+			}
+			return err
+		}
+		return nil
+	})
+	if err != nil || dt == nil {
+		return nil, err
+	}
+	return &secretMount{mount: m, data: dt, idmap: mm.cm.IdentityMapping()}, nil
+}
+
+type secretMount struct {
+	mount *pb.Mount
+	data  []byte
+	idmap *idtools.IdentityMapping
+}
+
+func (sm *secretMount) Mount(ctx context.Context, readonly bool, g session.Group) (snapshot.Mountable, error) {
+	return &secretMountInstance{sm: sm, idmap: sm.idmap}, nil
+}
+
+type secretMountInstance struct {
+	sm    *secretMount
+	root  string
+	idmap *idtools.IdentityMapping
+}
+
+func (sm *secretMountInstance) Mount() ([]mount.Mount, func() error, error) {
+	dir, err := ioutil.TempDir("", "buildkit-secrets")
+	if err != nil {
+		return nil, nil, errors.Wrap(err, "failed to create temp dir")
+	}
+	cleanupDir := func() error {
+		return os.RemoveAll(dir)
+	}
+
+	if err := os.Chmod(dir, 0711); err != nil {
+		cleanupDir()
+		return nil, nil, err
+	}
+
+	tmpMount := mount.Mount{
+		Type:    "tmpfs",
+		Source:  "tmpfs",
+		Options: []string{"nodev", "nosuid", "noexec", fmt.Sprintf("uid=%d,gid=%d", os.Geteuid(), os.Getegid())},
+	}
+
+	if sys.RunningInUserNS() {
+		tmpMount.Options = nil
+	}
+
+	if err := mount.All([]mount.Mount{tmpMount}, dir); err != nil {
+		cleanupDir()
+		return nil, nil, errors.Wrap(err, "unable to setup secret mount")
+	}
+	sm.root = dir
+
+	cleanup := func() error {
+		if err := mount.Unmount(dir, 0); err != nil {
+			return err
+		}
+		return cleanupDir()
+	}
+
+	randID := identity.NewID()
+	fp := filepath.Join(dir, randID)
+	if err := ioutil.WriteFile(fp, sm.sm.data, 0600); err != nil {
+		cleanup()
+		return nil, nil, err
+	}
+
+	uid := int(sm.sm.mount.SecretOpt.Uid)
+	gid := int(sm.sm.mount.SecretOpt.Gid)
+
+	if sm.idmap != nil {
+		identity, err := sm.idmap.ToHost(idtools.Identity{
+			UID: uid,
+			GID: gid,
+		})
+		if err != nil {
+			cleanup()
+			return nil, nil, err
+		}
+		uid = identity.UID
+		gid = identity.GID
+	}
+
+	if err := os.Chown(fp, uid, gid); err != nil {
+		cleanup()
+		return nil, nil, err
+	}
+
+	if err := os.Chmod(fp, os.FileMode(sm.sm.mount.SecretOpt.Mode&0777)); err != nil {
+		cleanup()
+		return nil, nil, err
+	}
+
+	return []mount.Mount{{
+		Type:    "bind",
+		Source:  fp,
+		Options: []string{"ro", "rbind", "nodev", "nosuid", "noexec"},
+	}}, cleanup, nil
+}
+
+func (sm *secretMountInstance) IdentityMapping() *idtools.IdentityMapping {
+	return sm.idmap
+}
+
+func (mm *MountManager) MountableCache(ctx context.Context, m *pb.Mount, ref cache.ImmutableRef, g session.Group) (cache.MutableRef, error) {
+	if m.CacheOpt == nil {
+		return nil, errors.Errorf("missing cache mount options")
+	}
+	return mm.getRefCacheDir(ctx, ref, m.CacheOpt.ID, m, m.CacheOpt.Sharing, g)
+}
+
+func (mm *MountManager) MountableTmpFS() cache.Mountable {
+	return newTmpfs(mm.cm.IdentityMapping())
+}
+
+func (mm *MountManager) MountableSecret(ctx context.Context, m *pb.Mount, g session.Group) (cache.Mountable, error) {
+	return mm.getSecretMountable(ctx, m, g)
+}
+
+func (mm *MountManager) MountableSSH(ctx context.Context, m *pb.Mount, g session.Group) (cache.Mountable, error) {
+	return mm.getSSHMountable(ctx, m, g)
+}
+
+func newTmpfs(idmap *idtools.IdentityMapping) cache.Mountable {
+	return &tmpfs{idmap: idmap}
+}
+
+type tmpfs struct {
+	idmap *idtools.IdentityMapping
+}
+
+func (f *tmpfs) Mount(ctx context.Context, readonly bool, g session.Group) (snapshot.Mountable, error) {
+	return &tmpfsMount{readonly: readonly, idmap: f.idmap}, nil
+}
+
+type tmpfsMount struct {
+	readonly bool
+	idmap    *idtools.IdentityMapping
+}
+
+func (m *tmpfsMount) Mount() ([]mount.Mount, func() error, error) {
+	opt := []string{"nosuid"}
+	if m.readonly {
+		opt = append(opt, "ro")
+	}
+	return []mount.Mount{{
+		Type:    "tmpfs",
+		Source:  "tmpfs",
+		Options: opt,
+	}}, func() error { return nil }, nil
+}
+
+func (m *tmpfsMount) IdentityMapping() *idtools.IdentityMapping {
+	return m.idmap
+}
+
+var cacheRefsLocker = locker.New()
+var sharedCacheRefs = &cacheRefs{}
+
+type cacheRefs struct {
+	mu     sync.Mutex
+	shares map[string]*cacheRefShare
+}
+
+// ClearActiveCacheMounts clears shared cache mounts currently in use.
+// Caller needs to hold CacheMountsLocker before calling
+func ClearActiveCacheMounts() {
+	sharedCacheRefs.shares = nil
+}
+
+func CacheMountsLocker() sync.Locker {
+	return &sharedCacheRefs.mu
+}
+
+func (r *cacheRefs) get(key string, fn func() (cache.MutableRef, error)) (cache.MutableRef, error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+
+	if r.shares == nil {
+		r.shares = map[string]*cacheRefShare{}
+	}
+
+	share, ok := r.shares[key]
+	if ok {
+		return share.clone(), nil
+	}
+
+	mref, err := fn()
+	if err != nil {
+		return nil, err
+	}
+
+	share = &cacheRefShare{MutableRef: mref, main: r, key: key, refs: map[*cacheRef]struct{}{}}
+	r.shares[key] = share
+	return share.clone(), nil
+}
+
+type cacheRefShare struct {
+	cache.MutableRef
+	mu   sync.Mutex
+	refs map[*cacheRef]struct{}
+	main *cacheRefs
+	key  string
+}
+
+func (r *cacheRefShare) clone() cache.MutableRef {
+	cacheRef := &cacheRef{cacheRefShare: r}
+	if cacheRefCloneHijack != nil {
+		cacheRefCloneHijack()
+	}
+	r.mu.Lock()
+	r.refs[cacheRef] = struct{}{}
+	r.mu.Unlock()
+	return cacheRef
+}
+
+func (r *cacheRefShare) release(ctx context.Context) error {
+	if r.main != nil {
+		delete(r.main.shares, r.key)
+	}
+	return r.MutableRef.Release(ctx)
+}
+
+var cacheRefReleaseHijack func()
+var cacheRefCloneHijack func()
+
+type cacheRef struct {
+	*cacheRefShare
+}
+
+func (r *cacheRef) Release(ctx context.Context) error {
+	if r.main != nil {
+		r.main.mu.Lock()
+		defer r.main.mu.Unlock()
+	}
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	delete(r.refs, r)
+	if len(r.refs) == 0 {
+		if cacheRefReleaseHijack != nil {
+			cacheRefReleaseHijack()
+		}
+		return r.release(ctx)
+	}
+	return nil
+}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/build.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/build.go
index d8b748d..5e7fbc7 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/build.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/build.go
@@ -54,6 +54,7 @@
 		Deps: make([]struct {
 			Selector          digest.Digest
 			ComputeDigestFunc solver.ResultBasedCacheFunc
+			PreprocessFunc    solver.PreprocessFunc
 		}, len(b.v.Inputs())),
 	}, true, nil
 }
@@ -80,7 +81,7 @@
 		return nil, errors.Errorf("invalid reference for build %T", inp.Sys())
 	}
 
-	mount, err := ref.ImmutableRef.Mount(ctx, true)
+	mount, err := ref.ImmutableRef.Mount(ctx, true, g)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go
index 6258ff5..5ec45fa 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go
@@ -5,34 +5,23 @@
 	"context"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
 	"net"
 	"os"
 	"path"
-	"path/filepath"
 	"sort"
 	"strings"
-	"sync"
-	"time"
 
-	"github.com/containerd/containerd/mount"
 	"github.com/containerd/containerd/platforms"
-	"github.com/containerd/containerd/sys"
-	"github.com/docker/docker/pkg/idtools"
-	"github.com/docker/docker/pkg/locker"
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/cache/metadata"
-	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/executor"
-	"github.com/moby/buildkit/identity"
+	"github.com/moby/buildkit/frontend/gateway"
 	"github.com/moby/buildkit/session"
-	"github.com/moby/buildkit/session/secrets"
-	"github.com/moby/buildkit/session/sshforward"
-	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/solver/llbsolver"
+	"github.com/moby/buildkit/solver/llbsolver/errdefs"
+	"github.com/moby/buildkit/solver/llbsolver/mounts"
 	"github.com/moby/buildkit/solver/pb"
-	"github.com/moby/buildkit/util/grpcerrors"
 	"github.com/moby/buildkit/util/progress/logs"
 	utilsystem "github.com/moby/buildkit/util/system"
 	"github.com/moby/buildkit/worker"
@@ -40,8 +29,6 @@
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-	bolt "go.etcd.io/bbolt"
-	"google.golang.org/grpc/codes"
 )
 
 const execCacheType = "buildkit.exec.v0"
@@ -49,31 +36,26 @@
 type execOp struct {
 	op        *pb.ExecOp
 	cm        cache.Manager
-	sm        *session.Manager
-	md        *metadata.Store
+	mm        *mounts.MountManager
 	exec      executor.Executor
 	w         worker.Worker
 	platform  *pb.Platform
 	numInputs int
-
-	cacheMounts   map[string]*cacheRefShare
-	cacheMountsMu sync.Mutex
 }
 
 func NewExecOp(v solver.Vertex, op *pb.Op_Exec, platform *pb.Platform, cm cache.Manager, sm *session.Manager, md *metadata.Store, exec executor.Executor, w worker.Worker) (solver.Op, error) {
 	if err := llbsolver.ValidateOp(&pb.Op{Op: op}); err != nil {
 		return nil, err
 	}
+	name := fmt.Sprintf("exec %s", strings.Join(op.Exec.Meta.Args, " "))
 	return &execOp{
-		op:          op.Exec,
-		cm:          cm,
-		sm:          sm,
-		md:          md,
-		exec:        exec,
-		numInputs:   len(v.Inputs()),
-		w:           w,
-		platform:    platform,
-		cacheMounts: map[string]*cacheRefShare{},
+		op:        op.Exec,
+		mm:        mounts.NewMountManager(name, cm, sm, md),
+		cm:        cm,
+		exec:      exec,
+		numInputs: len(v.Inputs()),
+		w:         w,
+		platform:  platform,
 	}, nil
 }
 
@@ -137,6 +119,7 @@
 		Deps: make([]struct {
 			Selector          digest.Digest
 			ComputeDigestFunc solver.ResultBasedCacheFunc
+			PreprocessFunc    solver.PreprocessFunc
 		}, e.numInputs),
 	}
 
@@ -156,6 +139,7 @@
 		if !dep.NoContentBasedHash {
 			cm.Deps[i].ComputeDigestFunc = llbsolver.NewContentHashFunc(toSelectors(dedupePaths(dep.Selectors)))
 		}
+		cm.Deps[i].PreprocessFunc = llbsolver.UnlazyResultFunc
 	}
 
 	return cm, true, nil
@@ -221,328 +205,6 @@
 	return deps, nil
 }
 
-func (e *execOp) getRefCacheDir(ctx context.Context, ref cache.ImmutableRef, id string, m *pb.Mount, sharing pb.CacheSharingOpt) (mref cache.MutableRef, err error) {
-	g := &cacheRefGetter{
-		locker:          &e.cacheMountsMu,
-		cacheMounts:     e.cacheMounts,
-		cm:              e.cm,
-		md:              e.md,
-		globalCacheRefs: sharedCacheRefs,
-		name:            fmt.Sprintf("cached mount %s from exec %s", m.Dest, strings.Join(e.op.Meta.Args, " ")),
-	}
-	return g.getRefCacheDir(ctx, ref, id, sharing)
-}
-
-type cacheRefGetter struct {
-	locker          sync.Locker
-	cacheMounts     map[string]*cacheRefShare
-	cm              cache.Manager
-	md              *metadata.Store
-	globalCacheRefs *cacheRefs
-	name            string
-}
-
-func (g *cacheRefGetter) getRefCacheDir(ctx context.Context, ref cache.ImmutableRef, id string, sharing pb.CacheSharingOpt) (mref cache.MutableRef, err error) {
-	key := "cache-dir:" + id
-	if ref != nil {
-		key += ":" + ref.ID()
-	}
-	mu := g.locker
-	mu.Lock()
-	defer mu.Unlock()
-
-	if ref, ok := g.cacheMounts[key]; ok {
-		return ref.clone(), nil
-	}
-	defer func() {
-		if err == nil {
-			share := &cacheRefShare{MutableRef: mref, refs: map[*cacheRef]struct{}{}}
-			g.cacheMounts[key] = share
-			mref = share.clone()
-		}
-	}()
-
-	switch sharing {
-	case pb.CacheSharingOpt_SHARED:
-		return g.globalCacheRefs.get(key, func() (cache.MutableRef, error) {
-			return g.getRefCacheDirNoCache(ctx, key, ref, id, false)
-		})
-	case pb.CacheSharingOpt_PRIVATE:
-		return g.getRefCacheDirNoCache(ctx, key, ref, id, false)
-	case pb.CacheSharingOpt_LOCKED:
-		return g.getRefCacheDirNoCache(ctx, key, ref, id, true)
-	default:
-		return nil, errors.Errorf("invalid cache sharing option: %s", sharing.String())
-	}
-}
-
-func (g *cacheRefGetter) getRefCacheDirNoCache(ctx context.Context, key string, ref cache.ImmutableRef, id string, block bool) (cache.MutableRef, error) {
-	makeMutable := func(ref cache.ImmutableRef) (cache.MutableRef, error) {
-		return g.cm.New(ctx, ref, cache.WithRecordType(client.UsageRecordTypeCacheMount), cache.WithDescription(g.name), cache.CachePolicyRetain)
-	}
-
-	cacheRefsLocker.Lock(key)
-	defer cacheRefsLocker.Unlock(key)
-	for {
-		sis, err := g.md.Search(key)
-		if err != nil {
-			return nil, err
-		}
-		locked := false
-		for _, si := range sis {
-			if mRef, err := g.cm.GetMutable(ctx, si.ID()); err == nil {
-				logrus.Debugf("reusing ref for cache dir: %s", mRef.ID())
-				return mRef, nil
-			} else if errors.Is(err, cache.ErrLocked) {
-				locked = true
-			}
-		}
-		if block && locked {
-			cacheRefsLocker.Unlock(key)
-			select {
-			case <-ctx.Done():
-				cacheRefsLocker.Lock(key)
-				return nil, ctx.Err()
-			case <-time.After(100 * time.Millisecond):
-				cacheRefsLocker.Lock(key)
-			}
-		} else {
-			break
-		}
-	}
-	mRef, err := makeMutable(ref)
-	if err != nil {
-		return nil, err
-	}
-
-	si, _ := g.md.Get(mRef.ID())
-	v, err := metadata.NewValue(key)
-	if err != nil {
-		mRef.Release(context.TODO())
-		return nil, err
-	}
-	v.Index = key
-	if err := si.Update(func(b *bolt.Bucket) error {
-		return si.SetValue(b, key, v)
-	}); err != nil {
-		mRef.Release(context.TODO())
-		return nil, err
-	}
-	return mRef, nil
-}
-
-func (e *execOp) getSSHMountable(ctx context.Context, m *pb.Mount, g session.Group) (cache.Mountable, error) {
-	var caller session.Caller
-	err := e.sm.Any(ctx, g, func(ctx context.Context, _ string, c session.Caller) error {
-		if err := sshforward.CheckSSHID(ctx, c, m.SSHOpt.ID); err != nil {
-			if m.SSHOpt.Optional {
-				return nil
-			}
-			if grpcerrors.Code(err) == codes.Unimplemented {
-				return errors.Errorf("no SSH key %q forwarded from the client", m.SSHOpt.ID)
-			}
-			return err
-		}
-		caller = c
-		return nil
-	})
-	if err != nil {
-		return nil, err
-	}
-	// because ssh socket remains active, to actually handle session disconnecting ssh error
-	// should restart the whole exec with new session
-	return &sshMount{mount: m, caller: caller, idmap: e.cm.IdentityMapping()}, nil
-}
-
-type sshMount struct {
-	mount  *pb.Mount
-	caller session.Caller
-	idmap  *idtools.IdentityMapping
-}
-
-func (sm *sshMount) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
-	return &sshMountInstance{sm: sm, idmap: sm.idmap}, nil
-}
-
-type sshMountInstance struct {
-	sm    *sshMount
-	idmap *idtools.IdentityMapping
-}
-
-func (sm *sshMountInstance) Mount() ([]mount.Mount, func() error, error) {
-	ctx, cancel := context.WithCancel(context.TODO())
-
-	uid := int(sm.sm.mount.SSHOpt.Uid)
-	gid := int(sm.sm.mount.SSHOpt.Gid)
-
-	if sm.idmap != nil {
-		identity, err := sm.idmap.ToHost(idtools.Identity{
-			UID: uid,
-			GID: gid,
-		})
-		if err != nil {
-			cancel()
-			return nil, nil, err
-		}
-		uid = identity.UID
-		gid = identity.GID
-	}
-
-	sock, cleanup, err := sshforward.MountSSHSocket(ctx, sm.sm.caller, sshforward.SocketOpt{
-		ID:   sm.sm.mount.SSHOpt.ID,
-		UID:  uid,
-		GID:  gid,
-		Mode: int(sm.sm.mount.SSHOpt.Mode & 0777),
-	})
-	if err != nil {
-		cancel()
-		return nil, nil, err
-	}
-	release := func() error {
-		var err error
-		if cleanup != nil {
-			err = cleanup()
-		}
-		cancel()
-		return err
-	}
-
-	return []mount.Mount{{
-		Type:    "bind",
-		Source:  sock,
-		Options: []string{"rbind"},
-	}}, release, nil
-}
-
-func (sm *sshMountInstance) IdentityMapping() *idtools.IdentityMapping {
-	return sm.idmap
-}
-
-func (e *execOp) getSecretMountable(ctx context.Context, m *pb.Mount, g session.Group) (cache.Mountable, error) {
-	if m.SecretOpt == nil {
-		return nil, errors.Errorf("invalid sercet mount options")
-	}
-	sopt := *m.SecretOpt
-
-	id := sopt.ID
-	if id == "" {
-		return nil, errors.Errorf("secret ID missing from mount options")
-	}
-	var dt []byte
-	var err error
-	err = e.sm.Any(ctx, g, func(ctx context.Context, _ string, caller session.Caller) error {
-		dt, err = secrets.GetSecret(ctx, caller, id)
-		if err != nil {
-			if errors.Is(err, secrets.ErrNotFound) && m.SecretOpt.Optional {
-				return nil
-			}
-			return err
-		}
-		return nil
-	})
-	if err != nil || dt == nil {
-		return nil, err
-	}
-	return &secretMount{mount: m, data: dt, idmap: e.cm.IdentityMapping()}, nil
-}
-
-type secretMount struct {
-	mount *pb.Mount
-	data  []byte
-	idmap *idtools.IdentityMapping
-}
-
-func (sm *secretMount) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
-	return &secretMountInstance{sm: sm, idmap: sm.idmap}, nil
-}
-
-type secretMountInstance struct {
-	sm    *secretMount
-	root  string
-	idmap *idtools.IdentityMapping
-}
-
-func (sm *secretMountInstance) Mount() ([]mount.Mount, func() error, error) {
-	dir, err := ioutil.TempDir("", "buildkit-secrets")
-	if err != nil {
-		return nil, nil, errors.Wrap(err, "failed to create temp dir")
-	}
-	cleanupDir := func() error {
-		return os.RemoveAll(dir)
-	}
-
-	if err := os.Chmod(dir, 0711); err != nil {
-		cleanupDir()
-		return nil, nil, err
-	}
-
-	tmpMount := mount.Mount{
-		Type:    "tmpfs",
-		Source:  "tmpfs",
-		Options: []string{"nodev", "nosuid", "noexec", fmt.Sprintf("uid=%d,gid=%d", os.Geteuid(), os.Getegid())},
-	}
-
-	if sys.RunningInUserNS() {
-		tmpMount.Options = nil
-	}
-
-	if err := mount.All([]mount.Mount{tmpMount}, dir); err != nil {
-		cleanupDir()
-		return nil, nil, errors.Wrap(err, "unable to setup secret mount")
-	}
-	sm.root = dir
-
-	cleanup := func() error {
-		if err := mount.Unmount(dir, 0); err != nil {
-			return err
-		}
-		return cleanupDir()
-	}
-
-	randID := identity.NewID()
-	fp := filepath.Join(dir, randID)
-	if err := ioutil.WriteFile(fp, sm.sm.data, 0600); err != nil {
-		cleanup()
-		return nil, nil, err
-	}
-
-	uid := int(sm.sm.mount.SecretOpt.Uid)
-	gid := int(sm.sm.mount.SecretOpt.Gid)
-
-	if sm.idmap != nil {
-		identity, err := sm.idmap.ToHost(idtools.Identity{
-			UID: uid,
-			GID: gid,
-		})
-		if err != nil {
-			cleanup()
-			return nil, nil, err
-		}
-		uid = identity.UID
-		gid = identity.GID
-	}
-
-	if err := os.Chown(fp, uid, gid); err != nil {
-		cleanup()
-		return nil, nil, err
-	}
-
-	if err := os.Chmod(fp, os.FileMode(sm.sm.mount.SecretOpt.Mode&0777)); err != nil {
-		cleanup()
-		return nil, nil, err
-	}
-
-	return []mount.Mount{{
-		Type:    "bind",
-		Source:  fp,
-		Options: []string{"ro", "rbind", "nodev", "nosuid", "noexec"},
-	}}, cleanup, nil
-}
-
-func (sm *secretMountInstance) IdentityMapping() *idtools.IdentityMapping {
-	return sm.idmap
-}
-
 func addDefaultEnvvar(env []string, k, v string) []string {
 	for _, e := range env {
 		if strings.HasPrefix(e, k+"=") {
@@ -552,146 +214,58 @@
 	return append(env, k+"="+v)
 }
 
-func (e *execOp) Exec(ctx context.Context, g session.Group, inputs []solver.Result) ([]solver.Result, error) {
-	var mounts []executor.Mount
-	var root cache.Mountable
-	var readonlyRootFS bool
-
-	var outputs []cache.Ref
-
-	defer func() {
-		for _, o := range outputs {
-			if o != nil {
-				go o.Release(context.TODO())
-			}
-		}
-	}()
-
-	// loop over all mounts, fill in mounts, root and outputs
-	for _, m := range e.op.Mounts {
-		var mountable cache.Mountable
-		var ref cache.ImmutableRef
-
-		if m.Dest == pb.RootMount && m.MountType != pb.MountType_BIND {
-			return nil, errors.Errorf("invalid mount type %s for %s", m.MountType.String(), m.Dest)
-		}
-
-		// if mount is based on input validate and load it
-		if m.Input != pb.Empty {
-			if int(m.Input) > len(inputs) {
-				return nil, errors.Errorf("missing input %d", m.Input)
-			}
-			inp := inputs[int(m.Input)]
-			workerRef, ok := inp.Sys().(*worker.WorkerRef)
-			if !ok {
-				return nil, errors.Errorf("invalid reference for exec %T", inp.Sys())
-			}
-			ref = workerRef.ImmutableRef
-			mountable = ref
-		}
-
-		makeMutable := func(ref cache.ImmutableRef) (cache.MutableRef, error) {
-			desc := fmt.Sprintf("mount %s from exec %s", m.Dest, strings.Join(e.op.Meta.Args, " "))
-			return e.cm.New(ctx, ref, cache.WithDescription(desc))
-		}
-
-		switch m.MountType {
-		case pb.MountType_BIND:
-			// if mount creates an output
-			if m.Output != pb.SkipOutput {
-				// it it is readonly and not root then output is the input
-				if m.Readonly && ref != nil && m.Dest != pb.RootMount {
-					outputs = append(outputs, ref.Clone())
-				} else {
-					// otherwise output and mount is the mutable child
-					active, err := makeMutable(ref)
-					if err != nil {
-						return nil, err
-					}
-					outputs = append(outputs, active)
-					mountable = active
-				}
-			} else if (!m.Readonly || ref == nil) && m.Dest != pb.RootMount {
-				// this case is empty readonly scratch without output that is not really useful for anything but don't error
-				active, err := makeMutable(ref)
-				if err != nil {
-					return nil, err
-				}
-				defer active.Release(context.TODO())
-				mountable = active
-			}
-
-		case pb.MountType_CACHE:
-			if m.CacheOpt == nil {
-				return nil, errors.Errorf("missing cache mount options")
-			}
-			mRef, err := e.getRefCacheDir(ctx, ref, m.CacheOpt.ID, m, m.CacheOpt.Sharing)
-			if err != nil {
-				return nil, err
-			}
-			mountable = mRef
-			defer func() {
-				go mRef.Release(context.TODO())
-			}()
-			if m.Output != pb.SkipOutput && ref != nil {
-				outputs = append(outputs, ref.Clone())
-			}
-
-		case pb.MountType_TMPFS:
-			mountable = newTmpfs(e.cm.IdentityMapping())
-
-		case pb.MountType_SECRET:
-			secretMount, err := e.getSecretMountable(ctx, m, g)
-			if err != nil {
-				return nil, err
-			}
-			if secretMount == nil {
-				continue
-			}
-			mountable = secretMount
-
-		case pb.MountType_SSH:
-			sshMount, err := e.getSSHMountable(ctx, m, g)
-			if err != nil {
-				return nil, err
-			}
-			if sshMount == nil {
-				continue
-			}
-			mountable = sshMount
-
-		default:
-			return nil, errors.Errorf("mount type %s not implemented", m.MountType)
-		}
-
-		// validate that there is a mount
-		if mountable == nil {
-			return nil, errors.Errorf("mount %s has no input", m.Dest)
-		}
-
-		// if dest is root we need mutable ref even if there is no output
-		if m.Dest == pb.RootMount {
-			root = mountable
-			readonlyRootFS = m.Readonly
-			if m.Output == pb.SkipOutput && readonlyRootFS {
-				active, err := makeMutable(ref)
-				if err != nil {
-					return nil, err
-				}
-				defer func() {
-					go active.Release(context.TODO())
-				}()
-				root = active
-			}
-		} else {
-			mounts = append(mounts, executor.Mount{Src: mountable, Dest: m.Dest, Readonly: m.Readonly, Selector: m.Selector})
+func (e *execOp) Exec(ctx context.Context, g session.Group, inputs []solver.Result) (results []solver.Result, err error) {
+	refs := make([]*worker.WorkerRef, len(inputs))
+	for i, inp := range inputs {
+		var ok bool
+		refs[i], ok = inp.Sys().(*worker.WorkerRef)
+		if !ok {
+			return nil, errors.Errorf("invalid reference for exec %T", inp.Sys())
 		}
 	}
 
-	// sort mounts so parents are mounted first
-	sort.Slice(mounts, func(i, j int) bool {
-		return mounts[i].Dest < mounts[j].Dest
+	p, err := gateway.PrepareMounts(ctx, e.mm, e.cm, g, e.op.Mounts, refs, func(m *pb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) {
+		desc := fmt.Sprintf("mount %s from exec %s", m.Dest, strings.Join(e.op.Meta.Args, " "))
+		return e.cm.New(ctx, ref, g, cache.WithDescription(desc))
 	})
+	defer func() {
+		if err != nil {
+			execInputs := make([]solver.Result, len(e.op.Mounts))
+			for i, m := range e.op.Mounts {
+				if m.Input == -1 {
+					continue
+				}
+				execInputs[i] = inputs[m.Input]
+			}
+			execMounts := make([]solver.Result, len(e.op.Mounts))
+			copy(execMounts, execInputs)
+			for i, res := range results {
+				execMounts[p.OutputRefs[i].MountIndex] = res
+			}
+			for _, active := range p.Actives {
+				ref, cerr := active.Ref.Commit(ctx)
+				if cerr != nil {
+					err = errors.Wrapf(err, "error committing %s: %s", active.Ref.ID(), cerr)
+					continue
+				}
+				execMounts[active.MountIndex] = worker.NewWorkerRefResult(ref, e.w)
+			}
+			err = errdefs.WithExecError(err, execInputs, execMounts)
+		} else {
+			// Only release actives if err is nil.
+			for i := len(p.Actives) - 1; i >= 0; i-- { // call in LIFO order
+				p.Actives[i].Ref.Release(context.TODO())
+			}
+		}
+		for _, o := range p.OutputRefs {
+			if o.Ref != nil {
+				o.Ref.Release(context.TODO())
+			}
+		}
+	}()
+	if err != nil {
+		return nil, err
+	}
 
 	extraHosts, err := parseExtraHosts(e.op.Meta.ExtraHosts)
 	if err != nil {
@@ -702,7 +276,7 @@
 	if err == nil && emu != nil {
 		e.op.Meta.Args = append([]string{qemuMountName}, e.op.Meta.Args...)
 
-		mounts = append(mounts, executor.Mount{
+		p.Mounts = append(p.Mounts, executor.Mount{
 			Readonly: true,
 			Src:      emu,
 			Dest:     qemuMountName,
@@ -717,7 +291,8 @@
 		Env:            e.op.Meta.Env,
 		Cwd:            e.op.Meta.Cwd,
 		User:           e.op.Meta.User,
-		ReadonlyRootFS: readonlyRootFS,
+		Hostname:       e.op.Meta.Hostname,
+		ReadonlyRootFS: p.ReadonlyRootFS,
 		ExtraHosts:     extraHosts,
 		NetMode:        e.op.Network,
 		SecurityMode:   e.op.Security,
@@ -726,30 +301,37 @@
 	if e.op.Meta.ProxyEnv != nil {
 		meta.Env = append(meta.Env, proxyEnvList(e.op.Meta.ProxyEnv)...)
 	}
-	meta.Env = addDefaultEnvvar(meta.Env, "PATH", utilsystem.DefaultPathEnv)
+	var currentOS string
+	if e.platform != nil {
+		currentOS = e.platform.OS
+	}
+	meta.Env = addDefaultEnvvar(meta.Env, "PATH", utilsystem.DefaultPathEnv(currentOS))
 
 	stdout, stderr := logs.NewLogStreams(ctx, os.Getenv("BUILDKIT_DEBUG_EXEC_OUTPUT") == "1")
 	defer stdout.Close()
 	defer stderr.Close()
 
-	if err := e.exec.Run(ctx, "", root, mounts, executor.ProcessInfo{Meta: meta, Stdin: nil, Stdout: stdout, Stderr: stderr}, nil); err != nil {
-		return nil, errors.Wrapf(err, "executor failed running %v", meta.Args)
-	}
+	execErr := e.exec.Run(ctx, "", p.Root, p.Mounts, executor.ProcessInfo{
+		Meta:   meta,
+		Stdin:  nil,
+		Stdout: stdout,
+		Stderr: stderr,
+	}, nil)
 
-	refs := []solver.Result{}
-	for i, out := range outputs {
-		if mutable, ok := out.(cache.MutableRef); ok {
+	for i, out := range p.OutputRefs {
+		if mutable, ok := out.Ref.(cache.MutableRef); ok {
 			ref, err := mutable.Commit(ctx)
 			if err != nil {
 				return nil, errors.Wrapf(err, "error committing %s", mutable.ID())
 			}
-			refs = append(refs, worker.NewWorkerRefResult(ref, e.w))
+			results = append(results, worker.NewWorkerRefResult(ref, e.w))
 		} else {
-			refs = append(refs, worker.NewWorkerRefResult(out.(cache.ImmutableRef), e.w))
+			results = append(results, worker.NewWorkerRefResult(out.Ref.(cache.ImmutableRef), e.w))
 		}
-		outputs[i] = nil
+		// Prevent the result from being released.
+		p.OutputRefs[i].Ref = nil
 	}
-	return refs, nil
+	return results, errors.Wrapf(execErr, "executor failed running %v", e.op.Meta.Args)
 }
 
 func proxyEnvList(p *pb.ProxyEnv) []string {
@@ -769,130 +351,6 @@
 	return out
 }
 
-func newTmpfs(idmap *idtools.IdentityMapping) cache.Mountable {
-	return &tmpfs{idmap: idmap}
-}
-
-type tmpfs struct {
-	idmap *idtools.IdentityMapping
-}
-
-func (f *tmpfs) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) {
-	return &tmpfsMount{readonly: readonly, idmap: f.idmap}, nil
-}
-
-type tmpfsMount struct {
-	readonly bool
-	idmap    *idtools.IdentityMapping
-}
-
-func (m *tmpfsMount) Mount() ([]mount.Mount, func() error, error) {
-	opt := []string{"nosuid"}
-	if m.readonly {
-		opt = append(opt, "ro")
-	}
-	return []mount.Mount{{
-		Type:    "tmpfs",
-		Source:  "tmpfs",
-		Options: opt,
-	}}, func() error { return nil }, nil
-}
-
-func (m *tmpfsMount) IdentityMapping() *idtools.IdentityMapping {
-	return m.idmap
-}
-
-var cacheRefsLocker = locker.New()
-var sharedCacheRefs = &cacheRefs{}
-
-type cacheRefs struct {
-	mu     sync.Mutex
-	shares map[string]*cacheRefShare
-}
-
-// ClearActiveCacheMounts clears shared cache mounts currently in use.
-// Caller needs to hold CacheMountsLocker before calling
-func ClearActiveCacheMounts() {
-	sharedCacheRefs.shares = nil
-}
-
-func CacheMountsLocker() sync.Locker {
-	return &sharedCacheRefs.mu
-}
-
-func (r *cacheRefs) get(key string, fn func() (cache.MutableRef, error)) (cache.MutableRef, error) {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	if r.shares == nil {
-		r.shares = map[string]*cacheRefShare{}
-	}
-
-	share, ok := r.shares[key]
-	if ok {
-		return share.clone(), nil
-	}
-
-	mref, err := fn()
-	if err != nil {
-		return nil, err
-	}
-
-	share = &cacheRefShare{MutableRef: mref, main: r, key: key, refs: map[*cacheRef]struct{}{}}
-	r.shares[key] = share
-	return share.clone(), nil
-}
-
-type cacheRefShare struct {
-	cache.MutableRef
-	mu   sync.Mutex
-	refs map[*cacheRef]struct{}
-	main *cacheRefs
-	key  string
-}
-
-func (r *cacheRefShare) clone() cache.MutableRef {
-	cacheRef := &cacheRef{cacheRefShare: r}
-	if cacheRefCloneHijack != nil {
-		cacheRefCloneHijack()
-	}
-	r.mu.Lock()
-	r.refs[cacheRef] = struct{}{}
-	r.mu.Unlock()
-	return cacheRef
-}
-
-func (r *cacheRefShare) release(ctx context.Context) error {
-	if r.main != nil {
-		delete(r.main.shares, r.key)
-	}
-	return r.MutableRef.Release(ctx)
-}
-
-var cacheRefReleaseHijack func()
-var cacheRefCloneHijack func()
-
-type cacheRef struct {
-	*cacheRefShare
-}
-
-func (r *cacheRef) Release(ctx context.Context) error {
-	if r.main != nil {
-		r.main.mu.Lock()
-		defer r.main.mu.Unlock()
-	}
-	r.mu.Lock()
-	defer r.mu.Unlock()
-	delete(r.refs, r)
-	if len(r.refs) == 0 {
-		if cacheRefReleaseHijack != nil {
-			cacheRefReleaseHijack()
-		}
-		return r.release(ctx)
-	}
-	return nil
-}
-
 func parseExtraHosts(ips []*pb.HostIP) ([]executor.HostIP, error) {
 	out := make([]executor.HostIP, len(ips))
 	for i, hip := range ips {
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go
index 5eea8ff..0603cf5 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go
@@ -12,7 +12,7 @@
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/moby/buildkit/snapshot"
 	"github.com/moby/buildkit/solver/pb"
-	"github.com/moby/buildkit/util/binfmt_misc"
+	"github.com/moby/buildkit/util/archutil"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	copy "github.com/tonistiigi/fsutil/copy"
@@ -83,7 +83,7 @@
 }
 
 func getEmulator(p *pb.Platform, idmap *idtools.IdentityMapping) (*emulator, error) {
-	all := binfmt_misc.SupportedPlatforms(false)
+	all := archutil.SupportedPlatforms(false)
 	m := make(map[string]struct{}, len(all))
 
 	for _, p := range all {
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go
index db10cfb..1111cdb 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go
@@ -15,6 +15,7 @@
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/solver/llbsolver"
+	"github.com/moby/buildkit/solver/llbsolver/errdefs"
 	"github.com/moby/buildkit/solver/llbsolver/file"
 	"github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes"
 	"github.com/moby/buildkit/solver/pb"
@@ -44,7 +45,7 @@
 		md:        md,
 		numInputs: len(v.Inputs()),
 		w:         w,
-		solver:    NewFileOpSolver(&file.Backend{}, file.NewRefManager(cm)),
+		solver:    NewFileOpSolver(w, &file.Backend{}, file.NewRefManager(cm)),
 	}, nil
 }
 
@@ -120,6 +121,7 @@
 		Deps: make([]struct {
 			Selector          digest.Digest
 			ComputeDigestFunc solver.ResultBasedCacheFunc
+			PreprocessFunc    solver.PreprocessFunc
 		}, f.numInputs),
 	}
 
@@ -138,6 +140,9 @@
 
 		cm.Deps[idx].ComputeDigestFunc = llbsolver.NewContentHashFunc(dedupeSelectors(m))
 	}
+	for idx := range cm.Deps {
+		cm.Deps[idx].PreprocessFunc = llbsolver.UnlazyResultFunc
+	}
 
 	return cm, true, nil
 }
@@ -152,7 +157,7 @@
 		inpRefs = append(inpRefs, workerRef.ImmutableRef)
 	}
 
-	outs, err := f.solver.Solve(ctx, inpRefs, f.op.Actions)
+	outs, err := f.solver.Solve(ctx, inpRefs, f.op.Actions, g)
 	if err != nil {
 		return nil, err
 	}
@@ -254,8 +259,9 @@
 	return nil
 }
 
-func NewFileOpSolver(b fileoptypes.Backend, r fileoptypes.RefManager) *FileOpSolver {
+func NewFileOpSolver(w worker.Worker, b fileoptypes.Backend, r fileoptypes.RefManager) *FileOpSolver {
 	return &FileOpSolver{
+		w:    w,
 		b:    b,
 		r:    r,
 		outs: map[int]int{},
@@ -264,6 +270,7 @@
 }
 
 type FileOpSolver struct {
+	w worker.Worker
 	b fileoptypes.Backend
 	r fileoptypes.RefManager
 
@@ -279,7 +286,7 @@
 	ref            fileoptypes.Ref
 }
 
-func (s *FileOpSolver) Solve(ctx context.Context, inputs []fileoptypes.Ref, actions []*pb.FileAction) ([]fileoptypes.Ref, error) {
+func (s *FileOpSolver) Solve(ctx context.Context, inputs []fileoptypes.Ref, actions []*pb.FileAction, g session.Group) ([]fileoptypes.Ref, error) {
 	for i, a := range actions {
 		if int(a.Input) < -1 || int(a.Input) >= len(inputs)+len(actions) {
 			return nil, errors.Errorf("invalid input index %d, %d provided", a.Input, len(inputs)+len(actions))
@@ -337,9 +344,9 @@
 				if err := s.validate(idx, inputs, actions, nil); err != nil {
 					return err
 				}
-				inp, err := s.getInput(ctx, idx, inputs, actions)
+				inp, err := s.getInput(ctx, idx, inputs, actions, g)
 				if err != nil {
-					return err
+					return errdefs.WithFileActionError(err, idx-len(inputs))
 				}
 				outs[i] = inp.ref
 				return nil
@@ -378,7 +385,7 @@
 	return nil
 }
 
-func (s *FileOpSolver) getInput(ctx context.Context, idx int, inputs []fileoptypes.Ref, actions []*pb.FileAction) (input, error) {
+func (s *FileOpSolver) getInput(ctx context.Context, idx int, inputs []fileoptypes.Ref, actions []*pb.FileAction, g session.Group) (input, error) {
 	inp, err := s.g.Do(ctx, fmt.Sprintf("inp-%d", idx), func(ctx context.Context) (_ interface{}, err error) {
 		s.mu.Lock()
 		inp := s.ins[idx]
@@ -397,31 +404,54 @@
 
 		var inpMount, inpMountSecondary fileoptypes.Mount
 		var toRelease []fileoptypes.Mount
-		var inpMountPrepared bool
+		action := actions[idx-len(inputs)]
+
 		defer func() {
+			if err != nil && inpMount != nil {
+				inputRes := make([]solver.Result, len(inputs))
+				for i, input := range inputs {
+					inputRes[i] = worker.NewWorkerRefResult(input.(cache.ImmutableRef), s.w)
+				}
+
+				outputRes := make([]solver.Result, len(actions))
+
+				// Commit the mutable for the primary input of the failed action.
+				if !inpMount.Readonly() {
+					ref, cerr := s.r.Commit(ctx, inpMount)
+					if cerr == nil {
+						outputRes[idx-len(inputs)] = worker.NewWorkerRefResult(ref.(cache.ImmutableRef), s.w)
+					}
+					inpMount.Release(context.TODO())
+				}
+
+				// If the action has a secondary input, commit it and set the ref on
+				// the output results.
+				if inpMountSecondary != nil && !inpMountSecondary.Readonly() {
+					ref2, cerr := s.r.Commit(ctx, inpMountSecondary)
+					if cerr == nil {
+						outputRes[int(action.SecondaryInput)-len(inputs)] = worker.NewWorkerRefResult(ref2.(cache.ImmutableRef), s.w)
+					}
+				}
+
+				err = errdefs.WithExecError(err, inputRes, outputRes)
+			}
 			for _, m := range toRelease {
 				m.Release(context.TODO())
 			}
-			if err != nil && inpMount != nil && inpMountPrepared {
-				inpMount.Release(context.TODO())
-			}
 		}()
 
-		action := actions[idx-len(inputs)]
-
 		loadInput := func(ctx context.Context) func() error {
 			return func() error {
-				inp, err := s.getInput(ctx, int(action.Input), inputs, actions)
+				inp, err := s.getInput(ctx, int(action.Input), inputs, actions, g)
 				if err != nil {
 					return err
 				}
 				if inp.ref != nil {
-					m, err := s.r.Prepare(ctx, inp.ref, false)
+					m, err := s.r.Prepare(ctx, inp.ref, false, g)
 					if err != nil {
 						return err
 					}
 					inpMount = m
-					inpMountPrepared = true
 					return nil
 				}
 				inpMount = inp.mount
@@ -431,12 +461,12 @@
 
 		loadSecondaryInput := func(ctx context.Context) func() error {
 			return func() error {
-				inp, err := s.getInput(ctx, int(action.SecondaryInput), inputs, actions)
+				inp, err := s.getInput(ctx, int(action.SecondaryInput), inputs, actions, g)
 				if err != nil {
 					return err
 				}
 				if inp.ref != nil {
-					m, err := s.r.Prepare(ctx, inp.ref, true)
+					m, err := s.r.Prepare(ctx, inp.ref, true, g)
 					if err != nil {
 						return err
 					}
@@ -459,12 +489,12 @@
 				if u.ByName.Input < 0 {
 					return nil, errors.Errorf("invalid user index: %d", u.ByName.Input)
 				}
-				inp, err := s.getInput(ctx, int(u.ByName.Input), inputs, actions)
+				inp, err := s.getInput(ctx, int(u.ByName.Input), inputs, actions, g)
 				if err != nil {
 					return nil, err
 				}
 				if inp.ref != nil {
-					mm, err := s.r.Prepare(ctx, inp.ref, true)
+					mm, err := s.r.Prepare(ctx, inp.ref, true, g)
 					if err != nil {
 						return nil, err
 					}
@@ -515,12 +545,11 @@
 		}
 
 		if inpMount == nil {
-			m, err := s.r.Prepare(ctx, nil, false)
+			m, err := s.r.Prepare(ctx, nil, false, g)
 			if err != nil {
 				return nil, err
 			}
 			inpMount = m
-			inpMountPrepared = true
 		}
 
 		switch a := action.Action.(type) {
@@ -546,7 +575,7 @@
 			}
 		case *pb.FileAction_Copy:
 			if inpMountSecondary == nil {
-				m, err := s.r.Prepare(ctx, nil, true)
+				m, err := s.r.Prepare(ctx, nil, true, g)
 				if err != nil {
 					return nil, err
 				}
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go
index 67aab02..3ceaaf3 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go
@@ -3,6 +3,7 @@
 import (
 	"context"
 
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver/pb"
 )
 
@@ -13,6 +14,7 @@
 type Mount interface {
 	IsFileOpMount()
 	Release(context.Context) error
+	Readonly() bool
 }
 
 type Backend interface {
@@ -23,6 +25,6 @@
 }
 
 type RefManager interface {
-	Prepare(ctx context.Context, ref Ref, readonly bool) (Mount, error)
+	Prepare(ctx context.Context, ref Ref, readonly bool, g session.Group) (Mount, error)
 	Commit(ctx context.Context, mount Mount) (Ref, error)
 }
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/source.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/source.go
index b1972ad..4f8b669 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/source.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/source.go
@@ -24,9 +24,10 @@
 	src      source.SourceInstance
 	sessM    *session.Manager
 	w        worker.Worker
+	vtx      solver.Vertex
 }
 
-func NewSourceOp(_ solver.Vertex, op *pb.Op_Source, platform *pb.Platform, sm *source.Manager, sessM *session.Manager, w worker.Worker) (solver.Op, error) {
+func NewSourceOp(vtx solver.Vertex, op *pb.Op_Source, platform *pb.Platform, sm *source.Manager, sessM *session.Manager, w worker.Worker) (solver.Op, error) {
 	if err := llbsolver.ValidateOp(&pb.Op{Op: op}); err != nil {
 		return nil, err
 	}
@@ -36,6 +37,7 @@
 		w:        w,
 		sessM:    sessM,
 		platform: platform,
+		vtx:      vtx,
 	}, nil
 }
 
@@ -49,7 +51,7 @@
 	if err != nil {
 		return nil, err
 	}
-	src, err := s.sm.Resolve(ctx, id, s.sessM)
+	src, err := s.sm.Resolve(ctx, id, s.sessM, s.vtx)
 	if err != nil {
 		return nil, err
 	}
@@ -62,7 +64,7 @@
 	if err != nil {
 		return nil, false, err
 	}
-	k, done, err := src.CacheKey(ctx, g, index)
+	k, cacheOpts, done, err := src.CacheKey(ctx, g, index)
 	if err != nil {
 		return nil, false, err
 	}
@@ -76,6 +78,7 @@
 	return &solver.CacheMap{
 		// TODO: add os/arch
 		Digest: dgst,
+		Opts:   cacheOpts,
 	}, done, nil
 }
 
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/result.go b/vendor/github.com/moby/buildkit/solver/llbsolver/result.go
index dc96e4d..4c72353 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/result.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/result.go
@@ -6,7 +6,9 @@
 	"path"
 
 	"github.com/moby/buildkit/cache/contenthash"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
 	"github.com/moby/buildkit/worker"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
@@ -19,8 +21,19 @@
 	FollowLinks bool
 }
 
+func UnlazyResultFunc(ctx context.Context, res solver.Result, g session.Group) error {
+	ref, ok := res.Sys().(*worker.WorkerRef)
+	if !ok {
+		return errors.Errorf("invalid reference: %T", res)
+	}
+	if ref.ImmutableRef == nil {
+		return nil
+	}
+	return ref.ImmutableRef.Extract(ctx, g)
+}
+
 func NewContentHashFunc(selectors []Selector) solver.ResultBasedCacheFunc {
-	return func(ctx context.Context, res solver.Result) (digest.Digest, error) {
+	return func(ctx context.Context, res solver.Result, s session.Group) (digest.Digest, error) {
 		ref, ok := res.Sys().(*worker.WorkerRef)
 		if !ok {
 			return "", errors.Errorf("invalid reference: %T", res)
@@ -35,25 +48,23 @@
 		eg, ctx := errgroup.WithContext(ctx)
 
 		for i, sel := range selectors {
-			// FIXME(tonistiigi): enabling this parallelization seems to create wrong results for some big inputs(like gobuild)
-			// func(i int) {
-			// 	eg.Go(func() error {
-			if !sel.Wildcard {
-				dgst, err := contenthash.Checksum(ctx, ref.ImmutableRef, path.Join("/", sel.Path), sel.FollowLinks)
-				if err != nil {
-					return "", err
+			i, sel := i, sel
+			eg.Go(func() error {
+				if !sel.Wildcard {
+					dgst, err := contenthash.Checksum(ctx, ref.ImmutableRef, path.Join("/", sel.Path), sel.FollowLinks, s)
+					if err != nil {
+						return err
+					}
+					dgsts[i] = []byte(dgst)
+				} else {
+					dgst, err := contenthash.ChecksumWildcard(ctx, ref.ImmutableRef, path.Join("/", sel.Path), sel.FollowLinks, s)
+					if err != nil {
+						return err
+					}
+					dgsts[i] = []byte(dgst)
 				}
-				dgsts[i] = []byte(dgst)
-			} else {
-				dgst, err := contenthash.ChecksumWildcard(ctx, ref.ImmutableRef, path.Join("/", sel.Path), sel.FollowLinks)
-				if err != nil {
-					return "", err
-				}
-				dgsts[i] = []byte(dgst)
-			}
-			// return nil
-			// })
-			// }(i)
+				return nil
+			})
 		}
 
 		if err := eg.Wait(); err != nil {
@@ -64,11 +75,13 @@
 	}
 }
 
-func workerRefConverter(ctx context.Context, res solver.Result) (*solver.Remote, error) {
-	ref, ok := res.Sys().(*worker.WorkerRef)
-	if !ok {
-		return nil, errors.Errorf("invalid result: %T", res.Sys())
-	}
+func workerRefConverter(g session.Group) func(ctx context.Context, res solver.Result) (*solver.Remote, error) {
+	return func(ctx context.Context, res solver.Result) (*solver.Remote, error) {
+		ref, ok := res.Sys().(*worker.WorkerRef)
+		if !ok {
+			return nil, errors.Errorf("invalid result: %T", res.Sys())
+		}
 
-	return ref.Worker.GetRemote(ctx, ref.ImmutableRef, true)
+		return ref.GetRemote(ctx, true, compression.Default, g)
+	}
 }
diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go b/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go
index 3d4f2da..d3ef585 100644
--- a/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go
+++ b/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go
@@ -16,6 +16,7 @@
 	"github.com/moby/buildkit/frontend/gateway"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
 	"github.com/moby/buildkit/util/entitlements"
 	"github.com/moby/buildkit/util/progress"
 	"github.com/moby/buildkit/worker"
@@ -106,7 +107,7 @@
 
 	var res *frontend.Result
 	if s.gatewayForwarder != nil && req.Definition == nil && req.Frontend == "" {
-		fwd := gateway.NewBridgeForwarder(ctx, s.Bridge(j), s.workerController, req.FrontendInputs, sessionID)
+		fwd := gateway.NewBridgeForwarder(ctx, s.Bridge(j), s.workerController, req.FrontendInputs, sessionID, s.sm)
 		defer fwd.Discard()
 		if err := s.gatewayForwarder.RegisterBuild(ctx, id, fwd); err != nil {
 			return nil, err
@@ -168,7 +169,7 @@
 			}
 			inp.Ref = workerRef.ImmutableRef
 
-			dt, err := inlineCache(ctx, exp.CacheExporter, r)
+			dt, err := inlineCache(ctx, exp.CacheExporter, r, session.NewGroup(sessionID))
 			if err != nil {
 				return nil, err
 			}
@@ -192,7 +193,7 @@
 					}
 					m[k] = workerRef.ImmutableRef
 
-					dt, err := inlineCache(ctx, exp.CacheExporter, r)
+					dt, err := inlineCache(ctx, exp.CacheExporter, r, session.NewGroup(sessionID))
 					if err != nil {
 						return nil, err
 					}
@@ -212,6 +213,7 @@
 		}
 	}
 
+	g := session.NewGroup(j.SessionID)
 	var cacheExporterResponse map[string]string
 	if e := exp.CacheExporter; e != nil {
 		if err := inBuilderContext(ctx, j, "exporting cache", "", func(ctx context.Context, _ session.Group) error {
@@ -223,8 +225,9 @@
 				}
 				// all keys have same export chain so exporting others is not needed
 				_, err = r.CacheKeys()[0].Exporter.ExportTo(ctx, e, solver.CacheExportOpt{
-					Convert: workerRefConverter,
+					Convert: workerRefConverter(g),
 					Mode:    exp.CacheExportMode,
+					Session: g,
 				})
 				return err
 			}); err != nil {
@@ -258,7 +261,7 @@
 	}, nil
 }
 
-func inlineCache(ctx context.Context, e remotecache.Exporter, res solver.CachedResult) ([]byte, error) {
+func inlineCache(ctx context.Context, e remotecache.Exporter, res solver.CachedResult, g session.Group) ([]byte, error) {
 	if efl, ok := e.(interface {
 		ExportForLayers([]digest.Digest) ([]byte, error)
 	}); ok {
@@ -267,7 +270,7 @@
 			return nil, errors.Errorf("invalid reference: %T", res.Sys())
 		}
 
-		remote, err := workerRef.Worker.GetRemote(ctx, workerRef.ImmutableRef, true)
+		remote, err := workerRef.GetRemote(ctx, true, compression.Default, g)
 		if err != nil || remote == nil {
 			return nil, nil
 		}
@@ -278,8 +281,9 @@
 		}
 
 		if _, err := res.CacheKeys()[0].Exporter.ExportTo(ctx, e, solver.CacheExportOpt{
-			Convert: workerRefConverter,
+			Convert: workerRefConverter(g),
 			Mode:    solver.CacheExportModeMin,
+			Session: g,
 		}); err != nil {
 			return nil, err
 		}
diff --git a/vendor/github.com/moby/buildkit/solver/memorycachestorage.go b/vendor/github.com/moby/buildkit/solver/memorycachestorage.go
index e0e58f0..6754d48 100644
--- a/vendor/github.com/moby/buildkit/solver/memorycachestorage.go
+++ b/vendor/github.com/moby/buildkit/solver/memorycachestorage.go
@@ -5,6 +5,7 @@
 	"sync"
 	"time"
 
+	"github.com/moby/buildkit/session"
 	"github.com/pkg/errors"
 )
 
@@ -297,7 +298,7 @@
 	return v.(Result), nil
 }
 
-func (s *inMemoryResultStore) LoadRemote(ctx context.Context, res CacheResult) (*Remote, error) {
+func (s *inMemoryResultStore) LoadRemote(_ context.Context, _ CacheResult, _ session.Group) (*Remote, error) {
 	return nil, nil
 }
 
diff --git a/vendor/github.com/moby/buildkit/solver/pb/attr.go b/vendor/github.com/moby/buildkit/solver/pb/attr.go
index f22d5d7..0bf9603 100644
--- a/vendor/github.com/moby/buildkit/solver/pb/attr.go
+++ b/vendor/github.com/moby/buildkit/solver/pb/attr.go
@@ -4,6 +4,8 @@
 const AttrFullRemoteURL = "git.fullurl"
 const AttrAuthHeaderSecret = "git.authheadersecret"
 const AttrAuthTokenSecret = "git.authtokensecret"
+const AttrKnownSSHHosts = "git.knownsshhosts"
+const AttrMountSSHSock = "git.mountsshsock"
 const AttrLocalSessionID = "local.session"
 const AttrLocalUniqueID = "local.unique"
 const AttrIncludePatterns = "local.includepattern"
diff --git a/vendor/github.com/moby/buildkit/solver/pb/caps.go b/vendor/github.com/moby/buildkit/solver/pb/caps.go
index 43a1817..5f9bc51 100644
--- a/vendor/github.com/moby/buildkit/solver/pb/caps.go
+++ b/vendor/github.com/moby/buildkit/solver/pb/caps.go
@@ -19,10 +19,12 @@
 	CapSourceLocalExcludePatterns apicaps.CapID = "source.local.excludepatterns"
 	CapSourceLocalSharedKeyHint   apicaps.CapID = "source.local.sharedkeyhint"
 
-	CapSourceGit         apicaps.CapID = "source.git"
-	CapSourceGitKeepDir  apicaps.CapID = "source.git.keepgitdir"
-	CapSourceGitFullURL  apicaps.CapID = "source.git.fullurl"
-	CapSourceGitHttpAuth apicaps.CapID = "source.git.httpauth"
+	CapSourceGit              apicaps.CapID = "source.git"
+	CapSourceGitKeepDir       apicaps.CapID = "source.git.keepgitdir"
+	CapSourceGitFullURL       apicaps.CapID = "source.git.fullurl"
+	CapSourceGitHTTPAuth      apicaps.CapID = "source.git.httpauth"
+	CapSourceGitKnownSSHHosts apicaps.CapID = "source.git.knownsshhosts"
+	CapSourceGitMountSSHSock  apicaps.CapID = "source.git.mountsshsock"
 
 	CapSourceHTTP         apicaps.CapID = "source.http"
 	CapSourceHTTPChecksum apicaps.CapID = "source.http.checksum"
@@ -133,7 +135,19 @@
 	})
 
 	Caps.Init(apicaps.Cap{
-		ID:      CapSourceGitHttpAuth,
+		ID:      CapSourceGitHTTPAuth,
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapSourceGitKnownSSHHosts,
+		Enabled: true,
+		Status:  apicaps.CapStatusExperimental,
+	})
+
+	Caps.Init(apicaps.Cap{
+		ID:      CapSourceGitMountSSHSock,
 		Enabled: true,
 		Status:  apicaps.CapStatusExperimental,
 	})
diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go b/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go
index 90e549d..93023b3 100644
--- a/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go
+++ b/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go
@@ -467,6 +467,7 @@
 	User       string    `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"`
 	ProxyEnv   *ProxyEnv `protobuf:"bytes,5,opt,name=proxy_env,json=proxyEnv,proto3" json:"proxy_env,omitempty"`
 	ExtraHosts []*HostIP `protobuf:"bytes,6,rep,name=extraHosts,proto3" json:"extraHosts,omitempty"`
+	Hostname   string    `protobuf:"bytes,7,opt,name=hostname,proto3" json:"hostname,omitempty"`
 }
 
 func (m *Meta) Reset()         { *m = Meta{} }
@@ -540,6 +541,13 @@
 	return nil
 }
 
+func (m *Meta) GetHostname() string {
+	if m != nil {
+		return m.Hostname
+	}
+	return ""
+}
+
 // Mount specifies how to mount an input Op as a filesystem.
 type Mount struct {
 	Input     InputIndex  `protobuf:"varint,1,opt,name=input,proto3,customtype=InputIndex" json:"input"`
@@ -551,6 +559,7 @@
 	CacheOpt  *CacheOpt   `protobuf:"bytes,20,opt,name=cacheOpt,proto3" json:"cacheOpt,omitempty"`
 	SecretOpt *SecretOpt  `protobuf:"bytes,21,opt,name=secretOpt,proto3" json:"secretOpt,omitempty"`
 	SSHOpt    *SSHOpt     `protobuf:"bytes,22,opt,name=SSHOpt,proto3" json:"SSHOpt,omitempty"`
+	ResultID  string      `protobuf:"bytes,23,opt,name=resultID,proto3" json:"resultID,omitempty"`
 }
 
 func (m *Mount) Reset()         { *m = Mount{} }
@@ -631,6 +640,13 @@
 	return nil
 }
 
+func (m *Mount) GetResultID() string {
+	if m != nil {
+		return m.ResultID
+	}
+	return ""
+}
+
 // CacheOpt defines options specific to cache mounts
 type CacheOpt struct {
 	// ID is an optional namespace for the mount
@@ -2316,144 +2332,146 @@
 func init() { proto.RegisterFile("ops.proto", fileDescriptor_8de16154b2733812) }
 
 var fileDescriptor_8de16154b2733812 = []byte{
-	// 2189 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4b, 0x6f, 0x1b, 0xc9,
-	0xf1, 0x17, 0xdf, 0x64, 0x51, 0x92, 0xf9, 0xef, 0xf5, 0xee, 0x9f, 0xab, 0x38, 0x92, 0x76, 0xec,
-	0x2c, 0x64, 0xd9, 0xa6, 0x00, 0x2d, 0xb0, 0x5e, 0x2c, 0x82, 0x20, 0xe2, 0xc3, 0x10, 0xd7, 0xb6,
-	0x28, 0x34, 0xfd, 0xc8, 0xcd, 0x18, 0x0d, 0x9b, 0xd4, 0x40, 0xe4, 0xf4, 0xa0, 0xa7, 0x69, 0x8b,
-	0x97, 0x1c, 0xfc, 0x09, 0x16, 0x08, 0x90, 0x5b, 0x02, 0xe4, 0x12, 0x20, 0xf7, 0x5c, 0x73, 0xdf,
-	0xe3, 0x22, 0xc8, 0x61, 0x91, 0xc3, 0x26, 0xb0, 0x3f, 0x47, 0x80, 0xa0, 0xaa, 0x7b, 0x1e, 0x94,
-	0x65, 0xd8, 0x46, 0x82, 0x9c, 0xd8, 0xfd, 0xab, 0x5f, 0x57, 0x57, 0x57, 0x55, 0xd7, 0x54, 0x13,
-	0x6a, 0x32, 0x8c, 0x5a, 0xa1, 0x92, 0x5a, 0xb2, 0x7c, 0x78, 0xb2, 0x71, 0x67, 0xe2, 0xeb, 0xd3,
-	0xf9, 0x49, 0xcb, 0x93, 0xb3, 0xbd, 0x89, 0x9c, 0xc8, 0x3d, 0x12, 0x9d, 0xcc, 0xc7, 0x34, 0xa3,
-	0x09, 0x8d, 0xcc, 0x12, 0xe7, 0x0f, 0x79, 0xc8, 0x0f, 0x42, 0xf6, 0x19, 0x94, 0xfd, 0x20, 0x9c,
-	0xeb, 0xa8, 0x99, 0xdb, 0x2e, 0xec, 0xd4, 0xf7, 0x6b, 0xad, 0xf0, 0xa4, 0xd5, 0x47, 0x84, 0x5b,
-	0x01, 0xdb, 0x86, 0xa2, 0x38, 0x17, 0x5e, 0x33, 0xbf, 0x9d, 0xdb, 0xa9, 0xef, 0x03, 0x12, 0x7a,
-	0xe7, 0xc2, 0x1b, 0x84, 0x87, 0x2b, 0x9c, 0x24, 0xec, 0x73, 0x28, 0x47, 0x72, 0xae, 0x3c, 0xd1,
-	0x2c, 0x10, 0x67, 0x15, 0x39, 0x43, 0x42, 0x88, 0x65, 0xa5, 0xa8, 0x69, 0xec, 0x4f, 0x45, 0xb3,
-	0x98, 0x6a, 0xba, 0xe7, 0x4f, 0x0d, 0x87, 0x24, 0xec, 0x3a, 0x94, 0x4e, 0xe6, 0xfe, 0x74, 0xd4,
-	0x2c, 0x11, 0xa5, 0x8e, 0x94, 0x36, 0x02, 0xc4, 0x31, 0x32, 0xb6, 0x03, 0xd5, 0x70, 0xea, 0xea,
-	0xb1, 0x54, 0xb3, 0x26, 0xa4, 0x1b, 0x1e, 0x5b, 0x8c, 0x27, 0x52, 0x76, 0x17, 0xea, 0x9e, 0x0c,
-	0x22, 0xad, 0x5c, 0x3f, 0xd0, 0x51, 0xb3, 0x4e, 0xe4, 0x8f, 0x91, 0xfc, 0x54, 0xaa, 0x33, 0xa1,
-	0x3a, 0xa9, 0x90, 0x67, 0x99, 0xed, 0x22, 0xe4, 0x65, 0xe8, 0xfc, 0x36, 0x07, 0xd5, 0x58, 0x2b,
-	0x73, 0x60, 0xf5, 0x40, 0x79, 0xa7, 0xbe, 0x16, 0x9e, 0x9e, 0x2b, 0xd1, 0xcc, 0x6d, 0xe7, 0x76,
-	0x6a, 0x7c, 0x09, 0x63, 0xeb, 0x90, 0x1f, 0x0c, 0xc9, 0x51, 0x35, 0x9e, 0x1f, 0x0c, 0x59, 0x13,
-	0x2a, 0x4f, 0x5c, 0xe5, 0xbb, 0x81, 0x26, 0xcf, 0xd4, 0x78, 0x3c, 0x65, 0xd7, 0xa0, 0x36, 0x18,
-	0x3e, 0x11, 0x2a, 0xf2, 0x65, 0x40, 0xfe, 0xa8, 0xf1, 0x14, 0x60, 0x9b, 0x00, 0x83, 0xe1, 0x3d,
-	0xe1, 0xa2, 0xd2, 0xa8, 0x59, 0xda, 0x2e, 0xec, 0xd4, 0x78, 0x06, 0x71, 0x7e, 0x0d, 0x25, 0x8a,
-	0x11, 0xfb, 0x06, 0xca, 0x23, 0x7f, 0x22, 0x22, 0x6d, 0xcc, 0x69, 0xef, 0x7f, 0xf7, 0xe3, 0xd6,
-	0xca, 0xdf, 0x7f, 0xdc, 0xda, 0xcd, 0x24, 0x83, 0x0c, 0x45, 0xe0, 0xc9, 0x40, 0xbb, 0x7e, 0x20,
-	0x54, 0xb4, 0x37, 0x91, 0x77, 0xcc, 0x92, 0x56, 0x97, 0x7e, 0xb8, 0xd5, 0xc0, 0x6e, 0x42, 0xc9,
-	0x0f, 0x46, 0xe2, 0x9c, 0xec, 0x2f, 0xb4, 0x3f, 0xb2, 0xaa, 0xea, 0x83, 0xb9, 0x0e, 0xe7, 0xba,
-	0x8f, 0x22, 0x6e, 0x18, 0xce, 0xef, 0x73, 0x50, 0x36, 0x39, 0xc0, 0xae, 0x41, 0x71, 0x26, 0xb4,
-	0x4b, 0xfb, 0xd7, 0xf7, 0xab, 0xe8, 0xdb, 0x87, 0x42, 0xbb, 0x9c, 0x50, 0x4c, 0xaf, 0x99, 0x9c,
-	0xa3, 0xef, 0xf3, 0x69, 0x7a, 0x3d, 0x44, 0x84, 0x5b, 0x01, 0xfb, 0x19, 0x54, 0x02, 0xa1, 0x5f,
-	0x48, 0x75, 0x46, 0x3e, 0x5a, 0x37, 0x41, 0x3f, 0x12, 0xfa, 0xa1, 0x1c, 0x09, 0x1e, 0xcb, 0xd8,
-	0x6d, 0xa8, 0x46, 0xc2, 0x9b, 0x2b, 0x5f, 0x2f, 0xc8, 0x5f, 0xeb, 0xfb, 0x0d, 0xca, 0x32, 0x8b,
-	0x11, 0x39, 0x61, 0x38, 0x7f, 0xca, 0x41, 0x11, 0xcd, 0x60, 0x0c, 0x8a, 0xae, 0x9a, 0x98, 0xec,
-	0xae, 0x71, 0x1a, 0xb3, 0x06, 0x14, 0x44, 0xf0, 0x9c, 0x2c, 0xaa, 0x71, 0x1c, 0x22, 0xe2, 0xbd,
-	0x18, 0xd9, 0x18, 0xe1, 0x10, 0xd7, 0xcd, 0x23, 0xa1, 0x6c, 0x68, 0x68, 0xcc, 0x6e, 0x42, 0x2d,
-	0x54, 0xf2, 0x7c, 0xf1, 0x0c, 0x57, 0x97, 0x32, 0x89, 0x87, 0x60, 0x2f, 0x78, 0xce, 0xab, 0xa1,
-	0x1d, 0xb1, 0x5d, 0x00, 0x71, 0xae, 0x95, 0x7b, 0x28, 0x23, 0x1d, 0x35, 0xcb, 0x74, 0x76, 0xca,
-	0x77, 0x04, 0xfa, 0xc7, 0x3c, 0x23, 0x75, 0xfe, 0x9a, 0x87, 0x12, 0xb9, 0x84, 0xed, 0x60, 0x04,
-	0xc2, 0xb9, 0x09, 0x66, 0xa1, 0xcd, 0x6c, 0x04, 0x80, 0x62, 0x9d, 0x04, 0x00, 0xe3, 0xbe, 0x81,
-	0xde, 0x98, 0x0a, 0x4f, 0x4b, 0x65, 0xd3, 0x2d, 0x99, 0xa3, 0xe9, 0x23, 0xcc, 0x08, 0x73, 0x1a,
-	0x1a, 0xb3, 0x5b, 0x50, 0x96, 0x14, 0x46, 0x3a, 0xd0, 0x5b, 0x82, 0x6b, 0x29, 0xa8, 0x5c, 0x09,
-	0x77, 0x24, 0x83, 0xe9, 0x82, 0x8e, 0x59, 0xe5, 0xc9, 0x9c, 0xdd, 0x82, 0x1a, 0xc5, 0xed, 0xd1,
-	0x22, 0x14, 0xcd, 0x32, 0xc5, 0x61, 0x2d, 0x89, 0x29, 0x82, 0x3c, 0x95, 0xe3, 0x45, 0xf5, 0x5c,
-	0xef, 0x54, 0x0c, 0x42, 0xdd, 0xbc, 0x9a, 0xfa, 0xab, 0x63, 0x31, 0x9e, 0x48, 0x51, 0x6d, 0x24,
-	0x3c, 0x25, 0x34, 0x52, 0x3f, 0x26, 0xea, 0x9a, 0x0d, 0xaf, 0x01, 0x79, 0x2a, 0x67, 0x0e, 0x94,
-	0x87, 0xc3, 0x43, 0x64, 0x7e, 0x92, 0x16, 0x12, 0x83, 0x70, 0x2b, 0x71, 0xfa, 0x50, 0x8d, 0xb7,
-	0xc1, 0x5b, 0xd9, 0xef, 0xda, 0xfb, 0x9a, 0xef, 0x77, 0xd9, 0x1d, 0xa8, 0x44, 0xa7, 0xae, 0xf2,
-	0x83, 0x09, 0xf9, 0x6e, 0x7d, 0xff, 0xa3, 0xc4, 0xaa, 0xa1, 0xc1, 0x51, 0x53, 0xcc, 0x71, 0x24,
-	0xd4, 0x12, 0x33, 0xde, 0xd0, 0xd5, 0x80, 0xc2, 0xdc, 0x1f, 0x91, 0x9e, 0x35, 0x8e, 0x43, 0x44,
-	0x26, 0xbe, 0xc9, 0xa5, 0x35, 0x8e, 0x43, 0x0c, 0xc8, 0x4c, 0x8e, 0x4c, 0xd9, 0x5b, 0xe3, 0x34,
-	0x46, 0x1f, 0xcb, 0x50, 0xfb, 0x32, 0x70, 0xa7, 0xb1, 0x8f, 0xe3, 0xb9, 0x33, 0x8d, 0xcf, 0xf7,
-	0x3f, 0xd9, 0xed, 0x37, 0x39, 0xa8, 0xc6, 0xb5, 0x1a, 0x0b, 0x8f, 0x3f, 0x12, 0x81, 0xf6, 0xc7,
-	0xbe, 0x50, 0x76, 0xe3, 0x0c, 0xc2, 0xee, 0x40, 0xc9, 0xd5, 0x5a, 0xc5, 0xd7, 0xf9, 0xff, 0xb3,
-	0x85, 0xbe, 0x75, 0x80, 0x92, 0x5e, 0xa0, 0xd5, 0x82, 0x1b, 0xd6, 0xc6, 0x57, 0x00, 0x29, 0x88,
-	0xb6, 0x9e, 0x89, 0x85, 0xd5, 0x8a, 0x43, 0x76, 0x15, 0x4a, 0xcf, 0xdd, 0xe9, 0x5c, 0xd8, 0x1c,
-	0x36, 0x93, 0xaf, 0xf3, 0x5f, 0xe5, 0x9c, 0xbf, 0xe4, 0xa1, 0x62, 0x0b, 0x3f, 0xbb, 0x0d, 0x15,
-	0x2a, 0xfc, 0xd6, 0xa2, 0xcb, 0x2f, 0x46, 0x4c, 0x61, 0x7b, 0xc9, 0x17, 0x2d, 0x63, 0xa3, 0x55,
-	0x65, 0xbe, 0x6c, 0xd6, 0xc6, 0xf4, 0xfb, 0x56, 0x18, 0x89, 0xb1, 0xfd, 0x74, 0xad, 0x23, 0xbb,
-	0x2b, 0xc6, 0x7e, 0xe0, 0xa3, 0x7f, 0x38, 0x8a, 0xd8, 0xed, 0xf8, 0xd4, 0x45, 0xd2, 0xf8, 0x49,
-	0x56, 0xe3, 0x9b, 0x87, 0xee, 0x43, 0x3d, 0xb3, 0xcd, 0x25, 0xa7, 0xbe, 0x91, 0x3d, 0xb5, 0xdd,
-	0x92, 0xd4, 0x99, 0xef, 0x6e, 0xea, 0x85, 0xff, 0xc0, 0x7f, 0x5f, 0x02, 0xa4, 0x2a, 0xdf, 0xbf,
-	0xb0, 0x38, 0x2f, 0x0b, 0x00, 0x83, 0x10, 0x4b, 0xe7, 0xc8, 0xa5, 0xfa, 0xbd, 0xea, 0x4f, 0x02,
-	0xa9, 0xc4, 0x33, 0xba, 0xaa, 0xb4, 0xbe, 0xca, 0xeb, 0x06, 0xa3, 0x1b, 0xc3, 0x0e, 0xa0, 0x3e,
-	0x12, 0x91, 0xa7, 0x7c, 0x4a, 0x28, 0xeb, 0xf4, 0x2d, 0x3c, 0x53, 0xaa, 0xa7, 0xd5, 0x4d, 0x19,
-	0xc6, 0x57, 0xd9, 0x35, 0x6c, 0x1f, 0x56, 0xc5, 0x79, 0x28, 0x95, 0xb6, 0xbb, 0x98, 0xfe, 0xe0,
-	0x8a, 0xe9, 0x34, 0x10, 0xa7, 0x9d, 0x78, 0x5d, 0xa4, 0x13, 0xe6, 0x42, 0xd1, 0x73, 0x43, 0xf3,
-	0x71, 0xac, 0xef, 0x37, 0x2f, 0xec, 0xd7, 0x71, 0x43, 0xe3, 0xb4, 0xf6, 0x17, 0x78, 0xd6, 0x97,
-	0xff, 0xd8, 0xba, 0x95, 0xf9, 0x22, 0xce, 0xe4, 0xc9, 0x62, 0x8f, 0xf2, 0xe5, 0xcc, 0xd7, 0x7b,
-	0x73, 0xed, 0x4f, 0xf7, 0xdc, 0xd0, 0x47, 0x75, 0xb8, 0xb0, 0xdf, 0xe5, 0xa4, 0x7a, 0xe3, 0x17,
-	0xd0, 0xb8, 0x68, 0xf7, 0x87, 0xc4, 0x60, 0xe3, 0x2e, 0xd4, 0x12, 0x3b, 0xde, 0xb5, 0xb0, 0x9a,
-	0x0d, 0xde, 0x9f, 0x73, 0x50, 0x36, 0xb7, 0x8a, 0xdd, 0x85, 0xda, 0x54, 0x7a, 0x2e, 0x1a, 0x10,
-	0xb7, 0x68, 0x9f, 0xa6, 0x97, 0xae, 0xf5, 0x20, 0x96, 0x19, 0xaf, 0xa6, 0x5c, 0x4c, 0x32, 0x3f,
-	0x18, 0xcb, 0xf8, 0x16, 0xac, 0xa7, 0x8b, 0xfa, 0xc1, 0x58, 0x72, 0x23, 0xdc, 0xb8, 0x0f, 0xeb,
-	0xcb, 0x2a, 0x2e, 0xb1, 0xf3, 0xfa, 0x72, 0xba, 0x52, 0x5d, 0x4e, 0x16, 0x65, 0xcd, 0xbe, 0x0b,
-	0xb5, 0x04, 0x67, 0xbb, 0x6f, 0x1a, 0xbe, 0x9a, 0x5d, 0x99, 0xb1, 0xd5, 0x99, 0x02, 0xa4, 0xa6,
-	0x61, 0xb1, 0xc2, 0x5e, 0x30, 0x70, 0x67, 0x71, 0x93, 0x95, 0xcc, 0xe9, 0xdb, 0xe6, 0x6a, 0x97,
-	0x4c, 0x59, 0xe5, 0x34, 0x66, 0x2d, 0x80, 0x51, 0x72, 0x61, 0xdf, 0x72, 0x8d, 0x33, 0x0c, 0x67,
-	0x00, 0xd5, 0xd8, 0x08, 0xb6, 0x0d, 0xf5, 0xc8, 0xee, 0x8c, 0x9d, 0x0f, 0x6e, 0x57, 0xe2, 0x59,
-	0x08, 0x3b, 0x18, 0xe5, 0x06, 0x13, 0xb1, 0xd4, 0xc1, 0x70, 0x44, 0xb8, 0x15, 0x38, 0x4f, 0xa1,
-	0x44, 0x00, 0x5e, 0xb3, 0x48, 0xbb, 0x4a, 0xdb, 0x66, 0xc8, 0x34, 0x07, 0x32, 0xa2, 0x6d, 0xdb,
-	0x45, 0x4c, 0x44, 0x6e, 0x08, 0xec, 0x06, 0xb6, 0x20, 0x23, 0xeb, 0xd1, 0xcb, 0x78, 0x28, 0x76,
-	0x7e, 0x0e, 0xd5, 0x18, 0xc6, 0x93, 0x3f, 0xf0, 0x03, 0x61, 0x4d, 0xa4, 0x31, 0x36, 0x91, 0x9d,
-	0x53, 0x57, 0xb9, 0x9e, 0x16, 0xa6, 0x0d, 0x28, 0xf1, 0x14, 0x70, 0xae, 0x43, 0x3d, 0x73, 0x7b,
-	0x30, 0xdd, 0x9e, 0x50, 0x18, 0xcd, 0x1d, 0x36, 0x13, 0xe7, 0x25, 0xb6, 0xb8, 0x71, 0xd7, 0xf2,
-	0x53, 0x80, 0x53, 0xad, 0xc3, 0x67, 0xd4, 0xc6, 0x58, 0xdf, 0xd7, 0x10, 0x21, 0x06, 0xdb, 0x82,
-	0x3a, 0x4e, 0x22, 0x2b, 0x37, 0xf9, 0x4e, 0x2b, 0x22, 0x43, 0xf8, 0x09, 0xd4, 0xc6, 0xc9, 0xf2,
-	0x82, 0x0d, 0x5d, 0xbc, 0xfa, 0x53, 0xa8, 0x06, 0xd2, 0xca, 0x4c, 0x57, 0x55, 0x09, 0x24, 0x89,
-	0x9c, 0x5b, 0xf0, 0x7f, 0x6f, 0xf4, 0xe3, 0xec, 0x13, 0x28, 0x8f, 0xfd, 0xa9, 0xa6, 0xa2, 0x8f,
-	0x8d, 0x9a, 0x9d, 0x39, 0xff, 0xca, 0x01, 0xa4, 0x91, 0xc5, 0x7c, 0xc5, 0xea, 0x8d, 0x9c, 0x55,
-	0x53, 0xad, 0xa7, 0x50, 0x9d, 0xd9, 0x3a, 0x60, 0x63, 0x76, 0x6d, 0x39, 0x1b, 0x5a, 0x71, 0x99,
-	0x30, 0x15, 0x62, 0xdf, 0x56, 0x88, 0x0f, 0xe9, 0x99, 0x93, 0x1d, 0xa8, 0x19, 0xc9, 0xbe, 0x7d,
-	0x20, 0xbd, 0x68, 0xdc, 0x4a, 0x36, 0xee, 0xc3, 0xda, 0xd2, 0x96, 0xef, 0xf9, 0x4d, 0x48, 0xeb,
-	0x59, 0xf6, 0x96, 0xdd, 0x86, 0xb2, 0x69, 0x22, 0x31, 0x25, 0x70, 0x64, 0xd5, 0xd0, 0x98, 0x3a,
-	0x86, 0xe3, 0xf8, 0x05, 0xd2, 0x3f, 0x76, 0xf6, 0xa1, 0x6c, 0x9e, 0x58, 0x6c, 0x07, 0x2a, 0xae,
-	0x67, 0xae, 0x63, 0xa6, 0x24, 0xa0, 0xf0, 0x80, 0x60, 0x1e, 0x8b, 0x9d, 0xbf, 0xe5, 0x01, 0x52,
-	0xfc, 0x03, 0xba, 0xd2, 0xaf, 0x61, 0x3d, 0x12, 0x9e, 0x0c, 0x46, 0xae, 0x5a, 0x90, 0xd4, 0x3e,
-	0x25, 0x2e, 0x5b, 0x72, 0x81, 0x99, 0xe9, 0x50, 0x0b, 0xef, 0xee, 0x50, 0x77, 0xa0, 0xe8, 0xc9,
-	0x70, 0x61, 0x3f, 0x14, 0x6c, 0xf9, 0x20, 0x1d, 0x19, 0x2e, 0xf0, 0x41, 0x89, 0x0c, 0xd6, 0x82,
-	0xf2, 0xec, 0x8c, 0x1e, 0x9d, 0xa6, 0x61, 0xbf, 0xba, 0xcc, 0x7d, 0x78, 0x86, 0x63, 0x7c, 0xa2,
-	0x1a, 0x16, 0xbb, 0x05, 0xa5, 0xd9, 0xd9, 0xc8, 0x57, 0xd4, 0xdb, 0xd6, 0x4d, 0x67, 0x98, 0xa5,
-	0x77, 0x7d, 0x85, 0x0f, 0x51, 0xe2, 0x30, 0x07, 0xf2, 0x6a, 0xd6, 0xac, 0x10, 0xb3, 0x71, 0xc1,
-	0x9b, 0xb3, 0xc3, 0x15, 0x9e, 0x57, 0xb3, 0x76, 0x15, 0xca, 0xc6, 0xaf, 0xce, 0x1f, 0x0b, 0xb0,
-	0xbe, 0x6c, 0x25, 0xe6, 0x41, 0xa4, 0xbc, 0x38, 0x0f, 0x22, 0xe5, 0x25, 0xcd, 0x7b, 0x3e, 0xd3,
-	0xbc, 0x3b, 0x50, 0x92, 0x2f, 0x02, 0xa1, 0xb2, 0xaf, 0xeb, 0xce, 0xa9, 0x7c, 0x11, 0x60, 0x9b,
-	0x6a, 0x44, 0x4b, 0x5d, 0x5f, 0xc9, 0x76, 0x7d, 0x37, 0x60, 0x6d, 0x2c, 0xa7, 0x53, 0xf9, 0x62,
-	0xb8, 0x98, 0x4d, 0xfd, 0xe0, 0xcc, 0xb6, 0x7e, 0xcb, 0x20, 0xdb, 0x81, 0x2b, 0x23, 0x5f, 0xa1,
-	0x39, 0x1d, 0x19, 0x68, 0x11, 0xd0, 0x7b, 0x05, 0x79, 0x17, 0x61, 0xf6, 0x0d, 0x6c, 0xbb, 0x5a,
-	0x8b, 0x59, 0xa8, 0x1f, 0x07, 0xa1, 0xeb, 0x9d, 0x75, 0xa5, 0x47, 0x77, 0x76, 0x16, 0xba, 0xda,
-	0x3f, 0xf1, 0xa7, 0xf8, 0x34, 0xab, 0xd0, 0xd2, 0x77, 0xf2, 0xd8, 0xe7, 0xb0, 0xee, 0x29, 0xe1,
-	0x6a, 0xd1, 0x15, 0x91, 0x3e, 0x76, 0xf5, 0x69, 0xb3, 0x4a, 0x2b, 0x2f, 0xa0, 0x78, 0x06, 0x17,
-	0xad, 0x7d, 0xea, 0x4f, 0x47, 0x9e, 0xab, 0x46, 0xcd, 0x9a, 0x39, 0xc3, 0x12, 0xc8, 0x5a, 0xc0,
-	0x08, 0xe8, 0xcd, 0x42, 0xbd, 0x48, 0xa8, 0x40, 0xd4, 0x4b, 0x24, 0x58, 0x38, 0xb5, 0x3f, 0x13,
-	0x91, 0x76, 0x67, 0x21, 0xfd, 0x2b, 0x50, 0xe0, 0x29, 0xe0, 0x7c, 0x9b, 0x83, 0xc6, 0xc5, 0x14,
-	0x41, 0x07, 0x87, 0x68, 0xa6, 0xbd, 0x6c, 0x38, 0x4e, 0x9c, 0x9e, 0xcf, 0x38, 0x3d, 0xfe, 0x42,
-	0x15, 0x32, 0x5f, 0xa8, 0x24, 0x80, 0xc5, 0xb7, 0x07, 0x70, 0xc9, 0xa4, 0xd2, 0x45, 0x93, 0x7e,
-	0x97, 0x83, 0x2b, 0x17, 0xd2, 0xf0, 0xbd, 0x2d, 0xda, 0x86, 0xfa, 0xcc, 0x3d, 0x13, 0xc7, 0xae,
-	0xa2, 0xe0, 0x16, 0x4c, 0x0b, 0x97, 0x81, 0xfe, 0x0b, 0xf6, 0x05, 0xb0, 0x9a, 0xcd, 0xfd, 0x4b,
-	0x6d, 0x8b, 0x43, 0x79, 0x24, 0xf5, 0x3d, 0x39, 0xb7, 0x5f, 0xbf, 0x38, 0x94, 0x31, 0xf8, 0x66,
-	0xc0, 0x0b, 0x97, 0x04, 0xdc, 0x39, 0x82, 0x6a, 0x6c, 0x20, 0xdb, 0xb2, 0x4f, 0xf5, 0x5c, 0xfa,
-	0x97, 0xd1, 0xe3, 0x48, 0x28, 0xb4, 0xdd, 0xbc, 0xdb, 0x3f, 0x83, 0xd2, 0x44, 0xc9, 0x79, 0x68,
-	0x6b, 0xeb, 0x12, 0xc3, 0x48, 0x9c, 0x21, 0x54, 0x2c, 0xc2, 0x76, 0xa1, 0x7c, 0xb2, 0x38, 0x8a,
-	0x9b, 0x0f, 0x7b, 0xb1, 0x71, 0x3e, 0xb2, 0x0c, 0xac, 0x16, 0x86, 0xc1, 0xae, 0x42, 0xf1, 0x64,
-	0xd1, 0xef, 0x9a, 0x07, 0x19, 0xd6, 0x1c, 0x9c, 0xb5, 0xcb, 0xc6, 0x20, 0xe7, 0x01, 0xac, 0x66,
-	0xd7, 0xa1, 0x53, 0x32, 0x4d, 0x0d, 0x8d, 0xd3, 0xe2, 0x9a, 0x7f, 0x47, 0x71, 0xdd, 0xdd, 0x81,
-	0x8a, 0xfd, 0x53, 0x84, 0xd5, 0xa0, 0xf4, 0xf8, 0x68, 0xd8, 0x7b, 0xd4, 0x58, 0x61, 0x55, 0x28,
-	0x1e, 0x0e, 0x86, 0x8f, 0x1a, 0x39, 0x1c, 0x1d, 0x0d, 0x8e, 0x7a, 0x8d, 0xfc, 0xee, 0x4d, 0x58,
-	0xcd, 0xfe, 0x2d, 0xc2, 0xea, 0x50, 0x19, 0x1e, 0x1c, 0x75, 0xdb, 0x83, 0x5f, 0x35, 0x56, 0xd8,
-	0x2a, 0x54, 0xfb, 0x47, 0xc3, 0x5e, 0xe7, 0x31, 0xef, 0x35, 0x72, 0xbb, 0xbf, 0x84, 0x5a, 0xf2,
-	0x72, 0x47, 0x0d, 0xed, 0xfe, 0x51, 0xb7, 0xb1, 0xc2, 0x00, 0xca, 0xc3, 0x5e, 0x87, 0xf7, 0x50,
-	0x6f, 0x05, 0x0a, 0xc3, 0xe1, 0x61, 0x23, 0x8f, 0xbb, 0x76, 0x0e, 0x3a, 0x87, 0xbd, 0x46, 0x01,
-	0x87, 0x8f, 0x1e, 0x1e, 0xdf, 0x1b, 0x36, 0x8a, 0xbb, 0x5f, 0xc2, 0x95, 0x0b, 0x2f, 0x67, 0x5a,
-	0x7d, 0x78, 0xc0, 0x7b, 0xa8, 0xa9, 0x0e, 0x95, 0x63, 0xde, 0x7f, 0x72, 0xf0, 0xa8, 0xd7, 0xc8,
-	0xa1, 0xe0, 0xc1, 0xa0, 0x73, 0xbf, 0xd7, 0x6d, 0xe4, 0xdb, 0xd7, 0xbe, 0x7b, 0xb5, 0x99, 0xfb,
-	0xfe, 0xd5, 0x66, 0xee, 0x87, 0x57, 0x9b, 0xb9, 0x7f, 0xbe, 0xda, 0xcc, 0x7d, 0xfb, 0x7a, 0x73,
-	0xe5, 0xfb, 0xd7, 0x9b, 0x2b, 0x3f, 0xbc, 0xde, 0x5c, 0x39, 0x29, 0xd3, 0x9f, 0x94, 0x5f, 0xfc,
-	0x3b, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x60, 0x46, 0x7d, 0xe4, 0x14, 0x00, 0x00,
+	// 2217 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcd, 0x6f, 0x1b, 0xc7,
+	0x15, 0x17, 0xbf, 0xc9, 0x47, 0x49, 0x66, 0x27, 0x4e, 0xc2, 0xa8, 0xae, 0xa4, 0x6c, 0xdc, 0x40,
+	0x96, 0x6d, 0x0a, 0x50, 0x80, 0x38, 0x08, 0x8a, 0xa2, 0xe2, 0x87, 0x21, 0xc6, 0xb6, 0x28, 0x0c,
+	0xfd, 0xd1, 0x9b, 0xb1, 0x5a, 0x0e, 0xa9, 0x85, 0xc8, 0x9d, 0xc5, 0xec, 0xd0, 0x16, 0x2f, 0x3d,
+	0xf8, 0x2f, 0x08, 0x50, 0xa0, 0xb7, 0x16, 0xe8, 0xa5, 0x7f, 0x41, 0xaf, 0x3d, 0x16, 0xc8, 0x31,
+	0x87, 0x1e, 0x82, 0x1e, 0xd2, 0xc2, 0xbe, 0xf7, 0x3f, 0x28, 0x50, 0xbc, 0x37, 0xb3, 0x1f, 0x94,
+	0x65, 0xd8, 0x46, 0x8b, 0x9e, 0x76, 0xe6, 0xbd, 0xdf, 0xbc, 0x79, 0xf3, 0xbe, 0xe6, 0xcd, 0x42,
+	0x4d, 0x86, 0x51, 0x2b, 0x54, 0x52, 0x4b, 0x96, 0x0f, 0x4f, 0x36, 0x6e, 0x4f, 0x7c, 0x7d, 0x3a,
+	0x3f, 0x69, 0x79, 0x72, 0xb6, 0x37, 0x91, 0x13, 0xb9, 0x47, 0xac, 0x93, 0xf9, 0x98, 0x66, 0x34,
+	0xa1, 0x91, 0x59, 0xe2, 0xfc, 0x31, 0x0f, 0xf9, 0x41, 0xc8, 0x3e, 0x85, 0xb2, 0x1f, 0x84, 0x73,
+	0x1d, 0x35, 0x73, 0xdb, 0x85, 0x9d, 0xfa, 0x7e, 0xad, 0x15, 0x9e, 0xb4, 0xfa, 0x48, 0xe1, 0x96,
+	0xc1, 0xb6, 0xa1, 0x28, 0xce, 0x85, 0xd7, 0xcc, 0x6f, 0xe7, 0x76, 0xea, 0xfb, 0x80, 0x80, 0xde,
+	0xb9, 0xf0, 0x06, 0xe1, 0xe1, 0x0a, 0x27, 0x0e, 0xfb, 0x1c, 0xca, 0x91, 0x9c, 0x2b, 0x4f, 0x34,
+	0x0b, 0x84, 0x59, 0x45, 0xcc, 0x90, 0x28, 0x84, 0xb2, 0x5c, 0x94, 0x34, 0xf6, 0xa7, 0xa2, 0x59,
+	0x4c, 0x25, 0xdd, 0xf5, 0xa7, 0x06, 0x43, 0x1c, 0xf6, 0x19, 0x94, 0x4e, 0xe6, 0xfe, 0x74, 0xd4,
+	0x2c, 0x11, 0xa4, 0x8e, 0x90, 0x36, 0x12, 0x08, 0x63, 0x78, 0x6c, 0x07, 0xaa, 0xe1, 0xd4, 0xd5,
+	0x63, 0xa9, 0x66, 0x4d, 0x48, 0x37, 0x3c, 0xb6, 0x34, 0x9e, 0x70, 0xd9, 0x1d, 0xa8, 0x7b, 0x32,
+	0x88, 0xb4, 0x72, 0xfd, 0x40, 0x47, 0xcd, 0x3a, 0x81, 0x3f, 0x44, 0xf0, 0x13, 0xa9, 0xce, 0x84,
+	0xea, 0xa4, 0x4c, 0x9e, 0x45, 0xb6, 0x8b, 0x90, 0x97, 0xa1, 0xf3, 0xbb, 0x1c, 0x54, 0x63, 0xa9,
+	0xcc, 0x81, 0xd5, 0x03, 0xe5, 0x9d, 0xfa, 0x5a, 0x78, 0x7a, 0xae, 0x44, 0x33, 0xb7, 0x9d, 0xdb,
+	0xa9, 0xf1, 0x25, 0x1a, 0x5b, 0x87, 0xfc, 0x60, 0x48, 0x86, 0xaa, 0xf1, 0xfc, 0x60, 0xc8, 0x9a,
+	0x50, 0x79, 0xec, 0x2a, 0xdf, 0x0d, 0x34, 0x59, 0xa6, 0xc6, 0xe3, 0x29, 0xbb, 0x06, 0xb5, 0xc1,
+	0xf0, 0xb1, 0x50, 0x91, 0x2f, 0x03, 0xb2, 0x47, 0x8d, 0xa7, 0x04, 0xb6, 0x09, 0x30, 0x18, 0xde,
+	0x15, 0x2e, 0x0a, 0x8d, 0x9a, 0xa5, 0xed, 0xc2, 0x4e, 0x8d, 0x67, 0x28, 0xce, 0x6f, 0xa0, 0x44,
+	0x3e, 0x62, 0xdf, 0x40, 0x79, 0xe4, 0x4f, 0x44, 0xa4, 0x8d, 0x3a, 0xed, 0xfd, 0xef, 0x7e, 0xdc,
+	0x5a, 0xf9, 0xfb, 0x8f, 0x5b, 0xbb, 0x99, 0x60, 0x90, 0xa1, 0x08, 0x3c, 0x19, 0x68, 0xd7, 0x0f,
+	0x84, 0x8a, 0xf6, 0x26, 0xf2, 0xb6, 0x59, 0xd2, 0xea, 0xd2, 0x87, 0x5b, 0x09, 0xec, 0x06, 0x94,
+	0xfc, 0x60, 0x24, 0xce, 0x49, 0xff, 0x42, 0xfb, 0x03, 0x2b, 0xaa, 0x3e, 0x98, 0xeb, 0x70, 0xae,
+	0xfb, 0xc8, 0xe2, 0x06, 0xe1, 0xfc, 0x21, 0x07, 0x65, 0x13, 0x03, 0xec, 0x1a, 0x14, 0x67, 0x42,
+	0xbb, 0xb4, 0x7f, 0x7d, 0xbf, 0x8a, 0xb6, 0x7d, 0x20, 0xb4, 0xcb, 0x89, 0x8a, 0xe1, 0x35, 0x93,
+	0x73, 0xb4, 0x7d, 0x3e, 0x0d, 0xaf, 0x07, 0x48, 0xe1, 0x96, 0xc1, 0x7e, 0x0e, 0x95, 0x40, 0xe8,
+	0xe7, 0x52, 0x9d, 0x91, 0x8d, 0xd6, 0x8d, 0xd3, 0x8f, 0x84, 0x7e, 0x20, 0x47, 0x82, 0xc7, 0x3c,
+	0x76, 0x0b, 0xaa, 0x91, 0xf0, 0xe6, 0xca, 0xd7, 0x0b, 0xb2, 0xd7, 0xfa, 0x7e, 0x83, 0xa2, 0xcc,
+	0xd2, 0x08, 0x9c, 0x20, 0x9c, 0xbf, 0xe6, 0xa0, 0x88, 0x6a, 0x30, 0x06, 0x45, 0x57, 0x4d, 0x4c,
+	0x74, 0xd7, 0x38, 0x8d, 0x59, 0x03, 0x0a, 0x22, 0x78, 0x46, 0x1a, 0xd5, 0x38, 0x0e, 0x91, 0xe2,
+	0x3d, 0x1f, 0x59, 0x1f, 0xe1, 0x10, 0xd7, 0xcd, 0x23, 0xa1, 0xac, 0x6b, 0x68, 0xcc, 0x6e, 0x40,
+	0x2d, 0x54, 0xf2, 0x7c, 0xf1, 0x14, 0x57, 0x97, 0x32, 0x81, 0x87, 0xc4, 0x5e, 0xf0, 0x8c, 0x57,
+	0x43, 0x3b, 0x62, 0xbb, 0x00, 0xe2, 0x5c, 0x2b, 0xf7, 0x50, 0x46, 0x3a, 0x6a, 0x96, 0xe9, 0xec,
+	0x14, 0xef, 0x48, 0xe8, 0x1f, 0xf3, 0x0c, 0x97, 0x6d, 0x40, 0xf5, 0x54, 0x46, 0x3a, 0x70, 0x67,
+	0xa2, 0x59, 0xa1, 0xed, 0x92, 0xb9, 0xf3, 0xaf, 0x3c, 0x94, 0xc8, 0x5c, 0x6c, 0x07, 0xbd, 0x13,
+	0xce, 0x8d, 0xa3, 0x0b, 0x6d, 0x66, 0xbd, 0x03, 0x14, 0x07, 0x89, 0x73, 0x30, 0x26, 0x36, 0xd0,
+	0x52, 0x53, 0xe1, 0x69, 0xa9, 0x6c, 0x28, 0x26, 0x73, 0x3c, 0xd6, 0x08, 0xa3, 0xc5, 0x9c, 0x94,
+	0xc6, 0xec, 0x26, 0x94, 0x25, 0xb9, 0x98, 0x0e, 0xfb, 0x06, 0xc7, 0x5b, 0x08, 0x0a, 0x57, 0xc2,
+	0x1d, 0xc9, 0x60, 0xba, 0x20, 0x13, 0x54, 0x79, 0x32, 0x67, 0x37, 0xa1, 0x46, 0x3e, 0x7d, 0xb8,
+	0x08, 0x45, 0xb3, 0x4c, 0x3e, 0x5a, 0x4b, 0xfc, 0x8d, 0x44, 0x9e, 0xf2, 0x31, 0x89, 0x3d, 0xd7,
+	0x3b, 0x15, 0x83, 0x50, 0x37, 0xaf, 0xa6, 0xb6, 0xec, 0x58, 0x1a, 0x4f, 0xb8, 0x28, 0x36, 0x12,
+	0x9e, 0x12, 0x1a, 0xa1, 0x1f, 0x12, 0x74, 0xcd, 0xba, 0xde, 0x10, 0x79, 0xca, 0x67, 0x0e, 0x94,
+	0x87, 0xc3, 0x43, 0x44, 0x7e, 0x94, 0x16, 0x19, 0x43, 0xe1, 0x96, 0x63, 0xce, 0x10, 0xcd, 0xa7,
+	0xba, 0xdf, 0x6d, 0x7e, 0x6c, 0x0c, 0x14, 0xcf, 0x9d, 0x3e, 0x54, 0x63, 0x15, 0x30, 0x9b, 0xfb,
+	0x5d, 0x9b, 0xe7, 0xf9, 0x7e, 0x97, 0xdd, 0x86, 0x4a, 0x74, 0xea, 0x2a, 0x3f, 0x98, 0x90, 0x5d,
+	0xd7, 0xf7, 0x3f, 0x48, 0x34, 0x1e, 0x1a, 0x3a, 0xee, 0x12, 0x63, 0x1c, 0x09, 0xb5, 0x44, 0xc5,
+	0xd7, 0x64, 0x35, 0xa0, 0x30, 0xf7, 0x47, 0x24, 0x67, 0x8d, 0xe3, 0x10, 0x29, 0x13, 0xdf, 0xc4,
+	0xe0, 0x1a, 0xc7, 0x21, 0x3a, 0x6b, 0x26, 0x47, 0xa6, 0x5c, 0xae, 0x71, 0x1a, 0xa3, 0xee, 0x32,
+	0xd4, 0xbe, 0x0c, 0xdc, 0x69, 0x6c, 0xff, 0x78, 0xee, 0x4c, 0xe3, 0xb3, 0xff, 0x5f, 0x76, 0xfb,
+	0x6d, 0x0e, 0xaa, 0x71, 0x8d, 0xc7, 0x82, 0xe5, 0x8f, 0x44, 0xa0, 0xfd, 0xb1, 0x2f, 0x94, 0xdd,
+	0x38, 0x43, 0x61, 0xb7, 0xa1, 0xe4, 0x6a, 0xad, 0xe2, 0x32, 0xf0, 0x71, 0xf6, 0x82, 0x68, 0x1d,
+	0x20, 0xa7, 0x17, 0x68, 0xb5, 0xe0, 0x06, 0xb5, 0xf1, 0x15, 0x40, 0x4a, 0x44, 0x5d, 0xcf, 0xc4,
+	0xc2, 0x4a, 0xc5, 0x21, 0xbb, 0x0a, 0xa5, 0x67, 0xee, 0x74, 0x2e, 0x6c, 0x7c, 0x9b, 0xc9, 0xd7,
+	0xf9, 0xaf, 0x72, 0xce, 0x5f, 0xf2, 0x50, 0xb1, 0x17, 0x06, 0xbb, 0x05, 0x15, 0xba, 0x30, 0xac,
+	0x46, 0x97, 0x27, 0x4d, 0x0c, 0x61, 0x7b, 0xc9, 0x4d, 0x98, 0xd1, 0xd1, 0x8a, 0x32, 0x37, 0xa2,
+	0xd5, 0x31, 0xbd, 0x17, 0x0b, 0x23, 0x31, 0xb6, 0x57, 0xde, 0x3a, 0xa2, 0xbb, 0x62, 0xec, 0x07,
+	0x3e, 0xda, 0x87, 0x23, 0x8b, 0xdd, 0x8a, 0x4f, 0x5d, 0x24, 0x89, 0x1f, 0x65, 0x25, 0xbe, 0x7e,
+	0xe8, 0x3e, 0xd4, 0x33, 0xdb, 0x5c, 0x72, 0xea, 0xeb, 0xd9, 0x53, 0xdb, 0x2d, 0x49, 0x9c, 0xb9,
+	0xaf, 0x53, 0x2b, 0xfc, 0x17, 0xf6, 0xfb, 0x12, 0x20, 0x15, 0xf9, 0xee, 0x45, 0xc7, 0x79, 0x51,
+	0x00, 0x18, 0x84, 0x58, 0x72, 0x47, 0x2e, 0xd5, 0xfd, 0x55, 0x7f, 0x12, 0x48, 0x25, 0x9e, 0x52,
+	0x1a, 0xd3, 0xfa, 0x2a, 0xaf, 0x1b, 0x1a, 0x65, 0x0c, 0x3b, 0x80, 0xfa, 0x48, 0x44, 0x9e, 0xf2,
+	0x29, 0xa0, 0xac, 0xd1, 0xb7, 0xf0, 0x4c, 0xa9, 0x9c, 0x56, 0x37, 0x45, 0x18, 0x5b, 0x65, 0xd7,
+	0xb0, 0x7d, 0x58, 0x15, 0xe7, 0xa1, 0x54, 0xda, 0xee, 0x62, 0xfa, 0x8a, 0x2b, 0xa6, 0x43, 0x41,
+	0x3a, 0xed, 0xc4, 0xeb, 0x22, 0x9d, 0x30, 0x17, 0x8a, 0x9e, 0x1b, 0x9a, 0x4b, 0xb5, 0xbe, 0xdf,
+	0xbc, 0xb0, 0x5f, 0xc7, 0x0d, 0x8d, 0xd1, 0xda, 0x5f, 0xe0, 0x59, 0x5f, 0xfc, 0x63, 0xeb, 0x66,
+	0xe6, 0x26, 0x9d, 0xc9, 0x93, 0xc5, 0x1e, 0xc5, 0xcb, 0x99, 0xaf, 0xf7, 0xe6, 0xda, 0x9f, 0xee,
+	0xb9, 0xa1, 0x8f, 0xe2, 0x70, 0x61, 0xbf, 0xcb, 0x49, 0xf4, 0xc6, 0x2f, 0xa1, 0x71, 0x51, 0xef,
+	0xf7, 0xf1, 0xc1, 0xc6, 0x1d, 0xa8, 0x25, 0x7a, 0xbc, 0x6d, 0x61, 0x35, 0xeb, 0xbc, 0x3f, 0xe7,
+	0xa0, 0x6c, 0xb2, 0x8a, 0xdd, 0x81, 0xda, 0x54, 0x7a, 0x2e, 0x2a, 0x10, 0xb7, 0x76, 0x9f, 0xa4,
+	0x49, 0xd7, 0xba, 0x1f, 0xf3, 0x8c, 0x55, 0x53, 0x2c, 0x06, 0x99, 0x1f, 0x8c, 0x65, 0x9c, 0x05,
+	0xeb, 0xe9, 0xa2, 0x7e, 0x30, 0x96, 0xdc, 0x30, 0x37, 0xee, 0xc1, 0xfa, 0xb2, 0x88, 0x4b, 0xf4,
+	0xfc, 0x6c, 0x39, 0x5c, 0xa9, 0x66, 0x27, 0x8b, 0xb2, 0x6a, 0xdf, 0x81, 0x5a, 0x42, 0x67, 0xbb,
+	0xaf, 0x2b, 0xbe, 0x9a, 0x5d, 0x99, 0xd1, 0xd5, 0x99, 0x02, 0xa4, 0xaa, 0x61, 0xb1, 0xc2, 0x1e,
+	0x92, 0xee, 0x51, 0xa3, 0x46, 0x32, 0xa7, 0x7b, 0xcf, 0xd5, 0x2e, 0xa9, 0xb2, 0xca, 0x69, 0xcc,
+	0x5a, 0x00, 0xa3, 0x24, 0x61, 0xdf, 0x90, 0xc6, 0x19, 0x84, 0x33, 0x80, 0x6a, 0xac, 0x04, 0xdb,
+	0x86, 0x7a, 0x64, 0x77, 0xc6, 0x8e, 0x09, 0xb7, 0x2b, 0xf1, 0x2c, 0x09, 0x3b, 0x1f, 0xe5, 0x06,
+	0x13, 0xb1, 0xd4, 0xf9, 0x70, 0xa4, 0x70, 0xcb, 0x70, 0x9e, 0x40, 0x89, 0x08, 0x98, 0x66, 0x91,
+	0x76, 0x95, 0xb6, 0x4d, 0x94, 0x69, 0x2a, 0x64, 0x44, 0xdb, 0xb6, 0x8b, 0x18, 0x88, 0xdc, 0x00,
+	0xd8, 0x75, 0x6c, 0x5d, 0x46, 0xd6, 0xa2, 0x97, 0xe1, 0x90, 0xed, 0xfc, 0x02, 0xaa, 0x31, 0x19,
+	0x4f, 0x7e, 0xdf, 0x0f, 0x84, 0x55, 0x91, 0xc6, 0xd8, 0x7c, 0x76, 0x4e, 0x5d, 0xe5, 0x7a, 0x5a,
+	0x98, 0x16, 0xa1, 0xc4, 0x53, 0x82, 0xf3, 0x19, 0xd4, 0x33, 0xd9, 0x83, 0xe1, 0xf6, 0x98, 0xdc,
+	0x68, 0x72, 0xd8, 0x4c, 0x9c, 0x17, 0xd8, 0x1a, 0xc7, 0xdd, 0xce, 0xcf, 0x00, 0x4e, 0xb5, 0x0e,
+	0x9f, 0x52, 0xfb, 0x63, 0x6d, 0x5f, 0x43, 0x0a, 0x21, 0xd8, 0x16, 0xd4, 0x71, 0x12, 0x59, 0xbe,
+	0x89, 0x77, 0x5a, 0x11, 0x19, 0xc0, 0x4f, 0xa1, 0x36, 0x4e, 0x96, 0x17, 0xac, 0xeb, 0xe2, 0xd5,
+	0x9f, 0x40, 0x35, 0x90, 0x96, 0x67, 0xba, 0xb1, 0x4a, 0x20, 0x89, 0xe5, 0xdc, 0x84, 0x9f, 0xbc,
+	0xd6, 0xc7, 0xb3, 0x8f, 0xa0, 0x3c, 0xf6, 0xa7, 0x9a, 0x8a, 0x3e, 0x36, 0x78, 0x76, 0xe6, 0xfc,
+	0x3b, 0x07, 0x90, 0x7a, 0x16, 0xe3, 0x15, 0xab, 0x37, 0x62, 0x56, 0x4d, 0xb5, 0x9e, 0x42, 0x75,
+	0x66, 0xeb, 0x80, 0xf5, 0xd9, 0xb5, 0xe5, 0x68, 0x68, 0xc5, 0x65, 0xc2, 0x54, 0x88, 0x7d, 0x5b,
+	0x21, 0xde, 0xa7, 0xd7, 0x4e, 0x76, 0xa0, 0x46, 0x25, 0xfb, 0x66, 0x82, 0x34, 0xd1, 0xb8, 0xe5,
+	0x6c, 0xdc, 0x83, 0xb5, 0xa5, 0x2d, 0xdf, 0xf1, 0x4e, 0x48, 0xeb, 0x59, 0x36, 0xcb, 0x6e, 0x41,
+	0xd9, 0x34, 0x9f, 0x18, 0x12, 0x38, 0xb2, 0x62, 0x68, 0x4c, 0x1d, 0xc3, 0x71, 0xfc, 0x72, 0xe9,
+	0x1f, 0x3b, 0xfb, 0x50, 0x36, 0x4f, 0x33, 0xb6, 0x03, 0x15, 0xd7, 0x33, 0xe9, 0x98, 0x29, 0x09,
+	0xc8, 0x3c, 0x20, 0x32, 0x8f, 0xd9, 0xce, 0xdf, 0xf2, 0x00, 0x29, 0xfd, 0x3d, 0x3a, 0xd6, 0xaf,
+	0x61, 0x3d, 0x12, 0x9e, 0x0c, 0x46, 0xae, 0x5a, 0x10, 0xd7, 0x3e, 0x41, 0x2e, 0x5b, 0x72, 0x01,
+	0x99, 0xe9, 0x5e, 0x0b, 0x6f, 0xef, 0x5e, 0x77, 0xa0, 0xe8, 0xc9, 0x70, 0x61, 0x2f, 0x0a, 0xb6,
+	0x7c, 0x90, 0x8e, 0x0c, 0x17, 0xf8, 0x10, 0x45, 0x04, 0x6b, 0x41, 0x79, 0x76, 0x46, 0x8f, 0x55,
+	0xd3, 0xe8, 0x5f, 0x5d, 0xc6, 0x3e, 0x38, 0xc3, 0x31, 0x3e, 0x6d, 0x0d, 0x8a, 0xdd, 0x84, 0xd2,
+	0xec, 0x6c, 0xe4, 0x2b, 0xea, 0x7b, 0xeb, 0xa6, 0x33, 0xcc, 0xc2, 0xbb, 0xbe, 0xc2, 0x07, 0x2c,
+	0x61, 0x98, 0x03, 0x79, 0x35, 0xa3, 0x5e, 0xbf, 0x6e, 0x5e, 0x31, 0x19, 0x6b, 0xce, 0x0e, 0x57,
+	0x78, 0x5e, 0xcd, 0xda, 0x55, 0x28, 0x1b, 0xbb, 0x3a, 0x7f, 0x2a, 0xc0, 0xfa, 0xb2, 0x96, 0x18,
+	0x07, 0x91, 0xf2, 0xe2, 0x38, 0x88, 0x94, 0x97, 0x34, 0xf6, 0xf9, 0x4c, 0x63, 0xef, 0x40, 0x49,
+	0x3e, 0x0f, 0x84, 0xca, 0xbe, 0xca, 0x3b, 0xa7, 0xf2, 0x79, 0x80, 0x6d, 0xaa, 0x61, 0x2d, 0x75,
+	0x7d, 0x25, 0xdb, 0xf5, 0x5d, 0x87, 0xb5, 0xb1, 0x9c, 0x4e, 0xe5, 0xf3, 0xe1, 0x62, 0x36, 0xf5,
+	0x83, 0x33, 0xdb, 0xfa, 0x2d, 0x13, 0xd9, 0x0e, 0x5c, 0x19, 0xf9, 0x0a, 0xd5, 0xe9, 0xc8, 0x40,
+	0x8b, 0x80, 0xde, 0x39, 0x88, 0xbb, 0x48, 0x66, 0xdf, 0xc0, 0xb6, 0xab, 0xb5, 0x98, 0x85, 0xfa,
+	0x51, 0x10, 0xba, 0xde, 0x59, 0x57, 0x7a, 0x94, 0xb3, 0xb3, 0xd0, 0xd5, 0xfe, 0x89, 0x3f, 0xc5,
+	0x27, 0x5d, 0x85, 0x96, 0xbe, 0x15, 0xc7, 0x3e, 0x87, 0x75, 0x4f, 0x09, 0x57, 0x8b, 0xae, 0x88,
+	0xf4, 0xb1, 0xab, 0x4f, 0x9b, 0x55, 0x5a, 0x79, 0x81, 0x8a, 0x67, 0x70, 0x51, 0xdb, 0x27, 0xfe,
+	0x74, 0xe4, 0xb9, 0x6a, 0xd4, 0xac, 0x99, 0x33, 0x2c, 0x11, 0x59, 0x0b, 0x18, 0x11, 0x7a, 0xb3,
+	0x50, 0x2f, 0x12, 0x28, 0x10, 0xf4, 0x12, 0x0e, 0x16, 0x4e, 0xed, 0xcf, 0x44, 0xa4, 0xdd, 0x59,
+	0x48, 0x7f, 0x13, 0x0a, 0x3c, 0x25, 0x38, 0xdf, 0xe6, 0xa0, 0x71, 0x31, 0x44, 0xd0, 0xc0, 0x21,
+	0xaa, 0x69, 0x93, 0x0d, 0xc7, 0x89, 0xd1, 0xf3, 0x19, 0xa3, 0xc7, 0x37, 0x54, 0x21, 0x73, 0x43,
+	0x25, 0x0e, 0x2c, 0xbe, 0xd9, 0x81, 0x4b, 0x2a, 0x95, 0x2e, 0xaa, 0xf4, 0xfb, 0x1c, 0x5c, 0xb9,
+	0x10, 0x86, 0xef, 0xac, 0xd1, 0x36, 0xd4, 0x67, 0xee, 0x99, 0x38, 0x76, 0x15, 0x39, 0xb7, 0x60,
+	0x5a, 0xb8, 0x0c, 0xe9, 0x7f, 0xa0, 0x5f, 0x00, 0xab, 0xd9, 0xd8, 0xbf, 0x54, 0xb7, 0xd8, 0x95,
+	0x47, 0x52, 0xdf, 0x95, 0x73, 0x7b, 0xfb, 0xc5, 0xae, 0x8c, 0x89, 0xaf, 0x3b, 0xbc, 0x70, 0x89,
+	0xc3, 0x9d, 0x23, 0xa8, 0xc6, 0x0a, 0xb2, 0x2d, 0xfb, 0xc4, 0xcf, 0xa5, 0xbf, 0x9a, 0x1e, 0x45,
+	0x42, 0xa1, 0xee, 0xe6, 0xbd, 0xff, 0x29, 0x94, 0x26, 0x4a, 0xce, 0x43, 0x5b, 0x5b, 0x97, 0x10,
+	0x86, 0xe3, 0x0c, 0xa1, 0x62, 0x29, 0x6c, 0x17, 0xca, 0x27, 0x8b, 0xa3, 0xb8, 0xf9, 0xb0, 0x89,
+	0x8d, 0xf3, 0x91, 0x45, 0x60, 0xb5, 0x30, 0x08, 0x76, 0x15, 0x8a, 0x27, 0x8b, 0x7e, 0xd7, 0x3c,
+	0xc8, 0xb0, 0xe6, 0xe0, 0xac, 0x5d, 0x36, 0x0a, 0x39, 0xf7, 0x61, 0x35, 0xbb, 0x0e, 0x8d, 0x92,
+	0x69, 0x6a, 0x68, 0x9c, 0x16, 0xd7, 0xfc, 0x5b, 0x8a, 0xeb, 0xee, 0x0e, 0x54, 0xec, 0xcf, 0x14,
+	0x56, 0x83, 0xd2, 0xa3, 0xa3, 0x61, 0xef, 0x61, 0x63, 0x85, 0x55, 0xa1, 0x78, 0x38, 0x18, 0x3e,
+	0x6c, 0xe4, 0x70, 0x74, 0x34, 0x38, 0xea, 0x35, 0xf2, 0xbb, 0x37, 0x60, 0x35, 0xfb, 0x3b, 0x85,
+	0xd5, 0xa1, 0x32, 0x3c, 0x38, 0xea, 0xb6, 0x07, 0xbf, 0x6e, 0xac, 0xb0, 0x55, 0xa8, 0xf6, 0x8f,
+	0x86, 0xbd, 0xce, 0x23, 0xde, 0x6b, 0xe4, 0x76, 0x7f, 0x05, 0xb5, 0xe4, 0x55, 0x8f, 0x12, 0xda,
+	0xfd, 0xa3, 0x6e, 0x63, 0x85, 0x01, 0x94, 0x87, 0xbd, 0x0e, 0xef, 0xa1, 0xdc, 0x0a, 0x14, 0x86,
+	0xc3, 0xc3, 0x46, 0x1e, 0x77, 0xed, 0x1c, 0x74, 0x0e, 0x7b, 0x8d, 0x02, 0x0e, 0x1f, 0x3e, 0x38,
+	0xbe, 0x3b, 0x6c, 0x14, 0x77, 0xbf, 0x84, 0x2b, 0x17, 0x5e, 0xce, 0xb4, 0xfa, 0xf0, 0x80, 0xf7,
+	0x50, 0x52, 0x1d, 0x2a, 0xc7, 0xbc, 0xff, 0xf8, 0xe0, 0x61, 0xaf, 0x91, 0x43, 0xc6, 0xfd, 0x41,
+	0xe7, 0x5e, 0xaf, 0xdb, 0xc8, 0xb7, 0xaf, 0x7d, 0xf7, 0x72, 0x33, 0xf7, 0xfd, 0xcb, 0xcd, 0xdc,
+	0x0f, 0x2f, 0x37, 0x73, 0xff, 0x7c, 0xb9, 0x99, 0xfb, 0xf6, 0xd5, 0xe6, 0xca, 0xf7, 0xaf, 0x36,
+	0x57, 0x7e, 0x78, 0xb5, 0xb9, 0x72, 0x52, 0xa6, 0x9f, 0x9b, 0x5f, 0xfc, 0x27, 0x00, 0x00, 0xff,
+	0xff, 0xa4, 0x50, 0x4f, 0x17, 0x1c, 0x15, 0x00, 0x00,
 }
 
 func (m *Op) Marshal() (dAtA []byte, err error) {
@@ -2784,6 +2802,13 @@
 	_ = i
 	var l int
 	_ = l
+	if len(m.Hostname) > 0 {
+		i -= len(m.Hostname)
+		copy(dAtA[i:], m.Hostname)
+		i = encodeVarintOps(dAtA, i, uint64(len(m.Hostname)))
+		i--
+		dAtA[i] = 0x3a
+	}
 	if len(m.ExtraHosts) > 0 {
 		for iNdEx := len(m.ExtraHosts) - 1; iNdEx >= 0; iNdEx-- {
 			{
@@ -2865,6 +2890,15 @@
 	_ = i
 	var l int
 	_ = l
+	if len(m.ResultID) > 0 {
+		i -= len(m.ResultID)
+		copy(dAtA[i:], m.ResultID)
+		i = encodeVarintOps(dAtA, i, uint64(len(m.ResultID)))
+		i--
+		dAtA[i] = 0x1
+		i--
+		dAtA[i] = 0xba
+	}
 	if m.SSHOpt != nil {
 		{
 			size, err := m.SSHOpt.MarshalToSizedBuffer(dAtA[:i])
@@ -4663,6 +4697,10 @@
 			n += 1 + l + sovOps(uint64(l))
 		}
 	}
+	l = len(m.Hostname)
+	if l > 0 {
+		n += 1 + l + sovOps(uint64(l))
+	}
 	return n
 }
 
@@ -4704,6 +4742,10 @@
 		l = m.SSHOpt.Size()
 		n += 2 + l + sovOps(uint64(l))
 	}
+	l = len(m.ResultID)
+	if l > 0 {
+		n += 2 + l + sovOps(uint64(l))
+	}
 	return n
 }
 
@@ -6359,6 +6401,38 @@
 				return err
 			}
 			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Hostname", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowOps
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthOps
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthOps
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Hostname = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipOps(dAtA[iNdEx:])
@@ -6661,6 +6735,38 @@
 				return err
 			}
 			iNdEx = postIndex
+		case 23:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ResultID", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowOps
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= uint64(b&0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthOps
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex < 0 {
+				return ErrInvalidLengthOps
+			}
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ResultID = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipOps(dAtA[iNdEx:])
diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops.proto b/vendor/github.com/moby/buildkit/solver/pb/ops.proto
index 087c346..a975e91 100644
--- a/vendor/github.com/moby/buildkit/solver/pb/ops.proto
+++ b/vendor/github.com/moby/buildkit/solver/pb/ops.proto
@@ -57,6 +57,7 @@
 	string user = 4;
 	ProxyEnv proxy_env = 5;
 	repeated HostIP extraHosts = 6;
+	string hostname = 7;
 }
 
 enum NetMode {
@@ -81,6 +82,7 @@
 	CacheOpt cacheOpt = 20;
 	SecretOpt secretOpt = 21;
 	SSHOpt SSHOpt = 22;
+	string resultID = 23;
 }
 
 // MountType defines a type of a mount from a supported set
diff --git a/vendor/github.com/moby/buildkit/solver/result.go b/vendor/github.com/moby/buildkit/solver/result.go
index c7e100b..75b378c 100644
--- a/vendor/github.com/moby/buildkit/solver/result.go
+++ b/vendor/github.com/moby/buildkit/solver/result.go
@@ -91,12 +91,12 @@
 	cr CachedResult
 }
 
-func (r *clonedCachedResult) ID() string {
-	return r.Result.ID()
+func (ccr *clonedCachedResult) ID() string {
+	return ccr.Result.ID()
 }
 
-func (cr *clonedCachedResult) CacheKeys() []ExportableCacheKey {
-	return cr.cr.CacheKeys()
+func (ccr *clonedCachedResult) CacheKeys() []ExportableCacheKey {
+	return ccr.cr.CacheKeys()
 }
 
 type SharedCachedResult struct {
diff --git a/vendor/github.com/moby/buildkit/solver/scheduler.go b/vendor/github.com/moby/buildkit/solver/scheduler.go
index 7fe981e..5b598bd 100644
--- a/vendor/github.com/moby/buildkit/solver/scheduler.go
+++ b/vendor/github.com/moby/buildkit/solver/scheduler.go
@@ -130,9 +130,13 @@
 	pf := &pipeFactory{s: s, e: e}
 
 	// unpark the edge
-	debugSchedulerPreUnpark(e, inc, updates, out)
+	if debugScheduler {
+		debugSchedulerPreUnpark(e, inc, updates, out)
+	}
 	e.unpark(inc, updates, out, pf)
-	debugSchedulerPostUnpark(e, inc)
+	if debugScheduler {
+		debugSchedulerPostUnpark(e, inc)
+	}
 
 postUnpark:
 	// set up new requests that didn't complete/were added by this run
@@ -361,9 +365,6 @@
 }
 
 func debugSchedulerPreUnpark(e *edge, inc []pipe.Sender, updates, allPipes []pipe.Receiver) {
-	if !debugScheduler {
-		return
-	}
 	logrus.Debugf(">> unpark %s req=%d upt=%d out=%d state=%s %s", e.edge.Vertex.Name(), len(inc), len(updates), len(allPipes), e.state, e.edge.Vertex.Digest())
 
 	for i, dep := range e.deps {
@@ -371,7 +372,7 @@
 		if dep.req != nil {
 			des = dep.req.Request().(*edgeRequest).desiredState
 		}
-		logrus.Debugf(":: dep%d %s state=%s des=%s keys=%d hasslowcache=%v", i, e.edge.Vertex.Inputs()[i].Vertex.Name(), dep.state, des, len(dep.keys), e.slowCacheFunc(dep) != nil)
+		logrus.Debugf(":: dep%d %s state=%s des=%s keys=%d hasslowcache=%v preprocessfunc=%v", i, e.edge.Vertex.Inputs()[i].Vertex.Name(), dep.state, des, len(dep.keys), e.slowCacheFunc(dep) != nil, e.preprocessFunc(dep) != nil)
 	}
 
 	for i, in := range inc {
@@ -400,9 +401,6 @@
 }
 
 func debugSchedulerPostUnpark(e *edge, inc []pipe.Sender) {
-	if !debugScheduler {
-		return
-	}
 	for i, in := range inc {
 		logrus.Debugf("< incoming-%d: %p completed=%v", i, in, in.Status().Completed)
 	}
diff --git a/vendor/github.com/moby/buildkit/solver/types.go b/vendor/github.com/moby/buildkit/solver/types.go
index f148ac1..76e4c91 100644
--- a/vendor/github.com/moby/buildkit/solver/types.go
+++ b/vendor/github.com/moby/buildkit/solver/types.go
@@ -95,6 +95,8 @@
 	Convert func(context.Context, Result) (*Remote, error)
 	// Mode defines a cache export algorithm
 	Mode CacheExportMode
+	// Session is the session group to client (for auth credentials etc)
+	Session session.Group
 }
 
 // CacheExporter can export the artifacts of the build chain
@@ -145,7 +147,8 @@
 	Exec(ctx context.Context, g session.Group, inputs []Result) (outputs []Result, err error)
 }
 
-type ResultBasedCacheFunc func(context.Context, Result) (digest.Digest, error)
+type ResultBasedCacheFunc func(context.Context, Result, session.Group) (digest.Digest, error)
+type PreprocessFunc func(context.Context, Result, session.Group) error
 
 // CacheMap is a description for calculating the cache key of an operation.
 type CacheMap struct {
@@ -171,7 +174,16 @@
 		// For example, in LLB this is invoked to calculate the cache key based on
 		// the checksum of file contents from input snapshots.
 		ComputeDigestFunc ResultBasedCacheFunc
+
+		// PreprocessFunc is a function that runs on an input before it is passed to op
+		PreprocessFunc PreprocessFunc
 	}
+
+	// Opts specifies generic options that will be passed to cache load calls if/when
+	// the key associated with this CacheMap is used to load a ref. It allows options
+	// such as oci descriptor content providers and progress writers to be passed to
+	// the cache. Opts should not have any impact on the computed cache key.
+	Opts CacheOpts
 }
 
 // ExportableCacheKey is a cache key connected with an exporter that can export
diff --git a/vendor/github.com/moby/buildkit/source/git/gitsource.go b/vendor/github.com/moby/buildkit/source/git/gitsource.go
index 2c96e1b..7cef764 100644
--- a/vendor/github.com/moby/buildkit/source/git/gitsource.go
+++ b/vendor/github.com/moby/buildkit/source/git/gitsource.go
@@ -6,26 +6,33 @@
 	"encoding/base64"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"net/url"
 	"os"
 	"os/exec"
+	"os/user"
 	"path/filepath"
 	"regexp"
+	"strconv"
 	"strings"
 
-	"github.com/docker/docker/pkg/locker"
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/cache/metadata"
 	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/identity"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/session/secrets"
+	"github.com/moby/buildkit/session/sshforward"
 	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/source"
 	"github.com/moby/buildkit/util/progress/logs"
+	"github.com/moby/locker"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	bolt "go.etcd.io/bbolt"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 )
 
 var validHex = regexp.MustCompile(`^[a-f0-9]{40}$`)
@@ -63,7 +70,7 @@
 }
 
 // needs to be called with repo lock
-func (gs *gitSource) mountRemote(ctx context.Context, remote string, auth []string) (target string, release func(), retErr error) {
+func (gs *gitSource) mountRemote(ctx context.Context, remote string, auth []string, g session.Group) (target string, release func(), retErr error) {
 	remoteKey := "git-remote::" + remote
 
 	sis, err := gs.md.Search(remoteKey)
@@ -87,7 +94,7 @@
 
 	initializeRepo := false
 	if remoteRef == nil {
-		remoteRef, err = gs.cache.New(ctx, nil, cache.CachePolicyRetain, cache.WithDescription(fmt.Sprintf("shared git repo for %s", remote)))
+		remoteRef, err = gs.cache.New(ctx, nil, g, cache.CachePolicyRetain, cache.WithDescription(fmt.Sprintf("shared git repo for %s", remote)))
 		if err != nil {
 			return "", nil, errors.Wrapf(err, "failed to create new mutable for %s", remote)
 		}
@@ -104,7 +111,7 @@
 		}
 	}()
 
-	mount, err := remoteRef.Mount(ctx, false)
+	mount, err := remoteRef.Mount(ctx, false, g)
 	if err != nil {
 		return "", nil, err
 	}
@@ -122,11 +129,11 @@
 	}()
 
 	if initializeRepo {
-		if _, err := gitWithinDir(ctx, dir, "", auth, "init", "--bare"); err != nil {
+		if _, err := gitWithinDir(ctx, dir, "", "", "", auth, "init", "--bare"); err != nil {
 			return "", nil, errors.Wrapf(err, "failed to init repo at %s", dir)
 		}
 
-		if _, err := gitWithinDir(ctx, dir, "", auth, "remote", "add", "origin", remote); err != nil {
+		if _, err := gitWithinDir(ctx, dir, "", "", "", auth, "remote", "add", "origin", remote); err != nil {
 			return "", nil, errors.Wrapf(err, "failed add origin repo at %s", dir)
 		}
 
@@ -166,7 +173,7 @@
 	return key
 }
 
-func (gs *gitSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager) (source.SourceInstance, error) {
+func (gs *gitSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, _ solver.Vertex) (source.SourceInstance, error) {
 	gitIdentifier, ok := id.(*source.GitIdentifier)
 	if !ok {
 		return nil, errors.Errorf("invalid git identifier %v", id)
@@ -231,7 +238,70 @@
 	})
 }
 
-func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, bool, error) {
+func (gs *gitSourceHandler) mountSSHAuthSock(ctx context.Context, sshID string, g session.Group) (string, func() error, error) {
+	var caller session.Caller
+	err := gs.sm.Any(ctx, g, func(ctx context.Context, _ string, c session.Caller) error {
+		if err := sshforward.CheckSSHID(ctx, c, sshID); err != nil {
+			if st, ok := status.FromError(err); ok && st.Code() == codes.Unimplemented {
+				return errors.Errorf("no SSH key %q forwarded from the client", sshID)
+			}
+
+			return err
+		}
+		caller = c
+		return nil
+	})
+	if err != nil {
+		return "", nil, err
+	}
+
+	usr, err := user.Current()
+	if err != nil {
+		return "", nil, err
+	}
+
+	// best effort, default to root
+	uid, _ := strconv.Atoi(usr.Uid)
+	gid, _ := strconv.Atoi(usr.Gid)
+
+	sock, cleanup, err := sshforward.MountSSHSocket(ctx, caller, sshforward.SocketOpt{
+		ID:   sshID,
+		UID:  uid,
+		GID:  gid,
+		Mode: 0700,
+	})
+	if err != nil {
+		return "", nil, err
+	}
+
+	return sock, cleanup, nil
+}
+
+func (gs *gitSourceHandler) mountKnownHosts(ctx context.Context) (string, func() error, error) {
+	if gs.src.KnownSSHHosts == "" {
+		return "", nil, errors.Errorf("no configured known hosts forwarded from the client")
+	}
+	knownHosts, err := ioutil.TempFile("", "")
+	if err != nil {
+		return "", nil, err
+	}
+	cleanup := func() error {
+		return os.Remove(knownHosts.Name())
+	}
+	_, err = knownHosts.Write([]byte(gs.src.KnownSSHHosts))
+	if err != nil {
+		cleanup()
+		return "", nil, err
+	}
+	err = knownHosts.Close()
+	if err != nil {
+		cleanup()
+		return "", nil, err
+	}
+	return knownHosts.Name(), cleanup, nil
+}
+
+func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, solver.CacheOpts, bool, error) {
 	remote := gs.src.Remote
 	ref := gs.src.Ref
 	if ref == "" {
@@ -243,36 +313,56 @@
 	if isCommitSHA(ref) {
 		ref = gs.shaToCacheKey(ref)
 		gs.cacheKey = ref
-		return ref, true, nil
+		return ref, nil, true, nil
 	}
 
 	gs.getAuthToken(ctx, g)
 
-	gitDir, unmountGitDir, err := gs.mountRemote(ctx, remote, gs.auth)
+	gitDir, unmountGitDir, err := gs.mountRemote(ctx, remote, gs.auth, g)
 	if err != nil {
-		return "", false, err
+		return "", nil, false, err
 	}
 	defer unmountGitDir()
 
+	var sock string
+	if gs.src.MountSSHSock != "" {
+		var unmountSock func() error
+		sock, unmountSock, err = gs.mountSSHAuthSock(ctx, gs.src.MountSSHSock, g)
+		if err != nil {
+			return "", nil, false, err
+		}
+		defer unmountSock()
+	}
+
+	var knownHosts string
+	if gs.src.KnownSSHHosts != "" {
+		var unmountKnownHosts func() error
+		knownHosts, unmountKnownHosts, err = gs.mountKnownHosts(ctx)
+		if err != nil {
+			return "", nil, false, err
+		}
+		defer unmountKnownHosts()
+	}
+
 	// TODO: should we assume that remote tag is immutable? add a timer?
 
-	buf, err := gitWithinDir(ctx, gitDir, "", gs.auth, "ls-remote", "origin", ref)
+	buf, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, "ls-remote", "origin", ref)
 	if err != nil {
-		return "", false, errors.Wrapf(err, "failed to fetch remote %s", remote)
+		return "", nil, false, errors.Wrapf(err, "failed to fetch remote %s", remote)
 	}
 	out := buf.String()
 	idx := strings.Index(out, "\t")
 	if idx == -1 {
-		return "", false, errors.Errorf("repository does not contain ref %s, output: %q", ref, string(out))
+		return "", nil, false, errors.Errorf("repository does not contain ref %s, output: %q", ref, string(out))
 	}
 
 	sha := string(out[:idx])
 	if !isCommitSHA(sha) {
-		return "", false, errors.Errorf("invalid commit sha %q", sha)
+		return "", nil, false, errors.Errorf("invalid commit sha %q", sha)
 	}
 	sha = gs.shaToCacheKey(sha)
 	gs.cacheKey = sha
-	return sha, true, nil
+	return sha, nil, true, nil
 }
 
 func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out cache.ImmutableRef, retErr error) {
@@ -284,7 +374,7 @@
 	cacheKey := gs.cacheKey
 	if cacheKey == "" {
 		var err error
-		cacheKey, _, err = gs.CacheKey(ctx, g, 0)
+		cacheKey, _, _, err = gs.CacheKey(ctx, g, 0)
 		if err != nil {
 			return nil, err
 		}
@@ -306,16 +396,36 @@
 
 	gs.locker.Lock(gs.src.Remote)
 	defer gs.locker.Unlock(gs.src.Remote)
-	gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.auth)
+	gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.auth, g)
 	if err != nil {
 		return nil, err
 	}
 	defer unmountGitDir()
 
+	var sock string
+	if gs.src.MountSSHSock != "" {
+		var unmountSock func() error
+		sock, unmountSock, err = gs.mountSSHAuthSock(ctx, gs.src.MountSSHSock, g)
+		if err != nil {
+			return nil, err
+		}
+		defer unmountSock()
+	}
+
+	var knownHosts string
+	if gs.src.KnownSSHHosts != "" {
+		var unmountKnownHosts func() error
+		knownHosts, unmountKnownHosts, err = gs.mountKnownHosts(ctx)
+		if err != nil {
+			return nil, err
+		}
+		defer unmountKnownHosts()
+	}
+
 	doFetch := true
 	if isCommitSHA(ref) {
 		// skip fetch if commit already exists
-		if _, err := gitWithinDir(ctx, gitDir, "", nil, "cat-file", "-e", ref+"^{commit}"); err == nil {
+		if _, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, nil, "cat-file", "-e", ref+"^{commit}"); err == nil {
 			doFetch = false
 		}
 	}
@@ -339,12 +449,12 @@
 			// in case the ref is a branch and it now points to a different commit sha
 			// TODO: is there a better way to do this?
 		}
-		if _, err := gitWithinDir(ctx, gitDir, "", gs.auth, args...); err != nil {
+		if _, err := gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, args...); err != nil {
 			return nil, errors.Wrapf(err, "failed to fetch remote %s", gs.src.Remote)
 		}
 	}
 
-	checkoutRef, err := gs.cache.New(ctx, nil, cache.WithRecordType(client.UsageRecordTypeGitCheckout), cache.WithDescription(fmt.Sprintf("git snapshot for %s#%s", gs.src.Remote, ref)))
+	checkoutRef, err := gs.cache.New(ctx, nil, g, cache.WithRecordType(client.UsageRecordTypeGitCheckout), cache.WithDescription(fmt.Sprintf("git snapshot for %s#%s", gs.src.Remote, ref)))
 	if err != nil {
 		return nil, errors.Wrapf(err, "failed to create new mutable for %s", gs.src.Remote)
 	}
@@ -355,7 +465,7 @@
 		}
 	}()
 
-	mount, err := checkoutRef.Mount(ctx, false)
+	mount, err := checkoutRef.Mount(ctx, false, g)
 	if err != nil {
 		return nil, err
 	}
@@ -375,41 +485,41 @@
 		if err := os.MkdirAll(checkoutDir, 0711); err != nil {
 			return nil, err
 		}
-		_, err = gitWithinDir(ctx, checkoutDirGit, "", nil, "init")
+		_, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, nil, "init")
 		if err != nil {
 			return nil, err
 		}
-		_, err = gitWithinDir(ctx, checkoutDirGit, "", nil, "remote", "add", "origin", gitDir)
+		_, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, nil, "remote", "add", "origin", gitDir)
 		if err != nil {
 			return nil, err
 		}
 		pullref := ref
 		if isCommitSHA(ref) {
 			pullref = "refs/buildkit/" + identity.NewID()
-			_, err = gitWithinDir(ctx, gitDir, "", gs.auth, "update-ref", pullref, ref)
+			_, err = gitWithinDir(ctx, gitDir, "", sock, knownHosts, gs.auth, "update-ref", pullref, ref)
 			if err != nil {
 				return nil, err
 			}
 		} else {
 			pullref += ":" + pullref
 		}
-		_, err = gitWithinDir(ctx, checkoutDirGit, "", gs.auth, "fetch", "-u", "--depth=1", "origin", pullref)
+		_, err = gitWithinDir(ctx, checkoutDirGit, "", sock, knownHosts, gs.auth, "fetch", "-u", "--depth=1", "origin", pullref)
 		if err != nil {
 			return nil, err
 		}
-		_, err = gitWithinDir(ctx, checkoutDirGit, checkoutDir, nil, "checkout", "FETCH_HEAD")
+		_, err = gitWithinDir(ctx, checkoutDirGit, checkoutDir, sock, knownHosts, nil, "checkout", "FETCH_HEAD")
 		if err != nil {
 			return nil, errors.Wrapf(err, "failed to checkout remote %s", gs.src.Remote)
 		}
 		gitDir = checkoutDirGit
 	} else {
-		_, err = gitWithinDir(ctx, gitDir, checkoutDir, nil, "checkout", ref, "--", ".")
+		_, err = gitWithinDir(ctx, gitDir, checkoutDir, sock, knownHosts, nil, "checkout", ref, "--", ".")
 		if err != nil {
 			return nil, errors.Wrapf(err, "failed to checkout remote %s", gs.src.Remote)
 		}
 	}
 
-	_, err = gitWithinDir(ctx, gitDir, checkoutDir, gs.auth, "submodule", "update", "--init", "--recursive", "--depth=1")
+	_, err = gitWithinDir(ctx, gitDir, checkoutDir, sock, knownHosts, gs.auth, "submodule", "update", "--init", "--recursive", "--depth=1")
 	if err != nil {
 		return nil, errors.Wrapf(err, "failed to update submodules for %s", gs.src.Remote)
 	}
@@ -458,15 +568,25 @@
 	return validHex.MatchString(str)
 }
 
-func gitWithinDir(ctx context.Context, gitDir, workDir string, auth []string, args ...string) (*bytes.Buffer, error) {
+func gitWithinDir(ctx context.Context, gitDir, workDir, sshAuthSock, knownHosts string, auth []string, args ...string) (*bytes.Buffer, error) {
 	a := append([]string{"--git-dir", gitDir}, auth...)
 	if workDir != "" {
 		a = append(a, "--work-tree", workDir)
 	}
-	return git(ctx, workDir, append(a, args...)...)
+	return git(ctx, workDir, sshAuthSock, knownHosts, append(a, args...)...)
 }
 
-func git(ctx context.Context, dir string, args ...string) (*bytes.Buffer, error) {
+func getGitSSHCommand(knownHosts string) string {
+	gitSSHCommand := "ssh -F /dev/null"
+	if knownHosts != "" {
+		gitSSHCommand += " -o UserKnownHostsFile=" + knownHosts
+	} else {
+		gitSSHCommand += " -o StrictHostKeyChecking=no"
+	}
+	return gitSSHCommand
+}
+
+func git(ctx context.Context, dir, sshAuthSock, knownHosts string, args ...string) (*bytes.Buffer, error) {
 	for {
 		stdout, stderr := logs.NewLogStreams(ctx, false)
 		defer stdout.Close()
@@ -481,8 +601,12 @@
 		cmd.Env = []string{
 			"PATH=" + os.Getenv("PATH"),
 			"GIT_TERMINAL_PROMPT=0",
+			"GIT_SSH_COMMAND=" + getGitSSHCommand(knownHosts),
 			//	"GIT_TRACE=1",
 		}
+		if sshAuthSock != "" {
+			cmd.Env = append(cmd.Env, "SSH_AUTH_SOCK="+sshAuthSock)
+		}
 		// remote git commands spawn helper processes that inherit FDs and don't
 		// handle parent death signal so exec.CommandContext can't be used
 		err := runProcessGroup(ctx, cmd)
diff --git a/vendor/github.com/moby/buildkit/source/gitidentifier.go b/vendor/github.com/moby/buildkit/source/gitidentifier.go
index 65f3f69..680af6a 100644
--- a/vendor/github.com/moby/buildkit/source/gitidentifier.go
+++ b/vendor/github.com/moby/buildkit/source/gitidentifier.go
@@ -14,6 +14,8 @@
 	KeepGitDir       bool
 	AuthTokenSecret  string
 	AuthHeaderSecret string
+	MountSSHSock     string
+	KnownSSHHosts    string
 }
 
 func NewGitIdentifier(remoteURL string) (*GitIdentifier, error) {
diff --git a/vendor/github.com/moby/buildkit/source/http/httpsource.go b/vendor/github.com/moby/buildkit/source/http/httpsource.go
index 951d99c..dd9c127 100644
--- a/vendor/github.com/moby/buildkit/source/http/httpsource.go
+++ b/vendor/github.com/moby/buildkit/source/http/httpsource.go
@@ -16,13 +16,14 @@
 	"time"
 
 	"github.com/docker/docker/pkg/idtools"
-	"github.com/docker/docker/pkg/locker"
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/cache/metadata"
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/source"
 	"github.com/moby/buildkit/util/tracing"
+	"github.com/moby/locker"
 	digest "github.com/opencontainers/go-digest"
 	"github.com/pkg/errors"
 	bolt "go.etcd.io/bbolt"
@@ -56,19 +57,19 @@
 }
 
 func (hs *httpSource) ID() string {
-	return source.HttpsScheme
+	return source.HTTPSScheme
 }
 
 type httpSourceHandler struct {
 	*httpSource
-	src      source.HttpIdentifier
+	src      source.HTTPIdentifier
 	refID    string
 	cacheKey digest.Digest
 	sm       *session.Manager
 }
 
-func (hs *httpSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager) (source.SourceInstance, error) {
-	httpIdentifier, ok := id.(*source.HttpIdentifier)
+func (hs *httpSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, _ solver.Vertex) (source.SourceInstance, error) {
+	httpIdentifier, ok := id.(*source.HTTPIdentifier)
 	if !ok {
 		return nil, errors.Errorf("invalid http identifier %v", id)
 	}
@@ -122,26 +123,26 @@
 	return digest.FromBytes(dt)
 }
 
-func (hs *httpSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, bool, error) {
+func (hs *httpSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, solver.CacheOpts, bool, error) {
 	if hs.src.Checksum != "" {
 		hs.cacheKey = hs.src.Checksum
-		return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, nil), hs.src.Checksum, "").String(), true, nil
+		return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, nil), hs.src.Checksum, "").String(), nil, true, nil
 	}
 
 	uh, err := hs.urlHash()
 	if err != nil {
-		return "", false, nil
+		return "", nil, false, nil
 	}
 
 	// look up metadata(previously stored headers) for that URL
 	sis, err := hs.md.Search(uh.String())
 	if err != nil {
-		return "", false, errors.Wrapf(err, "failed to search metadata for %s", uh)
+		return "", nil, false, errors.Wrapf(err, "failed to search metadata for %s", uh)
 	}
 
 	req, err := http.NewRequest("GET", hs.src.URL, nil)
 	if err != nil {
-		return "", false, err
+		return "", nil, false, err
 	}
 	req = req.WithContext(ctx)
 	m := map[string]*metadata.StorageItem{}
@@ -198,7 +199,7 @@
 					if dgst != "" {
 						modTime := getModTime(si)
 						resp.Body.Close()
-						return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, modTime).String(), true, nil
+						return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, modTime).String(), nil, true, nil
 					}
 				}
 			}
@@ -209,10 +210,10 @@
 
 	resp, err := client.Do(req)
 	if err != nil {
-		return "", false, err
+		return "", nil, false, err
 	}
 	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		return "", false, errors.Errorf("invalid response status %d", resp.StatusCode)
+		return "", nil, false, errors.Errorf("invalid response status %d", resp.StatusCode)
 	}
 	if resp.StatusCode == http.StatusNotModified {
 		respETag := resp.Header.Get("ETag")
@@ -225,31 +226,31 @@
 		}
 		si, ok := m[respETag]
 		if !ok {
-			return "", false, errors.Errorf("invalid not-modified ETag: %v", respETag)
+			return "", nil, false, errors.Errorf("invalid not-modified ETag: %v", respETag)
 		}
 		hs.refID = si.ID()
 		dgst := getChecksum(si)
 		if dgst == "" {
-			return "", false, errors.Errorf("invalid metadata change")
+			return "", nil, false, errors.Errorf("invalid metadata change")
 		}
 		modTime := getModTime(si)
 		resp.Body.Close()
-		return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, modTime).String(), true, nil
+		return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, modTime).String(), nil, true, nil
 	}
 
-	ref, dgst, err := hs.save(ctx, resp)
+	ref, dgst, err := hs.save(ctx, resp, g)
 	if err != nil {
-		return "", false, err
+		return "", nil, false, err
 	}
 	ref.Release(context.TODO())
 
 	hs.cacheKey = dgst
 
-	return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, resp.Header.Get("Last-Modified")).String(), true, nil
+	return hs.formatCacheKey(getFileName(hs.src.URL, hs.src.Filename, resp), dgst, resp.Header.Get("Last-Modified")).String(), nil, true, nil
 }
 
-func (hs *httpSourceHandler) save(ctx context.Context, resp *http.Response) (ref cache.ImmutableRef, dgst digest.Digest, retErr error) {
-	newRef, err := hs.cache.New(ctx, nil, cache.CachePolicyRetain, cache.WithDescription(fmt.Sprintf("http url %s", hs.src.URL)))
+func (hs *httpSourceHandler) save(ctx context.Context, resp *http.Response, s session.Group) (ref cache.ImmutableRef, dgst digest.Digest, retErr error) {
+	newRef, err := hs.cache.New(ctx, nil, s, cache.CachePolicyRetain, cache.WithDescription(fmt.Sprintf("http url %s", hs.src.URL)))
 	if err != nil {
 		return nil, "", err
 	}
@@ -264,7 +265,7 @@
 		}
 	}()
 
-	mount, err := newRef.Mount(ctx, false)
+	mount, err := newRef.Mount(ctx, false, s)
 	if err != nil {
 		return nil, "", err
 	}
@@ -391,7 +392,7 @@
 		return nil, err
 	}
 
-	ref, dgst, err := hs.save(ctx, resp)
+	ref, dgst, err := hs.save(ctx, resp, g)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/source/identifier.go b/vendor/github.com/moby/buildkit/source/identifier.go
index fd500a1..1120bd7 100644
--- a/vendor/github.com/moby/buildkit/source/identifier.go
+++ b/vendor/github.com/moby/buildkit/source/identifier.go
@@ -30,8 +30,8 @@
 	DockerImageScheme = "docker-image"
 	GitScheme         = "git"
 	LocalScheme       = "local"
-	HttpScheme        = "http"
-	HttpsScheme       = "https"
+	HTTPScheme        = "http"
+	HTTPSScheme       = "https"
 )
 
 type Identifier interface {
@@ -52,10 +52,10 @@
 		return NewGitIdentifier(parts[1])
 	case LocalScheme:
 		return NewLocalIdentifier(parts[1])
-	case HttpsScheme:
-		return NewHttpIdentifier(parts[1], true)
-	case HttpScheme:
-		return NewHttpIdentifier(parts[1], false)
+	case HTTPSScheme:
+		return NewHTTPIdentifier(parts[1], true)
+	case HTTPScheme:
+		return NewHTTPIdentifier(parts[1], false)
 	default:
 		return nil, errors.Wrapf(errNotFound, "unknown schema %s", parts[0])
 	}
@@ -107,6 +107,10 @@
 				id.AuthHeaderSecret = v
 			case pb.AttrAuthTokenSecret:
 				id.AuthTokenSecret = v
+			case pb.AttrKnownSSHHosts:
+				id.KnownSSHHosts = v
+			case pb.AttrMountSSHSock:
+				id.MountSSHSock = v
 			}
 		}
 	}
@@ -142,7 +146,7 @@
 			}
 		}
 	}
-	if id, ok := id.(*HttpIdentifier); ok {
+	if id, ok := id.(*HTTPIdentifier); ok {
 		for k, v := range op.Source.Attrs {
 			switch k {
 			case pb.AttrHTTPChecksum:
@@ -196,7 +200,7 @@
 	return &ImageIdentifier{Reference: ref}, nil
 }
 
-func (_ *ImageIdentifier) ID() string {
+func (*ImageIdentifier) ID() string {
 	return DockerImageScheme
 }
 
@@ -217,15 +221,15 @@
 	return LocalScheme
 }
 
-func NewHttpIdentifier(str string, tls bool) (*HttpIdentifier, error) {
+func NewHTTPIdentifier(str string, tls bool) (*HTTPIdentifier, error) {
 	proto := "https://"
 	if !tls {
 		proto = "http://"
 	}
-	return &HttpIdentifier{TLS: tls, URL: proto + str}, nil
+	return &HTTPIdentifier{TLS: tls, URL: proto + str}, nil
 }
 
-type HttpIdentifier struct {
+type HTTPIdentifier struct {
 	TLS      bool
 	URL      string
 	Checksum digest.Digest
@@ -235,8 +239,8 @@
 	GID      int
 }
 
-func (_ *HttpIdentifier) ID() string {
-	return HttpsScheme
+func (*HTTPIdentifier) ID() string {
+	return HTTPSScheme
 }
 
 func (r ResolveMode) String() string {
diff --git a/vendor/github.com/moby/buildkit/source/local/local.go b/vendor/github.com/moby/buildkit/source/local/local.go
index 06241d0..3d385ab 100644
--- a/vendor/github.com/moby/buildkit/source/local/local.go
+++ b/vendor/github.com/moby/buildkit/source/local/local.go
@@ -14,6 +14,7 @@
 	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/session/filesync"
 	"github.com/moby/buildkit/snapshot"
+	"github.com/moby/buildkit/solver"
 	"github.com/moby/buildkit/source"
 	"github.com/moby/buildkit/util/progress"
 	digest "github.com/opencontainers/go-digest"
@@ -51,7 +52,7 @@
 	return source.LocalScheme
 }
 
-func (ls *localSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager) (source.SourceInstance, error) {
+func (ls *localSource) Resolve(ctx context.Context, id source.Identifier, sm *session.Manager, _ solver.Vertex) (source.SourceInstance, error) {
 	localIdentifier, ok := id.(*source.LocalIdentifier)
 	if !ok {
 		return nil, errors.Errorf("invalid local identifier %v", id)
@@ -70,13 +71,13 @@
 	*localSource
 }
 
-func (ls *localSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, bool, error) {
+func (ls *localSourceHandler) CacheKey(ctx context.Context, g session.Group, index int) (string, solver.CacheOpts, bool, error) {
 	sessionID := ls.src.SessionID
 
 	if sessionID == "" {
 		id := g.SessionIterator().NextSession()
 		if id == "" {
-			return "", false, errors.New("could not access local files without session")
+			return "", nil, false, errors.New("could not access local files without session")
 		}
 		sessionID = id
 	}
@@ -87,15 +88,15 @@
 		FollowPaths     []string
 	}{SessionID: sessionID, IncludePatterns: ls.src.IncludePatterns, ExcludePatterns: ls.src.ExcludePatterns, FollowPaths: ls.src.FollowPaths})
 	if err != nil {
-		return "", false, err
+		return "", nil, false, err
 	}
-	return "session:" + ls.src.Name + ":" + digest.FromBytes(dt).String(), true, nil
+	return "session:" + ls.src.Name + ":" + digest.FromBytes(dt).String(), nil, true, nil
 }
 
 func (ls *localSourceHandler) Snapshot(ctx context.Context, g session.Group) (cache.ImmutableRef, error) {
 	var ref cache.ImmutableRef
 	err := ls.sm.Any(ctx, g, func(ctx context.Context, _ string, c session.Caller) error {
-		r, err := ls.snapshot(ctx, c)
+		r, err := ls.snapshot(ctx, g, c)
 		if err != nil {
 			return err
 		}
@@ -108,7 +109,7 @@
 	return ref, nil
 }
 
-func (ls *localSourceHandler) snapshot(ctx context.Context, caller session.Caller) (out cache.ImmutableRef, retErr error) {
+func (ls *localSourceHandler) snapshot(ctx context.Context, s session.Group, caller session.Caller) (out cache.ImmutableRef, retErr error) {
 	sharedKey := keySharedKey + ":" + ls.src.Name + ":" + ls.src.SharedKeyHint + ":" + caller.SharedKey() // TODO: replace caller.SharedKey() with source based hint from client(absolute-path+nodeid)
 
 	var mutable cache.MutableRef
@@ -125,7 +126,7 @@
 	}
 
 	if mutable == nil {
-		m, err := ls.cm.New(ctx, nil, cache.CachePolicyRetain, cache.WithRecordType(client.UsageRecordTypeLocalSource), cache.WithDescription(fmt.Sprintf("local source for %s", ls.src.Name)))
+		m, err := ls.cm.New(ctx, nil, s, cache.CachePolicyRetain, cache.WithRecordType(client.UsageRecordTypeLocalSource), cache.WithDescription(fmt.Sprintf("local source for %s", ls.src.Name)))
 		if err != nil {
 			return nil, err
 		}
@@ -145,7 +146,7 @@
 		}
 	}()
 
-	mount, err := mutable.Mount(ctx, false)
+	mount, err := mutable.Mount(ctx, false, s)
 	if err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/moby/buildkit/source/manager.go b/vendor/github.com/moby/buildkit/source/manager.go
index 9539389..aba45bf 100644
--- a/vendor/github.com/moby/buildkit/source/manager.go
+++ b/vendor/github.com/moby/buildkit/source/manager.go
@@ -6,16 +6,17 @@
 
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/solver"
 	"github.com/pkg/errors"
 )
 
 type Source interface {
 	ID() string
-	Resolve(ctx context.Context, id Identifier, sm *session.Manager) (SourceInstance, error)
+	Resolve(ctx context.Context, id Identifier, sm *session.Manager, vtx solver.Vertex) (SourceInstance, error)
 }
 
 type SourceInstance interface {
-	CacheKey(ctx context.Context, g session.Group, index int) (string, bool, error)
+	CacheKey(ctx context.Context, g session.Group, index int) (string, solver.CacheOpts, bool, error)
 	Snapshot(ctx context.Context, g session.Group) (cache.ImmutableRef, error)
 }
 
@@ -36,7 +37,7 @@
 	sm.mu.Unlock()
 }
 
-func (sm *Manager) Resolve(ctx context.Context, id Identifier, sessM *session.Manager) (SourceInstance, error) {
+func (sm *Manager) Resolve(ctx context.Context, id Identifier, sessM *session.Manager, vtx solver.Vertex) (SourceInstance, error) {
 	sm.mu.Lock()
 	src, ok := sm.sources[id.ID()]
 	sm.mu.Unlock()
@@ -45,5 +46,5 @@
 		return nil, errors.Errorf("no handler for %s", id.ID())
 	}
 
-	return src.Resolve(ctx, id, sessM)
+	return src.Resolve(ctx, id, sessM, vtx)
 }
diff --git a/vendor/github.com/moby/buildkit/util/apicaps/pb/generate.go b/vendor/github.com/moby/buildkit/util/apicaps/pb/generate.go
index 281dfab..addfccf 100644
--- a/vendor/github.com/moby/buildkit/util/apicaps/pb/generate.go
+++ b/vendor/github.com/moby/buildkit/util/apicaps/pb/generate.go
@@ -1,3 +1,3 @@
-package moby_buildkit_v1_apicaps
+package moby_buildkit_v1_apicaps //nolint:golint
 
 //go:generate protoc -I=. -I=../../../vendor/ -I=../../../../../../ --gogo_out=plugins=grpc:. caps.proto
diff --git a/vendor/github.com/moby/buildkit/util/archutil/386_binary.go b/vendor/github.com/moby/buildkit/util/archutil/386_binary.go
new file mode 100644
index 0000000..dab00ec
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/386_binary.go
@@ -0,0 +1,8 @@
+// +build !386
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binary386 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xec\xd8\x31\x8a\xc2\x40\x14\x06\xe0\x7f\x36\xb3\xd9\x84\xdd\x62\x0e\x10\x96\x2d\xb6\xd8\x6a\x58\x21\x57\x50\x1b\x11\x2c\x3c\x80\x62\xd0\x2a\x09\xc9\x08\x5a\x99\x23\x78\x18\x0b\x4b\x2f\x20\xd8\x5b\x7b\x0f\x79\xc9\x0b\xa4\x48\x63\xff\x3e\xf8\x19\x7c\xf3\x7c\xa9\xdf\x1c\x86\x93\x91\x52\x0a\xad\x37\x78\xa8\x7f\x1d\x75\x10\x03\xf8\x37\x4d\x3d\xc6\x0f\x34\xfe\xa0\xdb\x7b\x52\xe9\x80\x72\x03\x40\xd1\x54\x33\x68\xee\x4d\x33\x83\x12\x02\xa0\xbc\x73\x9d\xfa\x4e\x94\x4a\x07\x94\x08\x40\xc4\xff\xa7\xcc\x1e\x6e\x85\x1e\x3e\x8f\xa5\x9e\x2f\x9e\x37\x9e\xce\xe9\x7b\x17\xaa\x29\x08\x21\x84\x10\x42\x08\x21\x84\x10\xa2\xcf\x99\x96\xe6\xc1\xfd\x5a\xc1\x96\x9b\xd2\x15\x6e\xb1\x84\x4d\x33\x97\xd8\x75\xba\xb5\x79\x91\xe5\x49\xe1\xf6\xb0\x2e\xd9\xb9\x57\xe6\x7e\x02\xf8\xa8\xdf\x13\x78\xcf\xe7\x1d\xbf\xa5\xf9\xfc\xe6\xbd\xdd\xe7\x37\x07\x5a\xf0\xc3\x4e\x9f\xea\x9c\x5e\xa7\x1e\x1a\xe0\xb7\xa7\xef\x19\x00\x00\xff\xff\x32\x71\x64\x98\xd0\x10\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/386_check.go b/vendor/github.com/moby/buildkit/util/archutil/386_check.go
similarity index 78%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/386_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/386_check.go
index 8137d35..5ef488f 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/386_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/386_check.go
@@ -1,6 +1,6 @@
 // +build !386
 
-package binfmt_misc
+package archutil
 
 func i386Supported() error {
 	return check(Binary386)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/386_check_386.go b/vendor/github.com/moby/buildkit/util/archutil/386_check_386.go
similarity index 74%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/386_check_386.go
rename to vendor/github.com/moby/buildkit/util/archutil/386_check_386.go
index 2b2ab45..f2c0ee3 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/386_check_386.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/386_check_386.go
@@ -1,6 +1,6 @@
 // +build 386
 
-package binfmt_misc
+package archutil
 
 func i386Supported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/archutil/amd64_binary.go b/vendor/github.com/moby/buildkit/util/archutil/amd64_binary.go
new file mode 100644
index 0000000..59f135f
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/amd64_binary.go
@@ -0,0 +1,8 @@
+// +build !amd64
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binaryamd64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x06\x3b\x06\x30\x4f\xc0\x01\xcc\x77\x80\x8a\x1b\x08\xc0\x95\x30\x38\x30\x58\x30\xb0\x30\x38\x30\xb0\x30\x30\x83\xd5\xb2\x30\x20\x03\x07\x14\xda\x01\x6a\x34\x8c\x66\x80\x9a\x03\xe2\xb2\x22\xf1\x61\xf6\xc1\x68\x1e\xa8\x30\x8c\x86\xa9\x63\x81\x62\x05\xa8\x79\x0a\x8c\x0e\xa8\x34\x54\x39\x8c\xe6\x80\xd2\x81\x4f\x4b\x52\xd8\x18\x88\x07\x30\x67\xb1\x40\xd9\x20\xb7\xba\xfb\x85\x82\xdc\x7d\x80\x05\xea\xfe\x51\x30\x0a\x46\xc1\x28\x18\x05\xa3\x60\x14\x8c\x82\x51\x30\x0a\x46\xc1\x28\x18\x05\xa3\x60\xa8\x00\x8f\xe3\x07\x6c\x40\x94\xe1\x7f\x7e\x56\x06\xbd\xe2\x8c\xe2\x92\xa2\x92\xc4\x24\x06\xbd\xbc\xfc\x92\x54\xbd\xf4\xbc\x52\xbd\x82\xa2\xfc\x82\xd4\xa2\x92\x4a\x06\xbd\x92\xd4\x8a\x12\x8a\xed\xe3\x66\x60\x60\x60\x07\x8f\x33\xa0\xf7\xdf\x51\xfb\xed\x0c\x68\xfd\x77\x18\x90\x83\xf6\xbd\xe1\x7d\x79\xf8\xb8\x01\xda\x78\x01\x03\x62\x9c\x01\x9d\xcf\x8c\xc5\x5d\x3c\x50\xfd\x2a\x04\xf4\x03\x02\x00\x00\xff\xff\x90\x57\x64\xbb\x30\x11\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_check.go b/vendor/github.com/moby/buildkit/util/archutil/amd64_check.go
similarity index 79%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/amd64_check.go
index 6191338..3942860 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/amd64_check.go
@@ -1,6 +1,6 @@
 // +build !amd64
 
-package binfmt_misc
+package archutil
 
 func amd64Supported() error {
 	return check(Binaryamd64)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_check_amd64.go b/vendor/github.com/moby/buildkit/util/archutil/amd64_check_amd64.go
similarity index 75%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_check_amd64.go
rename to vendor/github.com/moby/buildkit/util/archutil/amd64_check_amd64.go
index e437dfe..538840d 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_check_amd64.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/amd64_check_amd64.go
@@ -1,6 +1,6 @@
 // +build amd64
 
-package binfmt_misc
+package archutil
 
 func amd64Supported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/archutil/arm64_binary.go b/vendor/github.com/moby/buildkit/util/archutil/arm64_binary.go
new file mode 100644
index 0000000..f5b7fef
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/arm64_binary.go
@@ -0,0 +1,8 @@
+// +build !arm64
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binaryarm64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x86\xed\x0c\x20\xde\x06\x06\x07\x30\xdf\x01\x2a\x7e\x81\x01\x01\x1c\x18\x2c\x18\x98\x18\x1c\x18\x98\x19\x98\xc0\x6a\x59\x19\x18\x50\x64\x91\xe9\x3d\x50\xde\x1e\xb8\x3c\xc4\xae\xc0\xa7\x25\x29\x6c\x0c\xc4\x03\x01\x38\xab\xe1\xd2\x0a\xee\x86\x4b\x8c\x0c\x0c\x57\x18\xf4\x8a\x33\x8a\x4b\x8a\x4a\x12\x93\x18\xf4\x4a\x52\x2b\x4a\x18\xa8\x00\xb8\xa1\x2e\x84\xb9\x0d\x16\x0e\x1b\xa0\x7c\x1e\x34\xf5\x2c\x68\x7c\x90\x5e\x66\x2c\xe6\xc2\xfc\x2f\x88\x45\x3d\x32\x00\x04\x00\x00\xff\xff\xbb\x46\x88\x1e\x90\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_check.go b/vendor/github.com/moby/buildkit/util/archutil/arm64_check.go
similarity index 79%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/arm64_check.go
index 334d314..76600d0 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/arm64_check.go
@@ -1,6 +1,6 @@
 // +build !arm64
 
-package binfmt_misc
+package archutil
 
 func arm64Supported() error {
 	return check(Binaryarm64)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_check_arm64.go b/vendor/github.com/moby/buildkit/util/archutil/arm64_check_arm64.go
similarity index 75%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_check_arm64.go
rename to vendor/github.com/moby/buildkit/util/archutil/arm64_check_arm64.go
index a5fc6dc..1b1c8c6 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_check_arm64.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/arm64_check_arm64.go
@@ -1,6 +1,6 @@
 // +build arm64
 
-package binfmt_misc
+package archutil
 
 func arm64Supported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go b/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go
new file mode 100644
index 0000000..15e6f25
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go
@@ -0,0 +1,8 @@
+// +build !arm
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binaryarm = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\x8c\x8f\x3d\x6e\xc2\x40\x10\x85\xbf\x89\x7f\x12\x29\x29\x92\x9c\x20\xe9\xa8\xb6\xf2\x05\x5c\x40\x05\x05\xdc\x60\x2d\x2c\xe1\xce\xb2\x07\x89\x0e\xce\xc0\x09\x7c\x08\x6e\x64\x51\x73\x05\xe4\x65\x2d\xb6\x70\xc1\x93\x46\xb3\xfb\xcd\x2b\xde\x3b\xce\x97\x0b\x11\x61\xd4\x1b\x33\x86\x9f\x22\x64\xc0\xe5\x01\x93\x8c\x3f\x77\x8b\x89\x78\xba\xc5\xcd\x09\xdc\x24\x9e\xad\xaf\xba\x65\x42\x29\xf0\xed\x5e\x5d\x2f\x75\xd7\x03\xb7\xfc\x07\xb0\xa5\x2d\x2a\xe4\x1d\xf8\x10\x4c\xbb\x6b\xb5\x51\x5b\x60\xb4\x3c\x28\x26\xdf\xac\x8c\x55\x6d\xaa\x62\xaf\x65\xcb\xcb\xfa\xf4\x09\x53\xdf\x47\x81\xaf\xe0\x1e\xfb\x3d\x44\x88\xa0\x1e\xf9\xd0\xe5\x37\xf0\x49\xb0\xa3\x80\x9f\x81\xff\x09\xdf\x3d\x00\x00\xff\xff\x0b\x8f\xbf\xbd\x54\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_check.go b/vendor/github.com/moby/buildkit/util/archutil/arm_check.go
similarity index 78%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/arm_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/arm_check.go
index 3a10daa..745e705 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/arm_check.go
@@ -1,6 +1,6 @@
 // +build !arm
 
-package binfmt_misc
+package archutil
 
 func armSupported() error {
 	return check(Binaryarm)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_check_arm.go b/vendor/github.com/moby/buildkit/util/archutil/arm_check_arm.go
similarity index 74%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/arm_check_arm.go
rename to vendor/github.com/moby/buildkit/util/archutil/arm_check_arm.go
index 11cfe61..d6dea6f 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_check_arm.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/arm_check_arm.go
@@ -1,6 +1,6 @@
 // +build arm
 
-package binfmt_misc
+package archutil
 
 func armSupported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/check_unix.go b/vendor/github.com/moby/buildkit/util/archutil/check_unix.go
similarity index 97%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/check_unix.go
rename to vendor/github.com/moby/buildkit/util/archutil/check_unix.go
index 670e6d2..236c96a 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/check_unix.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/check_unix.go
@@ -1,6 +1,6 @@
 // +build !windows
 
-package binfmt_misc
+package archutil
 
 import (
 	"bytes"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/check_windows.go b/vendor/github.com/moby/buildkit/util/archutil/check_windows.go
similarity index 90%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/check_windows.go
rename to vendor/github.com/moby/buildkit/util/archutil/check_windows.go
index f246184..18ec34d 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/check_windows.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/check_windows.go
@@ -1,6 +1,6 @@
 // +build windows
 
-package binfmt_misc
+package archutil
 
 import (
 	"errors"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/detect.go b/vendor/github.com/moby/buildkit/util/archutil/detect.go
similarity index 89%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/detect.go
rename to vendor/github.com/moby/buildkit/util/archutil/detect.go
index 73eb405..7b4673c 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/detect.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/detect.go
@@ -1,4 +1,4 @@
-package binfmt_misc
+package archutil
 
 import (
 	"strings"
@@ -82,37 +82,37 @@
 		if p != def {
 			if p == "linux/amd64" {
 				if err := amd64Supported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 			if p == "linux/arm64" {
 				if err := arm64Supported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 			if p == "linux/riscv64" {
 				if err := riscv64Supported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 			if p == "linux/ppc64le" {
 				if err := ppc64leSupported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 			if p == "linux/s390x" {
 				if err := s390xSupported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 			if p == "linux/386" {
 				if err := i386Supported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 			if strings.HasPrefix(p, "linux/arm/v6") || strings.HasPrefix(p, "linux/arm/v7") {
 				if err := armSupported(); err != nil {
-					printPlatfromWarning(p, err)
+					printPlatformWarning(p, err)
 				}
 			}
 		}
@@ -123,11 +123,11 @@
 	return platforms.Format(platforms.Normalize(platforms.DefaultSpec()))
 }
 
-func printPlatfromWarning(p string, err error) {
+func printPlatformWarning(p string, err error) {
 	if strings.Contains(err.Error(), "exec format error") {
 		logrus.Warnf("platform %s cannot pass the validation, kernel support for miscellaneous binary may have not enabled.", p)
 	} else if strings.Contains(err.Error(), "no such file or directory") {
-		logrus.Warnf("platforms %s cannot pass the validation, '-F' flag might have not set for 'binfmt_misc'.", p)
+		logrus.Warnf("platforms %s cannot pass the validation, '-F' flag might have not set for 'archutil'.", p)
 	} else {
 		logrus.Warnf("platforms %s cannot pass the validation: %s", p, err.Error())
 	}
diff --git a/vendor/github.com/moby/buildkit/util/archutil/ppc64le_binary.go b/vendor/github.com/moby/buildkit/util/archutil/ppc64le_binary.go
new file mode 100644
index 0000000..3e4d4b3
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/ppc64le_binary.go
@@ -0,0 +1,8 @@
+// +build !ppc64le
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binaryppc64le = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x06\x51\x06\x10\x6f\x03\x03\x83\x00\x88\xef\x00\x15\xbf\x01\x97\x07\x89\x59\x30\x30\x31\x38\x30\xb0\x30\x30\x83\xd5\xb2\x32\xa0\x00\x01\x64\x7a\x0f\x94\xb3\x07\x2e\x0d\xb1\x2b\xf0\x69\x49\x0a\x1b\x03\xf1\x40\x00\xa1\xdb\x82\x81\x21\xc1\x82\x89\x81\xc1\x85\x41\xaf\x38\xa3\xb8\xa4\xa8\x24\x31\x89\x41\xaf\x24\xb5\xa2\x84\x41\x2f\x35\x23\x3e\xad\x28\x31\x37\x95\x81\x62\xc0\x0d\x75\x29\xcc\x8d\xb0\xf0\xd8\x00\xe5\xf3\xa0\xa9\xe7\x40\xe3\x0b\x42\xf5\x33\x21\xfc\x2f\x80\x1a\x0e\xa8\x80\x05\x8d\x0f\xd2\xcb\x8c\x45\x1d\x4c\xbf\x34\x16\xf5\xc8\x00\x10\x00\x00\xff\xff\x59\x3e\xf6\x64\xd8\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_check.go b/vendor/github.com/moby/buildkit/util/archutil/ppc64le_check.go
similarity index 80%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/ppc64le_check.go
index 4d5b3bf..0172583 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/ppc64le_check.go
@@ -1,6 +1,6 @@
 // +build !ppc64le
 
-package binfmt_misc
+package archutil
 
 func ppc64leSupported() error {
 	return check(Binaryppc64le)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_check_ppc64le.go b/vendor/github.com/moby/buildkit/util/archutil/ppc64le_check_ppc64le.go
similarity index 76%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_check_ppc64le.go
rename to vendor/github.com/moby/buildkit/util/archutil/ppc64le_check_ppc64le.go
index 27e4ab8..7da12d4 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_check_ppc64le.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/ppc64le_check_ppc64le.go
@@ -1,6 +1,6 @@
 // +build ppc64le
 
-package binfmt_misc
+package archutil
 
 func ppc64leSupported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/archutil/riscv64_binary.go b/vendor/github.com/moby/buildkit/util/archutil/riscv64_binary.go
new file mode 100644
index 0000000..a5e115d
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/riscv64_binary.go
@@ -0,0 +1,8 @@
+// +build !riscv64
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binaryriscv64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x86\xcf\x0c\x20\xde\x06\x06\x88\x98\x03\x54\xfc\x02\x94\x66\x01\x8b\x59\x30\x30\x31\x38\x30\x30\x33\x30\x81\x55\xb1\x32\x20\x03\x46\x14\x7a\x0f\x94\x07\xa3\x19\x04\x20\x54\xe0\xd3\x92\x14\x36\x06\xe2\x01\x54\x1b\x83\x30\x2b\x03\xc3\x64\x8e\x0b\xac\xc5\x20\x8e\x5e\x71\x46\x71\x49\x51\x49\x62\x12\x83\x5e\x49\x6a\x45\x09\x03\x15\x00\x37\xd4\xe5\x30\xb7\xc1\xc2\x61\x03\x94\xcf\x83\xa6\x9e\x05\x8d\x0f\x52\xcd\x8c\xc5\x5c\x98\xff\x05\xb1\xa8\x47\x06\x80\x00\x00\x00\xff\xff\x34\x4f\x05\xf7\x90\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_check.go b/vendor/github.com/moby/buildkit/util/archutil/riscv64_check.go
similarity index 80%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/riscv64_check.go
index c2f31f7..c1272d0 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/riscv64_check.go
@@ -1,6 +1,6 @@
 // +build !riscv64
 
-package binfmt_misc
+package archutil
 
 func riscv64Supported() error {
 	return check(Binaryriscv64)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_check_riscv64.go b/vendor/github.com/moby/buildkit/util/archutil/riscv64_check_riscv64.go
similarity index 76%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_check_riscv64.go
rename to vendor/github.com/moby/buildkit/util/archutil/riscv64_check_riscv64.go
index 7ae5736..ceeb560 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_check_riscv64.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/riscv64_check_riscv64.go
@@ -1,6 +1,6 @@
 // +build riscv64
 
-package binfmt_misc
+package archutil
 
 func riscv64Supported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/archutil/s390x_binary.go b/vendor/github.com/moby/buildkit/util/archutil/s390x_binary.go
new file mode 100644
index 0000000..0f43a0b
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/archutil/s390x_binary.go
@@ -0,0 +1,8 @@
+// +build !s390x
+
+package archutil
+
+// This file is generated by running make inside the archutil package.
+// Do not edit manually.
+
+const Binarys390x = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x62\x64\x80\x03\x26\x06\x31\x06\x06\x06\xb0\x00\x23\x03\xc3\x06\xa8\xa8\x03\x94\xbe\x00\xe5\x59\x30\x30\x31\x38\x30\x30\x33\x30\x41\xd5\xb2\x32\x20\x01\x46\x34\x9a\x81\x81\x61\x07\x2a\x2d\xc0\x90\x52\xf2\x34\x90\x81\x81\x81\x8d\x81\x34\x20\xb0\x5c\x93\x81\x81\x8b\x91\x9d\x9d\x41\xaf\x38\xa3\xb8\xa4\xa8\x24\x31\x89\x41\xaf\x24\xb5\xa2\x84\x81\x7a\x80\x1b\xc9\xe9\x6c\x68\xe1\x00\xa3\x39\xd0\xf4\xb0\xa0\x79\x9f\x19\x87\xd9\xb0\x70\x10\x44\x13\x87\x07\x15\x20\x00\x00\xff\xff\x28\x7b\x76\xee\x90\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_check.go b/vendor/github.com/moby/buildkit/util/archutil/s390x_check.go
similarity index 79%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_check.go
rename to vendor/github.com/moby/buildkit/util/archutil/s390x_check.go
index 1d5b4a0..89f5cf4 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_check.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/s390x_check.go
@@ -1,6 +1,6 @@
 // +build !s390x
 
-package binfmt_misc
+package archutil
 
 func s390xSupported() error {
 	return check(Binarys390x)
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_check_s390x.go b/vendor/github.com/moby/buildkit/util/archutil/s390x_check_s390x.go
similarity index 75%
rename from vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_check_s390x.go
rename to vendor/github.com/moby/buildkit/util/archutil/s390x_check_s390x.go
index 9255422..664bb15 100644
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_check_s390x.go
+++ b/vendor/github.com/moby/buildkit/util/archutil/s390x_check_s390x.go
@@ -1,6 +1,6 @@
 // +build s390x
 
-package binfmt_misc
+package archutil
 
 func s390xSupported() error {
 	return nil
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/386_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/386_binary.go
deleted file mode 100644
index 580f152..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/386_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !386
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binary386 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xec\xd8\x31\x6e\xc2\x30\x14\x06\xe0\xdf\x8d\xdb\x26\x6a\x07\x1f\x20\xaa\x3a\x74\xe8\x64\xb5\x52\xae\x00\x2c\x88\x8d\x03\x80\x14\xc1\x94\x44\x89\x91\x60\x22\x47\x60\xe0\x20\x8c\x8c\x5c\x80\x13\x70\x19\xf4\xe2\x67\x91\x81\x25\xfb\xfb\xa4\x5f\x16\xcf\xe6\x29\xeb\x7b\xfb\xd1\x74\xac\x94\x42\xf0\x82\x08\xdd\xaf\x83\x8e\x33\x00\x7f\xc6\xd7\x33\x7c\x23\xc2\x2f\x74\xb8\x27\xad\x8e\x29\x27\x00\x14\x4d\x35\x03\x7f\x6f\x7c\x0f\x4a\x02\x80\xf2\xca\x75\x7a\x77\xa4\xb4\x3a\xa6\xa4\x00\x52\xfe\x7f\xc8\x27\xbf\x9f\xcc\xe6\xd4\xef\x42\xb5\xc7\x57\x0a\x21\x84\x10\x42\x08\x21\x84\x10\x62\x88\x33\x0d\xd5\xff\xb7\x6b\x0b\xdb\xac\x1b\x57\xbb\xc5\x12\xb6\x28\x5d\x6e\x57\xc5\xc6\x56\x75\x59\xe5\xb5\xdb\xc1\xba\x7c\xeb\x86\xf4\xfd\x00\xf0\xde\xed\x13\x78\xce\xe7\x19\x3f\xd0\x7c\x7e\xf1\x5c\xff\xc6\x3b\x07\x18\xbf\x2b\x08\x54\xef\x8c\x7a\xf5\xc4\x00\x3f\x4f\xde\xdd\x03\x00\x00\xff\xff\x8d\xf7\xd2\x72\xd0\x10\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_binary.go
deleted file mode 100644
index 3cafea9..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/amd64_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !amd64
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binaryamd64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x06\x3b\x06\x30\x4f\xc0\x01\xcc\x77\x80\x8a\x1b\x08\xc0\x95\x30\x38\x30\x58\x30\x30\x33\x38\x30\xb0\x30\x30\x83\xd5\xb2\x30\x20\x03\x07\x14\x9a\x03\x6a\x34\x8c\x66\x80\x9a\x03\xe2\xb2\x22\xf1\x61\xf6\xc1\x68\x1e\xa8\x30\x8c\x86\xa9\x63\x81\xe2\x17\x50\xe1\x17\x50\x7b\x60\xb4\x02\x54\x1c\x46\x73\x30\x20\xf4\x09\x40\xed\x74\xf7\x0b\x05\xd9\x7f\x80\x05\xea\x8e\x51\x30\x0a\x46\xc1\x28\x18\x05\xa3\x60\x14\x8c\x82\x51\x30\x0a\x46\xc1\x28\x18\x05\xa3\x60\xb8\x03\x8f\xe3\x07\x6c\x40\x94\xe1\x7f\x7e\x56\x06\xbd\xe2\x8c\xe2\x92\xa2\x92\xc4\x24\x06\xbd\xbc\xfc\x92\x54\xbd\xf4\xbc\x52\xbd\x82\xa2\xfc\x82\xd4\xa2\x92\x4a\x06\xbd\x92\xd4\x8a\x12\x8a\xed\xe3\x66\x60\x60\x60\x07\x8f\x33\xa0\xf7\xdf\x51\xfb\xed\x0c\x68\xfd\x77\x18\x90\x83\xf6\xd9\xd9\x18\xd0\xc7\x0d\xd0\xc6\x0b\x18\x10\xe3\x0c\xe8\x7c\x66\x2c\xee\xe2\x81\xea\x57\x21\xa0\x1f\x10\x00\x00\xff\xff\x8a\x1b\xd7\x73\x30\x11\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_binary.go
deleted file mode 100644
index 01cdf9a..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm64_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !arm64
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binaryarm64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x86\xed\x0c\x20\x5e\x05\x83\x03\x98\xef\x00\x15\x9f\xc1\x80\x00\x0e\x0c\x16\x0c\x8c\x0c\x0e\x0c\xcc\x0c\x4c\x60\xb5\xac\x0c\x0c\x28\xb2\xc8\x74\x0b\x94\xd7\x02\x97\x87\xd9\xd5\x70\x69\x05\x77\xc3\x25\x46\x06\x86\x2b\x0c\x7a\xc5\x19\xc5\x25\x45\x25\x89\x49\x0c\x7a\x25\xa9\x15\x25\x0c\x54\x00\xdc\x50\x9b\xd8\xa0\x7c\x98\x7f\x2a\xa0\x7c\x1e\x34\xf5\x2c\x68\x7c\x90\x5e\x66\x2c\xe6\xc2\xfc\x21\x88\x45\x3d\x32\x00\x04\x00\x00\xff\xff\xe7\x30\x54\x02\x58\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_binary.go
deleted file mode 100644
index c780578..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/arm_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !arm
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binaryarm = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\x8c\x8e\x31\x0e\x82\x40\x14\x44\xdf\x17\x50\x13\x6d\xf4\x04\xda\x51\x6d\xc5\x05\x28\xb4\xd2\xc6\x70\x00\x97\x84\x44\x3a\x02\xdf\xc4\xce\x4b\x78\x00\xee\xc6\x01\xbc\x82\x01\x17\xdd\xc2\xc2\x49\x26\x93\x7d\x3b\xc9\x9f\xfb\xee\xb0\x17\x11\x46\x4d\x88\xe9\x5f\x19\x42\x02\x3c\xde\x30\x4a\xd8\x20\xc4\x84\x04\x7c\xdb\x32\xf8\x0c\x83\xa3\x0f\x6b\x3b\xa9\xda\x0e\x78\xa6\x2b\xc0\x16\x36\x2f\x91\x19\x30\x17\x4c\x73\x69\xb4\x56\x9b\x63\xb4\xb8\x29\x26\x3d\x1d\x8d\x55\xad\xcb\xfc\xaa\x45\xc3\xdf\x5a\xb8\x6b\x53\xb7\x37\x03\x96\xde\x7f\xe8\xb2\x9f\x10\x40\x35\xf2\x7e\xeb\xda\xeb\x89\x97\x81\xc7\x6b\x60\xfb\xa3\xf7\x0a\x00\x00\xff\xff\x73\x8f\xca\xf1\x34\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_binary.go
deleted file mode 100644
index 511db71..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/ppc64le_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !ppc64le
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binaryppc64le = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x06\x51\x06\x10\xaf\x82\x81\x41\x00\xc4\x77\x80\x8a\x2f\x80\xcb\x83\xc4\x2c\x18\x18\x19\x1c\x18\x58\x18\x98\xc1\x6a\x59\x19\x50\x80\x00\x32\xdd\x02\xe5\xb4\xc0\xa5\x19\x61\xa4\x05\x03\x43\x82\x05\x13\x03\x83\x0b\x83\x5e\x71\x46\x71\x49\x51\x49\x62\x12\x83\x5e\x49\x6a\x45\x09\x83\x5e\x6a\x46\x7c\x5a\x51\x62\x6e\x2a\x03\xc5\x80\x1b\x6a\x23\x1b\x94\x0f\xf3\x57\x05\x94\xcf\x83\xa6\x9e\x03\x8d\x2f\x08\xd5\xcf\x84\xf0\x87\x00\xaa\x7f\x50\x01\x0b\x1a\x1f\xa4\x97\x19\x8b\x3a\x98\x7e\x69\x2c\xea\x91\x01\x20\x00\x00\xff\xff\xce\xf7\x15\x75\xa0\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_binary.go
deleted file mode 100644
index 146618e..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/riscv64_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !riscv64
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binaryriscv64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x86\xcf\x0c\x20\x5e\x05\x03\x44\xcc\x01\x2a\x3e\x03\x4a\xb3\x80\xc5\x2c\x18\x18\x19\x1c\x18\x98\x19\x98\xc0\xaa\x58\x19\x90\x01\x23\x0a\xdd\x02\xe5\xc1\x68\x06\x01\x08\x25\xcc\xca\xc0\x30\x99\xe3\x02\x6b\x31\x88\xa3\x57\x9c\x51\x5c\x52\x54\x92\x98\xc4\xa0\x57\x92\x5a\x51\xc2\x40\x05\xc0\x0d\x75\x01\x1b\x94\x0f\xf3\x4f\x05\x94\xcf\x83\xa6\x9e\x05\x8d\x0f\x52\xcd\x8c\xc5\x5c\x98\x3f\x04\xb1\xa8\x47\x06\x80\x00\x00\x00\xff\xff\x39\x41\xdf\xa1\x58\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_binary.go b/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_binary.go
deleted file mode 100644
index 3d34c2e..0000000
--- a/vendor/github.com/moby/buildkit/util/binfmt_misc/s390x_binary.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !s390x
-
-package binfmt_misc
-
-// This file is generated by running make inside the binfmt_misc package.
-// Do not edit manually.
-
-const Binarys390x = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x62\x64\x80\x03\x26\x06\x31\x06\x06\x06\xb0\x00\x23\x03\x43\x05\x54\xd4\x01\x4a\xcf\x80\xf2\x2c\x18\x18\x19\x1c\x18\x98\x19\x98\xa0\x6a\x59\x19\x90\x00\x23\x1a\xcd\xc0\xc0\xd0\x80\x4a\x0b\x30\x2c\xd7\x64\x60\xe0\x62\x64\x67\x67\xd0\x2b\xce\x28\x2e\x29\x2a\x49\x4c\x62\xd0\x2b\x49\xad\x28\x61\xa0\x1e\xe0\x46\x72\x02\x1b\x9a\x7f\x60\x34\x07\x9a\x1e\x16\x34\x6f\x30\xe3\x30\x1b\xe6\x1f\x41\x34\x71\xb8\x97\x01\x01\x00\x00\xff\xff\x0c\x76\x9a\xe1\x58\x01\x00\x00"
diff --git a/vendor/github.com/moby/buildkit/util/compression/compression.go b/vendor/github.com/moby/buildkit/util/compression/compression.go
new file mode 100644
index 0000000..f63d293
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/compression/compression.go
@@ -0,0 +1,136 @@
+package compression
+
+import (
+	"bytes"
+	"context"
+	"io"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/images"
+	digest "github.com/opencontainers/go-digest"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+// Type represents compression type for blob data.
+type Type int
+
+const (
+	// Uncompressed indicates no compression.
+	Uncompressed Type = iota
+
+	// Gzip is used for blob data.
+	Gzip
+
+	// UnknownCompression means not supported yet.
+	UnknownCompression Type = -1
+)
+
+var Default = Gzip
+
+func (ct Type) String() string {
+	switch ct {
+	case Uncompressed:
+		return "uncompressed"
+	case Gzip:
+		return "gzip"
+	default:
+		return "unknown"
+	}
+}
+
+// DetectLayerMediaType returns media type from existing blob data.
+func DetectLayerMediaType(ctx context.Context, cs content.Store, id digest.Digest, oci bool) (string, error) {
+	ra, err := cs.ReaderAt(ctx, ocispec.Descriptor{Digest: id})
+	if err != nil {
+		return "", err
+	}
+	defer ra.Close()
+
+	ct, err := detectCompressionType(content.NewReader(ra))
+	if err != nil {
+		return "", err
+	}
+
+	switch ct {
+	case Uncompressed:
+		if oci {
+			return ocispec.MediaTypeImageLayer, nil
+		}
+		return images.MediaTypeDockerSchema2Layer, nil
+	case Gzip:
+		if oci {
+			return ocispec.MediaTypeImageLayerGzip, nil
+		}
+		return images.MediaTypeDockerSchema2LayerGzip, nil
+	default:
+		return "", errors.Errorf("failed to detect layer %v compression type", id)
+	}
+}
+
+// detectCompressionType detects compression type from real blob data.
+func detectCompressionType(cr io.Reader) (Type, error) {
+	var buf [10]byte
+	var n int
+	var err error
+
+	if n, err = cr.Read(buf[:]); err != nil && err != io.EOF {
+		// Note: we'll ignore any io.EOF error because there are some
+		// odd cases where the layer.tar file will be empty (zero bytes)
+		// and we'll just treat it as a non-compressed stream and that
+		// means just create an empty layer.
+		//
+		// See issue docker/docker#18170
+		return UnknownCompression, err
+	}
+
+	for c, m := range map[Type][]byte{
+		Gzip: {0x1F, 0x8B, 0x08},
+	} {
+		if n < len(m) {
+			continue
+		}
+		if bytes.Equal(m, buf[:len(m)]) {
+			return c, nil
+		}
+	}
+	return Uncompressed, nil
+}
+
+var toDockerLayerType = map[string]string{
+	ocispec.MediaTypeImageLayer:            images.MediaTypeDockerSchema2Layer,
+	images.MediaTypeDockerSchema2Layer:     images.MediaTypeDockerSchema2Layer,
+	ocispec.MediaTypeImageLayerGzip:        images.MediaTypeDockerSchema2LayerGzip,
+	images.MediaTypeDockerSchema2LayerGzip: images.MediaTypeDockerSchema2LayerGzip,
+}
+
+var toOCILayerType = map[string]string{
+	ocispec.MediaTypeImageLayer:            ocispec.MediaTypeImageLayer,
+	images.MediaTypeDockerSchema2Layer:     ocispec.MediaTypeImageLayer,
+	ocispec.MediaTypeImageLayerGzip:        ocispec.MediaTypeImageLayerGzip,
+	images.MediaTypeDockerSchema2LayerGzip: ocispec.MediaTypeImageLayerGzip,
+}
+
+func convertLayerMediaType(mediaType string, oci bool) string {
+	var converted string
+	if oci {
+		converted = toOCILayerType[mediaType]
+	} else {
+		converted = toDockerLayerType[mediaType]
+	}
+	if converted == "" {
+		logrus.Warnf("unhandled conversion for mediatype %q", mediaType)
+		return mediaType
+	}
+	return converted
+}
+
+func ConvertAllLayerMediaTypes(oci bool, descs ...ocispec.Descriptor) []ocispec.Descriptor {
+	var converted []ocispec.Descriptor
+	for _, desc := range descs {
+		desc.MediaType = convertLayerMediaType(desc.MediaType, oci)
+		converted = append(converted, desc)
+	}
+	return converted
+}
diff --git a/vendor/github.com/moby/buildkit/util/contentutil/copy.go b/vendor/github.com/moby/buildkit/util/contentutil/copy.go
index 060d7a9..08c6047 100644
--- a/vendor/github.com/moby/buildkit/util/contentutil/copy.go
+++ b/vendor/github.com/moby/buildkit/util/contentutil/copy.go
@@ -8,12 +8,13 @@
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/remotes"
+	"github.com/moby/buildkit/util/resolver/retryhandler"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 )
 
-func Copy(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispec.Descriptor) error {
-	if _, err := remotes.FetchHandler(ingester, &localFetcher{provider})(ctx, desc); err != nil {
+func Copy(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispec.Descriptor, logger func([]byte)) error {
+	if _, err := retryhandler.New(remotes.FetchHandler(ingester, &localFetcher{provider}), logger)(ctx, desc); err != nil {
 		return err
 	}
 	return nil
@@ -64,7 +65,7 @@
 	handlers := []images.Handler{
 		images.ChildrenHandler(provider),
 		filterHandler,
-		remotes.FetchHandler(ingester, &localFetcher{provider}),
+		retryhandler.New(remotes.FetchHandler(ingester, &localFetcher{provider}), nil),
 	}
 
 	if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
@@ -72,7 +73,7 @@
 	}
 
 	for i := len(manifestStack) - 1; i >= 0; i-- {
-		if err := Copy(ctx, ingester, provider, manifestStack[i]); err != nil {
+		if err := Copy(ctx, ingester, provider, manifestStack[i], nil); err != nil {
 			return errors.WithStack(err)
 		}
 	}
diff --git a/vendor/github.com/moby/buildkit/util/contentutil/refs.go b/vendor/github.com/moby/buildkit/util/contentutil/refs.go
index e62d798..9e41ea0 100644
--- a/vendor/github.com/moby/buildkit/util/contentutil/refs.go
+++ b/vendor/github.com/moby/buildkit/util/contentutil/refs.go
@@ -9,7 +9,7 @@
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
-	"github.com/docker/docker/pkg/locker"
+	"github.com/moby/locker"
 	digest "github.com/opencontainers/go-digest"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
diff --git a/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go b/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go
index 7c0fe84..08e4408 100644
--- a/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go
+++ b/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go
@@ -154,7 +154,7 @@
 	}
 	defer fd.Close()
 
-	const _LOOP_CTL_GET_FREE = 0x4C82
+	const _LOOP_CTL_GET_FREE = 0x4C82 //nolint:golint
 	r1, _, uerr := unix.Syscall(unix.SYS_IOCTL, fd.Fd(), _LOOP_CTL_GET_FREE, 0)
 	if uerr == 0 {
 		return int(r1), nil
diff --git a/vendor/github.com/moby/buildkit/util/grpcerrors/grpcerrors.go b/vendor/github.com/moby/buildkit/util/grpcerrors/grpcerrors.go
index acba275..f12f10b 100644
--- a/vendor/github.com/moby/buildkit/util/grpcerrors/grpcerrors.go
+++ b/vendor/github.com/moby/buildkit/util/grpcerrors/grpcerrors.go
@@ -1,11 +1,15 @@
 package grpcerrors
 
 import (
+	"encoding/json"
+	"errors"
+
+	"github.com/containerd/typeurl"
 	gogotypes "github.com/gogo/protobuf/types"
 	"github.com/golang/protobuf/proto"
-	"github.com/golang/protobuf/ptypes"
 	"github.com/golang/protobuf/ptypes/any"
 	"github.com/moby/buildkit/util/stack"
+	"github.com/sirupsen/logrus"
 	spb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -29,8 +33,12 @@
 		st = status.New(Code(err), err.Error())
 	}
 	if st.Code() != Code(err) {
+		code := Code(err)
+		if code == codes.OK {
+			code = codes.Unknown
+		}
 		pb := st.Proto()
-		pb.Code = int32(Code(err))
+		pb.Code = int32(code)
 		st = status.FromProto(pb)
 	}
 
@@ -47,7 +55,7 @@
 	})
 
 	if len(details) > 0 {
-		if st2, err := st.WithDetails(details...); err == nil {
+		if st2, err := withDetails(st, details...); err == nil {
 			st = st2
 		}
 	}
@@ -55,6 +63,26 @@
 	return st.Err()
 }
 
+func withDetails(s *status.Status, details ...proto.Message) (*status.Status, error) {
+	if s.Code() == codes.OK {
+		return nil, errors.New("no error details for status with code OK")
+	}
+	p := s.Proto()
+	for _, detail := range details {
+		url, err := typeurl.TypeURL(detail)
+		if err != nil {
+			logrus.Warnf("ignoring typed error %T: not registered", detail)
+			continue
+		}
+		dt, err := json.Marshal(detail)
+		if err != nil {
+			return nil, err
+		}
+		p.Details = append(p.Details, &any.Any{TypeUrl: url, Value: dt})
+	}
+	return status.FromProto(p), nil
+}
+
 func Code(err error) codes.Code {
 	if se, ok := err.(interface {
 		Code() codes.Code
@@ -72,9 +100,10 @@
 		Unwrap() error
 	})
 	if ok {
-		return Code(wrapped.Unwrap())
+		if err := wrapped.Unwrap(); err != nil {
+			return Code(err)
+		}
 	}
-
 	return status.FromContextError(err).Code()
 }
 
@@ -96,7 +125,9 @@
 		Unwrap() error
 	})
 	if ok {
-		return AsGRPCStatus(wrapped.Unwrap())
+		if err := wrapped.Unwrap(); err != nil {
+			return AsGRPCStatus(err)
+		}
 	}
 
 	return nil, false
@@ -123,17 +154,9 @@
 
 	// details that we don't understand are copied as proto
 	for _, d := range pb.Details {
-		var m interface{}
-		detail := &ptypes.DynamicAny{}
-		if err := ptypes.UnmarshalAny(d, detail); err != nil {
-			detail := &gogotypes.DynamicAny{}
-			if err := gogotypes.UnmarshalAny(gogoAny(d), detail); err != nil {
-				n.Details = append(n.Details, d)
-				continue
-			}
-			m = detail.Message
-		} else {
-			m = detail.Message
+		m, err := typeurl.UnmarshalAny(gogoAny(d))
+		if err != nil {
+			continue
 		}
 
 		switch v := m.(type) {
@@ -144,7 +167,6 @@
 		default:
 			n.Details = append(n.Details, d)
 		}
-
 	}
 
 	err = status.FromProto(n).Err()
@@ -159,6 +181,10 @@
 		err = d.WrapError(err)
 	}
 
+	if err != nil {
+		stack.Helper()
+	}
+
 	return stack.Enable(err)
 }
 
@@ -167,6 +193,10 @@
 	error
 }
 
+func (e *withCode) Code() codes.Code {
+	return e.code
+}
+
 func (e *withCode) Unwrap() error {
 	return e.error
 }
diff --git a/vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go b/vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
index 77618c1..1c17e4c 100644
--- a/vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
+++ b/vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
@@ -2,27 +2,53 @@
 
 import (
 	"context"
+	"log"
+	"os"
 
+	"github.com/moby/buildkit/util/stack"
+	"github.com/pkg/errors"
 	"google.golang.org/grpc"
 )
 
 func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 	resp, err = handler(ctx, req)
+	oldErr := err
 	if err != nil {
+		stack.Helper()
 		err = ToGRPC(err)
 	}
+	if oldErr != nil && err == nil {
+		logErr := errors.Wrap(err, "invalid grpc error conversion")
+		if os.Getenv("BUILDKIT_DEBUG_PANIC_ON_ERROR") == "1" {
+			panic(logErr)
+		}
+		log.Printf("%v", logErr)
+		err = oldErr
+	}
+
 	return resp, err
 }
 
 func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
-	return ToGRPC(handler(srv, ss))
+	err := ToGRPC(handler(srv, ss))
+	if err != nil {
+		stack.Helper()
+	}
+	return err
 }
 
 func UnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
-	return FromGRPC(invoker(ctx, method, req, reply, cc, opts...))
+	err := FromGRPC(invoker(ctx, method, req, reply, cc, opts...))
+	if err != nil {
+		stack.Helper()
+	}
+	return err
 }
 
 func StreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
 	s, err := streamer(ctx, desc, cc, method, opts...)
+	if err != nil {
+		stack.Helper()
+	}
 	return s, ToGRPC(err)
 }
diff --git a/vendor/github.com/moby/buildkit/util/imageutil/config.go b/vendor/github.com/moby/buildkit/util/imageutil/config.go
index e0d9f17..c1ea021 100644
--- a/vendor/github.com/moby/buildkit/util/imageutil/config.go
+++ b/vendor/github.com/moby/buildkit/util/imageutil/config.go
@@ -14,6 +14,7 @@
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
 	"github.com/moby/buildkit/util/leaseutil"
+	"github.com/moby/buildkit/util/resolver/retryhandler"
 	digest "github.com/opencontainers/go-digest"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
@@ -36,6 +37,12 @@
 	leasesMu.Unlock()
 }
 
+func AddLease(f func(context.Context) error) {
+	leasesMu.Lock()
+	leasesF = append(leasesF, f)
+	leasesMu.Unlock()
+}
+
 func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, leaseManager leases.Manager, p *specs.Platform) (digest.Digest, []byte, error) {
 	// TODO: fix buildkit to take interface instead of struct
 	var platform platforms.MatchComparer
@@ -57,9 +64,7 @@
 		ctx = ctx2
 		defer func() {
 			// this lease is not deleted to allow other components to access manifest/config from cache. It will be deleted after 5 min deadline or on pruning inactive builder
-			leasesMu.Lock()
-			leasesF = append(leasesF, done)
-			leasesMu.Unlock()
+			AddLease(done)
 		}()
 	}
 
@@ -96,7 +101,7 @@
 	children := childrenConfigHandler(cache, platform)
 
 	handlers := []images.Handler{
-		remotes.FetchHandler(cache, fetcher),
+		retryhandler.New(remotes.FetchHandler(cache, fetcher), nil),
 		children,
 	}
 	if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
diff --git a/vendor/github.com/moby/buildkit/util/network/host.go b/vendor/github.com/moby/buildkit/util/network/host.go
index dc58b1c..09aefdf 100644
--- a/vendor/github.com/moby/buildkit/util/network/host.go
+++ b/vendor/github.com/moby/buildkit/util/network/host.go
@@ -1,3 +1,5 @@
+// +build !windows
+
 package network
 
 import (
@@ -19,8 +21,8 @@
 type hostNS struct {
 }
 
-func (h *hostNS) Set(s *specs.Spec) {
-	oci.WithHostNamespace(specs.NetworkNamespace)(nil, nil, nil, s)
+func (h *hostNS) Set(s *specs.Spec) error {
+	return oci.WithHostNamespace(specs.NetworkNamespace)(nil, nil, nil, s)
 }
 
 func (h *hostNS) Close() error {
diff --git a/vendor/github.com/moby/buildkit/util/network/network.go b/vendor/github.com/moby/buildkit/util/network/network.go
index 70b0ccc..befeef0 100644
--- a/vendor/github.com/moby/buildkit/util/network/network.go
+++ b/vendor/github.com/moby/buildkit/util/network/network.go
@@ -15,5 +15,5 @@
 type Namespace interface {
 	io.Closer
 	// Set the namespace on the spec
-	Set(*specs.Spec)
+	Set(*specs.Spec) error
 }
diff --git a/vendor/github.com/moby/buildkit/util/network/none.go b/vendor/github.com/moby/buildkit/util/network/none.go
index ebf1ebd..336ff68 100644
--- a/vendor/github.com/moby/buildkit/util/network/none.go
+++ b/vendor/github.com/moby/buildkit/util/network/none.go
@@ -18,7 +18,8 @@
 type noneNS struct {
 }
 
-func (h *noneNS) Set(s *specs.Spec) {
+func (h *noneNS) Set(s *specs.Spec) error {
+	return nil
 }
 
 func (h *noneNS) Close() error {
diff --git a/vendor/github.com/moby/buildkit/util/progress/logs/logs.go b/vendor/github.com/moby/buildkit/util/progress/logs/logs.go
index 54f6ff8..da82c69 100644
--- a/vendor/github.com/moby/buildkit/util/progress/logs/logs.go
+++ b/vendor/github.com/moby/buildkit/util/progress/logs/logs.go
@@ -2,17 +2,33 @@
 
 import (
 	"context"
+	"fmt"
 	"io"
+	"math"
 	"os"
+	"strconv"
+	"sync"
+	"time"
 
 	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/identity"
 	"github.com/moby/buildkit/util/progress"
 	"github.com/pkg/errors"
+	"github.com/tonistiigi/units"
 )
 
+var defaultMaxLogSize = 1024 * 1024
+var defaultMaxLogSpeed = 100 * 1024 // per second
+
+const (
+	stdout = 1
+	stderr = 2
+)
+
+var configCheckOnce sync.Once
+
 func NewLogStreams(ctx context.Context, printOutput bool) (io.WriteCloser, io.WriteCloser) {
-	return newStreamWriter(ctx, 1, printOutput), newStreamWriter(ctx, 2, printOutput)
+	return newStreamWriter(ctx, stdout, printOutput), newStreamWriter(ctx, stderr, printOutput)
 }
 
 func newStreamWriter(ctx context.Context, stream int, printOutput bool) io.WriteCloser {
@@ -21,33 +37,104 @@
 		pw:          pw,
 		stream:      stream,
 		printOutput: printOutput,
+		created:     time.Now(),
 	}
 }
 
 type streamWriter struct {
-	pw          progress.Writer
-	stream      int
-	printOutput bool
+	pw              progress.Writer
+	stream          int
+	printOutput     bool
+	created         time.Time
+	size            int
+	clipping        bool
+	clipReasonSpeed bool
+}
+
+func (sw *streamWriter) checkLimit(n int) int {
+	configCheckOnce.Do(func() {
+		maxLogSize, err := strconv.ParseInt(os.Getenv("BUILDKIT_STEP_LOG_MAX_SIZE"), 10, 32)
+		if err == nil {
+			defaultMaxLogSize = int(maxLogSize)
+		}
+		maxLogSpeed, err := strconv.ParseInt(os.Getenv("BUILDKIT_STEP_LOG_MAX_SPEED"), 10, 32)
+		if err == nil {
+			defaultMaxLogSpeed = int(maxLogSpeed)
+		}
+	})
+
+	oldSize := sw.size
+	sw.size += n
+
+	maxSize := -1
+	if defaultMaxLogSpeed != -1 {
+		maxSize = int(math.Ceil(time.Since(sw.created).Seconds())) * defaultMaxLogSpeed
+		sw.clipReasonSpeed = true
+	}
+	if maxSize > defaultMaxLogSize {
+		maxSize = defaultMaxLogSize
+		sw.clipReasonSpeed = false
+	}
+	if maxSize < oldSize {
+		return 0
+	}
+
+	if maxSize != -1 {
+		if sw.size > maxSize {
+			return maxSize - oldSize
+		}
+	}
+	return n
+}
+
+func (sw *streamWriter) clipLimitMessage() string {
+	if sw.clipReasonSpeed {
+		return fmt.Sprintf("%#g/s", units.Bytes(defaultMaxLogSpeed))
+	}
+	return fmt.Sprintf("%#g", units.Bytes(defaultMaxLogSize))
 }
 
 func (sw *streamWriter) Write(dt []byte) (int, error) {
-	sw.pw.Write(identity.NewID(), client.VertexLog{
-		Stream: sw.stream,
-		Data:   append([]byte{}, dt...),
-	})
-	if sw.printOutput {
-		switch sw.stream {
-		case 1:
-			return os.Stdout.Write(dt)
-		case 2:
-			return os.Stderr.Write(dt)
-		default:
-			return 0, errors.Errorf("invalid stream %d", sw.stream)
+	oldSize := len(dt)
+	dt = append([]byte{}, dt[:sw.checkLimit(len(dt))]...)
+
+	if sw.clipping && oldSize == len(dt) {
+		sw.clipping = false
+	}
+	if !sw.clipping && oldSize != len(dt) {
+		dt = append(dt, []byte(fmt.Sprintf("\n[output clipped, log limit %s reached]\n", sw.clipLimitMessage()))...)
+		sw.clipping = true
+	}
+
+	if len(dt) != 0 {
+		sw.pw.Write(identity.NewID(), client.VertexLog{
+			Stream: sw.stream,
+			Data:   dt,
+		})
+		if sw.printOutput {
+			switch sw.stream {
+			case 1:
+				return os.Stdout.Write(dt)
+			case 2:
+				return os.Stderr.Write(dt)
+			default:
+				return 0, errors.Errorf("invalid stream %d", sw.stream)
+			}
 		}
 	}
-	return len(dt), nil
+	return oldSize, nil
 }
 
 func (sw *streamWriter) Close() error {
 	return sw.pw.Close()
 }
+
+func LoggerFromContext(ctx context.Context) func([]byte) {
+	return func(dt []byte) {
+		pw, _, _ := progress.FromContext(ctx)
+		pw.Write(identity.NewID(), client.VertexLog{
+			Stream: stderr,
+			Data:   []byte(dt),
+		})
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/util/progress/multiwriter.go b/vendor/github.com/moby/buildkit/util/progress/multiwriter.go
index 5198936..1ce37ea 100644
--- a/vendor/github.com/moby/buildkit/util/progress/multiwriter.go
+++ b/vendor/github.com/moby/buildkit/util/progress/multiwriter.go
@@ -15,7 +15,6 @@
 	mu      sync.Mutex
 	items   []*Progress
 	writers map[rawProgressWriter]struct{}
-	done    bool
 	meta    map[string]interface{}
 }
 
diff --git a/vendor/github.com/moby/buildkit/util/progress/progress.go b/vendor/github.com/moby/buildkit/util/progress/progress.go
index ffe3d88..3ce2129 100644
--- a/vendor/github.com/moby/buildkit/util/progress/progress.go
+++ b/vendor/github.com/moby/buildkit/util/progress/progress.go
@@ -62,6 +62,11 @@
 	}
 }
 
+type Controller interface {
+	Start(context.Context) (context.Context, func(error))
+	Status(id string, action string) func()
+}
+
 type Writer interface {
 	Write(id string, value interface{}) error
 	Close() error
diff --git a/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go b/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go
new file mode 100644
index 0000000..f16a069
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go
@@ -0,0 +1,138 @@
+package pullprogress
+
+import (
+	"context"
+	"io"
+	"time"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/remotes"
+	"github.com/moby/buildkit/util/progress"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+type PullManager interface {
+	content.IngestManager
+	content.Manager
+}
+
+type ProviderWithProgress struct {
+	Provider content.Provider
+	Manager  PullManager
+}
+
+func (p *ProviderWithProgress) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {
+	ra, err := p.Provider.ReaderAt(ctx, desc)
+	if err != nil {
+		return nil, err
+	}
+
+	ctx, cancel := context.WithCancel(ctx)
+	doneCh := make(chan struct{})
+	go trackProgress(ctx, desc, p.Manager, doneCh)
+	return readerAtWithCancel{ReaderAt: ra, cancel: cancel, doneCh: doneCh}, nil
+}
+
+type readerAtWithCancel struct {
+	content.ReaderAt
+	cancel func()
+	doneCh <-chan struct{}
+}
+
+func (ra readerAtWithCancel) Close() error {
+	ra.cancel()
+	select {
+	case <-ra.doneCh:
+	case <-time.After(time.Second):
+		logrus.Warn("timeout waiting for pull progress to complete")
+	}
+	return ra.ReaderAt.Close()
+}
+
+type FetcherWithProgress struct {
+	Fetcher remotes.Fetcher
+	Manager PullManager
+}
+
+func (f *FetcherWithProgress) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {
+	rc, err := f.Fetcher.Fetch(ctx, desc)
+	if err != nil {
+		return nil, err
+	}
+
+	ctx, cancel := context.WithCancel(ctx)
+	doneCh := make(chan struct{})
+	go trackProgress(ctx, desc, f.Manager, doneCh)
+	return readerWithCancel{ReadCloser: rc, cancel: cancel, doneCh: doneCh}, nil
+}
+
+type readerWithCancel struct {
+	io.ReadCloser
+	cancel func()
+	doneCh <-chan struct{}
+}
+
+func (r readerWithCancel) Close() error {
+	r.cancel()
+	select {
+	case <-r.doneCh:
+	case <-time.After(time.Second):
+		logrus.Warn("timeout waiting for pull progress to complete")
+	}
+	return r.ReadCloser.Close()
+}
+
+func trackProgress(ctx context.Context, desc ocispec.Descriptor, manager PullManager, doneCh chan<- struct{}) {
+
+	defer close(doneCh)
+
+	ticker := time.NewTicker(150 * time.Millisecond)
+	defer ticker.Stop()
+	go func() {
+		<-ctx.Done()
+		ticker.Stop()
+	}()
+
+	pw, _, _ := progress.FromContext(ctx)
+	defer pw.Close()
+
+	ingestRef := remotes.MakeRefKey(ctx, desc)
+
+	started := time.Now()
+	onFinalStatus := false
+	for !onFinalStatus {
+		select {
+		case <-ctx.Done():
+			onFinalStatus = true
+		case <-ticker.C:
+		}
+
+		status, err := manager.Status(ctx, ingestRef)
+		if err == nil {
+			pw.Write(desc.Digest.String(), progress.Status{
+				Current: int(status.Offset),
+				Total:   int(status.Total),
+				Started: &started,
+			})
+			continue
+		} else if !errors.Is(err, errdefs.ErrNotFound) {
+			logrus.Errorf("unexpected error getting ingest status of %q: %v", ingestRef, err)
+			return
+		}
+
+		info, err := manager.Info(ctx, desc.Digest)
+		if err == nil {
+			pw.Write(desc.Digest.String(), progress.Status{
+				Current:   int(info.Size),
+				Total:     int(info.Size),
+				Started:   &started,
+				Completed: &info.CreatedAt,
+			})
+			return
+		}
+
+	}
+}
diff --git a/vendor/github.com/moby/buildkit/util/resolver/authorizer.go b/vendor/github.com/moby/buildkit/util/resolver/authorizer.go
new file mode 100644
index 0000000..80e2a35
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/resolver/authorizer.go
@@ -0,0 +1,489 @@
+package resolver
+
+import (
+	"context"
+	"encoding/base64"
+	"fmt"
+	"net/http"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/log"
+	"github.com/containerd/containerd/remotes/docker"
+	"github.com/containerd/containerd/remotes/docker/auth"
+	remoteserrors "github.com/containerd/containerd/remotes/errors"
+	"github.com/moby/buildkit/session"
+	sessionauth "github.com/moby/buildkit/session/auth"
+	"github.com/moby/buildkit/util/flightcontrol"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+type authHandlerNS struct {
+	counter int64 // needs to be 64bit aligned for 32bit systems
+
+	mu       sync.Mutex
+	handlers map[string]*authHandler
+	hosts    map[string][]docker.RegistryHost
+	sm       *session.Manager
+	g        flightcontrol.Group
+}
+
+func newAuthHandlerNS(sm *session.Manager) *authHandlerNS {
+	return &authHandlerNS{
+		handlers: map[string]*authHandler{},
+		hosts:    map[string][]docker.RegistryHost{},
+		sm:       sm,
+	}
+}
+
+func (a *authHandlerNS) get(host string, sm *session.Manager, g session.Group) *authHandler {
+	if g != nil {
+		if iter := g.SessionIterator(); iter != nil {
+			for {
+				id := iter.NextSession()
+				if id == "" {
+					break
+				}
+				h, ok := a.handlers[host+"/"+id]
+				if ok {
+					h.lastUsed = time.Now()
+					return h
+				}
+			}
+		}
+	}
+
+	// link another handler
+	for k, h := range a.handlers {
+		parts := strings.SplitN(k, "/", 2)
+		if len(parts) != 2 {
+			continue
+		}
+		if parts[0] == host {
+			if h.authority != nil {
+				session, ok, err := sessionauth.VerifyTokenAuthority(host, h.authority, sm, g)
+				if err == nil && ok {
+					a.handlers[host+"/"+session] = h
+					h.lastUsed = time.Now()
+					return h
+				}
+			} else {
+				session, username, password, err := sessionauth.CredentialsFunc(sm, g)(host)
+				if err == nil {
+					if username == h.common.Username && password == h.common.Secret {
+						a.handlers[host+"/"+session] = h
+						h.lastUsed = time.Now()
+						return h
+					}
+				}
+			}
+		}
+	}
+
+	return nil
+}
+
+func (a *authHandlerNS) set(host, session string, h *authHandler) {
+	a.handlers[host+"/"+session] = h
+}
+
+func (a *authHandlerNS) delete(h *authHandler) {
+	for k, v := range a.handlers {
+		if v == h {
+			delete(a.handlers, k)
+		}
+	}
+}
+
+type dockerAuthorizer struct {
+	client *http.Client
+
+	sm       *session.Manager
+	session  session.Group
+	handlers *authHandlerNS
+}
+
+func newDockerAuthorizer(client *http.Client, handlers *authHandlerNS, sm *session.Manager, group session.Group) *dockerAuthorizer {
+	return &dockerAuthorizer{
+		client:   client,
+		handlers: handlers,
+		sm:       sm,
+		session:  group,
+	}
+}
+
+// Authorize handles auth request.
+func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
+	a.handlers.mu.Lock()
+	defer a.handlers.mu.Unlock()
+
+	// skip if there is no auth handler
+	ah := a.handlers.get(req.URL.Host, a.sm, a.session)
+	if ah == nil {
+		return nil
+	}
+
+	auth, err := ah.authorize(ctx, a.sm, a.session)
+	if err != nil {
+		return err
+	}
+
+	req.Header.Set("Authorization", auth)
+	return nil
+}
+
+func (a *dockerAuthorizer) getCredentials(host string) (sessionID, username, secret string, err error) {
+	return sessionauth.CredentialsFunc(a.sm, a.session)(host)
+}
+
+func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
+	a.handlers.mu.Lock()
+	defer a.handlers.mu.Unlock()
+
+	last := responses[len(responses)-1]
+	host := last.Request.URL.Host
+
+	handler := a.handlers.get(host, a.sm, a.session)
+
+	for _, c := range auth.ParseAuthHeader(last.Header) {
+		if c.Scheme == auth.BearerAuth {
+			var oldScopes []string
+			if err := invalidAuthorization(c, responses); err != nil {
+				a.handlers.delete(handler)
+
+				if handler != nil {
+					oldScopes = handler.common.Scopes
+				}
+				handler = nil
+
+				// this hacky way seems to be best method to detect that error is fatal and should not be retried with a new token
+				if c.Parameters["error"] == "insufficient_scope" && parseScopes(oldScopes).contains(parseScopes(strings.Split(c.Parameters["scope"], " "))) {
+					return err
+				}
+			}
+
+			// reuse existing handler
+			//
+			// assume that one registry will return the common
+			// challenge information, including realm and service.
+			// and the resource scope is only different part
+			// which can be provided by each request.
+			if handler != nil {
+				return nil
+			}
+
+			var username, secret string
+			session, pubKey, err := sessionauth.GetTokenAuthority(host, a.sm, a.session)
+			if err != nil {
+				return err
+			}
+			if pubKey == nil {
+				session, username, secret, err = a.getCredentials(host)
+				if err != nil {
+					return err
+				}
+			}
+
+			common, err := auth.GenerateTokenOptions(ctx, host, username, secret, c)
+			if err != nil {
+				return err
+			}
+			common.Scopes = parseScopes(append(common.Scopes, oldScopes...)).normalize()
+
+			a.handlers.set(host, session, newAuthHandler(host, a.client, c.Scheme, pubKey, common))
+
+			return nil
+		} else if c.Scheme == auth.BasicAuth {
+			session, username, secret, err := a.getCredentials(host)
+			if err != nil {
+				return err
+			}
+
+			if username != "" && secret != "" {
+				common := auth.TokenOptions{
+					Username: username,
+					Secret:   secret,
+				}
+
+				a.handlers.set(host, session, newAuthHandler(host, a.client, c.Scheme, nil, common))
+
+				return nil
+			}
+		}
+	}
+	return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
+}
+
+// authResult is used to control limit rate.
+type authResult struct {
+	sync.WaitGroup
+	token   string
+	err     error
+	expires time.Time
+}
+
+// authHandler is used to handle auth request per registry server.
+type authHandler struct {
+	sync.Mutex
+
+	client *http.Client
+
+	// only support basic and bearer schemes
+	scheme auth.AuthenticationScheme
+
+	// common contains common challenge answer
+	common auth.TokenOptions
+
+	// scopedTokens caches token indexed by scopes, which used in
+	// bearer auth case
+	scopedTokens map[string]*authResult
+
+	lastUsed time.Time
+
+	host string
+
+	authority *[32]byte
+}
+
+func newAuthHandler(host string, client *http.Client, scheme auth.AuthenticationScheme, authority *[32]byte, opts auth.TokenOptions) *authHandler {
+	return &authHandler{
+		host:         host,
+		client:       client,
+		scheme:       scheme,
+		common:       opts,
+		scopedTokens: map[string]*authResult{},
+		lastUsed:     time.Now(),
+		authority:    authority,
+	}
+}
+
+func (ah *authHandler) authorize(ctx context.Context, sm *session.Manager, g session.Group) (string, error) {
+	switch ah.scheme {
+	case auth.BasicAuth:
+		return ah.doBasicAuth(ctx)
+	case auth.BearerAuth:
+		return ah.doBearerAuth(ctx, sm, g)
+	default:
+		return "", errors.Wrapf(errdefs.ErrNotImplemented, "failed to find supported auth scheme: %s", string(ah.scheme))
+	}
+}
+
+func (ah *authHandler) doBasicAuth(ctx context.Context) (string, error) {
+	username, secret := ah.common.Username, ah.common.Secret
+
+	if username == "" || secret == "" {
+		return "", fmt.Errorf("failed to handle basic auth because missing username or secret")
+	}
+
+	auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + secret))
+	return fmt.Sprintf("Basic %s", auth), nil
+}
+
+func (ah *authHandler) doBearerAuth(ctx context.Context, sm *session.Manager, g session.Group) (token string, err error) {
+	// copy common tokenOptions
+	to := ah.common
+
+	to.Scopes = parseScopes(docker.GetTokenScopes(ctx, to.Scopes)).normalize()
+
+	// Docs: https://docs.docker.com/registry/spec/auth/scope
+	scoped := strings.Join(to.Scopes, " ")
+
+	ah.Lock()
+	for {
+		r, exist := ah.scopedTokens[scoped]
+		if !exist {
+			// no entry cached
+			break
+		}
+		ah.Unlock()
+		r.Wait()
+		if r.err != nil {
+			select {
+			case <-ctx.Done():
+				return "", r.err
+			default:
+			}
+		}
+		if !errors.Is(r.err, context.Canceled) &&
+			(r.expires.IsZero() || r.expires.After(time.Now())) {
+			return r.token, r.err
+		}
+		// r.err is canceled or token expired. Get rid of it and try again
+		ah.Lock()
+		r2, exist := ah.scopedTokens[scoped]
+		if exist && r == r2 {
+			delete(ah.scopedTokens, scoped)
+		}
+	}
+
+	// only one fetch token job
+	r := new(authResult)
+	r.Add(1)
+	ah.scopedTokens[scoped] = r
+	ah.Unlock()
+
+	var issuedAt time.Time
+	var expires int
+	defer func() {
+		token = fmt.Sprintf("Bearer %s", token)
+		r.token, r.err = token, err
+		if err == nil {
+			if issuedAt.IsZero() {
+				issuedAt = time.Now()
+			}
+			if exp := issuedAt.Add(time.Duration(float64(expires)*0.9) * time.Second); time.Now().Before(exp) {
+				r.expires = exp
+			}
+		}
+		r.Done()
+	}()
+
+	if ah.authority != nil {
+		resp, err := sessionauth.FetchToken(&sessionauth.FetchTokenRequest{
+			ClientID: "buildkit-client",
+			Host:     ah.host,
+			Realm:    to.Realm,
+			Service:  to.Service,
+			Scopes:   to.Scopes,
+		}, sm, g)
+		if err != nil {
+			return "", err
+		}
+		issuedAt, expires = time.Unix(resp.IssuedAt, 0), int(resp.ExpiresIn)
+		return resp.Token, nil
+	}
+
+	// fetch token for the resource scope
+	if to.Secret != "" {
+		defer func() {
+			err = errors.Wrap(err, "failed to fetch oauth token")
+		}()
+		// try GET first because Docker Hub does not support POST
+		// switch once support has landed
+		resp, err := auth.FetchToken(ctx, ah.client, nil, to)
+		if err != nil {
+			var errStatus remoteserrors.ErrUnexpectedStatus
+			if errors.As(err, &errStatus) {
+				// retry with POST request
+				// As of September 2017, GCR is known to return 404.
+				// As of February 2018, JFrog Artifactory is known to return 401.
+				if (errStatus.StatusCode == 405 && to.Username != "") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 {
+					resp, err := auth.FetchTokenWithOAuth(ctx, ah.client, nil, "buildkit-client", to)
+					if err != nil {
+						return "", err
+					}
+					issuedAt, expires = resp.IssuedAt, resp.ExpiresIn
+					return resp.AccessToken, nil
+				}
+				log.G(ctx).WithFields(logrus.Fields{
+					"status": errStatus.Status,
+					"body":   string(errStatus.Body),
+				}).Debugf("token request failed")
+			}
+			return "", err
+		}
+		issuedAt, expires = resp.IssuedAt, resp.ExpiresIn
+		return resp.Token, nil
+	}
+	// do request anonymously
+	resp, err := auth.FetchToken(ctx, ah.client, nil, to)
+	if err != nil {
+		return "", errors.Wrap(err, "failed to fetch anonymous token")
+	}
+	issuedAt, expires = resp.IssuedAt, resp.ExpiresIn
+
+	return resp.Token, nil
+}
+
+func invalidAuthorization(c auth.Challenge, responses []*http.Response) error {
+	errStr := c.Parameters["error"]
+	if errStr == "" {
+		return nil
+	}
+
+	n := len(responses)
+	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
+		return nil
+	}
+
+	return errors.Wrapf(docker.ErrInvalidAuthorization, "server message: %s", errStr)
+}
+
+func sameRequest(r1, r2 *http.Request) bool {
+	if r1.Method != r2.Method {
+		return false
+	}
+	if *r1.URL != *r2.URL {
+		return false
+	}
+	return true
+}
+
+type scopes map[string]map[string]struct{}
+
+func parseScopes(s []string) scopes {
+	// https://docs.docker.com/registry/spec/auth/scope/
+	m := map[string]map[string]struct{}{}
+	for _, scope := range s {
+		parts := strings.SplitN(scope, ":", 3)
+		names := []string{parts[0]}
+		if len(parts) > 1 {
+			names = append(names, parts[1])
+		}
+		var actions []string
+		if len(parts) == 3 {
+			actions = append(actions, strings.Split(parts[2], ",")...)
+		}
+		name := strings.Join(names, ":")
+		ma, ok := m[name]
+		if !ok {
+			ma = map[string]struct{}{}
+			m[name] = ma
+		}
+
+		for _, a := range actions {
+			ma[a] = struct{}{}
+		}
+	}
+	return m
+}
+
+func (s scopes) normalize() []string {
+	names := make([]string, 0, len(s))
+	for n := range s {
+		names = append(names, n)
+	}
+	sort.Strings(names)
+
+	out := make([]string, 0, len(s))
+
+	for _, n := range names {
+		actions := make([]string, 0, len(s[n]))
+		for a := range s[n] {
+			actions = append(actions, a)
+		}
+		sort.Strings(actions)
+
+		out = append(out, n+":"+strings.Join(actions, ","))
+	}
+	return out
+}
+
+func (s scopes) contains(s2 scopes) bool {
+	for n := range s2 {
+		v, ok := s[n]
+		if !ok {
+			return false
+		}
+		for a := range s2[n] {
+			if _, ok := v[a]; !ok {
+				return false
+			}
+		}
+	}
+	return true
+}
diff --git a/vendor/github.com/moby/buildkit/util/resolver/pool.go b/vendor/github.com/moby/buildkit/util/resolver/pool.go
new file mode 100644
index 0000000..20344ea
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/resolver/pool.go
@@ -0,0 +1,206 @@
+package resolver
+
+import (
+	"context"
+	"fmt"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/remotes"
+	"github.com/containerd/containerd/remotes/docker"
+	distreference "github.com/docker/distribution/reference"
+	"github.com/moby/buildkit/session"
+	"github.com/moby/buildkit/source"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// DefaultPool is the default shared resolver pool instance
+var DefaultPool = NewPool()
+
+// Pool is a cache of recently used resolvers
+type Pool struct {
+	mu sync.Mutex
+	m  map[string]*authHandlerNS
+}
+
+// NewPool creates a new pool for caching resolvers
+func NewPool() *Pool {
+	p := &Pool{
+		m: map[string]*authHandlerNS{},
+	}
+	time.AfterFunc(5*time.Minute, p.gc)
+	return p
+}
+
+func (p *Pool) gc() {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+
+	for k, ns := range p.m {
+		ns.mu.Lock()
+		for key, h := range ns.handlers {
+			if time.Since(h.lastUsed) < 10*time.Minute {
+				continue
+			}
+			parts := strings.SplitN(key, "/", 2)
+			if len(parts) != 2 {
+				delete(ns.handlers, key)
+				continue
+			}
+			c, err := ns.sm.Get(context.TODO(), parts[1], true)
+			if c == nil || err != nil {
+				delete(ns.handlers, key)
+			}
+		}
+		if len(ns.handlers) == 0 {
+			delete(p.m, k)
+		}
+		ns.mu.Unlock()
+	}
+
+	time.AfterFunc(5*time.Minute, p.gc)
+}
+
+// Clear deletes currently cached items. This may be called on config changes for example.
+func (p *Pool) Clear() {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	p.m = map[string]*authHandlerNS{}
+}
+
+// GetResolver gets a resolver for a specified scope from the pool
+func (p *Pool) GetResolver(hosts docker.RegistryHosts, ref, scope string, sm *session.Manager, g session.Group) *Resolver {
+	name := ref
+	named, err := distreference.ParseNormalizedNamed(ref)
+	if err == nil {
+		name = named.Name()
+	}
+
+	key := fmt.Sprintf("%s::%s", name, scope)
+
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	h, ok := p.m[key]
+	if !ok {
+		h = newAuthHandlerNS(sm)
+		p.m[key] = h
+	}
+	return newResolver(hosts, h, sm, g)
+}
+
+func newResolver(hosts docker.RegistryHosts, handler *authHandlerNS, sm *session.Manager, g session.Group) *Resolver {
+	if hosts == nil {
+		hosts = docker.ConfigureDefaultRegistries(
+			docker.WithClient(newDefaultClient()),
+			docker.WithPlainHTTP(docker.MatchLocalhost),
+		)
+	}
+	r := &Resolver{
+		hosts:   hosts,
+		sm:      sm,
+		g:       g,
+		handler: handler,
+	}
+	r.Resolver = docker.NewResolver(docker.ResolverOptions{
+		Hosts: r.hostsFunc,
+	})
+	return r
+}
+
+// Resolver is a wrapper around remotes.Resolver
+type Resolver struct {
+	remotes.Resolver
+	hosts   docker.RegistryHosts
+	sm      *session.Manager
+	g       session.Group
+	handler *authHandlerNS
+	auth    *dockerAuthorizer
+
+	is   images.Store
+	mode source.ResolveMode
+}
+
+func (r *Resolver) hostsFunc(host string) ([]docker.RegistryHost, error) {
+	return func(domain string) ([]docker.RegistryHost, error) {
+		v, err := r.handler.g.Do(context.TODO(), domain, func(ctx context.Context) (interface{}, error) {
+			// long lock not needed because flightcontrol.Do
+			r.handler.mu.Lock()
+			v, ok := r.handler.hosts[domain]
+			r.handler.mu.Unlock()
+			if ok {
+				return v, nil
+			}
+			res, err := r.hosts(domain)
+			if err != nil {
+				return nil, err
+			}
+			r.handler.mu.Lock()
+			r.handler.hosts[domain] = res
+			r.handler.mu.Unlock()
+			return res, nil
+		})
+		if err != nil || v == nil {
+			return nil, err
+		}
+		res := v.([]docker.RegistryHost)
+		if len(res) == 0 {
+			return nil, nil
+		}
+		auth := newDockerAuthorizer(res[0].Client, r.handler, r.sm, r.g)
+		for i := range res {
+			res[i].Authorizer = auth
+		}
+		return res, nil
+	}(host)
+}
+
+// WithSession returns a new resolver that works with new session group
+func (r *Resolver) WithSession(s session.Group) *Resolver {
+	r2 := *r
+	r2.auth = nil
+	r2.g = s
+	return &r2
+}
+
+// WithImageStore returns new resolver that can also resolve from local images store
+func (r *Resolver) WithImageStore(is images.Store, mode source.ResolveMode) *Resolver {
+	r2 := *r
+	r2.Resolver = r.Resolver
+	r2.is = is
+	r2.mode = mode
+	return &r2
+}
+
+// Fetcher returns a new fetcher for the provided reference.
+func (r *Resolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {
+	if atomic.LoadInt64(&r.handler.counter) == 0 {
+		r.Resolve(ctx, ref)
+	}
+	return r.Resolver.Fetcher(ctx, ref)
+}
+
+// Resolve attempts to resolve the reference into a name and descriptor.
+func (r *Resolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) {
+	if r.mode == source.ResolveModePreferLocal && r.is != nil {
+		if img, err := r.is.Get(ctx, ref); err == nil {
+			return ref, img.Target, nil
+		}
+	}
+
+	n, desc, err := r.Resolver.Resolve(ctx, ref)
+	if err == nil {
+		atomic.AddInt64(&r.handler.counter, 1)
+		return n, desc, err
+	}
+
+	if r.mode == source.ResolveModeDefault && r.is != nil {
+		if img, err := r.is.Get(ctx, ref); err == nil {
+			return ref, img.Target, nil
+		}
+	}
+
+	return "", ocispec.Descriptor{}, err
+}
diff --git a/vendor/github.com/moby/buildkit/util/resolver/resolver.go b/vendor/github.com/moby/buildkit/util/resolver/resolver.go
index e7b3c97..42c940b 100644
--- a/vendor/github.com/moby/buildkit/util/resolver/resolver.go
+++ b/vendor/github.com/moby/buildkit/util/resolver/resolver.go
@@ -10,41 +10,59 @@
 	"path/filepath"
 	"runtime"
 	"strings"
-	"sync"
 	"time"
 
-	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
 	"github.com/moby/buildkit/cmd/buildkitd/config"
-	"github.com/moby/buildkit/session"
-	"github.com/moby/buildkit/session/auth"
 	"github.com/moby/buildkit/util/tracing"
 	"github.com/pkg/errors"
 )
 
-func fillInsecureOpts(host string, c config.RegistryConfig, h *docker.RegistryHost) error {
+func fillInsecureOpts(host string, c config.RegistryConfig, h docker.RegistryHost) ([]docker.RegistryHost, error) {
+	var hosts []docker.RegistryHost
+
 	tc, err := loadTLSConfig(c)
 	if err != nil {
-		return err
+		return nil, err
 	}
+	var isHTTP bool
 
 	if c.PlainHTTP != nil && *c.PlainHTTP {
-		h.Scheme = "http"
-	} else if c.Insecure != nil && *c.Insecure {
-		tc.InsecureSkipVerify = true
-	} else if c.PlainHTTP == nil {
+		isHTTP = true
+	}
+	if c.PlainHTTP == nil {
 		if ok, _ := docker.MatchLocalhost(host); ok {
-			h.Scheme = "http"
+			isHTTP = true
 		}
 	}
 
-	transport := newDefaultTransport()
-	transport.TLSClientConfig = tc
-
-	h.Client = &http.Client{
-		Transport: tracing.NewTransport(transport),
+	if isHTTP {
+		h2 := h
+		h2.Scheme = "http"
+		hosts = append(hosts, h2)
 	}
-	return nil
+	if c.Insecure != nil && *c.Insecure {
+		h2 := h
+		transport := newDefaultTransport()
+		transport.TLSClientConfig = tc
+		h2.Client = &http.Client{
+			Transport: tracing.NewTransport(transport),
+		}
+		tc.InsecureSkipVerify = true
+		hosts = append(hosts, h2)
+	}
+
+	if len(hosts) == 0 {
+		transport := newDefaultTransport()
+		transport.TLSClientConfig = tc
+
+		h.Client = &http.Client{
+			Transport: tracing.NewTransport(transport),
+		}
+		hosts = append(hosts, h)
+	}
+
+	return hosts, nil
 }
 
 func loadTLSConfig(c config.RegistryConfig) (*tls.Config, error) {
@@ -97,6 +115,7 @@
 	return tc, nil
 }
 
+// NewRegistryConfig converts registry config to docker.RegistryHosts callback
 func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts {
 	return docker.Registries(
 		func(host string) ([]docker.RegistryHost, error) {
@@ -116,11 +135,12 @@
 					Capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve,
 				}
 
-				if err := fillInsecureOpts(mirror, m[mirror], &h); err != nil {
+				hosts, err := fillInsecureOpts(mirror, m[mirror], h)
+				if err != nil {
 					return nil, err
 				}
 
-				out = append(out, h)
+				out = append(out, hosts...)
 			}
 
 			if host == "docker.io" {
@@ -135,11 +155,12 @@
 				Capabilities: docker.HostCapabilityPush | docker.HostCapabilityPull | docker.HostCapabilityResolve,
 			}
 
-			if err := fillInsecureOpts(host, c, &h); err != nil {
+			hosts, err := fillInsecureOpts(host, c, h)
+			if err != nil {
 				return nil, err
 			}
 
-			out = append(out, h)
+			out = append(out, hosts...)
 			return out, nil
 		},
 		docker.ConfigureDefaultRegistries(
@@ -149,92 +170,9 @@
 	)
 }
 
-type SessionAuthenticator struct {
-	sm      *session.Manager
-	groups  []session.Group
-	mu      sync.RWMutex
-	cache   map[string]credentials
-	cacheMu sync.RWMutex
-}
-
-type credentials struct {
-	user    string
-	secret  string
-	created time.Time
-}
-
-func NewSessionAuthenticator(sm *session.Manager, g session.Group) *SessionAuthenticator {
-	return &SessionAuthenticator{sm: sm, groups: []session.Group{g}, cache: map[string]credentials{}}
-}
-
-func (a *SessionAuthenticator) credentials(h string) (string, string, error) {
-	const credentialsTimeout = time.Minute
-
-	a.cacheMu.RLock()
-	c, ok := a.cache[h]
-	if ok && time.Since(c.created) < credentialsTimeout {
-		a.cacheMu.RUnlock()
-		return c.user, c.secret, nil
-	}
-	a.cacheMu.RUnlock()
-
-	a.mu.RLock()
-	defer a.mu.RUnlock()
-
-	var err error
-	for i := len(a.groups) - 1; i >= 0; i-- {
-		var user, secret string
-		user, secret, err = auth.CredentialsFunc(a.sm, a.groups[i])(h)
-		if err != nil {
-			continue
-		}
-		a.cacheMu.Lock()
-		a.cache[h] = credentials{user: user, secret: secret, created: time.Now()}
-		a.cacheMu.Unlock()
-		return user, secret, nil
-	}
-	return "", "", err
-}
-
-func (a *SessionAuthenticator) AddSession(g session.Group) {
-	a.mu.Lock()
-	a.groups = append(a.groups, g)
-	a.mu.Unlock()
-}
-
-func New(hosts docker.RegistryHosts, auth *SessionAuthenticator) remotes.Resolver {
-	return docker.NewResolver(docker.ResolverOptions{
-		Hosts: hostsWithCredentials(hosts, auth),
-	})
-}
-
-func hostsWithCredentials(hosts docker.RegistryHosts, auth *SessionAuthenticator) docker.RegistryHosts {
-	if hosts == nil {
-		return nil
-	}
-	return func(domain string) ([]docker.RegistryHost, error) {
-		res, err := hosts(domain)
-		if err != nil {
-			return nil, err
-		}
-		if len(res) == 0 {
-			return nil, nil
-		}
-
-		a := docker.NewDockerAuthorizer(
-			docker.WithAuthClient(res[0].Client),
-			docker.WithAuthCreds(auth.credentials),
-		)
-		for i := range res {
-			res[i].Authorizer = a
-		}
-		return res, nil
-	}
-}
-
 func newDefaultClient() *http.Client {
 	return &http.Client{
-		Transport: newDefaultTransport(),
+		Transport: tracing.NewTransport(newDefaultTransport()),
 	}
 }
 
@@ -250,14 +188,12 @@
 		Proxy: http.ProxyFromEnvironment,
 		DialContext: (&net.Dialer{
 			Timeout:   30 * time.Second,
-			KeepAlive: 30 * time.Second,
-			DualStack: true,
+			KeepAlive: 60 * time.Second,
 		}).DialContext,
 		MaxIdleConns:          10,
 		IdleConnTimeout:       30 * time.Second,
 		TLSHandshakeTimeout:   10 * time.Second,
 		ExpectContinueTimeout: 5 * time.Second,
-		DisableKeepAlives:     true,
 		TLSNextProto:          make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 	}
 }
diff --git a/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go b/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go
new file mode 100644
index 0000000..bddcfb8
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go
@@ -0,0 +1,64 @@
+package retryhandler
+
+import (
+	"context"
+	"fmt"
+	"io"
+	"strings"
+	"syscall"
+	"time"
+
+	"github.com/containerd/containerd/images"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+)
+
+func New(f images.HandlerFunc, logger func([]byte)) images.HandlerFunc {
+	return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
+		backoff := time.Second
+		for {
+			descs, err := f(ctx, desc)
+			if err != nil {
+				select {
+				case <-ctx.Done():
+					return nil, err
+				default:
+					if !retryError(err) {
+						return nil, err
+					}
+				}
+				if logger != nil {
+					logger([]byte(fmt.Sprintf("error: %v\n", err.Error())))
+				}
+			} else {
+				return descs, nil
+			}
+			// backoff logic
+			if backoff >= 8*time.Second {
+				return nil, err
+			}
+			if logger != nil {
+				logger([]byte(fmt.Sprintf("retrying in %v\n", backoff)))
+			}
+			time.Sleep(backoff)
+			backoff *= 2
+		}
+	}
+}
+
+func retryError(err error) bool {
+	if errors.Is(err, io.EOF) || errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.EPIPE) {
+		return true
+	}
+	// https://github.com/containerd/containerd/pull/4724
+	if errors.Cause(err).Error() == "no response" {
+		return true
+	}
+
+	// net.ErrClosed exposed in go1.16
+	if strings.Contains(err.Error(), "use of closed network connection") {
+		return true
+	}
+
+	return false
+}
diff --git a/vendor/github.com/moby/buildkit/util/rootless/specconv/specconv_nonlinux.go b/vendor/github.com/moby/buildkit/util/rootless/specconv/specconv_nonlinux.go
new file mode 100644
index 0000000..bb08ec1
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/rootless/specconv/specconv_nonlinux.go
@@ -0,0 +1,19 @@
+// +build !linux
+
+package specconv
+
+import (
+	"runtime"
+
+	"github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
+)
+
+// ToRootless converts spec to be compatible with "rootless" runc.
+// * Remove /sys mount
+// * Remove cgroups
+//
+// See docs/rootless.md for the supported runc revision.
+func ToRootless(spec *specs.Spec) error {
+	return errors.Errorf("not implemented on on %s", runtime.GOOS)
+}
diff --git a/vendor/github.com/moby/buildkit/util/sshutil/keyscan.go b/vendor/github.com/moby/buildkit/util/sshutil/keyscan.go
new file mode 100644
index 0000000..b6f2367
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/sshutil/keyscan.go
@@ -0,0 +1,51 @@
+package sshutil
+
+import (
+	"fmt"
+	"net"
+	"strconv"
+	"strings"
+
+	"golang.org/x/crypto/ssh"
+)
+
+const defaultPort = 22
+
+var errCallbackDone = fmt.Errorf("callback failed on purpose")
+
+// addDefaultPort appends a default port if hostport doesn't contain one
+func addDefaultPort(hostport string, defaultPort int) string {
+	_, _, err := net.SplitHostPort(hostport)
+	if err == nil {
+		return hostport
+	}
+	hostport = net.JoinHostPort(hostport, strconv.Itoa(defaultPort))
+	return hostport
+}
+
+// SshKeyScan scans a ssh server for the hostkey; server should be in the form hostname, or hostname:port
+func SSHKeyScan(server string) (string, error) {
+	var key string
+	KeyScanCallback := func(hostport string, remote net.Addr, pubKey ssh.PublicKey) error {
+		hostname, _, err := net.SplitHostPort(hostport)
+		if err != nil {
+			return err
+		}
+		key = strings.TrimSpace(fmt.Sprintf("%s %s", hostname, string(ssh.MarshalAuthorizedKey(pubKey))))
+		return errCallbackDone
+	}
+	config := &ssh.ClientConfig{
+		HostKeyCallback: KeyScanCallback,
+	}
+
+	server = addDefaultPort(server, defaultPort)
+	conn, err := ssh.Dial("tcp", server, config)
+	if key != "" {
+		// as long as we get the key, the function worked
+		err = nil
+	}
+	if conn != nil {
+		conn.Close()
+	}
+	return key, err
+}
diff --git a/vendor/github.com/moby/buildkit/util/stack/stack.go b/vendor/github.com/moby/buildkit/util/stack/stack.go
index 6d3cfc8..3409ac0 100644
--- a/vendor/github.com/moby/buildkit/util/stack/stack.go
+++ b/vendor/github.com/moby/buildkit/util/stack/stack.go
@@ -4,12 +4,24 @@
 	"fmt"
 	io "io"
 	"os"
+	"runtime"
 	"strconv"
 	"strings"
+	"sync"
 
+	"github.com/containerd/typeurl"
 	"github.com/pkg/errors"
 )
 
+var helpers map[string]struct{}
+var helpersMu sync.RWMutex
+
+func init() {
+	typeurl.Register((*Stack)(nil), "github.com/moby/buildkit", "stack.Stack+json")
+
+	helpers = map[string]struct{}{}
+}
+
 var version string
 var revision string
 
@@ -18,6 +30,19 @@
 	revision = r
 }
 
+func Helper() {
+	var pc [1]uintptr
+	n := runtime.Callers(2, pc[:])
+	if n == 0 {
+		return
+	}
+	frames := runtime.CallersFrames(pc[:n])
+	frame, _ := frames.Next()
+	helpersMu.Lock()
+	helpers[frame.Function] = struct{}{}
+	helpersMu.Unlock()
+}
+
 func Traces(err error) []*Stack {
 	var st []*Stack
 
@@ -47,6 +72,7 @@
 	if err == nil {
 		return nil
 	}
+	Helper()
 	if !hasLocalStackTrace(err) {
 		return errors.WithStack(err)
 	}
@@ -107,6 +133,8 @@
 
 func convertStack(s errors.StackTrace) *Stack {
 	var out Stack
+	helpersMu.RLock()
+	defer helpersMu.RUnlock()
 	for _, f := range s {
 		dt, err := f.MarshalText()
 		if err != nil {
@@ -116,6 +144,9 @@
 		if len(p) != 2 {
 			continue
 		}
+		if _, ok := helpers[p[0]]; ok {
+			continue
+		}
 		idx := strings.LastIndexByte(p[1], ':')
 		if idx == -1 {
 			continue
diff --git a/vendor/github.com/moby/buildkit/util/system/path.go b/vendor/github.com/moby/buildkit/util/system/path.go
new file mode 100644
index 0000000..f6dc70d
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/system/path.go
@@ -0,0 +1,18 @@
+package system
+
+// DefaultPathEnvUnix is unix style list of directories to search for
+// executables. Each directory is separated from the next by a colon
+// ':' character .
+const DefaultPathEnvUnix = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+// DefaultPathEnvWindows is windows style list of directories to search for
+// executables. Each directory is separated from the next by a colon
+// ';' character .
+const DefaultPathEnvWindows = "c:\\Windows\\System32;c:\\Windows"
+
+func DefaultPathEnv(os string) string {
+	if os == "windows" {
+		return DefaultPathEnvWindows
+	}
+	return DefaultPathEnvUnix
+}
diff --git a/vendor/github.com/moby/buildkit/util/system/path_unix.go b/vendor/github.com/moby/buildkit/util/system/path_unix.go
index c607c4d..f3762e6 100644
--- a/vendor/github.com/moby/buildkit/util/system/path_unix.go
+++ b/vendor/github.com/moby/buildkit/util/system/path_unix.go
@@ -2,11 +2,6 @@
 
 package system
 
-// DefaultPathEnv is unix style list of directories to search for
-// executables. Each directory is separated from the next by a colon
-// ':' character .
-const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
-
 // CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter,
 // is the system drive. This is a no-op on Linux.
 func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {
diff --git a/vendor/github.com/moby/buildkit/util/system/path_windows.go b/vendor/github.com/moby/buildkit/util/system/path_windows.go
index cbfe2c1..3fc4744 100644
--- a/vendor/github.com/moby/buildkit/util/system/path_windows.go
+++ b/vendor/github.com/moby/buildkit/util/system/path_windows.go
@@ -8,10 +8,6 @@
 	"strings"
 )
 
-// DefaultPathEnv is deliberately empty on Windows as the default path will be set by
-// the container. Docker has no context of what the default path should be.
-const DefaultPathEnv = ""
-
 // CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path.
 // This is used, for example, when validating a user provided path in docker cp.
 // If a drive letter is supplied, it must be the system drive. The drive letter
diff --git a/vendor/github.com/moby/buildkit/util/throttle/throttle.go b/vendor/github.com/moby/buildkit/util/throttle/throttle.go
index 490ccd9..dfc4aef 100644
--- a/vendor/github.com/moby/buildkit/util/throttle/throttle.go
+++ b/vendor/github.com/moby/buildkit/util/throttle/throttle.go
@@ -11,10 +11,10 @@
 	return throttle(d, f, true)
 }
 
-// ThrottleAfter wraps a function so that internal function does not get called
+// After wraps a function so that internal function does not get called
 // more frequently than the specified duration. The delay is added after function
 // has been called.
-func ThrottleAfter(d time.Duration, f func()) func() {
+func After(d time.Duration, f func()) func() {
 	return throttle(d, f, false)
 }
 
diff --git a/vendor/github.com/moby/buildkit/util/winlayers/applier.go b/vendor/github.com/moby/buildkit/util/winlayers/applier.go
new file mode 100644
index 0000000..91e4152
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/winlayers/applier.go
@@ -0,0 +1,187 @@
+package winlayers
+
+import (
+	"archive/tar"
+	"context"
+	"io"
+	"io/ioutil"
+	"runtime"
+	"strings"
+	"sync"
+
+	"github.com/containerd/containerd/archive"
+	"github.com/containerd/containerd/archive/compression"
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/diff"
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/mount"
+	digest "github.com/opencontainers/go-digest"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+)
+
+func NewFileSystemApplierWithWindows(cs content.Provider, a diff.Applier) diff.Applier {
+	if runtime.GOOS == "windows" {
+		return a
+	}
+
+	return &winApplier{
+		cs: cs,
+		a:  a,
+	}
+}
+
+type winApplier struct {
+	cs content.Provider
+	a  diff.Applier
+}
+
+func (s *winApplier) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (d ocispec.Descriptor, err error) {
+	if !hasWindowsLayerMode(ctx) {
+		return s.a.Apply(ctx, desc, mounts, opts...)
+	}
+
+	compressed, err := images.DiffCompression(ctx, desc.MediaType)
+	if err != nil {
+		return ocispec.Descriptor{}, errors.Wrapf(errdefs.ErrNotImplemented, "unsupported diff media type: %v", desc.MediaType)
+	}
+
+	var ocidesc ocispec.Descriptor
+	if err := mount.WithTempMount(ctx, mounts, func(root string) error {
+		ra, err := s.cs.ReaderAt(ctx, desc)
+		if err != nil {
+			return errors.Wrap(err, "failed to get reader from content store")
+		}
+		defer ra.Close()
+
+		r := content.NewReader(ra)
+		if compressed != "" {
+			ds, err := compression.DecompressStream(r)
+			if err != nil {
+				return err
+			}
+			defer ds.Close()
+			r = ds
+		}
+
+		digester := digest.Canonical.Digester()
+		rc := &readCounter{
+			r: io.TeeReader(r, digester.Hash()),
+		}
+
+		rc2, discard := filter(rc, func(hdr *tar.Header) bool {
+			if strings.HasPrefix(hdr.Name, "Files/") {
+				hdr.Name = strings.TrimPrefix(hdr.Name, "Files/")
+				hdr.Linkname = strings.TrimPrefix(hdr.Linkname, "Files/")
+				// TODO: could convert the windows PAX headers to xattr here to reuse
+				// the original ones in diff for parent directories and file modifications
+				return true
+			}
+			return false
+		})
+
+		if _, err := archive.Apply(ctx, root, rc2); err != nil {
+			discard(err)
+			return err
+		}
+
+		// Read any trailing data
+		if _, err := io.Copy(ioutil.Discard, rc); err != nil {
+			discard(err)
+			return err
+		}
+
+		ocidesc = ocispec.Descriptor{
+			MediaType: ocispec.MediaTypeImageLayer,
+			Size:      rc.c,
+			Digest:    digester.Digest(),
+		}
+		return nil
+
+	}); err != nil {
+		return ocispec.Descriptor{}, err
+	}
+	return ocidesc, nil
+}
+
+type readCounter struct {
+	r io.Reader
+	c int64
+}
+
+func (rc *readCounter) Read(p []byte) (n int, err error) {
+	n, err = rc.r.Read(p)
+	rc.c += int64(n)
+	return
+}
+
+func filter(in io.Reader, f func(*tar.Header) bool) (io.Reader, func(error)) {
+	pr, pw := io.Pipe()
+
+	rc := &readCanceler{Reader: in}
+
+	go func() {
+		tarReader := tar.NewReader(rc)
+		tarWriter := tar.NewWriter(pw)
+
+		pw.CloseWithError(func() error {
+			for {
+				h, err := tarReader.Next()
+				if err == io.EOF {
+					break
+				}
+				if err != nil {
+					return err
+				}
+				if f(h) {
+					if err := tarWriter.WriteHeader(h); err != nil {
+						return err
+					}
+					if h.Size > 0 {
+						if _, err := io.Copy(tarWriter, tarReader); err != nil {
+							return err
+						}
+					}
+				} else {
+					if h.Size > 0 {
+						if _, err := io.Copy(ioutil.Discard, tarReader); err != nil {
+							return err
+						}
+					}
+				}
+			}
+			return tarWriter.Close()
+		}())
+	}()
+
+	discard := func(err error) {
+		rc.cancel(err)
+		pw.CloseWithError(err)
+	}
+
+	return pr, discard
+}
+
+type readCanceler struct {
+	mu sync.Mutex
+	io.Reader
+	err error
+}
+
+func (r *readCanceler) Read(b []byte) (int, error) {
+	r.mu.Lock()
+	if r.err != nil {
+		r.mu.Unlock()
+		return 0, r.err
+	}
+	n, err := r.Reader.Read(b)
+	r.mu.Unlock()
+	return n, err
+}
+
+func (r *readCanceler) cancel(err error) {
+	r.mu.Lock()
+	r.err = err
+	r.mu.Unlock()
+}
diff --git a/vendor/github.com/moby/buildkit/util/winlayers/context.go b/vendor/github.com/moby/buildkit/util/winlayers/context.go
new file mode 100644
index 0000000..c0bd3f8
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/winlayers/context.go
@@ -0,0 +1,19 @@
+package winlayers
+
+import "context"
+
+type contextKeyT string
+
+var contextKey = contextKeyT("buildkit/winlayers-on")
+
+func UseWindowsLayerMode(ctx context.Context) context.Context {
+	return context.WithValue(ctx, contextKey, true)
+}
+
+func hasWindowsLayerMode(ctx context.Context) bool {
+	v := ctx.Value(contextKey)
+	if v == nil {
+		return false
+	}
+	return true
+}
diff --git a/vendor/github.com/moby/buildkit/util/winlayers/differ.go b/vendor/github.com/moby/buildkit/util/winlayers/differ.go
new file mode 100644
index 0000000..cdbc335
--- /dev/null
+++ b/vendor/github.com/moby/buildkit/util/winlayers/differ.go
@@ -0,0 +1,274 @@
+package winlayers
+
+import (
+	"archive/tar"
+	"context"
+	"crypto/rand"
+	"encoding/base64"
+	"fmt"
+	"io"
+	"time"
+
+	"github.com/containerd/containerd/archive"
+	"github.com/containerd/containerd/archive/compression"
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/diff"
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/log"
+	"github.com/containerd/containerd/mount"
+	digest "github.com/opencontainers/go-digest"
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+const (
+	keyFileAttr     = "MSWINDOWS.fileattr"
+	keySDRaw        = "MSWINDOWS.rawsd"
+	keyCreationTime = "LIBARCHIVE.creationtime"
+)
+
+func NewWalkingDiffWithWindows(store content.Store, d diff.Comparer) diff.Comparer {
+	return &winDiffer{
+		store: store,
+		d:     d,
+	}
+}
+
+var emptyDesc = ocispec.Descriptor{}
+
+type winDiffer struct {
+	store content.Store
+	d     diff.Comparer
+}
+
+// Compare creates a diff between the given mounts and uploads the result
+// to the content store.
+func (s *winDiffer) Compare(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) {
+	if !hasWindowsLayerMode(ctx) {
+		return s.d.Compare(ctx, lower, upper, opts...)
+	}
+
+	var config diff.Config
+	for _, opt := range opts {
+		if err := opt(&config); err != nil {
+			return emptyDesc, err
+		}
+	}
+
+	if config.MediaType == "" {
+		config.MediaType = ocispec.MediaTypeImageLayerGzip
+	}
+
+	var isCompressed bool
+	switch config.MediaType {
+	case ocispec.MediaTypeImageLayer:
+	case ocispec.MediaTypeImageLayerGzip:
+		isCompressed = true
+	default:
+		return emptyDesc, errors.Wrapf(errdefs.ErrNotImplemented, "unsupported diff media type: %v", config.MediaType)
+	}
+
+	var ocidesc ocispec.Descriptor
+	if err := mount.WithTempMount(ctx, lower, func(lowerRoot string) error {
+		return mount.WithTempMount(ctx, upper, func(upperRoot string) error {
+			var newReference bool
+			if config.Reference == "" {
+				newReference = true
+				config.Reference = uniqueRef()
+			}
+
+			cw, err := s.store.Writer(ctx,
+				content.WithRef(config.Reference),
+				content.WithDescriptor(ocispec.Descriptor{
+					MediaType: config.MediaType, // most contentstore implementations just ignore this
+				}))
+			if err != nil {
+				return errors.Wrap(err, "failed to open writer")
+			}
+			defer func() {
+				if err != nil {
+					cw.Close()
+					if newReference {
+						if err := s.store.Abort(ctx, config.Reference); err != nil {
+							log.G(ctx).WithField("ref", config.Reference).Warnf("failed to delete diff upload")
+						}
+					}
+				}
+			}()
+			if !newReference {
+				if err := cw.Truncate(0); err != nil {
+					return err
+				}
+			}
+
+			if isCompressed {
+				dgstr := digest.SHA256.Digester()
+				compressed, err := compression.CompressStream(cw, compression.Gzip)
+				if err != nil {
+					return errors.Wrap(err, "failed to get compressed stream")
+				}
+				var w io.Writer = io.MultiWriter(compressed, dgstr.Hash())
+				w, discard, done := makeWindowsLayer(w)
+				err = archive.WriteDiff(ctx, w, lowerRoot, upperRoot)
+				if err != nil {
+					discard(err)
+				}
+				<-done
+				compressed.Close()
+				if err != nil {
+					return errors.Wrap(err, "failed to write compressed diff")
+				}
+
+				if config.Labels == nil {
+					config.Labels = map[string]string{}
+				}
+				config.Labels["containerd.io/uncompressed"] = dgstr.Digest().String()
+			} else {
+				w, discard, done := makeWindowsLayer(cw)
+				if err = archive.WriteDiff(ctx, w, lowerRoot, upperRoot); err != nil {
+					discard(err)
+					return errors.Wrap(err, "failed to write diff")
+				}
+				<-done
+			}
+
+			var commitopts []content.Opt
+			if config.Labels != nil {
+				commitopts = append(commitopts, content.WithLabels(config.Labels))
+			}
+
+			dgst := cw.Digest()
+			if err := cw.Commit(ctx, 0, dgst, commitopts...); err != nil {
+				return errors.Wrap(err, "failed to commit")
+			}
+
+			info, err := s.store.Info(ctx, dgst)
+			if err != nil {
+				return errors.Wrap(err, "failed to get info from content store")
+			}
+
+			ocidesc = ocispec.Descriptor{
+				MediaType: config.MediaType,
+				Size:      info.Size,
+				Digest:    info.Digest,
+			}
+			return nil
+		})
+	}); err != nil {
+		return emptyDesc, err
+	}
+
+	return ocidesc, nil
+}
+
+func uniqueRef() string {
+	t := time.Now()
+	var b [3]byte
+	// Ignore read failures, just decreases uniqueness
+	rand.Read(b[:])
+	return fmt.Sprintf("%d-%s", t.UnixNano(), base64.URLEncoding.EncodeToString(b[:]))
+}
+
+func prepareWinHeader(h *tar.Header) {
+	if h.PAXRecords == nil {
+		h.PAXRecords = map[string]string{}
+	}
+	if h.Typeflag == tar.TypeDir {
+		h.Mode |= 1 << 14
+		h.PAXRecords[keyFileAttr] = "16"
+	}
+
+	if h.Typeflag == tar.TypeReg {
+		h.Mode |= 1 << 15
+		h.PAXRecords[keyFileAttr] = "32"
+	}
+
+	if !h.ModTime.IsZero() {
+		h.PAXRecords[keyCreationTime] = fmt.Sprintf("%d.%d", h.ModTime.Unix(), h.ModTime.Nanosecond())
+	}
+
+	h.Format = tar.FormatPAX
+}
+
+func addSecurityDescriptor(h *tar.Header) {
+	if h.Typeflag == tar.TypeDir {
+		// O:BAG:SYD:(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)(A;;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICI;0x1200a9;;;BU)(A;CI;LC;;;BU)(A;CI;DC;;;BU)
+		h.PAXRecords[keySDRaw] = "AQAEgBQAAAAkAAAAAAAAADAAAAABAgAAAAAABSAAAAAgAgAAAQEAAAAAAAUSAAAAAgCoAAcAAAAAAxgA/wEfAAECAAAAAAAFIAAAACACAAAAAxQA/wEfAAEBAAAAAAAFEgAAAAAAGAD/AR8AAQIAAAAAAAUgAAAAIAIAAAALFAAAAAAQAQEAAAAAAAMAAAAAAAMYAKkAEgABAgAAAAAABSAAAAAhAgAAAAIYAAQAAAABAgAAAAAABSAAAAAhAgAAAAIYAAIAAAABAgAAAAAABSAAAAAhAgAA"
+	}
+
+	if h.Typeflag == tar.TypeReg {
+		// O:BAG:SYD:(A;;FA;;;BA)(A;;FA;;;SY)(A;;0x1200a9;;;BU)
+		h.PAXRecords[keySDRaw] = "AQAEgBQAAAAkAAAAAAAAADAAAAABAgAAAAAABSAAAAAgAgAAAQEAAAAAAAUSAAAAAgBMAAMAAAAAABgA/wEfAAECAAAAAAAFIAAAACACAAAAABQA/wEfAAEBAAAAAAAFEgAAAAAAGACpABIAAQIAAAAAAAUgAAAAIQIAAA=="
+	}
+}
+
+func makeWindowsLayer(w io.Writer) (io.Writer, func(error), chan error) {
+	pr, pw := io.Pipe()
+	done := make(chan error)
+
+	go func() {
+		tarReader := tar.NewReader(pr)
+		tarWriter := tar.NewWriter(w)
+
+		err := func() error {
+
+			h := &tar.Header{
+				Name:     "Hives",
+				Typeflag: tar.TypeDir,
+				ModTime:  time.Now(),
+			}
+			prepareWinHeader(h)
+			if err := tarWriter.WriteHeader(h); err != nil {
+				return err
+			}
+
+			h = &tar.Header{
+				Name:     "Files",
+				Typeflag: tar.TypeDir,
+				ModTime:  time.Now(),
+			}
+			prepareWinHeader(h)
+			if err := tarWriter.WriteHeader(h); err != nil {
+				return err
+			}
+
+			for {
+				h, err := tarReader.Next()
+				if err == io.EOF {
+					break
+				}
+				if err != nil {
+					return err
+				}
+				h.Name = "Files/" + h.Name
+				if h.Linkname != "" {
+					h.Linkname = "Files/" + h.Linkname
+				}
+				prepareWinHeader(h)
+				addSecurityDescriptor(h)
+				if err := tarWriter.WriteHeader(h); err != nil {
+					return err
+				}
+				if h.Size > 0 {
+					if _, err := io.Copy(tarWriter, tarReader); err != nil {
+						return err
+					}
+				}
+			}
+			return tarWriter.Close()
+		}()
+		if err != nil {
+			logrus.Errorf("makeWindowsLayer %+v", err)
+		}
+		pw.CloseWithError(err)
+		done <- err
+		return
+	}()
+
+	discard := func(err error) {
+		pw.CloseWithError(err)
+	}
+
+	return pw, discard, done
+}
diff --git a/vendor/github.com/moby/buildkit/worker/cacheresult.go b/vendor/github.com/moby/buildkit/worker/cacheresult.go
index d0ee1a2..0e684e7 100644
--- a/vendor/github.com/moby/buildkit/worker/cacheresult.go
+++ b/vendor/github.com/moby/buildkit/worker/cacheresult.go
@@ -6,7 +6,9 @@
 	"time"
 
 	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
 	"github.com/pkg/errors"
 )
 
@@ -36,7 +38,7 @@
 	return solver.CacheResult{ID: ref.ID(), CreatedAt: createdAt}, nil
 }
 func (s *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult) (solver.Result, error) {
-	return s.load(res.ID, false)
+	return s.load(ctx, res.ID, false)
 }
 
 func (s *cacheResultStorage) getWorkerRef(id string) (Worker, string, error) {
@@ -51,7 +53,7 @@
 	return w, refID, nil
 }
 
-func (s *cacheResultStorage) load(id string, hidden bool) (solver.Result, error) {
+func (s *cacheResultStorage) load(ctx context.Context, id string, hidden bool) (solver.Result, error) {
 	w, refID, err := s.getWorkerRef(id)
 	if err != nil {
 		return nil, err
@@ -59,31 +61,32 @@
 	if refID == "" {
 		return NewWorkerRefResult(nil, w), nil
 	}
-	ref, err := w.LoadRef(refID, hidden)
+	ref, err := w.LoadRef(ctx, refID, hidden)
 	if err != nil {
 		return nil, err
 	}
 	return NewWorkerRefResult(ref, w), nil
 }
 
-func (s *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult) (*solver.Remote, error) {
+func (s *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheResult, g session.Group) (*solver.Remote, error) {
 	w, refID, err := s.getWorkerRef(res.ID)
 	if err != nil {
 		return nil, err
 	}
-	ref, err := w.LoadRef(refID, true)
+	ref, err := w.LoadRef(ctx, refID, true)
 	if err != nil {
 		return nil, err
 	}
 	defer ref.Release(context.TODO())
-	remote, err := w.GetRemote(ctx, ref, false)
+	wref := WorkerRef{ref, w}
+	remote, err := wref.GetRemote(ctx, false, compression.Default, g)
 	if err != nil {
 		return nil, nil // ignore error. loadRemote is best effort
 	}
 	return remote, nil
 }
 func (s *cacheResultStorage) Exists(id string) bool {
-	ref, err := s.load(id, true)
+	ref, err := s.load(context.TODO(), id, true)
 	if err != nil {
 		return false
 	}
diff --git a/vendor/github.com/moby/buildkit/worker/result.go b/vendor/github.com/moby/buildkit/worker/result.go
index 9aa6af4..e178ef3 100644
--- a/vendor/github.com/moby/buildkit/worker/result.go
+++ b/vendor/github.com/moby/buildkit/worker/result.go
@@ -4,7 +4,9 @@
 	"context"
 
 	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/session"
 	"github.com/moby/buildkit/solver"
+	"github.com/moby/buildkit/util/compression"
 )
 
 func NewWorkerRefResult(ref cache.ImmutableRef, worker Worker) solver.Result {
@@ -24,6 +26,18 @@
 	return wr.Worker.ID() + "::" + refID
 }
 
+// GetRemote method abstracts ImmutableRef's GetRemote to allow a Worker to override.
+// This is needed for moby integration.
+// Use this method instead of calling ImmutableRef.GetRemote() directly.
+func (wr *WorkerRef) GetRemote(ctx context.Context, createIfNeeded bool, compressionType compression.Type, g session.Group) (*solver.Remote, error) {
+	if w, ok := wr.Worker.(interface {
+		GetRemote(context.Context, cache.ImmutableRef, bool, compression.Type, session.Group) (*solver.Remote, error)
+	}); ok {
+		return w.GetRemote(ctx, wr.ImmutableRef, createIfNeeded, compressionType, g)
+	}
+	return wr.ImmutableRef.GetRemote(ctx, createIfNeeded, compressionType, g)
+}
+
 type workerRefResult struct {
 	*WorkerRef
 }
diff --git a/vendor/github.com/moby/buildkit/worker/worker.go b/vendor/github.com/moby/buildkit/worker/worker.go
index bc095bc..cee2f63 100644
--- a/vendor/github.com/moby/buildkit/worker/worker.go
+++ b/vendor/github.com/moby/buildkit/worker/worker.go
@@ -5,6 +5,7 @@
 
 	"github.com/containerd/containerd/content"
 	"github.com/moby/buildkit/cache"
+	"github.com/moby/buildkit/cache/metadata"
 	"github.com/moby/buildkit/client"
 	"github.com/moby/buildkit/client/llb"
 	"github.com/moby/buildkit/executor"
@@ -23,19 +24,24 @@
 	Platforms(noCache bool) []specs.Platform
 
 	GCPolicy() []client.PruneInfo
-	LoadRef(id string, hidden bool) (cache.ImmutableRef, error)
+	LoadRef(ctx context.Context, id string, hidden bool) (cache.ImmutableRef, error)
 	// ResolveOp resolves Vertex.Sys() to Op implementation.
 	ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge, sm *session.Manager) (solver.Op, error)
 	ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt, sm *session.Manager, g session.Group) (digest.Digest, []byte, error)
 	DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
 	Exporter(name string, sm *session.Manager) (exporter.Exporter, error)
 	Prune(ctx context.Context, ch chan client.UsageInfo, opt ...client.PruneInfo) error
-	GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool) (*solver.Remote, error)
 	FromRemote(ctx context.Context, remote *solver.Remote) (cache.ImmutableRef, error)
 	PruneCacheMounts(ctx context.Context, ids []string) error
 	ContentStore() content.Store
 	Executor() executor.Executor
 	CacheManager() cache.Manager
+	MetadataStore() *metadata.Store
+}
+
+type Infos interface {
+	GetDefault() (Worker, error)
+	WorkerInfos() []client.WorkerInfo
 }
 
 // Pre-defined label keys
diff --git a/vendor/github.com/moby/term/go.mod b/vendor/github.com/moby/term/go.mod
index 4088df8..f453204 100644
--- a/vendor/github.com/moby/term/go.mod
+++ b/vendor/github.com/moby/term/go.mod
@@ -4,7 +4,7 @@
 
 require (
 	github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78
-	github.com/creack/pty v1.1.9
+	github.com/creack/pty v1.1.11
 	github.com/google/go-cmp v0.4.0
 	github.com/pkg/errors v0.9.1 // indirect
 	golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a
diff --git a/vendor/github.com/moby/term/term_windows.go b/vendor/github.com/moby/term/term_windows.go
index 2e51275..ba82960 100644
--- a/vendor/github.com/moby/term/term_windows.go
+++ b/vendor/github.com/moby/term/term_windows.go
@@ -71,19 +71,22 @@
 	// go-ansiterm hasn't switch to x/sys/windows.
 	// TODO: switch back to x/sys/windows once go-ansiterm has switched
 	if emulateStdin {
-		stdIn = windowsconsole.NewAnsiReader(windows.STD_INPUT_HANDLE)
+		h := uint32(windows.STD_INPUT_HANDLE)
+		stdIn = windowsconsole.NewAnsiReader(int(h))
 	} else {
 		stdIn = os.Stdin
 	}
 
 	if emulateStdout {
-		stdOut = windowsconsole.NewAnsiWriter(windows.STD_OUTPUT_HANDLE)
+		h := uint32(windows.STD_OUTPUT_HANDLE)
+		stdOut = windowsconsole.NewAnsiWriter(int(h))
 	} else {
 		stdOut = os.Stdout
 	}
 
 	if emulateStderr {
-		stdErr = windowsconsole.NewAnsiWriter(windows.STD_ERROR_HANDLE)
+		h := uint32(windows.STD_ERROR_HANDLE)
+		stdErr = windowsconsole.NewAnsiWriter(int(h))
 	} else {
 		stdErr = os.Stderr
 	}
diff --git a/vendor/github.com/opentracing-contrib/go-stdlib/LICENSE b/vendor/github.com/opentracing-contrib/go-stdlib/LICENSE
index c259d12..261eeb9 100644
--- a/vendor/github.com/opentracing-contrib/go-stdlib/LICENSE
+++ b/vendor/github.com/opentracing-contrib/go-stdlib/LICENSE
@@ -1,27 +1,201 @@
-Copyright (c) 2016, opentracing-contrib
-All rights reserved.
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
+   1. Definitions.
 
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
 
-* Neither the name of go-stdlib nor the names of its
-  contributors may be used to endorse or promote products derived from
-  this software without specific prior written permission.
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vendor/github.com/opentracing-contrib/go-stdlib/README.md b/vendor/github.com/opentracing-contrib/go-stdlib/README.md
index 139709c..c820daa 100644
--- a/vendor/github.com/opentracing-contrib/go-stdlib/README.md
+++ b/vendor/github.com/opentracing-contrib/go-stdlib/README.md
@@ -16,3 +16,7 @@
 
 - **net/http**: Client and server instrumentation. *Only supported
   with Go 1.7 and later.*
+
+## License
+
+By contributing to this repository, you agree that your contributions will be licensed under [Apache 2.0 License](./LICENSE).
diff --git a/vendor/github.com/opentracing-contrib/go-stdlib/go.mod b/vendor/github.com/opentracing-contrib/go-stdlib/go.mod
new file mode 100644
index 0000000..3b3c5c2
--- /dev/null
+++ b/vendor/github.com/opentracing-contrib/go-stdlib/go.mod
@@ -0,0 +1,7 @@
+module github.com/opentracing-contrib/go-stdlib
+
+go 1.14
+
+require (
+	github.com/opentracing/opentracing-go v1.1.0
+)
diff --git a/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/client.go b/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/client.go
index 8d33bcb..bfb305f 100644
--- a/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/client.go
+++ b/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/client.go
@@ -7,6 +7,7 @@
 	"io"
 	"net/http"
 	"net/http/httptrace"
+	"net/url"
 
 	"github.com/opentracing/opentracing-go"
 	"github.com/opentracing/opentracing-go/ext"
@@ -31,9 +32,12 @@
 }
 
 type clientOptions struct {
-	operationName      string
-	componentName      string
-	disableClientTrace bool
+	operationName            string
+	componentName            string
+	urlTagFunc         func(u *url.URL) string
+	disableClientTrace       bool
+	disableInjectSpanContext bool
+	spanObserver             func(span opentracing.Span, r *http.Request)
 }
 
 // ClientOption contols the behavior of TraceRequest.
@@ -47,6 +51,15 @@
 	}
 }
 
+// URLTagFunc returns a ClientOption that uses given function f
+// to set the span's http.url tag. Can be used to change the default
+// http.url tag, eg to redact sensitive information.
+func URLTagFunc(f func(u *url.URL) string) ClientOption {
+	return func(options *clientOptions) {
+		options.urlTagFunc = f
+	}
+}
+
 // ComponentName returns a ClientOption that sets the component
 // name for the client-side span.
 func ComponentName(componentName string) ClientOption {
@@ -63,6 +76,24 @@
 	}
 }
 
+// InjectSpanContext returns a ClientOption that turns on or off
+// injection of the Span context in the request HTTP headers.
+// If this option is not used, the default behaviour is to
+// inject the span context.
+func InjectSpanContext(enabled bool) ClientOption {
+	return func(options *clientOptions) {
+		options.disableInjectSpanContext = !enabled
+	}
+}
+
+// ClientSpanObserver returns a ClientOption that observes the span
+// for the client-side span.
+func ClientSpanObserver(f func(span opentracing.Span, r *http.Request)) ClientOption {
+	return func(options *clientOptions) {
+		options.spanObserver = f
+	}
+}
+
 // TraceRequest adds a ClientTracer to req, tracing the request and
 // all requests caused due to redirects. When tracing requests this
 // way you must also use Transport.
@@ -88,7 +119,12 @@
 // 		return nil
 // 	}
 func TraceRequest(tr opentracing.Tracer, req *http.Request, options ...ClientOption) (*http.Request, *Tracer) {
-	opts := &clientOptions{}
+	opts := &clientOptions{
+		urlTagFunc: func(u *url.URL) string {
+			return u.String()
+		},
+		spanObserver: func(_ opentracing.Span, _ *http.Request) {},
+	}
 	for _, opt := range options {
 		opt(opts)
 	}
@@ -113,24 +149,38 @@
 	return err
 }
 
+// TracerFromRequest retrieves the Tracer from the request. If the request does
+// not have a Tracer it will return nil.
+func TracerFromRequest(req *http.Request) *Tracer {
+	tr, ok := req.Context().Value(keyTracer).(*Tracer)
+	if !ok {
+		return nil
+	}
+	return tr
+}
+
 // RoundTrip implements the RoundTripper interface.
 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
 	rt := t.RoundTripper
 	if rt == nil {
 		rt = http.DefaultTransport
 	}
-	tracer, ok := req.Context().Value(keyTracer).(*Tracer)
-	if !ok {
+	tracer := TracerFromRequest(req)
+	if tracer == nil {
 		return rt.RoundTrip(req)
 	}
 
 	tracer.start(req)
 
 	ext.HTTPMethod.Set(tracer.sp, req.Method)
-	ext.HTTPUrl.Set(tracer.sp, req.URL.String())
+	ext.HTTPUrl.Set(tracer.sp, tracer.opts.urlTagFunc(req.URL))
+	tracer.opts.spanObserver(tracer.sp, req)
 
-	carrier := opentracing.HTTPHeadersCarrier(req.Header)
-	tracer.sp.Tracer().Inject(tracer.sp.Context(), opentracing.HTTPHeaders, carrier)
+	if !tracer.opts.disableInjectSpanContext {
+		carrier := opentracing.HTTPHeadersCarrier(req.Header)
+		tracer.sp.Tracer().Inject(tracer.sp.Context(), opentracing.HTTPHeaders, carrier)
+	}
+
 	resp, err := rt.RoundTrip(req)
 
 	if err != nil {
@@ -138,6 +188,9 @@
 		return resp, err
 	}
 	ext.HTTPStatusCode.Set(tracer.sp, uint16(resp.StatusCode))
+	if resp.StatusCode >= http.StatusInternalServerError {
+		ext.Error.Set(tracer.sp, true)
+	}
 	if req.Method == "HEAD" {
 		tracer.sp.Finish()
 	} else {
diff --git a/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/server.go b/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/server.go
index 2b31415..db2df66 100644
--- a/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/server.go
+++ b/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/server.go
@@ -4,23 +4,17 @@
 
 import (
 	"net/http"
+	"net/url"
 
 	opentracing "github.com/opentracing/opentracing-go"
 	"github.com/opentracing/opentracing-go/ext"
 )
 
-type statusCodeTracker struct {
-	http.ResponseWriter
-	status int
-}
-
-func (w *statusCodeTracker) WriteHeader(status int) {
-	w.status = status
-	w.ResponseWriter.WriteHeader(status)
-}
-
 type mwOptions struct {
 	opNameFunc    func(r *http.Request) string
+	spanFilter    func(r *http.Request) bool
+	spanObserver  func(span opentracing.Span, r *http.Request)
+	urlTagFunc    func(u *url.URL) string
 	componentName string
 }
 
@@ -36,13 +30,39 @@
 }
 
 // MWComponentName returns a MWOption that sets the component name
-// name for the server-side span.
+// for the server-side span.
 func MWComponentName(componentName string) MWOption {
 	return func(options *mwOptions) {
 		options.componentName = componentName
 	}
 }
 
+// MWSpanFilter returns a MWOption that filters requests from creating a span
+// for the server-side span.
+// Span won't be created if it returns false.
+func MWSpanFilter(f func(r *http.Request) bool) MWOption {
+	return func(options *mwOptions) {
+		options.spanFilter = f
+	}
+}
+
+// MWSpanObserver returns a MWOption that observe the span
+// for the server-side span.
+func MWSpanObserver(f func(span opentracing.Span, r *http.Request)) MWOption {
+	return func(options *mwOptions) {
+		options.spanObserver = f
+	}
+}
+
+// MWURLTagFunc returns a MWOption that uses given function f
+// to set the span's http.url tag. Can be used to change the default
+// http.url tag, eg to redact sensitive information.
+func MWURLTagFunc(f func(u *url.URL) string) MWOption {
+	return func(options *mwOptions) {
+		options.urlTagFunc = f
+	}
+}
+
 // Middleware wraps an http.Handler and traces incoming requests.
 // Additionally, it adds the span to the request's context.
 //
@@ -58,39 +78,80 @@
 //   mw := nethttp.Middleware(
 //      tracer,
 //      http.DefaultServeMux,
-//      nethttp.OperationName(func(r *http.Request) string {
+//      nethttp.OperationNameFunc(func(r *http.Request) string {
 //	        return "HTTP " + r.Method + ":/api/customers"
 //      }),
+//      nethttp.MWSpanObserver(func(sp opentracing.Span, r *http.Request) {
+//			sp.SetTag("http.uri", r.URL.EscapedPath())
+//		}),
 //   )
 func Middleware(tr opentracing.Tracer, h http.Handler, options ...MWOption) http.Handler {
+	return MiddlewareFunc(tr, h.ServeHTTP, options...)
+}
+
+// MiddlewareFunc wraps an http.HandlerFunc and traces incoming requests.
+// It behaves identically to the Middleware function above.
+//
+// Example:
+//   http.ListenAndServe("localhost:80", nethttp.MiddlewareFunc(tracer, MyHandler))
+func MiddlewareFunc(tr opentracing.Tracer, h http.HandlerFunc, options ...MWOption) http.HandlerFunc {
 	opts := mwOptions{
 		opNameFunc: func(r *http.Request) string {
 			return "HTTP " + r.Method
 		},
+		spanFilter:   func(r *http.Request) bool { return true },
+		spanObserver: func(span opentracing.Span, r *http.Request) {},
+		urlTagFunc: func(u *url.URL) string {
+			return u.String()
+		},
 	}
 	for _, opt := range options {
 		opt(&opts)
 	}
+	// set component name, use "net/http" if caller does not specify
+	componentName := opts.componentName
+	if componentName == "" {
+		componentName = defaultComponentName
+	}
+
 	fn := func(w http.ResponseWriter, r *http.Request) {
+		if !opts.spanFilter(r) {
+			h(w, r)
+			return
+		}
 		ctx, _ := tr.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header))
 		sp := tr.StartSpan(opts.opNameFunc(r), ext.RPCServerOption(ctx))
 		ext.HTTPMethod.Set(sp, r.Method)
-		ext.HTTPUrl.Set(sp, r.URL.String())
-
-		// set component name, use "net/http" if caller does not specify
-		componentName := opts.componentName
-		if componentName == "" {
-			componentName = defaultComponentName
-		}
+		ext.HTTPUrl.Set(sp, opts.urlTagFunc(r.URL))
 		ext.Component.Set(sp, componentName)
+		opts.spanObserver(sp, r)
 
-		w = &statusCodeTracker{w, 200}
+		sct := &statusCodeTracker{ResponseWriter: w}
 		r = r.WithContext(opentracing.ContextWithSpan(r.Context(), sp))
 
-		h.ServeHTTP(w, r)
+		defer func() {
+			panicErr := recover()
+			didPanic := panicErr != nil
 
-		ext.HTTPStatusCode.Set(sp, uint16(w.(*statusCodeTracker).status))
-		sp.Finish()
+			if sct.status == 0 && !didPanic {
+				// Standard behavior of http.Server is to assume status code 200 if one was not written by a handler that returned successfully.
+				// https://github.com/golang/go/blob/fca286bed3ed0e12336532cc711875ae5b3cb02a/src/net/http/server.go#L120
+				sct.status = 200
+			}
+			if sct.status > 0 {
+				ext.HTTPStatusCode.Set(sp, uint16(sct.status))
+			}
+			if sct.status >= http.StatusInternalServerError || didPanic {
+				ext.Error.Set(sp, true)
+			}
+			sp.Finish()
+
+			if didPanic {
+				panic(panicErr)
+			}
+		}()
+
+		h(sct.wrappedResponseWriter(), r)
 	}
 	return http.HandlerFunc(fn)
 }
diff --git a/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/status-code-tracker.go b/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/status-code-tracker.go
new file mode 100644
index 0000000..80a5ce0
--- /dev/null
+++ b/vendor/github.com/opentracing-contrib/go-stdlib/nethttp/status-code-tracker.go
@@ -0,0 +1,251 @@
+// +build go1.8
+
+package nethttp
+
+import (
+	"io"
+	"net/http"
+)
+
+type statusCodeTracker struct {
+	http.ResponseWriter
+	status int
+}
+
+func (w *statusCodeTracker) WriteHeader(status int) {
+	w.status = status
+	w.ResponseWriter.WriteHeader(status)
+}
+
+func (w *statusCodeTracker) Write(b []byte) (int, error) {
+	return w.ResponseWriter.Write(b)
+}
+
+// wrappedResponseWriter returns a wrapped version of the original
+// ResponseWriter and only implements the same combination of additional
+// interfaces as the original.  This implementation is based on
+// https://github.com/felixge/httpsnoop.
+func (w *statusCodeTracker) wrappedResponseWriter() http.ResponseWriter {
+	var (
+		hj, i0 = w.ResponseWriter.(http.Hijacker)
+		cn, i1 = w.ResponseWriter.(http.CloseNotifier)
+		pu, i2 = w.ResponseWriter.(http.Pusher)
+		fl, i3 = w.ResponseWriter.(http.Flusher)
+		rf, i4 = w.ResponseWriter.(io.ReaderFrom)
+	)
+
+	switch {
+	case !i0 && !i1 && !i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+		}{w}
+	case !i0 && !i1 && !i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			io.ReaderFrom
+		}{w, rf}
+	case !i0 && !i1 && !i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Flusher
+		}{w, fl}
+	case !i0 && !i1 && !i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Flusher
+			io.ReaderFrom
+		}{w, fl, rf}
+	case !i0 && !i1 && i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Pusher
+		}{w, pu}
+	case !i0 && !i1 && i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Pusher
+			io.ReaderFrom
+		}{w, pu, rf}
+	case !i0 && !i1 && i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Pusher
+			http.Flusher
+		}{w, pu, fl}
+	case !i0 && !i1 && i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Pusher
+			http.Flusher
+			io.ReaderFrom
+		}{w, pu, fl, rf}
+	case !i0 && i1 && !i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+		}{w, cn}
+	case !i0 && i1 && !i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			io.ReaderFrom
+		}{w, cn, rf}
+	case !i0 && i1 && !i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			http.Flusher
+		}{w, cn, fl}
+	case !i0 && i1 && !i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			http.Flusher
+			io.ReaderFrom
+		}{w, cn, fl, rf}
+	case !i0 && i1 && i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			http.Pusher
+		}{w, cn, pu}
+	case !i0 && i1 && i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			http.Pusher
+			io.ReaderFrom
+		}{w, cn, pu, rf}
+	case !i0 && i1 && i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			http.Pusher
+			http.Flusher
+		}{w, cn, pu, fl}
+	case !i0 && i1 && i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.CloseNotifier
+			http.Pusher
+			http.Flusher
+			io.ReaderFrom
+		}{w, cn, pu, fl, rf}
+	case i0 && !i1 && !i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+		}{w, hj}
+	case i0 && !i1 && !i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			io.ReaderFrom
+		}{w, hj, rf}
+	case i0 && !i1 && !i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.Flusher
+		}{w, hj, fl}
+	case i0 && !i1 && !i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.Flusher
+			io.ReaderFrom
+		}{w, hj, fl, rf}
+	case i0 && !i1 && i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.Pusher
+		}{w, hj, pu}
+	case i0 && !i1 && i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.Pusher
+			io.ReaderFrom
+		}{w, hj, pu, rf}
+	case i0 && !i1 && i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.Pusher
+			http.Flusher
+		}{w, hj, pu, fl}
+	case i0 && !i1 && i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.Pusher
+			http.Flusher
+			io.ReaderFrom
+		}{w, hj, pu, fl, rf}
+	case i0 && i1 && !i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+		}{w, hj, cn}
+	case i0 && i1 && !i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			io.ReaderFrom
+		}{w, hj, cn, rf}
+	case i0 && i1 && !i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			http.Flusher
+		}{w, hj, cn, fl}
+	case i0 && i1 && !i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			http.Flusher
+			io.ReaderFrom
+		}{w, hj, cn, fl, rf}
+	case i0 && i1 && i2 && !i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			http.Pusher
+		}{w, hj, cn, pu}
+	case i0 && i1 && i2 && !i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			http.Pusher
+			io.ReaderFrom
+		}{w, hj, cn, pu, rf}
+	case i0 && i1 && i2 && i3 && !i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			http.Pusher
+			http.Flusher
+		}{w, hj, cn, pu, fl}
+	case i0 && i1 && i2 && i3 && i4:
+		return struct {
+			http.ResponseWriter
+			http.Hijacker
+			http.CloseNotifier
+			http.Pusher
+			http.Flusher
+			io.ReaderFrom
+		}{w, hj, cn, pu, fl, rf}
+	default:
+		return struct {
+			http.ResponseWriter
+		}{w}
+	}
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/LICENSE b/vendor/github.com/opentracing/opentracing-go/LICENSE
index 148509a..f002734 100644
--- a/vendor/github.com/opentracing/opentracing-go/LICENSE
+++ b/vendor/github.com/opentracing/opentracing-go/LICENSE
@@ -1,21 +1,201 @@
-The MIT License (MIT)
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
 
-Copyright (c) 2016 The OpenTracing Authors
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+   1. Definitions.
 
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2016 The OpenTracing Authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vendor/github.com/opentracing/opentracing-go/README.md b/vendor/github.com/opentracing/opentracing-go/README.md
index 19a541c..6ef1d7c 100644
--- a/vendor/github.com/opentracing/opentracing-go/README.md
+++ b/vendor/github.com/opentracing/opentracing-go/README.md
@@ -8,8 +8,8 @@
 ## Required Reading
 
 In order to understand the Go platform API, one must first be familiar with the
-[OpenTracing project](http://opentracing.io) and
-[terminology](http://opentracing.io/documentation/pages/spec.html) more specifically.
+[OpenTracing project](https://opentracing.io) and
+[terminology](https://opentracing.io/specification/) more specifically.
 
 ## API overview for those adding instrumentation
 
@@ -27,7 +27,7 @@
     import ".../some_tracing_impl"
 
     func main() {
-        opentracing.InitGlobalTracer(
+        opentracing.SetGlobalTracer(
             // tracing impl specific:
             some_tracing_impl.New(...),
         )
@@ -35,7 +35,7 @@
     }
 ```
 
-##### Non-Singleton initialization
+#### Non-Singleton initialization
 
 If you prefer direct control to singletons, manage ownership of the
 `opentracing.Tracer` implementation explicitly.
@@ -161,3 +161,11 @@
 ## API compatibility
 
 For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and `opentracing-go` mature, backwards compatibility will become more of a priority.
+
+## Tracer test suite
+
+A test suite is available in the [harness](https://godoc.org/github.com/opentracing/opentracing-go/harness) package that can assist Tracer implementors to assert that their Tracer is working correctly.
+
+## Licensing
+
+[Apache 2.0 License](./LICENSE).
diff --git a/vendor/github.com/opentracing/opentracing-go/ext.go b/vendor/github.com/opentracing/opentracing-go/ext.go
new file mode 100644
index 0000000..e11977e
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/ext.go
@@ -0,0 +1,24 @@
+package opentracing
+
+import (
+	"context"
+)
+
+// TracerContextWithSpanExtension is an extension interface that the
+// implementation of the Tracer interface may want to implement. It
+// allows to have some control over the go context when the
+// ContextWithSpan is invoked.
+//
+// The primary purpose of this extension are adapters from opentracing
+// API to some other tracing API.
+type TracerContextWithSpanExtension interface {
+	// ContextWithSpanHook gets called by the ContextWithSpan
+	// function, when the Tracer implementation also implements
+	// this interface. It allows to put extra information into the
+	// context and make it available to the callers of the
+	// ContextWithSpan.
+	//
+	// This hook is invoked before the ContextWithSpan function
+	// actually puts the span into the context.
+	ContextWithSpanHook(ctx context.Context, span Span) context.Context
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/ext/field.go b/vendor/github.com/opentracing/opentracing-go/ext/field.go
new file mode 100644
index 0000000..8282bd7
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/ext/field.go
@@ -0,0 +1,17 @@
+package ext
+
+import (
+	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/log"
+)
+
+// LogError sets the error=true tag on the Span and logs err as an "error" event.
+func LogError(span opentracing.Span, err error, fields ...log.Field) {
+	Error.Set(span, true)
+	ef := []log.Field{
+		log.Event("error"),
+		log.Error(err),
+	}
+	ef = append(ef, fields...)
+	span.LogFields(ef...)
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/ext/tags.go b/vendor/github.com/opentracing/opentracing-go/ext/tags.go
index 8800129..a414b59 100644
--- a/vendor/github.com/opentracing/opentracing-go/ext/tags.go
+++ b/vendor/github.com/opentracing/opentracing-go/ext/tags.go
@@ -1,6 +1,6 @@
 package ext
 
-import opentracing "github.com/opentracing/opentracing-go"
+import "github.com/opentracing/opentracing-go"
 
 // These constants define common tag names recommended for better portability across
 // tracing systems and languages/platforms.
@@ -47,40 +47,40 @@
 
 	// Component is a low-cardinality identifier of the module, library,
 	// or package that is generating a span.
-	Component = stringTagName("component")
+	Component = StringTagName("component")
 
 	//////////////////////////////////////////////////////////////////////
 	// Sampling hint
 	//////////////////////////////////////////////////////////////////////
 
 	// SamplingPriority determines the priority of sampling this Span.
-	SamplingPriority = uint16TagName("sampling.priority")
+	SamplingPriority = Uint16TagName("sampling.priority")
 
 	//////////////////////////////////////////////////////////////////////
-	// Peer tags. These tags can be emitted by either client-side of
+	// Peer tags. These tags can be emitted by either client-side or
 	// server-side to describe the other side/service in a peer-to-peer
 	// communications, like an RPC call.
 	//////////////////////////////////////////////////////////////////////
 
 	// PeerService records the service name of the peer.
-	PeerService = stringTagName("peer.service")
+	PeerService = StringTagName("peer.service")
 
 	// PeerAddress records the address name of the peer. This may be a "ip:port",
 	// a bare "hostname", a FQDN or even a database DSN substring
 	// like "mysql://username@127.0.0.1:3306/dbname"
-	PeerAddress = stringTagName("peer.address")
+	PeerAddress = StringTagName("peer.address")
 
 	// PeerHostname records the host name of the peer
-	PeerHostname = stringTagName("peer.hostname")
+	PeerHostname = StringTagName("peer.hostname")
 
 	// PeerHostIPv4 records IP v4 host address of the peer
-	PeerHostIPv4 = ipv4Tag("peer.ipv4")
+	PeerHostIPv4 = IPv4TagName("peer.ipv4")
 
 	// PeerHostIPv6 records IP v6 host address of the peer
-	PeerHostIPv6 = stringTagName("peer.ipv6")
+	PeerHostIPv6 = StringTagName("peer.ipv6")
 
 	// PeerPort records port number of the peer
-	PeerPort = uint16TagName("peer.port")
+	PeerPort = Uint16TagName("peer.port")
 
 	//////////////////////////////////////////////////////////////////////
 	// HTTP Tags
@@ -88,46 +88,46 @@
 
 	// HTTPUrl should be the URL of the request being handled in this segment
 	// of the trace, in standard URI format. The protocol is optional.
-	HTTPUrl = stringTagName("http.url")
+	HTTPUrl = StringTagName("http.url")
 
 	// HTTPMethod is the HTTP method of the request, and is case-insensitive.
-	HTTPMethod = stringTagName("http.method")
+	HTTPMethod = StringTagName("http.method")
 
 	// HTTPStatusCode is the numeric HTTP status code (200, 404, etc) of the
 	// HTTP response.
-	HTTPStatusCode = uint16TagName("http.status_code")
+	HTTPStatusCode = Uint16TagName("http.status_code")
 
 	//////////////////////////////////////////////////////////////////////
 	// DB Tags
 	//////////////////////////////////////////////////////////////////////
 
 	// DBInstance is database instance name.
-	DBInstance = stringTagName("db.instance")
+	DBInstance = StringTagName("db.instance")
 
 	// DBStatement is a database statement for the given database type.
 	// It can be a query or a prepared statement (i.e., before substitution).
-	DBStatement = stringTagName("db.statement")
+	DBStatement = StringTagName("db.statement")
 
 	// DBType is a database type. For any SQL database, "sql".
 	// For others, the lower-case database category, e.g. "redis"
-	DBType = stringTagName("db.type")
+	DBType = StringTagName("db.type")
 
 	// DBUser is a username for accessing database.
-	DBUser = stringTagName("db.user")
+	DBUser = StringTagName("db.user")
 
 	//////////////////////////////////////////////////////////////////////
 	// Message Bus Tag
 	//////////////////////////////////////////////////////////////////////
 
 	// MessageBusDestination is an address at which messages can be exchanged
-	MessageBusDestination = stringTagName("message_bus.destination")
+	MessageBusDestination = StringTagName("message_bus.destination")
 
 	//////////////////////////////////////////////////////////////////////
 	// Error Tag
 	//////////////////////////////////////////////////////////////////////
 
 	// Error indicates that operation represented by the span resulted in an error.
-	Error = boolTagName("error")
+	Error = BoolTagName("error")
 )
 
 // ---
@@ -163,48 +163,53 @@
 
 // ---
 
-type stringTagName string
+// StringTagName is a common tag name to be set to a string value
+type StringTagName string
 
 // Set adds a string tag to the `span`
-func (tag stringTagName) Set(span opentracing.Span, value string) {
+func (tag StringTagName) Set(span opentracing.Span, value string) {
 	span.SetTag(string(tag), value)
 }
 
 // ---
 
-type uint32TagName string
+// Uint32TagName is a common tag name to be set to a uint32 value
+type Uint32TagName string
 
 // Set adds a uint32 tag to the `span`
-func (tag uint32TagName) Set(span opentracing.Span, value uint32) {
+func (tag Uint32TagName) Set(span opentracing.Span, value uint32) {
 	span.SetTag(string(tag), value)
 }
 
 // ---
 
-type uint16TagName string
+// Uint16TagName is a common tag name to be set to a uint16 value
+type Uint16TagName string
 
 // Set adds a uint16 tag to the `span`
-func (tag uint16TagName) Set(span opentracing.Span, value uint16) {
+func (tag Uint16TagName) Set(span opentracing.Span, value uint16) {
 	span.SetTag(string(tag), value)
 }
 
 // ---
 
-type boolTagName string
+// BoolTagName is a common tag name to be set to a bool value
+type BoolTagName string
 
-// Add adds a bool tag to the `span`
-func (tag boolTagName) Set(span opentracing.Span, value bool) {
+// Set adds a bool tag to the `span`
+func (tag BoolTagName) Set(span opentracing.Span, value bool) {
 	span.SetTag(string(tag), value)
 }
 
-type ipv4Tag string
+// IPv4TagName is a common tag name to be set to an ipv4 value
+type IPv4TagName string
 
 // Set adds IP v4 host address of the peer as an uint32 value to the `span`, keep this for backward and zipkin compatibility
-func (tag ipv4Tag) Set(span opentracing.Span, value uint32) {
+func (tag IPv4TagName) Set(span opentracing.Span, value uint32) {
 	span.SetTag(string(tag), value)
 }
 
 // SetString records IP v4 host address of the peer as a .-separated tuple to the `span`. E.g., "127.0.0.1"
-func (tag ipv4Tag) SetString(span opentracing.Span, value string) {
+func (tag IPv4TagName) SetString(span opentracing.Span, value string) {
 	span.SetTag(string(tag), value)
 }
diff --git a/vendor/github.com/opentracing/opentracing-go/globaltracer.go b/vendor/github.com/opentracing/opentracing-go/globaltracer.go
index 8c8e793..4f7066a 100644
--- a/vendor/github.com/opentracing/opentracing-go/globaltracer.go
+++ b/vendor/github.com/opentracing/opentracing-go/globaltracer.go
@@ -1,7 +1,12 @@
 package opentracing
 
+type registeredTracer struct {
+	tracer       Tracer
+	isRegistered bool
+}
+
 var (
-	globalTracer Tracer = NoopTracer{}
+	globalTracer = registeredTracer{NoopTracer{}, false}
 )
 
 // SetGlobalTracer sets the [singleton] opentracing.Tracer returned by
@@ -11,22 +16,27 @@
 // Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan`
 // (etc) globals are noops.
 func SetGlobalTracer(tracer Tracer) {
-	globalTracer = tracer
+	globalTracer = registeredTracer{tracer, true}
 }
 
 // GlobalTracer returns the global singleton `Tracer` implementation.
 // Before `SetGlobalTracer()` is called, the `GlobalTracer()` is a noop
 // implementation that drops all data handed to it.
 func GlobalTracer() Tracer {
-	return globalTracer
+	return globalTracer.tracer
 }
 
 // StartSpan defers to `Tracer.StartSpan`. See `GlobalTracer()`.
 func StartSpan(operationName string, opts ...StartSpanOption) Span {
-	return globalTracer.StartSpan(operationName, opts...)
+	return globalTracer.tracer.StartSpan(operationName, opts...)
 }
 
 // InitGlobalTracer is deprecated. Please use SetGlobalTracer.
 func InitGlobalTracer(tracer Tracer) {
 	SetGlobalTracer(tracer)
 }
+
+// IsGlobalTracerRegistered returns a `bool` to indicate if a tracer has been globally registered
+func IsGlobalTracerRegistered() bool {
+	return globalTracer.isRegistered
+}
diff --git a/vendor/github.com/opentracing/opentracing-go/go.mod b/vendor/github.com/opentracing/opentracing-go/go.mod
new file mode 100644
index 0000000..bf48bb5
--- /dev/null
+++ b/vendor/github.com/opentracing/opentracing-go/go.mod
@@ -0,0 +1,5 @@
+module github.com/opentracing/opentracing-go
+
+go 1.14
+
+require github.com/stretchr/testify v1.3.0
diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext.go b/vendor/github.com/opentracing/opentracing-go/gocontext.go
index 222a652..1831bc9 100644
--- a/vendor/github.com/opentracing/opentracing-go/gocontext.go
+++ b/vendor/github.com/opentracing/opentracing-go/gocontext.go
@@ -1,14 +1,19 @@
 package opentracing
 
-import "golang.org/x/net/context"
+import "context"
 
 type contextKey struct{}
 
 var activeSpanKey = contextKey{}
 
 // ContextWithSpan returns a new `context.Context` that holds a reference to
-// `span`'s SpanContext.
+// the span. If span is nil, a new context without an active span is returned.
 func ContextWithSpan(ctx context.Context, span Span) context.Context {
+	if span != nil {
+		if tracerWithHook, ok := span.Tracer().(TracerContextWithSpanExtension); ok {
+			ctx = tracerWithHook.ContextWithSpanHook(ctx, span)
+		}
+	}
 	return context.WithValue(ctx, activeSpanKey, span)
 }
 
@@ -41,17 +46,20 @@
 //        ...
 //    }
 func StartSpanFromContext(ctx context.Context, operationName string, opts ...StartSpanOption) (Span, context.Context) {
-	return startSpanFromContextWithTracer(ctx, GlobalTracer(), operationName, opts...)
+	return StartSpanFromContextWithTracer(ctx, GlobalTracer(), operationName, opts...)
 }
 
-// startSpanFromContextWithTracer is factored out for testing purposes.
-func startSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) {
-	var span Span
+// StartSpanFromContextWithTracer starts and returns a span with `operationName`
+// using  a span found within the context as a ChildOfRef. If that doesn't exist
+// it creates a root span. It also returns a context.Context object built
+// around the returned span.
+//
+// It's behavior is identical to StartSpanFromContext except that it takes an explicit
+// tracer as opposed to using the global tracer.
+func StartSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) {
 	if parentSpan := SpanFromContext(ctx); parentSpan != nil {
 		opts = append(opts, ChildOf(parentSpan.Context()))
-		span = tracer.StartSpan(operationName, opts...)
-	} else {
-		span = tracer.StartSpan(operationName, opts...)
 	}
+	span := tracer.StartSpan(operationName, opts...)
 	return span, ContextWithSpan(ctx, span)
 }
diff --git a/vendor/github.com/opentracing/opentracing-go/log/field.go b/vendor/github.com/opentracing/opentracing-go/log/field.go
index 50feea3..f222ded 100644
--- a/vendor/github.com/opentracing/opentracing-go/log/field.go
+++ b/vendor/github.com/opentracing/opentracing-go/log/field.go
@@ -122,16 +122,19 @@
 	}
 }
 
-// Error adds an error with the key "error" to a Span.LogFields() record
+// Error adds an error with the key "error.object" to a Span.LogFields() record
 func Error(err error) Field {
 	return Field{
-		key:          "error",
+		key:          "error.object",
 		fieldType:    errorType,
 		interfaceVal: err,
 	}
 }
 
 // Object adds an object-valued key:value pair to a Span.LogFields() record
+// Please pass in an immutable object, otherwise there may be concurrency issues.
+// Such as passing in the map, log.Object may result in "fatal error: concurrent map iteration and map write".
+// Because span is sent asynchronously, it is possible that this map will also be modified.
 func Object(key string, obj interface{}) Field {
 	return Field{
 		key:          key,
@@ -140,6 +143,16 @@
 	}
 }
 
+// Event creates a string-valued Field for span logs with key="event" and value=val.
+func Event(val string) Field {
+	return String("event", val)
+}
+
+// Message creates a string-valued Field for span logs with key="message" and value=val.
+func Message(val string) Field {
+	return String("message", val)
+}
+
 // LazyLogger allows for user-defined, late-bound logging of arbitrary data
 type LazyLogger func(fv Encoder)
 
diff --git a/vendor/github.com/opentracing/opentracing-go/log/util.go b/vendor/github.com/opentracing/opentracing-go/log/util.go
index 3832feb..d57e28a 100644
--- a/vendor/github.com/opentracing/opentracing-go/log/util.go
+++ b/vendor/github.com/opentracing/opentracing-go/log/util.go
@@ -1,6 +1,9 @@
 package log
 
-import "fmt"
+import (
+	"fmt"
+	"reflect"
+)
 
 // InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice
 // a la Span.LogFields().
@@ -46,6 +49,10 @@
 		case float64:
 			fields[i] = Float64(key, typedVal)
 		default:
+			if typedVal == nil || (reflect.ValueOf(typedVal).Kind() == reflect.Ptr && reflect.ValueOf(typedVal).IsNil()) {
+				fields[i] = String(key, "nil")
+				continue
+			}
 			// When in doubt, coerce to a string
 			fields[i] = String(key, fmt.Sprint(typedVal))
 		}
diff --git a/vendor/github.com/opentracing/opentracing-go/noop.go b/vendor/github.com/opentracing/opentracing-go/noop.go
index 0d32f69..f9b680a 100644
--- a/vendor/github.com/opentracing/opentracing-go/noop.go
+++ b/vendor/github.com/opentracing/opentracing-go/noop.go
@@ -21,9 +21,9 @@
 type noopSpanContext struct{}
 
 var (
-	defaultNoopSpanContext = noopSpanContext{}
-	defaultNoopSpan        = noopSpan{}
-	defaultNoopTracer      = NoopTracer{}
+	defaultNoopSpanContext SpanContext = noopSpanContext{}
+	defaultNoopSpan        Span        = noopSpan{}
+	defaultNoopTracer      Tracer      = NoopTracer{}
 )
 
 const (
@@ -35,7 +35,7 @@
 
 // noopSpan:
 func (n noopSpan) Context() SpanContext                                  { return defaultNoopSpanContext }
-func (n noopSpan) SetBaggageItem(key, val string) Span                   { return defaultNoopSpan }
+func (n noopSpan) SetBaggageItem(key, val string) Span                   { return n }
 func (n noopSpan) BaggageItem(key string) string                         { return emptyString }
 func (n noopSpan) SetTag(key string, value interface{}) Span             { return n }
 func (n noopSpan) LogFields(fields ...log.Field)                         {}
diff --git a/vendor/github.com/opentracing/opentracing-go/propagation.go b/vendor/github.com/opentracing/opentracing-go/propagation.go
index 0dd466a..b0c275e 100644
--- a/vendor/github.com/opentracing/opentracing-go/propagation.go
+++ b/vendor/github.com/opentracing/opentracing-go/propagation.go
@@ -160,7 +160,7 @@
 // Set conforms to the TextMapWriter interface.
 func (c HTTPHeadersCarrier) Set(key, val string) {
 	h := http.Header(c)
-	h.Add(key, val)
+	h.Set(key, val)
 }
 
 // ForeachKey conforms to the TextMapReader interface.
diff --git a/vendor/github.com/opentracing/opentracing-go/span.go b/vendor/github.com/opentracing/opentracing-go/span.go
index f6c3234..0d3fb53 100644
--- a/vendor/github.com/opentracing/opentracing-go/span.go
+++ b/vendor/github.com/opentracing/opentracing-go/span.go
@@ -41,6 +41,8 @@
 	Context() SpanContext
 
 	// Sets or changes the operation name.
+	//
+	// Returns a reference to this Span for chaining.
 	SetOperationName(operationName string) Span
 
 	// Adds a tag to the span.
@@ -51,6 +53,8 @@
 	// other tag value types is undefined at the OpenTracing level. If a
 	// tracing system does not know how to handle a particular value type, it
 	// may ignore the tag, but shall not panic.
+	//
+	// Returns a reference to this Span for chaining.
 	SetTag(key string, value interface{}) Span
 
 	// LogFields is an efficient and type-checked way to record key:value
diff --git a/vendor/github.com/opentracing/opentracing-go/tracer.go b/vendor/github.com/opentracing/opentracing-go/tracer.go
index 7bca1f7..715f0ce 100644
--- a/vendor/github.com/opentracing/opentracing-go/tracer.go
+++ b/vendor/github.com/opentracing/opentracing-go/tracer.go
@@ -44,8 +44,7 @@
 	// and each has an expected carrier type.
 	//
 	// Other packages may declare their own `format` values, much like the keys
-	// used by `context.Context` (see
-	// https://godoc.org/golang.org/x/net/context#WithValue).
+	// used by `context.Context` (see https://godoc.org/context#WithValue).
 	//
 	// Example usage (sans error handling):
 	//
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md
index 9d79934..3cf1b25 100644
--- a/vendor/github.com/spf13/cobra/README.md
+++ b/vendor/github.com/spf13/cobra/README.md
@@ -2,35 +2,14 @@
 
 Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files.
 
-Many of the most widely used Go projects are built using Cobra, such as:
-[Kubernetes](http://kubernetes.io/),
-[Hugo](http://gohugo.io),
-[rkt](https://github.com/coreos/rkt),
-[etcd](https://github.com/coreos/etcd),
-[Moby (former Docker)](https://github.com/moby/moby),
-[Docker (distribution)](https://github.com/docker/distribution),
-[OpenShift](https://www.openshift.com/),
-[Delve](https://github.com/derekparker/delve),
-[GopherJS](http://www.gopherjs.org/),
-[CockroachDB](http://www.cockroachlabs.com/),
-[Bleve](http://www.blevesearch.com/),
-[ProjectAtomic (enterprise)](http://www.projectatomic.io/),
-[Giant Swarm's gsctl](https://github.com/giantswarm/gsctl),
-[Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack),
-[rclone](http://rclone.org/),
-[nehm](https://github.com/bogem/nehm),
-[Pouch](https://github.com/alibaba/pouch),
-[Istio](https://istio.io),
-[Prototool](https://github.com/uber/prototool),
-[mattermost-server](https://github.com/mattermost/mattermost-server),
-[Gardener](https://github.com/gardener/gardenctl),
-[Linkerd](https://linkerd.io/),
-[Github CLI](https://github.com/cli/cli)
-etc.
+Cobra is used in many Go projects such as [Kubernetes](http://kubernetes.io/),
+[Hugo](https://gohugo.io), and [Github CLI](https://github.com/cli/cli) to
+name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra.
 
 [![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra)
 [![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra)
 [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cobra)](https://goreportcard.com/report/github.com/spf13/cobra)
+[![Slack](https://img.shields.io/badge/Slack-cobra-brightgreen)](https://gophers.slack.com/archives/CD3LP1199)
 
 # Table of Contents
 
@@ -50,9 +29,8 @@
   * [PreRun and PostRun Hooks](#prerun-and-postrun-hooks)
   * [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens)
   * [Generating documentation for your command](#generating-documentation-for-your-command)
-  * [Generating bash completions](#generating-bash-completions)
-  * [Generating zsh completions](#generating-zsh-completions)
-- [Contributing](#contributing)
+  * [Generating shell completions](#generating-shell-completions)
+- [Contributing](CONTRIBUTING.md)
 - [License](#license)
 
 # Overview
@@ -72,7 +50,7 @@
 * Intelligent suggestions (`app srver`... did you mean `app server`?)
 * Automatic help generation for commands and flags
 * Automatic help flag recognition of `-h`, `--help`, etc.
-* Automatically generated bash autocomplete for your application
+* Automatically generated shell autocomplete for your application (bash, zsh, fish, powershell)
 * Automatically generated man pages for your application
 * Command aliases so you can change things without breaking them
 * The flexibility to define your own help, usage, etc.
@@ -130,7 +108,7 @@
 of the library. This command will install the `cobra` generator executable
 along with the library and its dependencies:
 
-    go get -u github.com/spf13/cobra/cobra
+    go get -u github.com/spf13/cobra
 
 Next, include Cobra in your application:
 
@@ -199,7 +177,7 @@
 
 func Execute() {
   if err := rootCmd.Execute(); err != nil {
-    fmt.Println(err)
+    fmt.Fprintln(os.Stderr, err)
     os.Exit(1)
   }
 }
@@ -335,6 +313,37 @@
 }
 ```
 
+### Returning and handling errors
+
+If you wish to return an error to the caller of a command, `RunE` can be used.
+
+```go
+package cmd
+
+import (
+  "fmt"
+
+  "github.com/spf13/cobra"
+)
+
+func init() {
+  rootCmd.AddCommand(tryCmd)
+}
+
+var tryCmd = &cobra.Command{
+  Use:   "try",
+  Short: "Try and possibly fail at something",
+  RunE: func(cmd *cobra.Command, args []string) error {
+    if err := someFunc(); err != nil {
+	return err
+    }
+    return nil
+  },
+}
+```
+
+The error can then be caught at the execute function call.
+
 ## Working with Flags
 
 Flags provide modifiers to control how the action command operates.
@@ -410,6 +419,12 @@
 rootCmd.MarkFlagRequired("region")
 ```
 
+Or, for persistent flags:
+```go
+rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
+rootCmd.MarkPersistentFlagRequired("region")
+```
+
 ## Positional and Custom Arguments
 
 Validation of positional arguments can be specified using the `Args` field
@@ -740,30 +755,11 @@
 
 ## Generating documentation for your command
 
-Cobra can generate documentation based on subcommands, flags, etc. in the following formats:
+Cobra can generate documentation based on subcommands, flags, etc. Read more about it in the [docs generation documentation](doc/README.md).
 
-- [Markdown](doc/md_docs.md)
-- [ReStructured Text](doc/rest_docs.md)
-- [Man Page](doc/man_docs.md)
+## Generating shell completions
 
-## Generating bash completions
-
-Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible.  Read more about it in [Bash Completions](bash_completions.md).
-
-## Generating zsh completions
-
-Cobra can generate zsh-completion file. Read more about it in
-[Zsh Completions](zsh_completions.md).
-
-# Contributing
-
-1. Fork it
-2. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`)
-3. Create your feature branch (`git checkout -b my-new-feature`)
-4. Make changes and add them (`git add .`)
-5. Commit your changes (`git commit -m 'Add some feature'`)
-6. Push to the branch (`git push origin my-new-feature`)
-7. Create new pull request
+Cobra can generate a shell-completion file for the following shells: Bash, Zsh, Fish, Powershell. If you add more information to your commands, these completions can be amazingly powerful and flexible.  Read more about it in [Shell Completions](shell_completions.md).
 
 # License
 
diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go
index 1e27188..846636d 100644
--- a/vendor/github.com/spf13/cobra/bash_completions.go
+++ b/vendor/github.com/spf13/cobra/bash_completions.go
@@ -62,6 +62,12 @@
 {
     __%[1]s_debug "${FUNCNAME[0]}: cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}"
 
+    local shellCompDirectiveError=%[3]d
+    local shellCompDirectiveNoSpace=%[4]d
+    local shellCompDirectiveNoFileComp=%[5]d
+    local shellCompDirectiveFilterFileExt=%[6]d
+    local shellCompDirectiveFilterDirs=%[7]d
+
     local out requestComp lastParam lastChar comp directive args
 
     # Prepare the command to request completions for the program.
@@ -95,24 +101,50 @@
     __%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}"
     __%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out[*]}"
 
-    if [ $((directive & %[3]d)) -ne 0 ]; then
+    if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
         # Error code.  No completion.
         __%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code"
         return
     else
-        if [ $((directive & %[4]d)) -ne 0 ]; then
+        if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
             if [[ $(type -t compopt) = "builtin" ]]; then
                 __%[1]s_debug "${FUNCNAME[0]}: activating no space"
                 compopt -o nospace
             fi
         fi
-        if [ $((directive & %[5]d)) -ne 0 ]; then
+        if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
             if [[ $(type -t compopt) = "builtin" ]]; then
                 __%[1]s_debug "${FUNCNAME[0]}: activating no file completion"
                 compopt +o default
             fi
         fi
+    fi
 
+    if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
+        # File extension filtering
+        local fullFilter filter filteringCmd
+        # Do not use quotes around the $out variable or else newline
+        # characters will be kept.
+        for filter in ${out[*]}; do
+            fullFilter+="$filter|"
+        done
+
+        filteringCmd="_filedir $fullFilter"
+        __%[1]s_debug "File filtering command: $filteringCmd"
+        $filteringCmd
+    elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
+        # File completion for directories only
+        local subDir
+        # Use printf to strip any trailing newline
+        subdir=$(printf "%%s" "${out[0]}")
+        if [ -n "$subdir" ]; then
+            __%[1]s_debug "Listing directories in $subdir"
+            __%[1]s_handle_subdirs_in_dir_flag "$subdir"
+        else
+            __%[1]s_debug "Listing directories in ."
+            _filedir -d
+        fi
+    else
         while IFS='' read -r comp; do
             COMPREPLY+=("$comp")
         done < <(compgen -W "${out[*]}" -- "$cur")
@@ -181,10 +213,9 @@
     local completions
     completions=("${commands[@]}")
     if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
-        completions=("${must_have_one_noun[@]}")
+        completions+=("${must_have_one_noun[@]}")
     elif [[ -n "${has_completion_function}" ]]; then
         # if a go completion function is provided, defer to that function
-        completions=()
         __%[1]s_handle_go_custom_completion
     fi
     if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
@@ -344,7 +375,9 @@
     __%[1]s_handle_word
 }
 
-`, name, ShellCompNoDescRequestCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp))
+`, name, ShellCompNoDescRequestCmd,
+		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
+		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
 }
 
 func writePostscript(buf *bytes.Buffer, name string) {
@@ -390,7 +423,7 @@
 func writeCommands(buf *bytes.Buffer, cmd *Command) {
 	buf.WriteString("    commands=()\n")
 	for _, c := range cmd.Commands() {
-		if !c.IsAvailableCommand() || c == cmd.helpCommand {
+		if !c.IsAvailableCommand() && c != cmd.helpCommand {
 			continue
 		}
 		buf.WriteString(fmt.Sprintf("    commands+=(%q)\n", c.Name()))
@@ -462,12 +495,14 @@
 
 func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
 	name := flag.Name
-	format := "    local_nonpersistent_flags+=(\"--%s"
+	format := "    local_nonpersistent_flags+=(\"--%[1]s\")\n"
 	if len(flag.NoOptDefVal) == 0 {
-		format += "="
+		format += "    local_nonpersistent_flags+=(\"--%[1]s=\")\n"
 	}
-	format += "\")\n"
 	buf.WriteString(fmt.Sprintf(format, name))
+	if len(flag.Shorthand) > 0 {
+		buf.WriteString(fmt.Sprintf("    local_nonpersistent_flags+=(\"-%s\")\n", flag.Shorthand))
+	}
 }
 
 // Setup annotations for go completions for registered flags
@@ -502,7 +537,9 @@
 		if len(flag.Shorthand) > 0 {
 			writeShortFlag(buf, flag, cmd)
 		}
-		if localNonPersistentFlags.Lookup(flag.Name) != nil {
+		// localNonPersistentFlags are used to stop the completion of subcommands when one is set
+		// if TraverseChildren is true we should allow to complete subcommands
+		if localNonPersistentFlags.Lookup(flag.Name) != nil && !cmd.Root().TraverseChildren {
 			writeLocalNonPersistentFlag(buf, flag)
 		}
 	})
@@ -583,7 +620,7 @@
 
 func gen(buf *bytes.Buffer, cmd *Command) {
 	for _, c := range cmd.Commands() {
-		if !c.IsAvailableCommand() || c == cmd.helpCommand {
+		if !c.IsAvailableCommand() && c != cmd.helpCommand {
 			continue
 		}
 		gen(buf, c)
diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go
index 88e6ed7..77b399e 100644
--- a/vendor/github.com/spf13/cobra/command.go
+++ b/vendor/github.com/spf13/cobra/command.go
@@ -37,6 +37,14 @@
 // definition to ensure usability.
 type Command struct {
 	// Use is the one-line usage message.
+	// Recommended syntax is as follow:
+	//   [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required.
+	//   ... indicates that you can specify multiple values for the previous argument.
+	//   |   indicates mutually exclusive information. You can use the argument to the left of the separator or the
+	//       argument to the right of the separator. You cannot use both arguments in a single use of the command.
+	//   { } delimits a set of mutually exclusive arguments when one of the arguments is required. If the arguments are
+	//       optional, they are enclosed in brackets ([ ]).
+	// Example: add [-F file | -D dir]... [-f format] profile
 	Use string
 
 	// Aliases is an array of aliases that can be used instead of the first word in Use.
@@ -359,7 +367,7 @@
 		c.mergePersistentFlags()
 		err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
 		if err != nil {
-			c.Println(err)
+			c.PrintErrln(err)
 		}
 		return err
 	}
@@ -387,7 +395,7 @@
 		// See https://github.com/spf13/cobra/issues/1002
 		err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
 		if err != nil {
-			c.Println(err)
+			c.PrintErrln(err)
 		}
 	}
 }
@@ -930,8 +938,8 @@
 			c = cmd
 		}
 		if !c.SilenceErrors {
-			c.Println("Error:", err.Error())
-			c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
+			c.PrintErrln("Error:", err.Error())
+			c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
 		}
 		return c, err
 	}
@@ -959,7 +967,7 @@
 		// If root command has SilentErrors flagged,
 		// all subcommands should respect it
 		if !cmd.SilenceErrors && !c.SilenceErrors {
-			c.Println("Error:", err.Error())
+			c.PrintErrln("Error:", err.Error())
 		}
 
 		// If root command has SilentUsage flagged,
@@ -979,6 +987,10 @@
 }
 
 func (c *Command) validateRequiredFlags() error {
+	if c.DisableFlagParsing {
+		return nil
+	}
+
 	flags := c.Flags()
 	missingFlagNames := []string{}
 	flags.VisitAll(func(pflag *flag.Flag) {
@@ -1052,7 +1064,25 @@
 			Short: "Help about any command",
 			Long: `Help provides help for any command in the application.
 Simply type ` + c.Name() + ` help [path to command] for full details.`,
-
+			ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) {
+				var completions []string
+				cmd, _, e := c.Root().Find(args)
+				if e != nil {
+					return nil, ShellCompDirectiveNoFileComp
+				}
+				if cmd == nil {
+					// Root help command.
+					cmd = c.Root()
+				}
+				for _, subCmd := range cmd.Commands() {
+					if subCmd.IsAvailableCommand() || subCmd == cmd.helpCommand {
+						if strings.HasPrefix(subCmd.Name(), toComplete) {
+							completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
+						}
+					}
+				}
+				return completions, ShellCompDirectiveNoFileComp
+			},
 			Run: func(c *Command, args []string) {
 				cmd, _, e := c.Root().Find(args)
 				if cmd == nil || e != nil {
@@ -1179,12 +1209,12 @@
 
 // PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.
 func (c *Command) PrintErrln(i ...interface{}) {
-	c.Print(fmt.Sprintln(i...))
+	c.PrintErr(fmt.Sprintln(i...))
 }
 
 // PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.
 func (c *Command) PrintErrf(format string, i ...interface{}) {
-	c.Print(fmt.Sprintf(format, i...))
+	c.PrintErr(fmt.Sprintf(format, i...))
 }
 
 // CommandPath returns the full path to this command.
diff --git a/vendor/github.com/spf13/cobra/custom_completions.go b/vendor/github.com/spf13/cobra/custom_completions.go
index ba57327..f9e88e0 100644
--- a/vendor/github.com/spf13/cobra/custom_completions.go
+++ b/vendor/github.com/spf13/cobra/custom_completions.go
@@ -1,7 +1,6 @@
 package cobra
 
 import (
-	"errors"
 	"fmt"
 	"os"
 	"strings"
@@ -38,8 +37,29 @@
 	// This currently does not work for zsh or bash < 4
 	ShellCompDirectiveNoFileComp
 
+	// ShellCompDirectiveFilterFileExt indicates that the provided completions
+	// should be used as file extension filters.
+	// For flags, using Command.MarkFlagFilename() and Command.MarkPersistentFlagFilename()
+	// is a shortcut to using this directive explicitly.  The BashCompFilenameExt
+	// annotation can also be used to obtain the same behavior for flags.
+	ShellCompDirectiveFilterFileExt
+
+	// ShellCompDirectiveFilterDirs indicates that only directory names should
+	// be provided in file completion.  To request directory names within another
+	// directory, the returned completions should specify the directory within
+	// which to search.  The BashCompSubdirsInDir annotation can be used to
+	// obtain the same behavior but only for flags.
+	ShellCompDirectiveFilterDirs
+
+	// ===========================================================================
+
+	// All directives using iota should be above this one.
+	// For internal use.
+	shellCompDirectiveMaxValue
+
 	// ShellCompDirectiveDefault indicates to let the shell perform its default
 	// behavior after completions have been provided.
+	// This one must be last to avoid messing up the iota count.
 	ShellCompDirectiveDefault ShellCompDirective = 0
 )
 
@@ -68,11 +88,17 @@
 	if d&ShellCompDirectiveNoFileComp != 0 {
 		directives = append(directives, "ShellCompDirectiveNoFileComp")
 	}
+	if d&ShellCompDirectiveFilterFileExt != 0 {
+		directives = append(directives, "ShellCompDirectiveFilterFileExt")
+	}
+	if d&ShellCompDirectiveFilterDirs != 0 {
+		directives = append(directives, "ShellCompDirectiveFilterDirs")
+	}
 	if len(directives) == 0 {
 		directives = append(directives, "ShellCompDirectiveDefault")
 	}
 
-	if d > ShellCompDirectiveError+ShellCompDirectiveNoSpace+ShellCompDirectiveNoFileComp {
+	if d >= shellCompDirectiveMaxValue {
 		return fmt.Sprintf("ERROR: unexpected ShellCompDirective value: %d", d)
 	}
 	return strings.Join(directives, ", ")
@@ -105,11 +131,25 @@
 					// Remove any description that may be included following a tab character.
 					comp = strings.Split(comp, "\t")[0]
 				}
+
+				// Make sure we only write the first line to the output.
+				// This is needed if a description contains a linebreak.
+				// Otherwise the shell scripts will interpret the other lines as new flags
+				// and could therefore provide a wrong completion.
+				comp = strings.Split(comp, "\n")[0]
+
+				// Finally trim the completion.  This is especially important to get rid
+				// of a trailing tab when there are no description following it.
+				// For example, a sub-command without a description should not be completed
+				// with a tab at the end (or else zsh will show a -- following it
+				// although there is no description).
+				comp = strings.TrimSpace(comp)
+
 				// Print each possible completion to stdout for the completion script to consume.
 				fmt.Fprintln(finalCmd.OutOrStdout(), comp)
 			}
 
-			if directive > ShellCompDirectiveError+ShellCompDirectiveNoSpace+ShellCompDirectiveNoFileComp {
+			if directive >= shellCompDirectiveMaxValue {
 				directive = ShellCompDirectiveDefault
 			}
 
@@ -136,82 +176,104 @@
 }
 
 func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) {
-	var completions []string
-
 	// The last argument, which is not completely typed by the user,
 	// should not be part of the list of arguments
 	toComplete := args[len(args)-1]
 	trimmedArgs := args[:len(args)-1]
 
+	var finalCmd *Command
+	var finalArgs []string
+	var err error
 	// Find the real command for which completion must be performed
-	finalCmd, finalArgs, err := c.Root().Find(trimmedArgs)
+	// check if we need to traverse here to parse local flags on parent commands
+	if c.Root().TraverseChildren {
+		finalCmd, finalArgs, err = c.Root().Traverse(trimmedArgs)
+	} else {
+		finalCmd, finalArgs, err = c.Root().Find(trimmedArgs)
+	}
 	if err != nil {
 		// Unable to find the real command. E.g., <program> someInvalidCmd <TAB>
-		return c, completions, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs)
+		return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs)
+	}
+
+	// Check if we are doing flag value completion before parsing the flags.
+	// This is important because if we are completing a flag value, we need to also
+	// remove the flag name argument from the list of finalArgs or else the parsing
+	// could fail due to an invalid value (incomplete) for the flag.
+	flag, finalArgs, toComplete, err := checkIfFlagCompletion(finalCmd, finalArgs, toComplete)
+	if err != nil {
+		// Error while attempting to parse flags
+		return finalCmd, []string{}, ShellCompDirectiveDefault, err
+	}
+
+	// Parse the flags early so we can check if required flags are set
+	if err = finalCmd.ParseFlags(finalArgs); err != nil {
+		return finalCmd, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
+	}
+
+	if flag != nil {
+		// Check if we are completing a flag value subject to annotations
+		if validExts, present := flag.Annotations[BashCompFilenameExt]; present {
+			if len(validExts) != 0 {
+				// File completion filtered by extensions
+				return finalCmd, validExts, ShellCompDirectiveFilterFileExt, nil
+			}
+
+			// The annotation requests simple file completion.  There is no reason to do
+			// that since it is the default behavior anyway.  Let's ignore this annotation
+			// in case the program also registered a completion function for this flag.
+			// Even though it is a mistake on the program's side, let's be nice when we can.
+		}
+
+		if subDir, present := flag.Annotations[BashCompSubdirsInDir]; present {
+			if len(subDir) == 1 {
+				// Directory completion from within a directory
+				return finalCmd, subDir, ShellCompDirectiveFilterDirs, nil
+			}
+			// Directory completion
+			return finalCmd, []string{}, ShellCompDirectiveFilterDirs, nil
+		}
 	}
 
 	// When doing completion of a flag name, as soon as an argument starts with
 	// a '-' we know it is a flag.  We cannot use isFlagArg() here as it requires
-	// the flag to be complete
-	if len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") {
-		// We are completing a flag name
-		finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
-			completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
-		})
-		finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
-			completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
-		})
+	// the flag name to be complete
+	if flag == nil && len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") {
+		var completions []string
 
-		directive := ShellCompDirectiveDefault
-		if len(completions) > 0 {
-			if strings.HasSuffix(completions[0], "=") {
-				directive = ShellCompDirectiveNoSpace
-			}
-		}
-		return finalCmd, completions, directive, nil
-	}
+		// First check for required flags
+		completions = completeRequireFlags(finalCmd, toComplete)
 
-	var flag *pflag.Flag
-	if !finalCmd.DisableFlagParsing {
-		// We only do flag completion if we are allowed to parse flags
-		// This is important for commands which have requested to do their own flag completion.
-		flag, finalArgs, toComplete, err = checkIfFlagCompletion(finalCmd, finalArgs, toComplete)
-		if err != nil {
-			// Error while attempting to parse flags
-			return finalCmd, completions, ShellCompDirectiveDefault, err
-		}
-	}
-
-	if flag == nil {
-		// Complete subcommand names
-		for _, subCmd := range finalCmd.Commands() {
-			if subCmd.IsAvailableCommand() && strings.HasPrefix(subCmd.Name(), toComplete) {
-				completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
-			}
-		}
-
-		if len(finalCmd.ValidArgs) > 0 {
-			// Always complete ValidArgs, even if we are completing a subcommand name.
-			// This is for commands that have both subcommands and ValidArgs.
-			for _, validArg := range finalCmd.ValidArgs {
-				if strings.HasPrefix(validArg, toComplete) {
-					completions = append(completions, validArg)
+		// If we have not found any required flags, only then can we show regular flags
+		if len(completions) == 0 {
+			doCompleteFlags := func(flag *pflag.Flag) {
+				if !flag.Changed ||
+					strings.Contains(flag.Value.Type(), "Slice") ||
+					strings.Contains(flag.Value.Type(), "Array") {
+					// If the flag is not already present, or if it can be specified multiple times (Array or Slice)
+					// we suggest it as a completion
+					completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
 				}
 			}
 
-			// If there are ValidArgs specified (even if they don't match), we stop completion.
-			// Only one of ValidArgs or ValidArgsFunction can be used for a single command.
-			return finalCmd, completions, ShellCompDirectiveNoFileComp, nil
+			// We cannot use finalCmd.Flags() because we may not have called ParsedFlags() for commands
+			// that have set DisableFlagParsing; it is ParseFlags() that merges the inherited and
+			// non-inherited flags.
+			finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
+				doCompleteFlags(flag)
+			})
+			finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
+				doCompleteFlags(flag)
+			})
 		}
 
-		// Always let the logic continue so as to add any ValidArgsFunction completions,
-		// even if we already found sub-commands.
-		// This is for commands that have subcommands but also specify a ValidArgsFunction.
-	}
-
-	// Parse the flags and extract the arguments to prepare for calling the completion function
-	if err = finalCmd.ParseFlags(finalArgs); err != nil {
-		return finalCmd, completions, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
+		directive := ShellCompDirectiveNoFileComp
+		if len(completions) == 1 && strings.HasSuffix(completions[0], "=") {
+			// If there is a single completion, the shell usually adds a space
+			// after the completion.  We don't want that if the flag ends with an =
+			directive = ShellCompDirectiveNoSpace
+		}
+		return finalCmd, completions, directive, nil
 	}
 
 	// We only remove the flags from the arguments if DisableFlagParsing is not set.
@@ -220,6 +282,73 @@
 		finalArgs = finalCmd.Flags().Args()
 	}
 
+	var completions []string
+	directive := ShellCompDirectiveDefault
+	if flag == nil {
+		foundLocalNonPersistentFlag := false
+		// If TraverseChildren is true on the root command we don't check for
+		// local flags because we can use a local flag on a parent command
+		if !finalCmd.Root().TraverseChildren {
+			// Check if there are any local, non-persistent flags on the command-line
+			localNonPersistentFlags := finalCmd.LocalNonPersistentFlags()
+			finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
+				if localNonPersistentFlags.Lookup(flag.Name) != nil && flag.Changed {
+					foundLocalNonPersistentFlag = true
+				}
+			})
+		}
+
+		// Complete subcommand names, including the help command
+		if len(finalArgs) == 0 && !foundLocalNonPersistentFlag {
+			// We only complete sub-commands if:
+			// - there are no arguments on the command-line and
+			// - there are no local, non-peristent flag on the command-line or TraverseChildren is true
+			for _, subCmd := range finalCmd.Commands() {
+				if subCmd.IsAvailableCommand() || subCmd == finalCmd.helpCommand {
+					if strings.HasPrefix(subCmd.Name(), toComplete) {
+						completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
+					}
+					directive = ShellCompDirectiveNoFileComp
+				}
+			}
+		}
+
+		// Complete required flags even without the '-' prefix
+		completions = append(completions, completeRequireFlags(finalCmd, toComplete)...)
+
+		// Always complete ValidArgs, even if we are completing a subcommand name.
+		// This is for commands that have both subcommands and ValidArgs.
+		if len(finalCmd.ValidArgs) > 0 {
+			if len(finalArgs) == 0 {
+				// ValidArgs are only for the first argument
+				for _, validArg := range finalCmd.ValidArgs {
+					if strings.HasPrefix(validArg, toComplete) {
+						completions = append(completions, validArg)
+					}
+				}
+				directive = ShellCompDirectiveNoFileComp
+
+				// If no completions were found within commands or ValidArgs,
+				// see if there are any ArgAliases that should be completed.
+				if len(completions) == 0 {
+					for _, argAlias := range finalCmd.ArgAliases {
+						if strings.HasPrefix(argAlias, toComplete) {
+							completions = append(completions, argAlias)
+						}
+					}
+				}
+			}
+
+			// If there are ValidArgs specified (even if they don't match), we stop completion.
+			// Only one of ValidArgs or ValidArgsFunction can be used for a single command.
+			return finalCmd, completions, directive, nil
+		}
+
+		// Let the logic continue so as to add any ValidArgsFunction completions,
+		// even if we already found sub-commands.
+		// This is for commands that have subcommands but also specify a ValidArgsFunction.
+	}
+
 	// Find the completion function for the flag or command
 	var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
 	if flag != nil {
@@ -227,14 +356,14 @@
 	} else {
 		completionFn = finalCmd.ValidArgsFunction
 	}
-	if completionFn == nil {
-		// Go custom completion not supported/needed for this flag or command
-		return finalCmd, completions, ShellCompDirectiveDefault, nil
+	if completionFn != nil {
+		// Go custom completion defined for this flag or command.
+		// Call the registered completion function to get the completions.
+		var comps []string
+		comps, directive = completionFn(finalCmd, finalArgs, toComplete)
+		completions = append(completions, comps...)
 	}
 
-	// Call the registered completion function to get the completions
-	comps, directive := completionFn(finalCmd, finalArgs, toComplete)
-	completions = append(completions, comps...)
 	return finalCmd, completions, directive, nil
 }
 
@@ -249,11 +378,18 @@
 		// Flag without the =
 		completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
 
-		if len(flag.NoOptDefVal) == 0 {
-			// Flag requires a value, so it can be suffixed with =
-			flagName += "="
-			completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
-		}
+		// Why suggest both long forms: --flag and --flag= ?
+		// This forces the user to *always* have to type either an = or a space after the flag name.
+		// Let's be nice and avoid making users have to do that.
+		// Since boolean flags and shortname flags don't show the = form, let's go that route and never show it.
+		// The = form will still work, we just won't suggest it.
+		// This also makes the list of suggested flags shorter as we avoid all the = forms.
+		//
+		// if len(flag.NoOptDefVal) == 0 {
+		// 	// Flag requires a value, so it can be suffixed with =
+		// 	flagName += "="
+		// 	completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
+		// }
 	}
 
 	flagName = "-" + flag.Shorthand
@@ -264,17 +400,54 @@
 	return completions
 }
 
+func completeRequireFlags(finalCmd *Command, toComplete string) []string {
+	var completions []string
+
+	doCompleteRequiredFlags := func(flag *pflag.Flag) {
+		if _, present := flag.Annotations[BashCompOneRequiredFlag]; present {
+			if !flag.Changed {
+				// If the flag is not already present, we suggest it as a completion
+				completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
+			}
+		}
+	}
+
+	// We cannot use finalCmd.Flags() because we may not have called ParsedFlags() for commands
+	// that have set DisableFlagParsing; it is ParseFlags() that merges the inherited and
+	// non-inherited flags.
+	finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
+		doCompleteRequiredFlags(flag)
+	})
+	finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
+		doCompleteRequiredFlags(flag)
+	})
+
+	return completions
+}
+
 func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*pflag.Flag, []string, string, error) {
+	if finalCmd.DisableFlagParsing {
+		// We only do flag completion if we are allowed to parse flags
+		// This is important for commands which have requested to do their own flag completion.
+		return nil, args, lastArg, nil
+	}
+
 	var flagName string
 	trimmedArgs := args
 	flagWithEqual := false
-	if isFlagArg(lastArg) {
+
+	// When doing completion of a flag name, as soon as an argument starts with
+	// a '-' we know it is a flag.  We cannot use isFlagArg() here as that function
+	// requires the flag name to be complete
+	if len(lastArg) > 0 && lastArg[0] == '-' {
 		if index := strings.Index(lastArg, "="); index >= 0 {
+			// Flag with an =
 			flagName = strings.TrimLeft(lastArg[:index], "-")
 			lastArg = lastArg[index+1:]
 			flagWithEqual = true
 		} else {
-			return nil, nil, "", errors.New("Unexpected completion request for flag")
+			// Normal flag completion
+			return nil, args, lastArg, nil
 		}
 	}
 
diff --git a/vendor/github.com/spf13/cobra/fish_completions.go b/vendor/github.com/spf13/cobra/fish_completions.go
index c83609c..eaae9bc 100644
--- a/vendor/github.com/spf13/cobra/fish_completions.go
+++ b/vendor/github.com/spf13/cobra/fish_completions.go
@@ -5,9 +5,15 @@
 	"fmt"
 	"io"
 	"os"
+	"strings"
 )
 
 func genFishComp(buf *bytes.Buffer, name string, includeDesc bool) {
+	// Variables should not contain a '-' or ':' character
+	nameForVar := name
+	nameForVar = strings.Replace(nameForVar, "-", "_", -1)
+	nameForVar = strings.Replace(nameForVar, ":", "_", -1)
+
 	compCmd := ShellCompRequestCmd
 	if !includeDesc {
 		compCmd = ShellCompNoDescRequestCmd
@@ -37,7 +43,13 @@
     end
     __%[1]s_debug "emptyArg: $emptyArg"
 
-    set requestComp "$args[1] %[2]s $args[2..-1] $emptyArg"
+    if not type -q "$args[1]"
+        # This can happen when "complete --do-complete %[2]s" is called when running this script.
+        __%[1]s_debug "Cannot find $args[1]. No completions."
+        return
+    end
+
+    set requestComp "$args[1] %[3]s $args[2..-1] $emptyArg"
     __%[1]s_debug "Calling $requestComp"
 
     set results (eval $requestComp 2> /dev/null)
@@ -71,7 +83,8 @@
 
     # Check if the command-line is already provided.  This is useful for testing.
     if not set --query __%[1]s_comp_commandLine
-        set __%[1]s_comp_commandLine (commandline)
+        # Use the -c flag to allow for completion in the middle of the line
+        set __%[1]s_comp_commandLine (commandline -c)
     end
     __%[1]s_debug "commandLine is: $__%[1]s_comp_commandLine"
 
@@ -83,7 +96,7 @@
         __%[1]s_debug "No completion, probably due to a failure"
         # Might as well do file completion, in case it helps
         set --global __%[1]s_comp_do_file_comp 1
-        return 0
+        return 1
     end
 
     set directive (string sub --start 2 $results[-1])
@@ -92,20 +105,35 @@
     __%[1]s_debug "Completions are: $__%[1]s_comp_results"
     __%[1]s_debug "Directive is: $directive"
 
+    set shellCompDirectiveError %[4]d
+    set shellCompDirectiveNoSpace %[5]d
+    set shellCompDirectiveNoFileComp %[6]d
+    set shellCompDirectiveFilterFileExt %[7]d
+    set shellCompDirectiveFilterDirs %[8]d
+
     if test -z "$directive"
         set directive 0
     end
 
-    set compErr (math (math --scale 0 $directive / %[3]d) %% 2)
+    set compErr (math (math --scale 0 $directive / $shellCompDirectiveError) %% 2)
     if test $compErr -eq 1
         __%[1]s_debug "Received error directive: aborting."
         # Might as well do file completion, in case it helps
         set --global __%[1]s_comp_do_file_comp 1
-        return 0
+        return 1
     end
 
-    set nospace (math (math --scale 0 $directive / %[4]d) %% 2)
-    set nofiles (math (math --scale 0 $directive / %[5]d) %% 2)
+    set filefilter (math (math --scale 0 $directive / $shellCompDirectiveFilterFileExt) %% 2)
+    set dirfilter (math (math --scale 0 $directive / $shellCompDirectiveFilterDirs) %% 2)
+    if test $filefilter -eq 1; or test $dirfilter -eq 1
+        __%[1]s_debug "File extension filtering or directory filtering not supported"
+        # Do full file completion instead
+        set --global __%[1]s_comp_do_file_comp 1
+        return 1
+    end
+
+    set nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) %% 2)
+    set nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) %% 2)
 
     __%[1]s_debug "nospace: $nospace, nofiles: $nofiles"
 
@@ -132,24 +160,31 @@
     return (not set --query __%[1]s_comp_do_file_comp)
 end
 
-# Remove any pre-existing completions for the program since we will be handling all of them
-# TODO this cleanup is not sufficient.  Fish completions are only loaded once the user triggers
-# them, so the below deletion will not work as it is run too early.  What else can we do?
-complete -c %[1]s -e
+# Since Fish completions are only loaded once the user triggers them, we trigger them ourselves
+# so we can properly delete any completions provided by another script.
+# The space after the the program name is essential to trigger completion for the program
+# and not completion of the program name itself.
+complete --do-complete "%[2]s " > /dev/null 2>&1
+# Using '> /dev/null 2>&1' since '&>' is not supported in older versions of fish.
+
+# Remove any pre-existing completions for the program since we will be handling all of them.
+complete -c %[2]s -e
 
 # The order in which the below two lines are defined is very important so that __%[1]s_prepare_completions
 # is called first.  It is __%[1]s_prepare_completions that sets up the __%[1]s_comp_do_file_comp variable.
 #
 # This completion will be run second as complete commands are added FILO.
 # It triggers file completion choices when __%[1]s_comp_do_file_comp is set.
-complete -c %[1]s -n 'set --query __%[1]s_comp_do_file_comp'
+complete -c %[2]s -n 'set --query __%[1]s_comp_do_file_comp'
 
 # This completion will be run first as complete commands are added FILO.
-# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results abd __%[1]s_comp_do_file_comp.
+# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results and __%[1]s_comp_do_file_comp.
 # It provides the program's completion choices.
-complete -c %[1]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
+complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
 
-`, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp))
+`, nameForVar, name, compCmd,
+		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
+		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
 }
 
 // GenFishCompletion generates fish completion file and writes to the passed writer.
diff --git a/vendor/github.com/spf13/cobra/go.mod b/vendor/github.com/spf13/cobra/go.mod
index dea1030..57e3244 100644
--- a/vendor/github.com/spf13/cobra/go.mod
+++ b/vendor/github.com/spf13/cobra/go.mod
@@ -6,7 +6,7 @@
 	github.com/cpuguy83/go-md2man/v2 v2.0.0
 	github.com/inconshreveable/mousetrap v1.0.0
 	github.com/mitchellh/go-homedir v1.1.0
-	github.com/spf13/pflag v1.0.3
-	github.com/spf13/viper v1.4.0
-	gopkg.in/yaml.v2 v2.2.2
+	github.com/spf13/pflag v1.0.5
+	github.com/spf13/viper v1.7.0
+	gopkg.in/yaml.v2 v2.2.8
 )
diff --git a/vendor/github.com/spf13/cobra/shell_completions.go b/vendor/github.com/spf13/cobra/shell_completions.go
index ba0af9c..d99bf91 100644
--- a/vendor/github.com/spf13/cobra/shell_completions.go
+++ b/vendor/github.com/spf13/cobra/shell_completions.go
@@ -4,82 +4,81 @@
 	"github.com/spf13/pflag"
 )
 
-// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists,
+// MarkFlagRequired instructs the various shell completion implementations to
+// prioritize the named flag when performing completion,
 // and causes your command to report an error if invoked without the flag.
 func (c *Command) MarkFlagRequired(name string) error {
 	return MarkFlagRequired(c.Flags(), name)
 }
 
-// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists,
+// MarkPersistentFlagRequired instructs the various shell completion implementations to
+// prioritize the named persistent flag when performing completion,
 // and causes your command to report an error if invoked without the flag.
 func (c *Command) MarkPersistentFlagRequired(name string) error {
 	return MarkFlagRequired(c.PersistentFlags(), name)
 }
 
-// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists,
+// MarkFlagRequired instructs the various shell completion implementations to
+// prioritize the named flag when performing completion,
 // and causes your command to report an error if invoked without the flag.
 func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
 	return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"})
 }
 
-// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists.
-// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
+// MarkFlagFilename instructs the various shell completion implementations to
+// limit completions for the named flag to the specified file extensions.
 func (c *Command) MarkFlagFilename(name string, extensions ...string) error {
 	return MarkFlagFilename(c.Flags(), name, extensions...)
 }
 
 // MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.
-// Generated bash autocompletion will call the bash function f for the flag.
+// The bash completion script will call the bash function f for the flag.
+//
+// This will only work for bash completion.
+// It is recommended to instead use c.RegisterFlagCompletionFunc(...) which allows
+// to register a Go function which will work across all shells.
 func (c *Command) MarkFlagCustom(name string, f string) error {
 	return MarkFlagCustom(c.Flags(), name, f)
 }
 
 // MarkPersistentFlagFilename instructs the various shell completion
-// implementations to limit completions for this persistent flag to the
-// specified extensions (patterns).
-//
-// Shell Completion compatibility matrix: bash, zsh
+// implementations to limit completions for the named persistent flag to the
+// specified file extensions.
 func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error {
 	return MarkFlagFilename(c.PersistentFlags(), name, extensions...)
 }
 
 // MarkFlagFilename instructs the various shell completion implementations to
-// limit completions for this flag to the specified extensions (patterns).
-//
-// Shell Completion compatibility matrix: bash, zsh
+// limit completions for the named flag to the specified file extensions.
 func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error {
 	return flags.SetAnnotation(name, BashCompFilenameExt, extensions)
 }
 
-// MarkFlagCustom instructs the various shell completion implementations to
-// limit completions for this flag to the specified extensions (patterns).
+// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists.
+// The bash completion script will call the bash function f for the flag.
 //
-// Shell Completion compatibility matrix: bash, zsh
+// This will only work for bash completion.
+// It is recommended to instead use c.RegisterFlagCompletionFunc(...) which allows
+// to register a Go function which will work across all shells.
 func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error {
 	return flags.SetAnnotation(name, BashCompCustom, []string{f})
 }
 
 // MarkFlagDirname instructs the various shell completion implementations to
-// complete only directories with this named flag.
-//
-// Shell Completion compatibility matrix: zsh
+// limit completions for the named flag to directory names.
 func (c *Command) MarkFlagDirname(name string) error {
 	return MarkFlagDirname(c.Flags(), name)
 }
 
 // MarkPersistentFlagDirname instructs the various shell completion
-// implementations to complete only directories with this persistent named flag.
-//
-// Shell Completion compatibility matrix: zsh
+// implementations to limit completions for the named persistent flag to
+// directory names.
 func (c *Command) MarkPersistentFlagDirname(name string) error {
 	return MarkFlagDirname(c.PersistentFlags(), name)
 }
 
 // MarkFlagDirname instructs the various shell completion implementations to
-// complete only directories with this specified flag.
-//
-// Shell Completion compatibility matrix: zsh
+// limit completions for the named flag to directory names.
 func MarkFlagDirname(flags *pflag.FlagSet, name string) error {
-	zshPattern := "-(/)"
-	return flags.SetAnnotation(name, zshCompDirname, []string{zshPattern})
+	return flags.SetAnnotation(name, BashCompSubdirsInDir, []string{})
 }
diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go
index 1275548..92a7039 100644
--- a/vendor/github.com/spf13/cobra/zsh_completions.go
+++ b/vendor/github.com/spf13/cobra/zsh_completions.go
@@ -1,336 +1,240 @@
 package cobra
 
 import (
-	"encoding/json"
+	"bytes"
 	"fmt"
 	"io"
 	"os"
-	"sort"
-	"strings"
-	"text/template"
-
-	"github.com/spf13/pflag"
 )
 
-const (
-	zshCompArgumentAnnotation   = "cobra_annotations_zsh_completion_argument_annotation"
-	zshCompArgumentFilenameComp = "cobra_annotations_zsh_completion_argument_file_completion"
-	zshCompArgumentWordComp     = "cobra_annotations_zsh_completion_argument_word_completion"
-	zshCompDirname              = "cobra_annotations_zsh_dirname"
-)
-
-var (
-	zshCompFuncMap = template.FuncMap{
-		"genZshFuncName":              zshCompGenFuncName,
-		"extractFlags":                zshCompExtractFlag,
-		"genFlagEntryForZshArguments": zshCompGenFlagEntryForArguments,
-		"extractArgsCompletions":      zshCompExtractArgumentCompletionHintsForRendering,
-	}
-	zshCompletionText = `
-{{/* should accept Command (that contains subcommands) as parameter */}}
-{{define "argumentsC" -}}
-{{ $cmdPath := genZshFuncName .}}
-function {{$cmdPath}} {
-  local -a commands
-
-  _arguments -C \{{- range extractFlags .}}
-    {{genFlagEntryForZshArguments .}} \{{- end}}
-    "1: :->cmnds" \
-    "*::arg:->args"
-
-  case $state in
-  cmnds)
-    commands=({{range .Commands}}{{if not .Hidden}}
-      "{{.Name}}:{{.Short}}"{{end}}{{end}}
-    )
-    _describe "command" commands
-    ;;
-  esac
-
-  case "$words[1]" in {{- range .Commands}}{{if not .Hidden}}
-  {{.Name}})
-    {{$cmdPath}}_{{.Name}}
-    ;;{{end}}{{end}}
-  esac
-}
-{{range .Commands}}{{if not .Hidden}}
-{{template "selectCmdTemplate" .}}
-{{- end}}{{end}}
-{{- end}}
-
-{{/* should accept Command without subcommands as parameter */}}
-{{define "arguments" -}}
-function {{genZshFuncName .}} {
-{{"  _arguments"}}{{range extractFlags .}} \
-    {{genFlagEntryForZshArguments . -}}
-{{end}}{{range extractArgsCompletions .}} \
-    {{.}}{{end}}
-}
-{{end}}
-
-{{/* dispatcher for commands with or without subcommands */}}
-{{define "selectCmdTemplate" -}}
-{{if .Hidden}}{{/* ignore hidden*/}}{{else -}}
-{{if .Commands}}{{template "argumentsC" .}}{{else}}{{template "arguments" .}}{{end}}
-{{- end}}
-{{- end}}
-
-{{/* template entry point */}}
-{{define "Main" -}}
-#compdef _{{.Name}} {{.Name}}
-
-{{template "selectCmdTemplate" .}}
-{{end}}
-`
-)
-
-// zshCompArgsAnnotation is used to encode/decode zsh completion for
-// arguments to/from Command.Annotations.
-type zshCompArgsAnnotation map[int]zshCompArgHint
-
-type zshCompArgHint struct {
-	// Indicates the type of the completion to use. One of:
-	// zshCompArgumentFilenameComp or zshCompArgumentWordComp
-	Tipe string `json:"type"`
-
-	// A value for the type above (globs for file completion or words)
-	Options []string `json:"options"`
-}
-
-// GenZshCompletionFile generates zsh completion file.
+// GenZshCompletionFile generates zsh completion file including descriptions.
 func (c *Command) GenZshCompletionFile(filename string) error {
+	return c.genZshCompletionFile(filename, true)
+}
+
+// GenZshCompletion generates zsh completion file including descriptions
+// and writes it to the passed writer.
+func (c *Command) GenZshCompletion(w io.Writer) error {
+	return c.genZshCompletion(w, true)
+}
+
+// GenZshCompletionFileNoDesc generates zsh completion file without descriptions.
+func (c *Command) GenZshCompletionFileNoDesc(filename string) error {
+	return c.genZshCompletionFile(filename, false)
+}
+
+// GenZshCompletionNoDesc generates zsh completion file without descriptions
+// and writes it to the passed writer.
+func (c *Command) GenZshCompletionNoDesc(w io.Writer) error {
+	return c.genZshCompletion(w, false)
+}
+
+// MarkZshCompPositionalArgumentFile only worked for zsh and its behavior was
+// not consistent with Bash completion. It has therefore been disabled.
+// Instead, when no other completion is specified, file completion is done by
+// default for every argument. One can disable file completion on a per-argument
+// basis by using ValidArgsFunction and ShellCompDirectiveNoFileComp.
+// To achieve file extension filtering, one can use ValidArgsFunction and
+// ShellCompDirectiveFilterFileExt.
+//
+// Deprecated
+func (c *Command) MarkZshCompPositionalArgumentFile(argPosition int, patterns ...string) error {
+	return nil
+}
+
+// MarkZshCompPositionalArgumentWords only worked for zsh. It has therefore
+// been disabled.
+// To achieve the same behavior across all shells, one can use
+// ValidArgs (for the first argument only) or ValidArgsFunction for
+// any argument (can include the first one also).
+//
+// Deprecated
+func (c *Command) MarkZshCompPositionalArgumentWords(argPosition int, words ...string) error {
+	return nil
+}
+
+func (c *Command) genZshCompletionFile(filename string, includeDesc bool) error {
 	outFile, err := os.Create(filename)
 	if err != nil {
 		return err
 	}
 	defer outFile.Close()
 
-	return c.GenZshCompletion(outFile)
+	return c.genZshCompletion(outFile, includeDesc)
 }
 
-// GenZshCompletion generates a zsh completion file and writes to the passed
-// writer. The completion always run on the root command regardless of the
-// command it was called from.
-func (c *Command) GenZshCompletion(w io.Writer) error {
-	tmpl, err := template.New("Main").Funcs(zshCompFuncMap).Parse(zshCompletionText)
-	if err != nil {
-		return fmt.Errorf("error creating zsh completion template: %v", err)
-	}
-	return tmpl.Execute(w, c.Root())
+func (c *Command) genZshCompletion(w io.Writer, includeDesc bool) error {
+	buf := new(bytes.Buffer)
+	genZshComp(buf, c.Name(), includeDesc)
+	_, err := buf.WriteTo(w)
+	return err
 }
 
-// MarkZshCompPositionalArgumentFile marks the specified argument (first
-// argument is 1) as completed by file selection. patterns (e.g. "*.txt") are
-// optional - if not provided the completion will search for all files.
-func (c *Command) MarkZshCompPositionalArgumentFile(argPosition int, patterns ...string) error {
-	if argPosition < 1 {
-		return fmt.Errorf("Invalid argument position (%d)", argPosition)
+func genZshComp(buf *bytes.Buffer, name string, includeDesc bool) {
+	compCmd := ShellCompRequestCmd
+	if !includeDesc {
+		compCmd = ShellCompNoDescRequestCmd
 	}
-	annotation, err := c.zshCompGetArgsAnnotations()
-	if err != nil {
-		return err
-	}
-	if c.zshcompArgsAnnotationnIsDuplicatePosition(annotation, argPosition) {
-		return fmt.Errorf("Duplicate annotation for positional argument at index %d", argPosition)
-	}
-	annotation[argPosition] = zshCompArgHint{
-		Tipe:    zshCompArgumentFilenameComp,
-		Options: patterns,
-	}
-	return c.zshCompSetArgsAnnotations(annotation)
+	buf.WriteString(fmt.Sprintf(`#compdef _%[1]s %[1]s
+
+# zsh completion for %-36[1]s -*- shell-script -*-
+
+__%[1]s_debug()
+{
+    local file="$BASH_COMP_DEBUG_FILE"
+    if [[ -n ${file} ]]; then
+        echo "$*" >> "${file}"
+    fi
 }
 
-// MarkZshCompPositionalArgumentWords marks the specified positional argument
-// (first argument is 1) as completed by the provided words. At east one word
-// must be provided, spaces within words will be offered completion with
-// "word\ word".
-func (c *Command) MarkZshCompPositionalArgumentWords(argPosition int, words ...string) error {
-	if argPosition < 1 {
-		return fmt.Errorf("Invalid argument position (%d)", argPosition)
-	}
-	if len(words) == 0 {
-		return fmt.Errorf("Trying to set empty word list for positional argument %d", argPosition)
-	}
-	annotation, err := c.zshCompGetArgsAnnotations()
-	if err != nil {
-		return err
-	}
-	if c.zshcompArgsAnnotationnIsDuplicatePosition(annotation, argPosition) {
-		return fmt.Errorf("Duplicate annotation for positional argument at index %d", argPosition)
-	}
-	annotation[argPosition] = zshCompArgHint{
-		Tipe:    zshCompArgumentWordComp,
-		Options: words,
-	}
-	return c.zshCompSetArgsAnnotations(annotation)
+_%[1]s()
+{
+    local shellCompDirectiveError=%[3]d
+    local shellCompDirectiveNoSpace=%[4]d
+    local shellCompDirectiveNoFileComp=%[5]d
+    local shellCompDirectiveFilterFileExt=%[6]d
+    local shellCompDirectiveFilterDirs=%[7]d
+
+    local lastParam lastChar flagPrefix requestComp out directive compCount comp lastComp
+    local -a completions
+
+    __%[1]s_debug "\n========= starting completion logic =========="
+    __%[1]s_debug "CURRENT: ${CURRENT}, words[*]: ${words[*]}"
+
+    # The user could have moved the cursor backwards on the command-line.
+    # We need to trigger completion from the $CURRENT location, so we need
+    # to truncate the command-line ($words) up to the $CURRENT location.
+    # (We cannot use $CURSOR as its value does not work when a command is an alias.)
+    words=("${=words[1,CURRENT]}")
+    __%[1]s_debug "Truncated words[*]: ${words[*]},"
+
+    lastParam=${words[-1]}
+    lastChar=${lastParam[-1]}
+    __%[1]s_debug "lastParam: ${lastParam}, lastChar: ${lastChar}"
+
+    # For zsh, when completing a flag with an = (e.g., %[1]s -n=<TAB>)
+    # completions must be prefixed with the flag
+    setopt local_options BASH_REMATCH
+    if [[ "${lastParam}" =~ '-.*=' ]]; then
+        # We are dealing with a flag with an =
+        flagPrefix="-P ${BASH_REMATCH}"
+    fi
+
+    # Prepare the command to obtain completions
+    requestComp="${words[1]} %[2]s ${words[2,-1]}"
+    if [ "${lastChar}" = "" ]; then
+        # If the last parameter is complete (there is a space following it)
+        # We add an extra empty parameter so we can indicate this to the go completion code.
+        __%[1]s_debug "Adding extra empty parameter"
+        requestComp="${requestComp} \"\""
+    fi
+
+    __%[1]s_debug "About to call: eval ${requestComp}"
+
+    # Use eval to handle any environment variables and such
+    out=$(eval ${requestComp} 2>/dev/null)
+    __%[1]s_debug "completion output: ${out}"
+
+    # Extract the directive integer following a : from the last line
+    local lastLine
+    while IFS='\n' read -r line; do
+        lastLine=${line}
+    done < <(printf "%%s\n" "${out[@]}")
+    __%[1]s_debug "last line: ${lastLine}"
+
+    if [ "${lastLine[1]}" = : ]; then
+        directive=${lastLine[2,-1]}
+        # Remove the directive including the : and the newline
+        local suffix
+        (( suffix=${#lastLine}+2))
+        out=${out[1,-$suffix]}
+    else
+        # There is no directive specified.  Leave $out as is.
+        __%[1]s_debug "No directive found.  Setting do default"
+        directive=0
+    fi
+
+    __%[1]s_debug "directive: ${directive}"
+    __%[1]s_debug "completions: ${out}"
+    __%[1]s_debug "flagPrefix: ${flagPrefix}"
+
+    if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
+        __%[1]s_debug "Completion received error. Ignoring completions."
+        return
+    fi
+
+    compCount=0
+    while IFS='\n' read -r comp; do
+        if [ -n "$comp" ]; then
+            # If requested, completions are returned with a description.
+            # The description is preceded by a TAB character.
+            # For zsh's _describe, we need to use a : instead of a TAB.
+            # We first need to escape any : as part of the completion itself.
+            comp=${comp//:/\\:}
+
+            local tab=$(printf '\t')
+            comp=${comp//$tab/:}
+
+            ((compCount++))
+            __%[1]s_debug "Adding completion: ${comp}"
+            completions+=${comp}
+            lastComp=$comp
+        fi
+    done < <(printf "%%s\n" "${out[@]}")
+
+    if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
+        # File extension filtering
+        local filteringCmd
+        filteringCmd='_files'
+        for filter in ${completions[@]}; do
+            if [ ${filter[1]} != '*' ]; then
+                # zsh requires a glob pattern to do file filtering
+                filter="\*.$filter"
+            fi
+            filteringCmd+=" -g $filter"
+        done
+        filteringCmd+=" ${flagPrefix}"
+
+        __%[1]s_debug "File filtering command: $filteringCmd"
+        _arguments '*:filename:'"$filteringCmd"
+    elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
+        # File completion for directories only
+        local subDir
+        subdir="${completions[1]}"
+        if [ -n "$subdir" ]; then
+            __%[1]s_debug "Listing directories in $subdir"
+            pushd "${subdir}" >/dev/null 2>&1
+        else
+            __%[1]s_debug "Listing directories in ."
+        fi
+
+        _arguments '*:dirname:_files -/'" ${flagPrefix}"
+        if [ -n "$subdir" ]; then
+            popd >/dev/null 2>&1
+        fi
+    elif [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ] && [ ${compCount} -eq 1 ]; then
+        __%[1]s_debug "Activating nospace."
+        # We can use compadd here as there is no description when
+        # there is only one completion.
+        compadd -S '' "${lastComp}"
+    elif [ ${compCount} -eq 0 ]; then
+        if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
+            __%[1]s_debug "deactivating file completion"
+        else
+            # Perform file completion
+            __%[1]s_debug "activating file completion"
+            _arguments '*:filename:_files'" ${flagPrefix}"
+        fi
+    else
+        _describe "completions" completions $(echo $flagPrefix)
+    fi
 }
 
-func zshCompExtractArgumentCompletionHintsForRendering(c *Command) ([]string, error) {
-	var result []string
-	annotation, err := c.zshCompGetArgsAnnotations()
-	if err != nil {
-		return nil, err
-	}
-	for k, v := range annotation {
-		s, err := zshCompRenderZshCompArgHint(k, v)
-		if err != nil {
-			return nil, err
-		}
-		result = append(result, s)
-	}
-	if len(c.ValidArgs) > 0 {
-		if _, positionOneExists := annotation[1]; !positionOneExists {
-			s, err := zshCompRenderZshCompArgHint(1, zshCompArgHint{
-				Tipe:    zshCompArgumentWordComp,
-				Options: c.ValidArgs,
-			})
-			if err != nil {
-				return nil, err
-			}
-			result = append(result, s)
-		}
-	}
-	sort.Strings(result)
-	return result, nil
-}
-
-func zshCompRenderZshCompArgHint(i int, z zshCompArgHint) (string, error) {
-	switch t := z.Tipe; t {
-	case zshCompArgumentFilenameComp:
-		var globs []string
-		for _, g := range z.Options {
-			globs = append(globs, fmt.Sprintf(`-g "%s"`, g))
-		}
-		return fmt.Sprintf(`'%d: :_files %s'`, i, strings.Join(globs, " ")), nil
-	case zshCompArgumentWordComp:
-		var words []string
-		for _, w := range z.Options {
-			words = append(words, fmt.Sprintf("%q", w))
-		}
-		return fmt.Sprintf(`'%d: :(%s)'`, i, strings.Join(words, " ")), nil
-	default:
-		return "", fmt.Errorf("Invalid zsh argument completion annotation: %s", t)
-	}
-}
-
-func (c *Command) zshcompArgsAnnotationnIsDuplicatePosition(annotation zshCompArgsAnnotation, position int) bool {
-	_, dup := annotation[position]
-	return dup
-}
-
-func (c *Command) zshCompGetArgsAnnotations() (zshCompArgsAnnotation, error) {
-	annotation := make(zshCompArgsAnnotation)
-	annotationString, ok := c.Annotations[zshCompArgumentAnnotation]
-	if !ok {
-		return annotation, nil
-	}
-	err := json.Unmarshal([]byte(annotationString), &annotation)
-	if err != nil {
-		return annotation, fmt.Errorf("Error unmarshaling zsh argument annotation: %v", err)
-	}
-	return annotation, nil
-}
-
-func (c *Command) zshCompSetArgsAnnotations(annotation zshCompArgsAnnotation) error {
-	jsn, err := json.Marshal(annotation)
-	if err != nil {
-		return fmt.Errorf("Error marshaling zsh argument annotation: %v", err)
-	}
-	if c.Annotations == nil {
-		c.Annotations = make(map[string]string)
-	}
-	c.Annotations[zshCompArgumentAnnotation] = string(jsn)
-	return nil
-}
-
-func zshCompGenFuncName(c *Command) string {
-	if c.HasParent() {
-		return zshCompGenFuncName(c.Parent()) + "_" + c.Name()
-	}
-	return "_" + c.Name()
-}
-
-func zshCompExtractFlag(c *Command) []*pflag.Flag {
-	var flags []*pflag.Flag
-	c.LocalFlags().VisitAll(func(f *pflag.Flag) {
-		if !f.Hidden {
-			flags = append(flags, f)
-		}
-	})
-	c.InheritedFlags().VisitAll(func(f *pflag.Flag) {
-		if !f.Hidden {
-			flags = append(flags, f)
-		}
-	})
-	return flags
-}
-
-// zshCompGenFlagEntryForArguments returns an entry that matches _arguments
-// zsh-completion parameters. It's too complicated to generate in a template.
-func zshCompGenFlagEntryForArguments(f *pflag.Flag) string {
-	if f.Name == "" || f.Shorthand == "" {
-		return zshCompGenFlagEntryForSingleOptionFlag(f)
-	}
-	return zshCompGenFlagEntryForMultiOptionFlag(f)
-}
-
-func zshCompGenFlagEntryForSingleOptionFlag(f *pflag.Flag) string {
-	var option, multiMark, extras string
-
-	if zshCompFlagCouldBeSpecifiedMoreThenOnce(f) {
-		multiMark = "*"
-	}
-
-	option = "--" + f.Name
-	if option == "--" {
-		option = "-" + f.Shorthand
-	}
-	extras = zshCompGenFlagEntryExtras(f)
-
-	return fmt.Sprintf(`'%s%s[%s]%s'`, multiMark, option, zshCompQuoteFlagDescription(f.Usage), extras)
-}
-
-func zshCompGenFlagEntryForMultiOptionFlag(f *pflag.Flag) string {
-	var options, parenMultiMark, curlyMultiMark, extras string
-
-	if zshCompFlagCouldBeSpecifiedMoreThenOnce(f) {
-		parenMultiMark = "*"
-		curlyMultiMark = "\\*"
-	}
-
-	options = fmt.Sprintf(`'(%s-%s %s--%s)'{%s-%s,%s--%s}`,
-		parenMultiMark, f.Shorthand, parenMultiMark, f.Name, curlyMultiMark, f.Shorthand, curlyMultiMark, f.Name)
-	extras = zshCompGenFlagEntryExtras(f)
-
-	return fmt.Sprintf(`%s'[%s]%s'`, options, zshCompQuoteFlagDescription(f.Usage), extras)
-}
-
-func zshCompGenFlagEntryExtras(f *pflag.Flag) string {
-	if f.NoOptDefVal != "" {
-		return ""
-	}
-
-	extras := ":" // allow options for flag (even without assistance)
-	for key, values := range f.Annotations {
-		switch key {
-		case zshCompDirname:
-			extras = fmt.Sprintf(":filename:_files -g %q", values[0])
-		case BashCompFilenameExt:
-			extras = ":filename:_files"
-			for _, pattern := range values {
-				extras = extras + fmt.Sprintf(` -g "%s"`, pattern)
-			}
-		}
-	}
-
-	return extras
-}
-
-func zshCompFlagCouldBeSpecifiedMoreThenOnce(f *pflag.Flag) bool {
-	return strings.Contains(f.Value.Type(), "Slice") ||
-		strings.Contains(f.Value.Type(), "Array")
-}
-
-func zshCompQuoteFlagDescription(s string) string {
-	return strings.Replace(s, "'", `'\''`, -1)
+# don't run the completion function when being source-ed or eval-ed
+if [ "$funcstack[1]" = "_%[1]s" ]; then
+	_%[1]s
+fi
+`, name, compCmd,
+		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
+		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs))
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/chtimes_nolinux.go b/vendor/github.com/tonistiigi/fsutil/chtimes_nolinux.go
index cdd80ec..a3ba098 100644
--- a/vendor/github.com/tonistiigi/fsutil/chtimes_nolinux.go
+++ b/vendor/github.com/tonistiigi/fsutil/chtimes_nolinux.go
@@ -5,16 +5,18 @@
 import (
 	"os"
 	"time"
+
+	"github.com/pkg/errors"
 )
 
 func chtimes(path string, un int64) error {
 	mtime := time.Unix(0, un)
 	fi, err := os.Lstat(path)
 	if err != nil {
-		return err
+		return errors.WithStack(err)
 	}
 	if fi.Mode()&os.ModeSymlink != 0 {
 		return nil
 	}
-	return os.Chtimes(path, mtime, mtime)
+	return errors.WithStack(os.Chtimes(path, mtime, mtime))
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy.go b/vendor/github.com/tonistiigi/fsutil/copy/copy.go
index 27b7d56..02b3dc9 100644
--- a/vendor/github.com/tonistiigi/fsutil/copy/copy.go
+++ b/vendor/github.com/tonistiigi/fsutil/copy/copy.go
@@ -147,7 +147,7 @@
 }
 
 type User struct {
-	Uid, Gid int
+	UID, GID int
 }
 
 type Chowner func(*User) (*User, error)
@@ -175,7 +175,7 @@
 func WithChown(uid, gid int) Opt {
 	return func(ci *CopyInfo) {
 		ci.Chown = func(*User) (*User, error) {
-			return &User{Uid: uid, Gid: gid}, nil
+			return &User{UID: uid, GID: gid}, nil
 		}
 	}
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_darwin.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_darwin.go
index 2882dfd..0d81496 100644
--- a/vendor/github.com/tonistiigi/fsutil/copy/copy_darwin.go
+++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_darwin.go
@@ -5,21 +5,13 @@
 import (
 	"io"
 	"os"
-	"syscall"
-	"unsafe"
 
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
 )
 
-// <sys/clonefile.h
-// int clonefileat(int, const char *, int, const char *, uint32_t) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);
-
-const CLONE_NOFOLLOW = 0x0001    /* Don't follow symbolic links */
-const CLONE_NOOWNERCOPY = 0x0002 /* Don't copy ownership information from */
-
 func copyFile(source, target string) error {
-	if err := clonefile(source, target); err != nil {
+	if err := unix.Clonefileat(unix.AT_FDCWD, source, unix.AT_FDCWD, target, unix.CLONE_NOFOLLOW); err != nil {
 		if err != unix.EINVAL {
 			return err
 		}
@@ -48,37 +40,3 @@
 
 	return err
 }
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
-	switch e {
-	case 0:
-		return nil
-	case unix.EAGAIN:
-		return syscall.EAGAIN
-	case unix.EINVAL:
-		return syscall.EINVAL
-	case unix.ENOENT:
-		return syscall.ENOENT
-	}
-	return e
-}
-
-func clonefile(src, dst string) (err error) {
-	var _p0, _p1 *byte
-	_p0, err = unix.BytePtrFromString(src)
-	if err != nil {
-		return
-	}
-	_p1, err = unix.BytePtrFromString(dst)
-	if err != nil {
-		return
-	}
-	fdcwd := unix.AT_FDCWD
-	_, _, e1 := unix.Syscall6(unix.SYS_CLONEFILEAT, uintptr(fdcwd), uintptr(unsafe.Pointer(_p0)), uintptr(fdcwd), uintptr(unsafe.Pointer(_p1)), uintptr(CLONE_NOFOLLOW), 0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go
index 268a9fc..4e6b93c 100644
--- a/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go
+++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_linux.go
@@ -10,7 +10,7 @@
 	"golang.org/x/sys/unix"
 )
 
-func getUidGid(fi os.FileInfo) (uid, gid int) {
+func getUIDGID(fi os.FileInfo) (uid, gid int) {
 	st := fi.Sys().(*syscall.Stat_t)
 	return int(st.Uid), int(st.Gid)
 }
@@ -19,8 +19,8 @@
 	st := fi.Sys().(*syscall.Stat_t)
 
 	chown := c.chown
-	uid, gid := getUidGid(fi)
-	old := &User{Uid: uid, Gid: gid}
+	uid, gid := getUIDGID(fi)
+	old := &User{UID: uid, GID: gid}
 	if chown == nil {
 		chown = func(u *User) (*User, error) {
 			return u, nil
diff --git a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go
index e80ee78..6debee2 100644
--- a/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go
+++ b/vendor/github.com/tonistiigi/fsutil/copy/copy_unix.go
@@ -10,7 +10,7 @@
 	"golang.org/x/sys/unix"
 )
 
-func getUidGid(fi os.FileInfo) (uid, gid int) {
+func getUIDGID(fi os.FileInfo) (uid, gid int) {
 	st := fi.Sys().(*syscall.Stat_t)
 	return int(st.Uid), int(st.Gid)
 }
@@ -18,8 +18,8 @@
 func (c *copier) copyFileInfo(fi os.FileInfo, name string) error {
 	st := fi.Sys().(*syscall.Stat_t)
 	chown := c.chown
-	uid, gid := getUidGid(fi)
-	old := &User{Uid: uid, Gid: gid}
+	uid, gid := getUIDGID(fi)
+	old := &User{UID: uid, GID: gid}
 	if chown == nil {
 		chown = func(u *User) (*User, error) {
 			return u, nil
diff --git a/vendor/github.com/tonistiigi/fsutil/copy/mkdir.go b/vendor/github.com/tonistiigi/fsutil/copy/mkdir.go
index b5eeb90..9854754 100644
--- a/vendor/github.com/tonistiigi/fsutil/copy/mkdir.go
+++ b/vendor/github.com/tonistiigi/fsutil/copy/mkdir.go
@@ -17,7 +17,7 @@
 		return errors.WithStack(err)
 	}
 	if user != nil {
-		if err := os.Lchown(p, user.Uid, user.Gid); err != nil {
+		if err := os.Lchown(p, user.UID, user.GID); err != nil {
 			return err
 		}
 	}
diff --git a/vendor/github.com/tonistiigi/fsutil/diff.go b/vendor/github.com/tonistiigi/fsutil/diff.go
index 1cbc32b..a7405dc 100644
--- a/vendor/github.com/tonistiigi/fsutil/diff.go
+++ b/vendor/github.com/tonistiigi/fsutil/diff.go
@@ -19,9 +19,9 @@
 
 type ContentHasher func(*types.Stat) (hash.Hash, error)
 
-func GetWalkerFn(root string) walkerFn {
+func getWalkerFn(root string) walkerFn {
 	return func(ctx context.Context, pathC chan<- *currentPath) error {
-		return Walk(ctx, root, nil, func(path string, f os.FileInfo, err error) error {
+		return errors.Wrap(Walk(ctx, root, nil, func(path string, f os.FileInfo, err error) error {
 			if err != nil {
 				return err
 			}
@@ -42,7 +42,7 @@
 			case pathC <- p:
 				return nil
 			}
-		})
+		}), "failed to walk")
 	}
 }
 
diff --git a/vendor/github.com/tonistiigi/fsutil/diff_containerd_linux.go b/vendor/github.com/tonistiigi/fsutil/diff_containerd_linux.go
deleted file mode 100644
index 4ac7ec5..0000000
--- a/vendor/github.com/tonistiigi/fsutil/diff_containerd_linux.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package fsutil
-
-import (
-	"bytes"
-	"syscall"
-
-	"github.com/containerd/continuity/sysx"
-	"github.com/pkg/errors"
-)
-
-// compareSysStat returns whether the stats are equivalent,
-// whether the files are considered the same file, and
-// an error
-func compareSysStat(s1, s2 interface{}) (bool, error) {
-	ls1, ok := s1.(*syscall.Stat_t)
-	if !ok {
-		return false, nil
-	}
-	ls2, ok := s2.(*syscall.Stat_t)
-	if !ok {
-		return false, nil
-	}
-
-	return ls1.Mode == ls2.Mode && ls1.Uid == ls2.Uid && ls1.Gid == ls2.Gid && ls1.Rdev == ls2.Rdev, nil
-}
-
-func compareCapabilities(p1, p2 string) (bool, error) {
-	c1, err := sysx.LGetxattr(p1, "security.capability")
-	if err != nil && err != syscall.ENODATA {
-		return false, errors.Wrapf(err, "failed to get xattr for %s", p1)
-	}
-	c2, err := sysx.LGetxattr(p2, "security.capability")
-	if err != nil && err != syscall.ENODATA {
-		return false, errors.Wrapf(err, "failed to get xattr for %s", p2)
-	}
-	return bytes.Equal(c1, c2), nil
-}
diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter.go b/vendor/github.com/tonistiigi/fsutil/diskwriter.go
index 70323c8..7864322 100644
--- a/vendor/github.com/tonistiigi/fsutil/diskwriter.go
+++ b/vendor/github.com/tonistiigi/fsutil/diskwriter.go
@@ -8,6 +8,7 @@
 	"path/filepath"
 	"strconv"
 	"sync"
+	"syscall"
 	"time"
 
 	"github.com/opencontainers/go-digest"
@@ -32,7 +33,6 @@
 	opt  DiskWriterOpt
 	dest string
 
-	wg     sync.WaitGroup
 	ctx    context.Context
 	cancel func()
 	eg     *errgroup.Group
@@ -104,7 +104,7 @@
 
 	stat, ok := fi.Sys().(*types.Stat)
 	if !ok {
-		return errors.Errorf("%s invalid change without stat information", p)
+		return errors.WithStack(&os.PathError{Path: p, Err: syscall.EBADMSG, Op: "change without stat info"})
 	}
 
 	statCopy := *stat
@@ -118,13 +118,13 @@
 	rename := true
 	oldFi, err := os.Lstat(destPath)
 	if err != nil {
-		if os.IsNotExist(err) {
+		if errors.Is(err, os.ErrNotExist) {
 			if kind != ChangeKindAdd {
-				return errors.Wrapf(err, "invalid addition: %s", destPath)
+				return errors.Wrap(err, "modify/rm")
 			}
 			rename = false
 		} else {
-			return errors.Wrapf(err, "failed to stat %s", destPath)
+			return errors.WithStack(err)
 		}
 	}
 
@@ -285,7 +285,6 @@
 
 type lazyFileWriter struct {
 	dest     string
-	ctx      context.Context
 	f        *os.File
 	fileMode *os.FileMode
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go b/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
index ff0a22e..aa2d298 100644
--- a/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
+++ b/vendor/github.com/tonistiigi/fsutil/diskwriter_unix.go
@@ -17,17 +17,17 @@
 	}
 
 	if err := os.Lchown(p, int(stat.Uid), int(stat.Gid)); err != nil {
-		return errors.Wrapf(err, "failed to lchown %s", p)
+		return errors.WithStack(err)
 	}
 
 	if os.FileMode(stat.Mode)&os.ModeSymlink == 0 {
 		if err := os.Chmod(p, os.FileMode(stat.Mode)); err != nil {
-			return errors.Wrapf(err, "failed to chown %s", p)
+			return errors.WithStack(err)
 		}
 	}
 
 	if err := chtimes(p, stat.ModTime); err != nil {
-		return errors.Wrapf(err, "failed to chtimes %s", p)
+		return err
 	}
 
 	return nil
@@ -46,7 +46,7 @@
 	}
 
 	if err := syscall.Mknod(path, mode, int(mkdev(stat.Devmajor, stat.Devminor))); err != nil {
-		return err
+		return errors.WithStack(err)
 	}
 	return nil
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/followlinks.go b/vendor/github.com/tonistiigi/fsutil/followlinks.go
index ed4af6e..a094241 100644
--- a/vendor/github.com/tonistiigi/fsutil/followlinks.go
+++ b/vendor/github.com/tonistiigi/fsutil/followlinks.go
@@ -77,10 +77,10 @@
 	if allowWildcard && containsWildcards(base) {
 		fis, err := ioutil.ReadDir(filepath.Dir(realPath))
 		if err != nil {
-			if os.IsNotExist(err) {
+			if errors.Is(err, os.ErrNotExist) {
 				return nil, nil
 			}
-			return nil, errors.Wrapf(err, "failed to read dir %s", filepath.Dir(realPath))
+			return nil, errors.Wrap(err, "readdir")
 		}
 		var out []string
 		for _, f := range fis {
@@ -97,17 +97,17 @@
 
 	fi, err := os.Lstat(realPath)
 	if err != nil {
-		if os.IsNotExist(err) {
+		if errors.Is(err, os.ErrNotExist) {
 			return nil, nil
 		}
-		return nil, errors.Wrapf(err, "failed to lstat %s", realPath)
+		return nil, errors.WithStack(err)
 	}
 	if fi.Mode()&os.ModeSymlink == 0 {
 		return nil, nil
 	}
 	link, err := os.Readlink(realPath)
 	if err != nil {
-		return nil, errors.Wrapf(err, "failed to readlink %s", realPath)
+		return nil, errors.WithStack(err)
 	}
 	link = filepath.Clean(link)
 	if filepath.IsAbs(link) {
diff --git a/vendor/github.com/tonistiigi/fsutil/fs.go b/vendor/github.com/tonistiigi/fsutil/fs.go
index a9467e9..e26110b 100644
--- a/vendor/github.com/tonistiigi/fsutil/fs.go
+++ b/vendor/github.com/tonistiigi/fsutil/fs.go
@@ -9,6 +9,7 @@
 	"path/filepath"
 	"sort"
 	"strings"
+	"syscall"
 
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil/types"
@@ -36,7 +37,8 @@
 }
 
 func (fs *fs) Open(p string) (io.ReadCloser, error) {
-	return os.Open(filepath.Join(fs.root, p))
+	rc, err := os.Open(filepath.Join(fs.root, p))
+	return rc, errors.WithStack(err)
 }
 
 type Dir struct {
@@ -51,10 +53,10 @@
 	m := map[string]Dir{}
 	for _, d := range dirs {
 		if path.Base(d.Stat.Path) != d.Stat.Path {
-			return nil, errors.Errorf("subdir %s must be single file", d.Stat.Path)
+			return nil, errors.WithStack(&os.PathError{Path: d.Stat.Path, Err: syscall.EISDIR, Op: "invalid path"})
 		}
 		if _, ok := m[d.Stat.Path]; ok {
-			return nil, errors.Errorf("invalid path %s", d.Stat.Path)
+			return nil, errors.WithStack(&os.PathError{Path: d.Stat.Path, Err: syscall.EEXIST, Op: "duplicate path"})
 		}
 		m[d.Stat.Path] = d
 	}
@@ -70,7 +72,7 @@
 	for _, d := range fs.dirs {
 		fi := &StatInfo{Stat: &d.Stat}
 		if !fi.IsDir() {
-			return errors.Errorf("fs subdir %s not mode directory", d.Stat.Path)
+			return errors.WithStack(&os.PathError{Path: d.Stat.Path, Err: syscall.ENOTDIR, Op: "walk subdir"})
 		}
 		if err := fn(d.Stat.Path, fi, nil); err != nil {
 			return err
@@ -78,7 +80,7 @@
 		if err := d.FS.Walk(ctx, func(p string, fi os.FileInfo, err error) error {
 			stat, ok := fi.Sys().(*types.Stat)
 			if !ok {
-				return errors.Wrapf(err, "invalid fileinfo without stat info: %s", p)
+				return errors.WithStack(&os.PathError{Path: d.Stat.Path, Err: syscall.EBADMSG, Op: "fileinfo without stat info"})
 			}
 			stat.Path = path.Join(d.Stat.Path, stat.Path)
 			if stat.Linkname != "" {
@@ -105,7 +107,7 @@
 	}
 	d, ok := fs.m[parts[0]]
 	if !ok {
-		return nil, os.ErrNotExist
+		return nil, errors.WithStack(&os.PathError{Path: parts[0], Err: syscall.ENOENT, Op: "open"})
 	}
 	return d.FS.Open(parts[1])
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/go.mod b/vendor/github.com/tonistiigi/fsutil/go.mod
index ed41f53..075742a 100644
--- a/vendor/github.com/tonistiigi/fsutil/go.mod
+++ b/vendor/github.com/tonistiigi/fsutil/go.mod
@@ -5,21 +5,16 @@
 require (
 	github.com/Microsoft/hcsshim v0.8.9 // indirect
 	github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc
-	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/docker/docker v0.0.0-20200511152416-a93e9eb0e95c
 	github.com/gogo/protobuf v1.3.1
-	github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
 	github.com/moby/sys/mount v0.1.0 // indirect
 	github.com/moby/sys/mountinfo v0.1.3 // indirect
-	github.com/onsi/ginkgo v1.7.0 // indirect
-	github.com/onsi/gomega v1.4.3 // indirect
-	github.com/opencontainers/go-digest v1.0.0-rc1
+	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/image-spec v1.0.1 // indirect
 	github.com/opencontainers/runc v1.0.0-rc10 // indirect
 	github.com/pkg/errors v0.9.1
 	github.com/stretchr/testify v1.5.1
 	golang.org/x/sync v0.0.0-20190423024810-112230192c58
-	golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae
-	gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
-	gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
+	golang.org/x/sys v0.0.0-20200917073148-efd3b9a0ff20
+	gotest.tools/v3 v3.0.2 // indirect
 )
diff --git a/vendor/github.com/tonistiigi/fsutil/hardlinks.go b/vendor/github.com/tonistiigi/fsutil/hardlinks.go
index d977f0d..ef8bbfb 100644
--- a/vendor/github.com/tonistiigi/fsutil/hardlinks.go
+++ b/vendor/github.com/tonistiigi/fsutil/hardlinks.go
@@ -2,6 +2,7 @@
 
 import (
 	"os"
+	"syscall"
 
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil/types"
@@ -28,7 +29,7 @@
 
 	stat, ok := fi.Sys().(*types.Stat)
 	if !ok {
-		return errors.Errorf("invalid change without stat info: %s", p)
+		return errors.WithStack(&os.PathError{Path: p, Err: syscall.EBADMSG, Op: "change without stat info"})
 	}
 
 	if fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 {
diff --git a/vendor/github.com/tonistiigi/fsutil/receive.go b/vendor/github.com/tonistiigi/fsutil/receive.go
index 0210dcd..5c6a486 100644
--- a/vendor/github.com/tonistiigi/fsutil/receive.go
+++ b/vendor/github.com/tonistiigi/fsutil/receive.go
@@ -20,7 +20,7 @@
 }
 
 func Receive(ctx context.Context, conn Stream, dest string, opt ReceiveOpt) error {
-	ctx, cancel := context.WithCancel(context.Background())
+	ctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 
 	r := &receiver{
@@ -105,7 +105,6 @@
 			return ctx.Err()
 		}
 	}
-	return nil
 }
 
 func (r *receiver) run(ctx context.Context) error {
@@ -131,7 +130,7 @@
 		}()
 		destWalker := emptyWalker
 		if !r.merge {
-			destWalker = GetWalkerFn(r.dest)
+			destWalker = getWalkerFn(r.dest)
 		}
 		err := doubleWalkDiff(ctx, dw.HandleChange, destWalker, w.fill, r.filter)
 		if err != nil {
diff --git a/vendor/github.com/tonistiigi/fsutil/send.go b/vendor/github.com/tonistiigi/fsutil/send.go
index e7c5a37..2c1a380 100644
--- a/vendor/github.com/tonistiigi/fsutil/send.go
+++ b/vendor/github.com/tonistiigi/fsutil/send.go
@@ -5,6 +5,7 @@
 	"io"
 	"os"
 	"sync"
+	"syscall"
 
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil/types"
@@ -13,7 +14,8 @@
 
 var bufPool = sync.Pool{
 	New: func() interface{} {
-		return make([]byte, 32*1<<10)
+		buf := make([]byte, 32*1<<10)
+		return &buf
 	},
 }
 
@@ -131,9 +133,9 @@
 	f, err := s.fs.Open(h.path)
 	if err == nil {
 		defer f.Close()
-		buf := bufPool.Get().([]byte)
+		buf := bufPool.Get().(*[]byte)
 		defer bufPool.Put(buf)
-		if _, err := io.CopyBuffer(&fileSender{sender: s, id: h.id}, f, buf); err != nil {
+		if _, err := io.CopyBuffer(&fileSender{sender: s, id: h.id}, f, *buf); err != nil {
 			return err
 		}
 	}
@@ -148,7 +150,7 @@
 		}
 		stat, ok := fi.Sys().(*types.Stat)
 		if !ok {
-			return errors.Wrapf(err, "invalid fileinfo without stat info: %s", path)
+			return errors.WithStack(&os.PathError{Path: path, Err: syscall.EBADMSG, Op: "fileinfo without stat info"})
 		}
 
 		p := &types.Packet{
diff --git a/vendor/github.com/tonistiigi/fsutil/stat.go b/vendor/github.com/tonistiigi/fsutil/stat.go
index 789dce3..2ab8da1 100644
--- a/vendor/github.com/tonistiigi/fsutil/stat.go
+++ b/vendor/github.com/tonistiigi/fsutil/stat.go
@@ -31,13 +31,13 @@
 		if fi.Mode()&os.ModeSymlink != 0 {
 			link, err := os.Readlink(path)
 			if err != nil {
-				return nil, errors.Wrapf(err, "failed to readlink %s", path)
+				return nil, errors.WithStack(err)
 			}
 			stat.Linkname = link
 		}
 	}
 	if err := loadXattr(path, stat); err != nil {
-		return nil, errors.Wrapf(err, "failed to xattr %s", relpath)
+		return nil, err
 	}
 
 	if runtime.GOOS == "windows" {
@@ -58,7 +58,7 @@
 func Stat(path string) (*types.Stat, error) {
 	fi, err := os.Lstat(path)
 	if err != nil {
-		return nil, errors.Wrap(err, "os stat")
+		return nil, errors.WithStack(err)
 	}
 	return mkstat(path, filepath.Base(path), fi, nil)
 }
diff --git a/vendor/github.com/tonistiigi/fsutil/tarwriter.go b/vendor/github.com/tonistiigi/fsutil/tarwriter.go
index 06f28c5..bd46a22 100644
--- a/vendor/github.com/tonistiigi/fsutil/tarwriter.go
+++ b/vendor/github.com/tonistiigi/fsutil/tarwriter.go
@@ -7,6 +7,7 @@
 	"os"
 	"path/filepath"
 	"strings"
+	"syscall"
 
 	"github.com/pkg/errors"
 	"github.com/tonistiigi/fsutil/types"
@@ -15,9 +16,12 @@
 func WriteTar(ctx context.Context, fs FS, w io.Writer) error {
 	tw := tar.NewWriter(w)
 	err := fs.Walk(ctx, func(path string, fi os.FileInfo, err error) error {
+		if err != nil && !errors.Is(err, os.ErrNotExist) {
+			return err
+		}
 		stat, ok := fi.Sys().(*types.Stat)
 		if !ok {
-			return errors.Wrapf(err, "invalid fileinfo without stat info: %s", path)
+			return errors.WithStack(&os.PathError{Path: path, Err: syscall.EBADMSG, Op: "fileinfo without stat info"})
 		}
 		hdr, err := tar.FileInfoHeader(fi, stat.Linkname)
 		if err != nil {
@@ -37,7 +41,7 @@
 		hdr.Linkname = stat.Linkname
 		if hdr.Linkname != "" {
 			hdr.Size = 0
-			if fi.Mode() & os.ModeSymlink != 0 {
+			if fi.Mode()&os.ModeSymlink != 0 {
 				hdr.Typeflag = tar.TypeSymlink
 			} else {
 				hdr.Typeflag = tar.TypeLink
@@ -52,7 +56,7 @@
 		}
 
 		if err := tw.WriteHeader(hdr); err != nil {
-			return errors.Wrap(err, "failed to write file header")
+			return errors.Wrapf(err, "failed to write file header %s", name)
 		}
 
 		if hdr.Typeflag == tar.TypeReg && hdr.Size > 0 && hdr.Linkname == "" {
@@ -61,10 +65,10 @@
 				return err
 			}
 			if _, err := io.Copy(tw, rc); err != nil {
-				return err
+				return errors.WithStack(err)
 			}
 			if err := rc.Close(); err != nil {
-				return err
+				return errors.WithStack(err)
 			}
 		}
 		return nil
diff --git a/vendor/github.com/tonistiigi/fsutil/validator.go b/vendor/github.com/tonistiigi/fsutil/validator.go
index 2bd1287..9bd7d94 100644
--- a/vendor/github.com/tonistiigi/fsutil/validator.go
+++ b/vendor/github.com/tonistiigi/fsutil/validator.go
@@ -6,6 +6,7 @@
 	"runtime"
 	"sort"
 	"strings"
+	"syscall"
 
 	"github.com/pkg/errors"
 )
@@ -31,10 +32,10 @@
 		p = strings.Replace(p, "\\", "", -1)
 	}
 	if p != path.Clean(p) {
-		return errors.Errorf("invalid unclean path %s", p)
+		return errors.WithStack(&os.PathError{Path: p, Err: syscall.EINVAL, Op: "unclean path"})
 	}
 	if path.IsAbs(p) {
-		return errors.Errorf("abolute path %s not allowed", p)
+		return errors.WithStack(&os.PathError{Path: p, Err: syscall.EINVAL, Op: "absolute path"})
 	}
 	dir := path.Dir(p)
 	base := path.Base(p)
@@ -42,7 +43,7 @@
 		dir = ""
 	}
 	if dir == ".." || strings.HasPrefix(p, "../") {
-		return errors.Errorf("invalid path: %s", p)
+		return errors.WithStack(&os.PathError{Path: p, Err: syscall.EINVAL, Op: "escape check"})
 	}
 
 	// find a parent dir from saved records
diff --git a/vendor/github.com/tonistiigi/fsutil/walker.go b/vendor/github.com/tonistiigi/fsutil/walker.go
index 6004b88..b10383e 100644
--- a/vendor/github.com/tonistiigi/fsutil/walker.go
+++ b/vendor/github.com/tonistiigi/fsutil/walker.go
@@ -25,21 +25,21 @@
 func Walk(ctx context.Context, p string, opt *WalkOpt, fn filepath.WalkFunc) error {
 	root, err := filepath.EvalSymlinks(p)
 	if err != nil {
-		return errors.Wrapf(err, "failed to resolve %s", root)
+		return errors.WithStack(&os.PathError{Op: "resolve", Path: root, Err: err})
 	}
 	fi, err := os.Stat(root)
 	if err != nil {
-		return errors.Wrapf(err, "failed to stat: %s", root)
+		return errors.WithStack(err)
 	}
 	if !fi.IsDir() {
-		return errors.Errorf("%s is not a directory", root)
+		return errors.WithStack(&os.PathError{Op: "walk", Path: root, Err: syscall.ENOTDIR})
 	}
 
 	var pm *fileutils.PatternMatcher
 	if opt != nil && opt.ExcludePatterns != nil {
 		pm, err = fileutils.NewPatternMatcher(opt.ExcludePatterns)
 		if err != nil {
-			return errors.Wrapf(err, "invalid excludepaths %s", opt.ExcludePatterns)
+			return errors.Wrapf(err, "invalid excludepatterns: %s", opt.ExcludePatterns)
 		}
 	}
 
@@ -65,17 +65,15 @@
 
 	seenFiles := make(map[uint64]string)
 	return filepath.Walk(root, func(path string, fi os.FileInfo, err error) (retErr error) {
-		if err != nil {
-			if os.IsNotExist(err) {
-				return filepath.SkipDir
-			}
-			return err
-		}
 		defer func() {
 			if retErr != nil && isNotExist(retErr) {
 				retErr = filepath.SkipDir
 			}
 		}()
+		if err != nil {
+			return err
+		}
+
 		origpath := path
 		path, err = filepath.Rel(root, path)
 		if err != nil {
diff --git a/vendor/github.com/tonistiigi/units/LICENSE b/vendor/github.com/tonistiigi/units/LICENSE
new file mode 100644
index 0000000..5c1095d
--- /dev/null
+++ b/vendor/github.com/tonistiigi/units/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Tõnis Tiigi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/tonistiigi/units/bytes.go b/vendor/github.com/tonistiigi/units/bytes.go
new file mode 100644
index 0000000..5a82fc1
--- /dev/null
+++ b/vendor/github.com/tonistiigi/units/bytes.go
@@ -0,0 +1,125 @@
+/*
+	Simple byte size formatting.
+
+	This package implements types that can be used in stdlib formatting functions
+	like `fmt.Printf` to control the output of the expected printed string.
+
+
+	Floating point flags %f and %g print the value in using the correct unit
+	suffix. Decimal units are default, # switches to binary units. If a value is
+	best represented as full bytes, integer bytes are printed instead.
+
+		Examples:
+			fmt.Printf("%.2f", 123 * B)   => "123B"
+			fmt.Printf("%.2f", 1234 * B)  => "1.23kB"
+			fmt.Printf("%g", 1200 * B)    => "1.2kB"
+			fmt.Printf("%#g", 1024 * B)   => "1KiB"
+
+
+	Integer flag %d always prints the value in bytes. # flag adds an unit prefix.
+
+		Examples:
+			fmt.Printf("%d", 1234 * B)    => "1234"
+			fmt.Printf("%#d", 1234 * B)   => "1234B"
+
+	%v is equal to %g
+
+*/
+package units
+
+import (
+	"fmt"
+	"io"
+	"math"
+	"math/big"
+)
+
+type Bytes int64
+
+const (
+	B Bytes = 1 << (10 * iota)
+	KiB
+	MiB
+	GiB
+	TiB
+	PiB
+	EiB
+
+	KB = 1e3 * B
+	MB = 1e3 * KB
+	GB = 1e3 * MB
+	TB = 1e3 * GB
+	PB = 1e3 * TB
+	EB = 1e3 * PB
+)
+
+var units = map[bool][]string{
+	false: []string{
+		"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB",
+	},
+	true: []string{
+		"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB",
+	},
+}
+
+func (b Bytes) Format(f fmt.State, c rune) {
+	switch c {
+	case 'f', 'g':
+		fv, unit, ok := b.floatValue(f.Flag('#'))
+		if !ok {
+			b.formatInt(&noPrecision{f}, 'd', true)
+			return
+		}
+		big.NewFloat(fv).Format(f, c)
+		io.WriteString(f, unit)
+	case 'd':
+		b.formatInt(f, c, f.Flag('#'))
+	default:
+		if f.Flag('#') {
+			fmt.Fprintf(f, "bytes(%d)", int64(b))
+		} else {
+			fmt.Fprintf(f, "%g", b)
+		}
+	}
+}
+
+func (b Bytes) formatInt(f fmt.State, c rune, withUnit bool) {
+	big.NewInt(int64(b)).Format(f, c)
+	if withUnit {
+		io.WriteString(f, "B")
+	}
+}
+
+func (b Bytes) floatValue(binary bool) (float64, string, bool) {
+	i := 0
+	var baseUnit Bytes = 1
+	if b < 0 {
+		baseUnit *= -1
+	}
+	for {
+		next := baseUnit
+		if binary {
+			next *= 1 << 10
+		} else {
+			next *= 1e3
+		}
+		if (baseUnit > 0 && b >= next) || (baseUnit < 0 && b <= next) {
+			i++
+			baseUnit = next
+			continue
+		}
+		if i == 0 {
+			return 0, "", false
+		}
+
+		return float64(b) / math.Abs(float64(baseUnit)), units[binary][i], true
+	}
+}
+
+type noPrecision struct {
+	fmt.State
+}
+
+func (*noPrecision) Precision() (prec int, ok bool) {
+	return 0, false
+}
diff --git a/vendor/github.com/tonistiigi/units/readme.md b/vendor/github.com/tonistiigi/units/readme.md
new file mode 100644
index 0000000..5c67d30
--- /dev/null
+++ b/vendor/github.com/tonistiigi/units/readme.md
@@ -0,0 +1,29 @@
+#### Simple byte size formatting.
+
+This package implements types that can be used in stdlib formatting functions
+like `fmt.Printf` to control the output of the expected printed string.
+
+Floating point flags `%f` and %g print the value in using the correct unit
+suffix. Decimal units are default, `#` switches to binary units. If a value is
+best represented as full bytes, integer bytes are printed instead.
+
+##### Examples:
+
+```
+fmt.Printf("%.2f", 123 * B)   => "123B"
+fmt.Printf("%.2f", 1234 * B)  => "1.23kB"
+fmt.Printf("%g", 1200 * B)    => "1.2kB"
+fmt.Printf("%#g", 1024 * B)   => "1KiB"
+```
+
+
+Integer flag `%d` always prints the value in bytes. `#` flag adds an unit prefix.
+
+##### Examples:
+
+```
+fmt.Printf("%d", 1234 * B)    => "1234"
+fmt.Printf("%#d", 1234 * B)   => "1234B"
+```
+
+`%v` is equal to `%g`
\ No newline at end of file
diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go
new file mode 100644
index 0000000..9d80f19
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/block.go
@@ -0,0 +1,159 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package blowfish
+
+// getNextWord returns the next big-endian uint32 value from the byte slice
+// at the given position in a circular manner, updating the position.
+func getNextWord(b []byte, pos *int) uint32 {
+	var w uint32
+	j := *pos
+	for i := 0; i < 4; i++ {
+		w = w<<8 | uint32(b[j])
+		j++
+		if j >= len(b) {
+			j = 0
+		}
+	}
+	*pos = j
+	return w
+}
+
+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
+// pi and substitution tables for calls to Encrypt. This is used, primarily,
+// by the bcrypt package to reuse the Blowfish key schedule during its
+// set up. It's unlikely that you need to use this directly.
+func ExpandKey(key []byte, c *Cipher) {
+	j := 0
+	for i := 0; i < 18; i++ {
+		// Using inlined getNextWord for performance.
+		var d uint32
+		for k := 0; k < 4; k++ {
+			d = d<<8 | uint32(key[j])
+			j++
+			if j >= len(key) {
+				j = 0
+			}
+		}
+		c.p[i] ^= d
+	}
+
+	var l, r uint32
+	for i := 0; i < 18; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.p[i], c.p[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s0[i], c.s0[i+1] = l, r
+	}
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s1[i], c.s1[i+1] = l, r
+	}
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s2[i], c.s2[i+1] = l, r
+	}
+	for i := 0; i < 256; i += 2 {
+		l, r = encryptBlock(l, r, c)
+		c.s3[i], c.s3[i+1] = l, r
+	}
+}
+
+// This is similar to ExpandKey, but folds the salt during the key
+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
+// and specializing it here is useful.
+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
+	j := 0
+	for i := 0; i < 18; i++ {
+		c.p[i] ^= getNextWord(key, &j)
+	}
+
+	j = 0
+	var l, r uint32
+	for i := 0; i < 18; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.p[i], c.p[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s0[i], c.s0[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s1[i], c.s1[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s2[i], c.s2[i+1] = l, r
+	}
+
+	for i := 0; i < 256; i += 2 {
+		l ^= getNextWord(salt, &j)
+		r ^= getNextWord(salt, &j)
+		l, r = encryptBlock(l, r, c)
+		c.s3[i], c.s3[i+1] = l, r
+	}
+}
+
+func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+	xl, xr := l, r
+	xl ^= c.p[0]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
+	xr ^= c.p[17]
+	return xr, xl
+}
+
+func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
+	xl, xr := l, r
+	xl ^= c.p[17]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
+	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
+	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
+	xr ^= c.p[0]
+	return xr, xl
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go
new file mode 100644
index 0000000..213bf20
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/cipher.go
@@ -0,0 +1,99 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
+//
+// Blowfish is a legacy cipher and its short block size makes it vulnerable to
+// birthday bound attacks (see https://sweet32.info). It should only be used
+// where compatibility with legacy systems, not security, is the goal.
+//
+// Deprecated: any new system should use AES (from crypto/aes, if necessary in
+// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
+// golang.org/x/crypto/chacha20poly1305).
+package blowfish // import "golang.org/x/crypto/blowfish"
+
+// The code is a port of Bruce Schneier's C implementation.
+// See https://www.schneier.com/blowfish.html.
+
+import "strconv"
+
+// The Blowfish block size in bytes.
+const BlockSize = 8
+
+// A Cipher is an instance of Blowfish encryption using a particular key.
+type Cipher struct {
+	p              [18]uint32
+	s0, s1, s2, s3 [256]uint32
+}
+
+type KeySizeError int
+
+func (k KeySizeError) Error() string {
+	return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
+}
+
+// NewCipher creates and returns a Cipher.
+// The key argument should be the Blowfish key, from 1 to 56 bytes.
+func NewCipher(key []byte) (*Cipher, error) {
+	var result Cipher
+	if k := len(key); k < 1 || k > 56 {
+		return nil, KeySizeError(k)
+	}
+	initCipher(&result)
+	ExpandKey(key, &result)
+	return &result, nil
+}
+
+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
+// sufficient and desirable. For bcrypt compatibility, the key can be over 56
+// bytes.
+func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
+	if len(salt) == 0 {
+		return NewCipher(key)
+	}
+	var result Cipher
+	if k := len(key); k < 1 {
+		return nil, KeySizeError(k)
+	}
+	initCipher(&result)
+	expandKeyWithSalt(key, salt, &result)
+	return &result, nil
+}
+
+// BlockSize returns the Blowfish block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypt encrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	l, r = encryptBlock(l, r, c)
+	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+// Decrypt decrypts the 8-byte buffer src using the key k
+// and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) {
+	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
+	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
+	l, r = decryptBlock(l, r, c)
+	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
+	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
+}
+
+func initCipher(c *Cipher) {
+	copy(c.p[0:], p[0:])
+	copy(c.s0[0:], s0[0:])
+	copy(c.s1[0:], s1[0:])
+	copy(c.s2[0:], s2[0:])
+	copy(c.s3[0:], s3[0:])
+}
diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go
new file mode 100644
index 0000000..d040775
--- /dev/null
+++ b/vendor/golang.org/x/crypto/blowfish/const.go
@@ -0,0 +1,199 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The startup permutation array and substitution boxes.
+// They are the hexadecimal digits of PI; see:
+// https://www.schneier.com/code/constants.txt.
+
+package blowfish
+
+var s0 = [256]uint32{
+	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
+	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
+	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
+	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
+	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
+	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
+	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
+	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
+	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
+	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
+	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
+	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
+	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
+	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
+	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
+	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
+	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
+	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
+	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
+	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
+	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
+	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+}
+
+var s1 = [256]uint32{
+	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
+	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
+	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
+	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
+	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
+	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
+	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
+	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
+	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
+	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
+	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
+	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
+	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
+	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
+	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
+	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
+	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
+	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
+	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
+	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
+	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
+	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+}
+
+var s2 = [256]uint32{
+	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
+	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
+	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
+	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
+	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
+	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
+	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
+	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
+	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
+	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
+	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
+	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
+	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
+	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
+	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
+	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
+	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
+	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
+	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
+	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
+	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
+	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+}
+
+var s3 = [256]uint32{
+	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
+	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
+	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
+	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
+	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
+	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
+	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
+	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
+	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
+	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
+	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
+	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
+	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
+	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
+	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
+	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
+	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
+	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
+	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
+	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
+	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
+	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+}
+
+var p = [18]uint32{
+	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
+	0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
+}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
new file mode 100644
index 0000000..b799e44
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
@@ -0,0 +1,16 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.11,!gccgo,!purego
+
+package chacha20
+
+const bufSize = 256
+
+//go:noescape
+func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
+
+func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
+	xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
+}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s
new file mode 100644
index 0000000..8914815
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s
@@ -0,0 +1,307 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.11,!gccgo,!purego
+
+#include "textflag.h"
+
+#define NUM_ROUNDS 10
+
+// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
+TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
+	MOVD	dst+0(FP), R1
+	MOVD	src+24(FP), R2
+	MOVD	src_len+32(FP), R3
+	MOVD	key+48(FP), R4
+	MOVD	nonce+56(FP), R6
+	MOVD	counter+64(FP), R7
+
+	MOVD	$·constants(SB), R10
+	MOVD	$·incRotMatrix(SB), R11
+
+	MOVW	(R7), R20
+
+	AND	$~255, R3, R13
+	ADD	R2, R13, R12 // R12 for block end
+	AND	$255, R3, R13
+loop:
+	MOVD	$NUM_ROUNDS, R21
+	VLD1	(R11), [V30.S4, V31.S4]
+
+	// load contants
+	// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4]
+	WORD	$0x4D60E940
+
+	// load keys
+	// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4]
+	WORD	$0x4DFFE884
+	// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4]
+	WORD	$0x4DFFE888
+	SUB	$32, R4
+
+	// load counter + nonce
+	// VLD1R (R7), [V12.S4]
+	WORD	$0x4D40C8EC
+
+	// VLD3R (R6), [V13.S4, V14.S4, V15.S4]
+	WORD	$0x4D40E8CD
+
+	// update counter
+	VADD	V30.S4, V12.S4, V12.S4
+
+chacha:
+	// V0..V3 += V4..V7
+	// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16)
+	VADD	V0.S4, V4.S4, V0.S4
+	VADD	V1.S4, V5.S4, V1.S4
+	VADD	V2.S4, V6.S4, V2.S4
+	VADD	V3.S4, V7.S4, V3.S4
+	VEOR	V12.B16, V0.B16, V12.B16
+	VEOR	V13.B16, V1.B16, V13.B16
+	VEOR	V14.B16, V2.B16, V14.B16
+	VEOR	V15.B16, V3.B16, V15.B16
+	VREV32	V12.H8, V12.H8
+	VREV32	V13.H8, V13.H8
+	VREV32	V14.H8, V14.H8
+	VREV32	V15.H8, V15.H8
+	// V8..V11 += V12..V15
+	// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12)
+	VADD	V8.S4, V12.S4, V8.S4
+	VADD	V9.S4, V13.S4, V9.S4
+	VADD	V10.S4, V14.S4, V10.S4
+	VADD	V11.S4, V15.S4, V11.S4
+	VEOR	V8.B16, V4.B16, V16.B16
+	VEOR	V9.B16, V5.B16, V17.B16
+	VEOR	V10.B16, V6.B16, V18.B16
+	VEOR	V11.B16, V7.B16, V19.B16
+	VSHL	$12, V16.S4, V4.S4
+	VSHL	$12, V17.S4, V5.S4
+	VSHL	$12, V18.S4, V6.S4
+	VSHL	$12, V19.S4, V7.S4
+	VSRI	$20, V16.S4, V4.S4
+	VSRI	$20, V17.S4, V5.S4
+	VSRI	$20, V18.S4, V6.S4
+	VSRI	$20, V19.S4, V7.S4
+
+	// V0..V3 += V4..V7
+	// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8)
+	VADD	V0.S4, V4.S4, V0.S4
+	VADD	V1.S4, V5.S4, V1.S4
+	VADD	V2.S4, V6.S4, V2.S4
+	VADD	V3.S4, V7.S4, V3.S4
+	VEOR	V12.B16, V0.B16, V12.B16
+	VEOR	V13.B16, V1.B16, V13.B16
+	VEOR	V14.B16, V2.B16, V14.B16
+	VEOR	V15.B16, V3.B16, V15.B16
+	VTBL	V31.B16, [V12.B16], V12.B16
+	VTBL	V31.B16, [V13.B16], V13.B16
+	VTBL	V31.B16, [V14.B16], V14.B16
+	VTBL	V31.B16, [V15.B16], V15.B16
+
+	// V8..V11 += V12..V15
+	// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7)
+	VADD	V12.S4, V8.S4, V8.S4
+	VADD	V13.S4, V9.S4, V9.S4
+	VADD	V14.S4, V10.S4, V10.S4
+	VADD	V15.S4, V11.S4, V11.S4
+	VEOR	V8.B16, V4.B16, V16.B16
+	VEOR	V9.B16, V5.B16, V17.B16
+	VEOR	V10.B16, V6.B16, V18.B16
+	VEOR	V11.B16, V7.B16, V19.B16
+	VSHL	$7, V16.S4, V4.S4
+	VSHL	$7, V17.S4, V5.S4
+	VSHL	$7, V18.S4, V6.S4
+	VSHL	$7, V19.S4, V7.S4
+	VSRI	$25, V16.S4, V4.S4
+	VSRI	$25, V17.S4, V5.S4
+	VSRI	$25, V18.S4, V6.S4
+	VSRI	$25, V19.S4, V7.S4
+
+	// V0..V3 += V5..V7, V4
+	// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16)
+	VADD	V0.S4, V5.S4, V0.S4
+	VADD	V1.S4, V6.S4, V1.S4
+	VADD	V2.S4, V7.S4, V2.S4
+	VADD	V3.S4, V4.S4, V3.S4
+	VEOR	V15.B16, V0.B16, V15.B16
+	VEOR	V12.B16, V1.B16, V12.B16
+	VEOR	V13.B16, V2.B16, V13.B16
+	VEOR	V14.B16, V3.B16, V14.B16
+	VREV32	V12.H8, V12.H8
+	VREV32	V13.H8, V13.H8
+	VREV32	V14.H8, V14.H8
+	VREV32	V15.H8, V15.H8
+
+	// V10 += V15; V5 <<<= ((V10 XOR V5), 12)
+	// ...
+	VADD	V15.S4, V10.S4, V10.S4
+	VADD	V12.S4, V11.S4, V11.S4
+	VADD	V13.S4, V8.S4, V8.S4
+	VADD	V14.S4, V9.S4, V9.S4
+	VEOR	V10.B16, V5.B16, V16.B16
+	VEOR	V11.B16, V6.B16, V17.B16
+	VEOR	V8.B16, V7.B16, V18.B16
+	VEOR	V9.B16, V4.B16, V19.B16
+	VSHL	$12, V16.S4, V5.S4
+	VSHL	$12, V17.S4, V6.S4
+	VSHL	$12, V18.S4, V7.S4
+	VSHL	$12, V19.S4, V4.S4
+	VSRI	$20, V16.S4, V5.S4
+	VSRI	$20, V17.S4, V6.S4
+	VSRI	$20, V18.S4, V7.S4
+	VSRI	$20, V19.S4, V4.S4
+
+	// V0 += V5; V15 <<<= ((V0 XOR V15), 8)
+	// ...
+	VADD	V5.S4, V0.S4, V0.S4
+	VADD	V6.S4, V1.S4, V1.S4
+	VADD	V7.S4, V2.S4, V2.S4
+	VADD	V4.S4, V3.S4, V3.S4
+	VEOR	V0.B16, V15.B16, V15.B16
+	VEOR	V1.B16, V12.B16, V12.B16
+	VEOR	V2.B16, V13.B16, V13.B16
+	VEOR	V3.B16, V14.B16, V14.B16
+	VTBL	V31.B16, [V12.B16], V12.B16
+	VTBL	V31.B16, [V13.B16], V13.B16
+	VTBL	V31.B16, [V14.B16], V14.B16
+	VTBL	V31.B16, [V15.B16], V15.B16
+
+	// V10 += V15; V5 <<<= ((V10 XOR V5), 7)
+	// ...
+	VADD	V15.S4, V10.S4, V10.S4
+	VADD	V12.S4, V11.S4, V11.S4
+	VADD	V13.S4, V8.S4, V8.S4
+	VADD	V14.S4, V9.S4, V9.S4
+	VEOR	V10.B16, V5.B16, V16.B16
+	VEOR	V11.B16, V6.B16, V17.B16
+	VEOR	V8.B16, V7.B16, V18.B16
+	VEOR	V9.B16, V4.B16, V19.B16
+	VSHL	$7, V16.S4, V5.S4
+	VSHL	$7, V17.S4, V6.S4
+	VSHL	$7, V18.S4, V7.S4
+	VSHL	$7, V19.S4, V4.S4
+	VSRI	$25, V16.S4, V5.S4
+	VSRI	$25, V17.S4, V6.S4
+	VSRI	$25, V18.S4, V7.S4
+	VSRI	$25, V19.S4, V4.S4
+
+	SUB	$1, R21
+	CBNZ	R21, chacha
+
+	// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4]
+	WORD	$0x4D60E950
+
+	// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4]
+	WORD	$0x4DFFE894
+	VADD	V30.S4, V12.S4, V12.S4
+	VADD	V16.S4, V0.S4, V0.S4
+	VADD	V17.S4, V1.S4, V1.S4
+	VADD	V18.S4, V2.S4, V2.S4
+	VADD	V19.S4, V3.S4, V3.S4
+	// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4]
+	WORD	$0x4DFFE898
+	// restore R4
+	SUB	$32, R4
+
+	// load counter + nonce
+	// VLD1R (R7), [V28.S4]
+	WORD	$0x4D40C8FC
+	// VLD3R (R6), [V29.S4, V30.S4, V31.S4]
+	WORD	$0x4D40E8DD
+
+	VADD	V20.S4, V4.S4, V4.S4
+	VADD	V21.S4, V5.S4, V5.S4
+	VADD	V22.S4, V6.S4, V6.S4
+	VADD	V23.S4, V7.S4, V7.S4
+	VADD	V24.S4, V8.S4, V8.S4
+	VADD	V25.S4, V9.S4, V9.S4
+	VADD	V26.S4, V10.S4, V10.S4
+	VADD	V27.S4, V11.S4, V11.S4
+	VADD	V28.S4, V12.S4, V12.S4
+	VADD	V29.S4, V13.S4, V13.S4
+	VADD	V30.S4, V14.S4, V14.S4
+	VADD	V31.S4, V15.S4, V15.S4
+
+	VZIP1	V1.S4, V0.S4, V16.S4
+	VZIP2	V1.S4, V0.S4, V17.S4
+	VZIP1	V3.S4, V2.S4, V18.S4
+	VZIP2	V3.S4, V2.S4, V19.S4
+	VZIP1	V5.S4, V4.S4, V20.S4
+	VZIP2	V5.S4, V4.S4, V21.S4
+	VZIP1	V7.S4, V6.S4, V22.S4
+	VZIP2	V7.S4, V6.S4, V23.S4
+	VZIP1	V9.S4, V8.S4, V24.S4
+	VZIP2	V9.S4, V8.S4, V25.S4
+	VZIP1	V11.S4, V10.S4, V26.S4
+	VZIP2	V11.S4, V10.S4, V27.S4
+	VZIP1	V13.S4, V12.S4, V28.S4
+	VZIP2	V13.S4, V12.S4, V29.S4
+	VZIP1	V15.S4, V14.S4, V30.S4
+	VZIP2	V15.S4, V14.S4, V31.S4
+	VZIP1	V18.D2, V16.D2, V0.D2
+	VZIP2	V18.D2, V16.D2, V4.D2
+	VZIP1	V19.D2, V17.D2, V8.D2
+	VZIP2	V19.D2, V17.D2, V12.D2
+	VLD1.P	64(R2), [V16.B16, V17.B16, V18.B16, V19.B16]
+
+	VZIP1	V22.D2, V20.D2, V1.D2
+	VZIP2	V22.D2, V20.D2, V5.D2
+	VZIP1	V23.D2, V21.D2, V9.D2
+	VZIP2	V23.D2, V21.D2, V13.D2
+	VLD1.P	64(R2), [V20.B16, V21.B16, V22.B16, V23.B16]
+	VZIP1	V26.D2, V24.D2, V2.D2
+	VZIP2	V26.D2, V24.D2, V6.D2
+	VZIP1	V27.D2, V25.D2, V10.D2
+	VZIP2	V27.D2, V25.D2, V14.D2
+	VLD1.P	64(R2), [V24.B16, V25.B16, V26.B16, V27.B16]
+	VZIP1	V30.D2, V28.D2, V3.D2
+	VZIP2	V30.D2, V28.D2, V7.D2
+	VZIP1	V31.D2, V29.D2, V11.D2
+	VZIP2	V31.D2, V29.D2, V15.D2
+	VLD1.P	64(R2), [V28.B16, V29.B16, V30.B16, V31.B16]
+	VEOR	V0.B16, V16.B16, V16.B16
+	VEOR	V1.B16, V17.B16, V17.B16
+	VEOR	V2.B16, V18.B16, V18.B16
+	VEOR	V3.B16, V19.B16, V19.B16
+	VST1.P	[V16.B16, V17.B16, V18.B16, V19.B16], 64(R1)
+	VEOR	V4.B16, V20.B16, V20.B16
+	VEOR	V5.B16, V21.B16, V21.B16
+	VEOR	V6.B16, V22.B16, V22.B16
+	VEOR	V7.B16, V23.B16, V23.B16
+	VST1.P	[V20.B16, V21.B16, V22.B16, V23.B16], 64(R1)
+	VEOR	V8.B16, V24.B16, V24.B16
+	VEOR	V9.B16, V25.B16, V25.B16
+	VEOR	V10.B16, V26.B16, V26.B16
+	VEOR	V11.B16, V27.B16, V27.B16
+	VST1.P	[V24.B16, V25.B16, V26.B16, V27.B16], 64(R1)
+	VEOR	V12.B16, V28.B16, V28.B16
+	VEOR	V13.B16, V29.B16, V29.B16
+	VEOR	V14.B16, V30.B16, V30.B16
+	VEOR	V15.B16, V31.B16, V31.B16
+	VST1.P	[V28.B16, V29.B16, V30.B16, V31.B16], 64(R1)
+
+	ADD	$4, R20
+	MOVW	R20, (R7) // update counter
+
+	CMP	R2, R12
+	BGT	loop
+
+	RET
+
+
+DATA	·constants+0x00(SB)/4, $0x61707865
+DATA	·constants+0x04(SB)/4, $0x3320646e
+DATA	·constants+0x08(SB)/4, $0x79622d32
+DATA	·constants+0x0c(SB)/4, $0x6b206574
+GLOBL	·constants(SB), NOPTR|RODATA, $32
+
+DATA	·incRotMatrix+0x00(SB)/4, $0x00000000
+DATA	·incRotMatrix+0x04(SB)/4, $0x00000001
+DATA	·incRotMatrix+0x08(SB)/4, $0x00000002
+DATA	·incRotMatrix+0x0c(SB)/4, $0x00000003
+DATA	·incRotMatrix+0x10(SB)/4, $0x02010003
+DATA	·incRotMatrix+0x14(SB)/4, $0x06050407
+DATA	·incRotMatrix+0x18(SB)/4, $0x0A09080B
+DATA	·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F
+GLOBL	·incRotMatrix(SB), NOPTR|RODATA, $32
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_generic.go b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go
new file mode 100644
index 0000000..a2ecf5c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_generic.go
@@ -0,0 +1,398 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms
+// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01.
+package chacha20
+
+import (
+	"crypto/cipher"
+	"encoding/binary"
+	"errors"
+	"math/bits"
+
+	"golang.org/x/crypto/internal/subtle"
+)
+
+const (
+	// KeySize is the size of the key used by this cipher, in bytes.
+	KeySize = 32
+
+	// NonceSize is the size of the nonce used with the standard variant of this
+	// cipher, in bytes.
+	//
+	// Note that this is too short to be safely generated at random if the same
+	// key is reused more than 2³² times.
+	NonceSize = 12
+
+	// NonceSizeX is the size of the nonce used with the XChaCha20 variant of
+	// this cipher, in bytes.
+	NonceSizeX = 24
+)
+
+// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key
+// and nonce. A *Cipher implements the cipher.Stream interface.
+type Cipher struct {
+	// The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter
+	// (incremented after each block), and 3 of nonce.
+	key     [8]uint32
+	counter uint32
+	nonce   [3]uint32
+
+	// The last len bytes of buf are leftover key stream bytes from the previous
+	// XORKeyStream invocation. The size of buf depends on how many blocks are
+	// computed at a time by xorKeyStreamBlocks.
+	buf [bufSize]byte
+	len int
+
+	// overflow is set when the counter overflowed, no more blocks can be
+	// generated, and the next XORKeyStream call should panic.
+	overflow bool
+
+	// The counter-independent results of the first round are cached after they
+	// are computed the first time.
+	precompDone      bool
+	p1, p5, p9, p13  uint32
+	p2, p6, p10, p14 uint32
+	p3, p7, p11, p15 uint32
+}
+
+var _ cipher.Stream = (*Cipher)(nil)
+
+// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given
+// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided,
+// the XChaCha20 construction will be used. It returns an error if key or nonce
+// have any other length.
+//
+// Note that ChaCha20, like all stream ciphers, is not authenticated and allows
+// attackers to silently tamper with the plaintext. For this reason, it is more
+// appropriate as a building block than as a standalone encryption mechanism.
+// Instead, consider using package golang.org/x/crypto/chacha20poly1305.
+func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
+	// This function is split into a wrapper so that the Cipher allocation will
+	// be inlined, and depending on how the caller uses the return value, won't
+	// escape to the heap.
+	c := &Cipher{}
+	return newUnauthenticatedCipher(c, key, nonce)
+}
+
+func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
+	if len(key) != KeySize {
+		return nil, errors.New("chacha20: wrong key size")
+	}
+	if len(nonce) == NonceSizeX {
+		// XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a
+		// derived key, allowing it to operate on a nonce of 24 bytes. See
+		// draft-irtf-cfrg-xchacha-01, Section 2.3.
+		key, _ = HChaCha20(key, nonce[0:16])
+		cNonce := make([]byte, NonceSize)
+		copy(cNonce[4:12], nonce[16:24])
+		nonce = cNonce
+	} else if len(nonce) != NonceSize {
+		return nil, errors.New("chacha20: wrong nonce size")
+	}
+
+	key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint
+	c.key = [8]uint32{
+		binary.LittleEndian.Uint32(key[0:4]),
+		binary.LittleEndian.Uint32(key[4:8]),
+		binary.LittleEndian.Uint32(key[8:12]),
+		binary.LittleEndian.Uint32(key[12:16]),
+		binary.LittleEndian.Uint32(key[16:20]),
+		binary.LittleEndian.Uint32(key[20:24]),
+		binary.LittleEndian.Uint32(key[24:28]),
+		binary.LittleEndian.Uint32(key[28:32]),
+	}
+	c.nonce = [3]uint32{
+		binary.LittleEndian.Uint32(nonce[0:4]),
+		binary.LittleEndian.Uint32(nonce[4:8]),
+		binary.LittleEndian.Uint32(nonce[8:12]),
+	}
+	return c, nil
+}
+
+// The constant first 4 words of the ChaCha20 state.
+const (
+	j0 uint32 = 0x61707865 // expa
+	j1 uint32 = 0x3320646e // nd 3
+	j2 uint32 = 0x79622d32 // 2-by
+	j3 uint32 = 0x6b206574 // te k
+)
+
+const blockSize = 64
+
+// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words.
+// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16
+// words each round, in columnar or diagonal groups of 4 at a time.
+func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
+	a += b
+	d ^= a
+	d = bits.RotateLeft32(d, 16)
+	c += d
+	b ^= c
+	b = bits.RotateLeft32(b, 12)
+	a += b
+	d ^= a
+	d = bits.RotateLeft32(d, 8)
+	c += d
+	b ^= c
+	b = bits.RotateLeft32(b, 7)
+	return a, b, c, d
+}
+
+// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
+// behave as if (64 * counter) bytes had been encrypted so far.
+//
+// To prevent accidental counter reuse, SetCounter panics if counter is less
+// than the current value.
+//
+// Note that the execution time of XORKeyStream is not independent of the
+// counter value.
+func (s *Cipher) SetCounter(counter uint32) {
+	// Internally, s may buffer multiple blocks, which complicates this
+	// implementation slightly. When checking whether the counter has rolled
+	// back, we must use both s.counter and s.len to determine how many blocks
+	// we have already output.
+	outputCounter := s.counter - uint32(s.len)/blockSize
+	if s.overflow || counter < outputCounter {
+		panic("chacha20: SetCounter attempted to rollback counter")
+	}
+
+	// In the general case, we set the new counter value and reset s.len to 0,
+	// causing the next call to XORKeyStream to refill the buffer. However, if
+	// we're advancing within the existing buffer, we can save work by simply
+	// setting s.len.
+	if counter < s.counter {
+		s.len = int(s.counter-counter) * blockSize
+	} else {
+		s.counter = counter
+		s.len = 0
+	}
+}
+
+// XORKeyStream XORs each byte in the given slice with a byte from the
+// cipher's key stream. Dst and src must overlap entirely or not at all.
+//
+// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
+// to pass a dst bigger than src, and in that case, XORKeyStream will
+// only update dst[:len(src)] and will not touch the rest of dst.
+//
+// Multiple calls to XORKeyStream behave as if the concatenation of
+// the src buffers was passed in a single run. That is, Cipher
+// maintains state and does not reset at each XORKeyStream call.
+func (s *Cipher) XORKeyStream(dst, src []byte) {
+	if len(src) == 0 {
+		return
+	}
+	if len(dst) < len(src) {
+		panic("chacha20: output smaller than input")
+	}
+	dst = dst[:len(src)]
+	if subtle.InexactOverlap(dst, src) {
+		panic("chacha20: invalid buffer overlap")
+	}
+
+	// First, drain any remaining key stream from a previous XORKeyStream.
+	if s.len != 0 {
+		keyStream := s.buf[bufSize-s.len:]
+		if len(src) < len(keyStream) {
+			keyStream = keyStream[:len(src)]
+		}
+		_ = src[len(keyStream)-1] // bounds check elimination hint
+		for i, b := range keyStream {
+			dst[i] = src[i] ^ b
+		}
+		s.len -= len(keyStream)
+		dst, src = dst[len(keyStream):], src[len(keyStream):]
+	}
+	if len(src) == 0 {
+		return
+	}
+
+	// If we'd need to let the counter overflow and keep generating output,
+	// panic immediately. If instead we'd only reach the last block, remember
+	// not to generate any more output after the buffer is drained.
+	numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize
+	if s.overflow || uint64(s.counter)+numBlocks > 1<<32 {
+		panic("chacha20: counter overflow")
+	} else if uint64(s.counter)+numBlocks == 1<<32 {
+		s.overflow = true
+	}
+
+	// xorKeyStreamBlocks implementations expect input lengths that are a
+	// multiple of bufSize. Platform-specific ones process multiple blocks at a
+	// time, so have bufSizes that are a multiple of blockSize.
+
+	full := len(src) - len(src)%bufSize
+	if full > 0 {
+		s.xorKeyStreamBlocks(dst[:full], src[:full])
+	}
+	dst, src = dst[full:], src[full:]
+
+	// If using a multi-block xorKeyStreamBlocks would overflow, use the generic
+	// one that does one block at a time.
+	const blocksPerBuf = bufSize / blockSize
+	if uint64(s.counter)+blocksPerBuf > 1<<32 {
+		s.buf = [bufSize]byte{}
+		numBlocks := (len(src) + blockSize - 1) / blockSize
+		buf := s.buf[bufSize-numBlocks*blockSize:]
+		copy(buf, src)
+		s.xorKeyStreamBlocksGeneric(buf, buf)
+		s.len = len(buf) - copy(dst, buf)
+		return
+	}
+
+	// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
+	// keep the leftover keystream for the next XORKeyStream invocation.
+	if len(src) > 0 {
+		s.buf = [bufSize]byte{}
+		copy(s.buf[:], src)
+		s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
+		s.len = bufSize - copy(dst, s.buf[:])
+	}
+}
+
+func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
+	if len(dst) != len(src) || len(dst)%blockSize != 0 {
+		panic("chacha20: internal error: wrong dst and/or src length")
+	}
+
+	// To generate each block of key stream, the initial cipher state
+	// (represented below) is passed through 20 rounds of shuffling,
+	// alternatively applying quarterRounds by columns (like 1, 5, 9, 13)
+	// or by diagonals (like 1, 6, 11, 12).
+	//
+	//      0:cccccccc   1:cccccccc   2:cccccccc   3:cccccccc
+	//      4:kkkkkkkk   5:kkkkkkkk   6:kkkkkkkk   7:kkkkkkkk
+	//      8:kkkkkkkk   9:kkkkkkkk  10:kkkkkkkk  11:kkkkkkkk
+	//     12:bbbbbbbb  13:nnnnnnnn  14:nnnnnnnn  15:nnnnnnnn
+	//
+	//            c=constant k=key b=blockcount n=nonce
+	var (
+		c0, c1, c2, c3   = j0, j1, j2, j3
+		c4, c5, c6, c7   = s.key[0], s.key[1], s.key[2], s.key[3]
+		c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7]
+		_, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2]
+	)
+
+	// Three quarters of the first round don't depend on the counter, so we can
+	// calculate them here, and reuse them for multiple blocks in the loop, and
+	// for future XORKeyStream invocations.
+	if !s.precompDone {
+		s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13)
+		s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14)
+		s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15)
+		s.precompDone = true
+	}
+
+	// A condition of len(src) > 0 would be sufficient, but this also
+	// acts as a bounds check elimination hint.
+	for len(src) >= 64 && len(dst) >= 64 {
+		// The remainder of the first column round.
+		fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
+
+		// The second diagonal round.
+		x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15)
+		x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12)
+		x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13)
+		x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14)
+
+		// The remaining 18 rounds.
+		for i := 0; i < 9; i++ {
+			// Column round.
+			x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
+			x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
+			x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
+			x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
+
+			// Diagonal round.
+			x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
+			x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
+			x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
+			x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
+		}
+
+		// Add back the initial state to generate the key stream, then
+		// XOR the key stream with the source and write out the result.
+		addXor(dst[0:4], src[0:4], x0, c0)
+		addXor(dst[4:8], src[4:8], x1, c1)
+		addXor(dst[8:12], src[8:12], x2, c2)
+		addXor(dst[12:16], src[12:16], x3, c3)
+		addXor(dst[16:20], src[16:20], x4, c4)
+		addXor(dst[20:24], src[20:24], x5, c5)
+		addXor(dst[24:28], src[24:28], x6, c6)
+		addXor(dst[28:32], src[28:32], x7, c7)
+		addXor(dst[32:36], src[32:36], x8, c8)
+		addXor(dst[36:40], src[36:40], x9, c9)
+		addXor(dst[40:44], src[40:44], x10, c10)
+		addXor(dst[44:48], src[44:48], x11, c11)
+		addXor(dst[48:52], src[48:52], x12, s.counter)
+		addXor(dst[52:56], src[52:56], x13, c13)
+		addXor(dst[56:60], src[56:60], x14, c14)
+		addXor(dst[60:64], src[60:64], x15, c15)
+
+		s.counter += 1
+
+		src, dst = src[blockSize:], dst[blockSize:]
+	}
+}
+
+// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes
+// key and a 16 bytes nonce. It returns an error if key or nonce have any other
+// length. It is used as part of the XChaCha20 construction.
+func HChaCha20(key, nonce []byte) ([]byte, error) {
+	// This function is split into a wrapper so that the slice allocation will
+	// be inlined, and depending on how the caller uses the return value, won't
+	// escape to the heap.
+	out := make([]byte, 32)
+	return hChaCha20(out, key, nonce)
+}
+
+func hChaCha20(out, key, nonce []byte) ([]byte, error) {
+	if len(key) != KeySize {
+		return nil, errors.New("chacha20: wrong HChaCha20 key size")
+	}
+	if len(nonce) != 16 {
+		return nil, errors.New("chacha20: wrong HChaCha20 nonce size")
+	}
+
+	x0, x1, x2, x3 := j0, j1, j2, j3
+	x4 := binary.LittleEndian.Uint32(key[0:4])
+	x5 := binary.LittleEndian.Uint32(key[4:8])
+	x6 := binary.LittleEndian.Uint32(key[8:12])
+	x7 := binary.LittleEndian.Uint32(key[12:16])
+	x8 := binary.LittleEndian.Uint32(key[16:20])
+	x9 := binary.LittleEndian.Uint32(key[20:24])
+	x10 := binary.LittleEndian.Uint32(key[24:28])
+	x11 := binary.LittleEndian.Uint32(key[28:32])
+	x12 := binary.LittleEndian.Uint32(nonce[0:4])
+	x13 := binary.LittleEndian.Uint32(nonce[4:8])
+	x14 := binary.LittleEndian.Uint32(nonce[8:12])
+	x15 := binary.LittleEndian.Uint32(nonce[12:16])
+
+	for i := 0; i < 10; i++ {
+		// Diagonal round.
+		x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
+		x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
+		x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
+		x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
+
+		// Column round.
+		x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
+		x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
+		x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
+		x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
+	}
+
+	_ = out[31] // bounds check elimination hint
+	binary.LittleEndian.PutUint32(out[0:4], x0)
+	binary.LittleEndian.PutUint32(out[4:8], x1)
+	binary.LittleEndian.PutUint32(out[8:12], x2)
+	binary.LittleEndian.PutUint32(out[12:16], x3)
+	binary.LittleEndian.PutUint32(out[16:20], x12)
+	binary.LittleEndian.PutUint32(out[20:24], x13)
+	binary.LittleEndian.PutUint32(out[24:28], x14)
+	binary.LittleEndian.PutUint32(out[28:32], x15)
+	return out, nil
+}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
new file mode 100644
index 0000000..4635307
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
@@ -0,0 +1,13 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego
+
+package chacha20
+
+const bufSize = blockSize
+
+func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) {
+	s.xorKeyStreamBlocksGeneric(dst, src)
+}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
new file mode 100644
index 0000000..b799330
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
@@ -0,0 +1,16 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo,!purego
+
+package chacha20
+
+const bufSize = 256
+
+//go:noescape
+func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
+
+func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
+	chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
+}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
new file mode 100644
index 0000000..23c6021
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s
@@ -0,0 +1,449 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Based on CRYPTOGAMS code with the following comment:
+// # ====================================================================
+// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+// # project. The module is, however, dual licensed under OpenSSL and
+// # CRYPTOGAMS licenses depending on where you obtain it. For further
+// # details see http://www.openssl.org/~appro/cryptogams/.
+// # ====================================================================
+
+// Code for the perl script that generates the ppc64 assembler
+// can be found in the cryptogams repository at the link below. It is based on
+// the original from openssl.
+
+// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91
+
+// The differences in this and the original implementation are
+// due to the calling conventions and initialization of constants.
+
+// +build !gccgo,!purego
+
+#include "textflag.h"
+
+#define OUT  R3
+#define INP  R4
+#define LEN  R5
+#define KEY  R6
+#define CNT  R7
+#define TMP  R15
+
+#define CONSTBASE  R16
+#define BLOCKS R17
+
+DATA consts<>+0x00(SB)/8, $0x3320646e61707865
+DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
+DATA consts<>+0x10(SB)/8, $0x0000000000000001
+DATA consts<>+0x18(SB)/8, $0x0000000000000000
+DATA consts<>+0x20(SB)/8, $0x0000000000000004
+DATA consts<>+0x28(SB)/8, $0x0000000000000000
+DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d
+DATA consts<>+0x38(SB)/8, $0x0203000106070405
+DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c
+DATA consts<>+0x48(SB)/8, $0x0102030005060704
+DATA consts<>+0x50(SB)/8, $0x6170786561707865
+DATA consts<>+0x58(SB)/8, $0x6170786561707865
+DATA consts<>+0x60(SB)/8, $0x3320646e3320646e
+DATA consts<>+0x68(SB)/8, $0x3320646e3320646e
+DATA consts<>+0x70(SB)/8, $0x79622d3279622d32
+DATA consts<>+0x78(SB)/8, $0x79622d3279622d32
+DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
+DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
+DATA consts<>+0x90(SB)/8, $0x0000000100000000
+DATA consts<>+0x98(SB)/8, $0x0000000300000002
+GLOBL consts<>(SB), RODATA, $0xa0
+
+//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
+TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
+	MOVD out+0(FP), OUT
+	MOVD inp+8(FP), INP
+	MOVD len+16(FP), LEN
+	MOVD key+24(FP), KEY
+	MOVD counter+32(FP), CNT
+
+	// Addressing for constants
+	MOVD $consts<>+0x00(SB), CONSTBASE
+	MOVD $16, R8
+	MOVD $32, R9
+	MOVD $48, R10
+	MOVD $64, R11
+	SRD $6, LEN, BLOCKS
+	// V16
+	LXVW4X (CONSTBASE)(R0), VS48
+	ADD $80,CONSTBASE
+
+	// Load key into V17,V18
+	LXVW4X (KEY)(R0), VS49
+	LXVW4X (KEY)(R8), VS50
+
+	// Load CNT, NONCE into V19
+	LXVW4X (CNT)(R0), VS51
+
+	// Clear V27
+	VXOR V27, V27, V27
+
+	// V28
+	LXVW4X (CONSTBASE)(R11), VS60
+
+	// splat slot from V19 -> V26
+	VSPLTW $0, V19, V26
+
+	VSLDOI $4, V19, V27, V19
+	VSLDOI $12, V27, V19, V19
+
+	VADDUWM V26, V28, V26
+
+	MOVD $10, R14
+	MOVD R14, CTR
+
+loop_outer_vsx:
+	// V0, V1, V2, V3
+	LXVW4X (R0)(CONSTBASE), VS32
+	LXVW4X (R8)(CONSTBASE), VS33
+	LXVW4X (R9)(CONSTBASE), VS34
+	LXVW4X (R10)(CONSTBASE), VS35
+
+	// splat values from V17, V18 into V4-V11
+	VSPLTW $0, V17, V4
+	VSPLTW $1, V17, V5
+	VSPLTW $2, V17, V6
+	VSPLTW $3, V17, V7
+	VSPLTW $0, V18, V8
+	VSPLTW $1, V18, V9
+	VSPLTW $2, V18, V10
+	VSPLTW $3, V18, V11
+
+	// VOR
+	VOR V26, V26, V12
+
+	// splat values from V19 -> V13, V14, V15
+	VSPLTW $1, V19, V13
+	VSPLTW $2, V19, V14
+	VSPLTW $3, V19, V15
+
+	// splat   const values
+	VSPLTISW $-16, V27
+	VSPLTISW $12, V28
+	VSPLTISW $8, V29
+	VSPLTISW $7, V30
+
+loop_vsx:
+	VADDUWM V0, V4, V0
+	VADDUWM V1, V5, V1
+	VADDUWM V2, V6, V2
+	VADDUWM V3, V7, V3
+
+	VXOR V12, V0, V12
+	VXOR V13, V1, V13
+	VXOR V14, V2, V14
+	VXOR V15, V3, V15
+
+	VRLW V12, V27, V12
+	VRLW V13, V27, V13
+	VRLW V14, V27, V14
+	VRLW V15, V27, V15
+
+	VADDUWM V8, V12, V8
+	VADDUWM V9, V13, V9
+	VADDUWM V10, V14, V10
+	VADDUWM V11, V15, V11
+
+	VXOR V4, V8, V4
+	VXOR V5, V9, V5
+	VXOR V6, V10, V6
+	VXOR V7, V11, V7
+
+	VRLW V4, V28, V4
+	VRLW V5, V28, V5
+	VRLW V6, V28, V6
+	VRLW V7, V28, V7
+
+	VADDUWM V0, V4, V0
+	VADDUWM V1, V5, V1
+	VADDUWM V2, V6, V2
+	VADDUWM V3, V7, V3
+
+	VXOR V12, V0, V12
+	VXOR V13, V1, V13
+	VXOR V14, V2, V14
+	VXOR V15, V3, V15
+
+	VRLW V12, V29, V12
+	VRLW V13, V29, V13
+	VRLW V14, V29, V14
+	VRLW V15, V29, V15
+
+	VADDUWM V8, V12, V8
+	VADDUWM V9, V13, V9
+	VADDUWM V10, V14, V10
+	VADDUWM V11, V15, V11
+
+	VXOR V4, V8, V4
+	VXOR V5, V9, V5
+	VXOR V6, V10, V6
+	VXOR V7, V11, V7
+
+	VRLW V4, V30, V4
+	VRLW V5, V30, V5
+	VRLW V6, V30, V6
+	VRLW V7, V30, V7
+
+	VADDUWM V0, V5, V0
+	VADDUWM V1, V6, V1
+	VADDUWM V2, V7, V2
+	VADDUWM V3, V4, V3
+
+	VXOR V15, V0, V15
+	VXOR V12, V1, V12
+	VXOR V13, V2, V13
+	VXOR V14, V3, V14
+
+	VRLW V15, V27, V15
+	VRLW V12, V27, V12
+	VRLW V13, V27, V13
+	VRLW V14, V27, V14
+
+	VADDUWM V10, V15, V10
+	VADDUWM V11, V12, V11
+	VADDUWM V8, V13, V8
+	VADDUWM V9, V14, V9
+
+	VXOR V5, V10, V5
+	VXOR V6, V11, V6
+	VXOR V7, V8, V7
+	VXOR V4, V9, V4
+
+	VRLW V5, V28, V5
+	VRLW V6, V28, V6
+	VRLW V7, V28, V7
+	VRLW V4, V28, V4
+
+	VADDUWM V0, V5, V0
+	VADDUWM V1, V6, V1
+	VADDUWM V2, V7, V2
+	VADDUWM V3, V4, V3
+
+	VXOR V15, V0, V15
+	VXOR V12, V1, V12
+	VXOR V13, V2, V13
+	VXOR V14, V3, V14
+
+	VRLW V15, V29, V15
+	VRLW V12, V29, V12
+	VRLW V13, V29, V13
+	VRLW V14, V29, V14
+
+	VADDUWM V10, V15, V10
+	VADDUWM V11, V12, V11
+	VADDUWM V8, V13, V8
+	VADDUWM V9, V14, V9
+
+	VXOR V5, V10, V5
+	VXOR V6, V11, V6
+	VXOR V7, V8, V7
+	VXOR V4, V9, V4
+
+	VRLW V5, V30, V5
+	VRLW V6, V30, V6
+	VRLW V7, V30, V7
+	VRLW V4, V30, V4
+	BC   16, LT, loop_vsx
+
+	VADDUWM V12, V26, V12
+
+	WORD $0x13600F8C		// VMRGEW V0, V1, V27
+	WORD $0x13821F8C		// VMRGEW V2, V3, V28
+
+	WORD $0x10000E8C		// VMRGOW V0, V1, V0
+	WORD $0x10421E8C		// VMRGOW V2, V3, V2
+
+	WORD $0x13A42F8C		// VMRGEW V4, V5, V29
+	WORD $0x13C63F8C		// VMRGEW V6, V7, V30
+
+	XXPERMDI VS32, VS34, $0, VS33
+	XXPERMDI VS32, VS34, $3, VS35
+	XXPERMDI VS59, VS60, $0, VS32
+	XXPERMDI VS59, VS60, $3, VS34
+
+	WORD $0x10842E8C		// VMRGOW V4, V5, V4
+	WORD $0x10C63E8C		// VMRGOW V6, V7, V6
+
+	WORD $0x13684F8C		// VMRGEW V8, V9, V27
+	WORD $0x138A5F8C		// VMRGEW V10, V11, V28
+
+	XXPERMDI VS36, VS38, $0, VS37
+	XXPERMDI VS36, VS38, $3, VS39
+	XXPERMDI VS61, VS62, $0, VS36
+	XXPERMDI VS61, VS62, $3, VS38
+
+	WORD $0x11084E8C		// VMRGOW V8, V9, V8
+	WORD $0x114A5E8C		// VMRGOW V10, V11, V10
+
+	WORD $0x13AC6F8C		// VMRGEW V12, V13, V29
+	WORD $0x13CE7F8C		// VMRGEW V14, V15, V30
+
+	XXPERMDI VS40, VS42, $0, VS41
+	XXPERMDI VS40, VS42, $3, VS43
+	XXPERMDI VS59, VS60, $0, VS40
+	XXPERMDI VS59, VS60, $3, VS42
+
+	WORD $0x118C6E8C		// VMRGOW V12, V13, V12
+	WORD $0x11CE7E8C		// VMRGOW V14, V15, V14
+
+	VSPLTISW $4, V27
+	VADDUWM V26, V27, V26
+
+	XXPERMDI VS44, VS46, $0, VS45
+	XXPERMDI VS44, VS46, $3, VS47
+	XXPERMDI VS61, VS62, $0, VS44
+	XXPERMDI VS61, VS62, $3, VS46
+
+	VADDUWM V0, V16, V0
+	VADDUWM V4, V17, V4
+	VADDUWM V8, V18, V8
+	VADDUWM V12, V19, V12
+
+	CMPU LEN, $64
+	BLT tail_vsx
+
+	// Bottom of loop
+	LXVW4X (INP)(R0), VS59
+	LXVW4X (INP)(R8), VS60
+	LXVW4X (INP)(R9), VS61
+	LXVW4X (INP)(R10), VS62
+
+	VXOR V27, V0, V27
+	VXOR V28, V4, V28
+	VXOR V29, V8, V29
+	VXOR V30, V12, V30
+
+	STXVW4X VS59, (OUT)(R0)
+	STXVW4X VS60, (OUT)(R8)
+	ADD     $64, INP
+	STXVW4X VS61, (OUT)(R9)
+	ADD     $-64, LEN
+	STXVW4X VS62, (OUT)(R10)
+	ADD     $64, OUT
+	BEQ     done_vsx
+
+	VADDUWM V1, V16, V0
+	VADDUWM V5, V17, V4
+	VADDUWM V9, V18, V8
+	VADDUWM V13, V19, V12
+
+	CMPU  LEN, $64
+	BLT   tail_vsx
+
+	LXVW4X (INP)(R0), VS59
+	LXVW4X (INP)(R8), VS60
+	LXVW4X (INP)(R9), VS61
+	LXVW4X (INP)(R10), VS62
+	VXOR   V27, V0, V27
+
+	VXOR V28, V4, V28
+	VXOR V29, V8, V29
+	VXOR V30, V12, V30
+
+	STXVW4X VS59, (OUT)(R0)
+	STXVW4X VS60, (OUT)(R8)
+	ADD     $64, INP
+	STXVW4X VS61, (OUT)(R9)
+	ADD     $-64, LEN
+	STXVW4X VS62, (OUT)(V10)
+	ADD     $64, OUT
+	BEQ     done_vsx
+
+	VADDUWM V2, V16, V0
+	VADDUWM V6, V17, V4
+	VADDUWM V10, V18, V8
+	VADDUWM V14, V19, V12
+
+	CMPU LEN, $64
+	BLT  tail_vsx
+
+	LXVW4X (INP)(R0), VS59
+	LXVW4X (INP)(R8), VS60
+	LXVW4X (INP)(R9), VS61
+	LXVW4X (INP)(R10), VS62
+
+	VXOR V27, V0, V27
+	VXOR V28, V4, V28
+	VXOR V29, V8, V29
+	VXOR V30, V12, V30
+
+	STXVW4X VS59, (OUT)(R0)
+	STXVW4X VS60, (OUT)(R8)
+	ADD     $64, INP
+	STXVW4X VS61, (OUT)(R9)
+	ADD     $-64, LEN
+	STXVW4X VS62, (OUT)(R10)
+	ADD     $64, OUT
+	BEQ     done_vsx
+
+	VADDUWM V3, V16, V0
+	VADDUWM V7, V17, V4
+	VADDUWM V11, V18, V8
+	VADDUWM V15, V19, V12
+
+	CMPU  LEN, $64
+	BLT   tail_vsx
+
+	LXVW4X (INP)(R0), VS59
+	LXVW4X (INP)(R8), VS60
+	LXVW4X (INP)(R9), VS61
+	LXVW4X (INP)(R10), VS62
+
+	VXOR V27, V0, V27
+	VXOR V28, V4, V28
+	VXOR V29, V8, V29
+	VXOR V30, V12, V30
+
+	STXVW4X VS59, (OUT)(R0)
+	STXVW4X VS60, (OUT)(R8)
+	ADD     $64, INP
+	STXVW4X VS61, (OUT)(R9)
+	ADD     $-64, LEN
+	STXVW4X VS62, (OUT)(R10)
+	ADD     $64, OUT
+
+	MOVD $10, R14
+	MOVD R14, CTR
+	BNE  loop_outer_vsx
+
+done_vsx:
+	// Increment counter by number of 64 byte blocks
+	MOVD (CNT), R14
+	ADD  BLOCKS, R14
+	MOVD R14, (CNT)
+	RET
+
+tail_vsx:
+	ADD  $32, R1, R11
+	MOVD LEN, CTR
+
+	// Save values on stack to copy from
+	STXVW4X VS32, (R11)(R0)
+	STXVW4X VS36, (R11)(R8)
+	STXVW4X VS40, (R11)(R9)
+	STXVW4X VS44, (R11)(R10)
+	ADD $-1, R11, R12
+	ADD $-1, INP
+	ADD $-1, OUT
+
+looptail_vsx:
+	// Copying the result to OUT
+	// in bytes.
+	MOVBZU 1(R12), KEY
+	MOVBZU 1(INP), TMP
+	XOR    KEY, TMP, KEY
+	MOVBU  KEY, 1(OUT)
+	BC     16, LT, looptail_vsx
+
+	// Clear the stack values
+	STXVW4X VS48, (R11)(R0)
+	STXVW4X VS48, (R11)(R8)
+	STXVW4X VS48, (R11)(R9)
+	STXVW4X VS48, (R11)(R10)
+	BR      done_vsx
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
new file mode 100644
index 0000000..a9244bd
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
@@ -0,0 +1,26 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo,!purego
+
+package chacha20
+
+import "golang.org/x/sys/cpu"
+
+var haveAsm = cpu.S390X.HasVX
+
+const bufSize = 256
+
+// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
+// be called when the vector facility is available. Implementation in asm_s390x.s.
+//go:noescape
+func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
+
+func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
+	if cpu.S390X.HasVX {
+		xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
+	} else {
+		c.xorKeyStreamBlocksGeneric(dst, src)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s
new file mode 100644
index 0000000..89c658c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/chacha_s390x.s
@@ -0,0 +1,224 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo,!purego
+
+#include "go_asm.h"
+#include "textflag.h"
+
+// This is an implementation of the ChaCha20 encryption algorithm as
+// specified in RFC 7539. It uses vector instructions to compute
+// 4 keystream blocks in parallel (256 bytes) which are then XORed
+// with the bytes in the input slice.
+
+GLOBL ·constants<>(SB), RODATA|NOPTR, $32
+// BSWAP: swap bytes in each 4-byte element
+DATA ·constants<>+0x00(SB)/4, $0x03020100
+DATA ·constants<>+0x04(SB)/4, $0x07060504
+DATA ·constants<>+0x08(SB)/4, $0x0b0a0908
+DATA ·constants<>+0x0c(SB)/4, $0x0f0e0d0c
+// J0: [j0, j1, j2, j3]
+DATA ·constants<>+0x10(SB)/4, $0x61707865
+DATA ·constants<>+0x14(SB)/4, $0x3320646e
+DATA ·constants<>+0x18(SB)/4, $0x79622d32
+DATA ·constants<>+0x1c(SB)/4, $0x6b206574
+
+#define BSWAP V5
+#define J0    V6
+#define KEY0  V7
+#define KEY1  V8
+#define NONCE V9
+#define CTR   V10
+#define M0    V11
+#define M1    V12
+#define M2    V13
+#define M3    V14
+#define INC   V15
+#define X0    V16
+#define X1    V17
+#define X2    V18
+#define X3    V19
+#define X4    V20
+#define X5    V21
+#define X6    V22
+#define X7    V23
+#define X8    V24
+#define X9    V25
+#define X10   V26
+#define X11   V27
+#define X12   V28
+#define X13   V29
+#define X14   V30
+#define X15   V31
+
+#define NUM_ROUNDS 20
+
+#define ROUND4(a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3, d0, d1, d2, d3) \
+	VAF    a1, a0, a0  \
+	VAF    b1, b0, b0  \
+	VAF    c1, c0, c0  \
+	VAF    d1, d0, d0  \
+	VX     a0, a2, a2  \
+	VX     b0, b2, b2  \
+	VX     c0, c2, c2  \
+	VX     d0, d2, d2  \
+	VERLLF $16, a2, a2 \
+	VERLLF $16, b2, b2 \
+	VERLLF $16, c2, c2 \
+	VERLLF $16, d2, d2 \
+	VAF    a2, a3, a3  \
+	VAF    b2, b3, b3  \
+	VAF    c2, c3, c3  \
+	VAF    d2, d3, d3  \
+	VX     a3, a1, a1  \
+	VX     b3, b1, b1  \
+	VX     c3, c1, c1  \
+	VX     d3, d1, d1  \
+	VERLLF $12, a1, a1 \
+	VERLLF $12, b1, b1 \
+	VERLLF $12, c1, c1 \
+	VERLLF $12, d1, d1 \
+	VAF    a1, a0, a0  \
+	VAF    b1, b0, b0  \
+	VAF    c1, c0, c0  \
+	VAF    d1, d0, d0  \
+	VX     a0, a2, a2  \
+	VX     b0, b2, b2  \
+	VX     c0, c2, c2  \
+	VX     d0, d2, d2  \
+	VERLLF $8, a2, a2  \
+	VERLLF $8, b2, b2  \
+	VERLLF $8, c2, c2  \
+	VERLLF $8, d2, d2  \
+	VAF    a2, a3, a3  \
+	VAF    b2, b3, b3  \
+	VAF    c2, c3, c3  \
+	VAF    d2, d3, d3  \
+	VX     a3, a1, a1  \
+	VX     b3, b1, b1  \
+	VX     c3, c1, c1  \
+	VX     d3, d1, d1  \
+	VERLLF $7, a1, a1  \
+	VERLLF $7, b1, b1  \
+	VERLLF $7, c1, c1  \
+	VERLLF $7, d1, d1
+
+#define PERMUTE(mask, v0, v1, v2, v3) \
+	VPERM v0, v0, mask, v0 \
+	VPERM v1, v1, mask, v1 \
+	VPERM v2, v2, mask, v2 \
+	VPERM v3, v3, mask, v3
+
+#define ADDV(x, v0, v1, v2, v3) \
+	VAF x, v0, v0 \
+	VAF x, v1, v1 \
+	VAF x, v2, v2 \
+	VAF x, v3, v3
+
+#define XORV(off, dst, src, v0, v1, v2, v3) \
+	VLM  off(src), M0, M3          \
+	PERMUTE(BSWAP, v0, v1, v2, v3) \
+	VX   v0, M0, M0                \
+	VX   v1, M1, M1                \
+	VX   v2, M2, M2                \
+	VX   v3, M3, M3                \
+	VSTM M0, M3, off(dst)
+
+#define SHUFFLE(a, b, c, d, t, u, v, w) \
+	VMRHF a, c, t \ // t = {a[0], c[0], a[1], c[1]}
+	VMRHF b, d, u \ // u = {b[0], d[0], b[1], d[1]}
+	VMRLF a, c, v \ // v = {a[2], c[2], a[3], c[3]}
+	VMRLF b, d, w \ // w = {b[2], d[2], b[3], d[3]}
+	VMRHF t, u, a \ // a = {a[0], b[0], c[0], d[0]}
+	VMRLF t, u, b \ // b = {a[1], b[1], c[1], d[1]}
+	VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
+	VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
+
+// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
+TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
+	MOVD $·constants<>(SB), R1
+	MOVD dst+0(FP), R2         // R2=&dst[0]
+	LMG  src+24(FP), R3, R4    // R3=&src[0] R4=len(src)
+	MOVD key+48(FP), R5        // R5=key
+	MOVD nonce+56(FP), R6      // R6=nonce
+	MOVD counter+64(FP), R7    // R7=counter
+
+	// load BSWAP and J0
+	VLM (R1), BSWAP, J0
+
+	// setup
+	MOVD  $95, R0
+	VLM   (R5), KEY0, KEY1
+	VLL   R0, (R6), NONCE
+	VZERO M0
+	VLEIB $7, $32, M0
+	VSRLB M0, NONCE, NONCE
+
+	// initialize counter values
+	VLREPF (R7), CTR
+	VZERO  INC
+	VLEIF  $1, $1, INC
+	VLEIF  $2, $2, INC
+	VLEIF  $3, $3, INC
+	VAF    INC, CTR, CTR
+	VREPIF $4, INC
+
+chacha:
+	VREPF $0, J0, X0
+	VREPF $1, J0, X1
+	VREPF $2, J0, X2
+	VREPF $3, J0, X3
+	VREPF $0, KEY0, X4
+	VREPF $1, KEY0, X5
+	VREPF $2, KEY0, X6
+	VREPF $3, KEY0, X7
+	VREPF $0, KEY1, X8
+	VREPF $1, KEY1, X9
+	VREPF $2, KEY1, X10
+	VREPF $3, KEY1, X11
+	VLR   CTR, X12
+	VREPF $1, NONCE, X13
+	VREPF $2, NONCE, X14
+	VREPF $3, NONCE, X15
+
+	MOVD $(NUM_ROUNDS/2), R1
+
+loop:
+	ROUND4(X0, X4, X12,  X8, X1, X5, X13,  X9, X2, X6, X14, X10, X3, X7, X15, X11)
+	ROUND4(X0, X5, X15, X10, X1, X6, X12, X11, X2, X7, X13, X8,  X3, X4, X14, X9)
+
+	ADD $-1, R1
+	BNE loop
+
+	// decrement length
+	ADD $-256, R4
+
+	// rearrange vectors
+	SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
+	ADDV(J0, X0, X1, X2, X3)
+	SHUFFLE(X4, X5, X6, X7, M0, M1, M2, M3)
+	ADDV(KEY0, X4, X5, X6, X7)
+	SHUFFLE(X8, X9, X10, X11, M0, M1, M2, M3)
+	ADDV(KEY1, X8, X9, X10, X11)
+	VAF CTR, X12, X12
+	SHUFFLE(X12, X13, X14, X15, M0, M1, M2, M3)
+	ADDV(NONCE, X12, X13, X14, X15)
+
+	// increment counters
+	VAF INC, CTR, CTR
+
+	// xor keystream with plaintext
+	XORV(0*64, R2, R3, X0, X4,  X8, X12)
+	XORV(1*64, R2, R3, X1, X5,  X9, X13)
+	XORV(2*64, R2, R3, X2, X6, X10, X14)
+	XORV(3*64, R2, R3, X3, X7, X11, X15)
+
+	// increment pointers
+	MOVD $256(R2), R2
+	MOVD $256(R3), R3
+
+	CMPBNE  R4, $0, chacha
+
+	VSTEF $0, CTR, (R7)
+	RET
diff --git a/vendor/golang.org/x/crypto/chacha20/xor.go b/vendor/golang.org/x/crypto/chacha20/xor.go
new file mode 100644
index 0000000..c2d0485
--- /dev/null
+++ b/vendor/golang.org/x/crypto/chacha20/xor.go
@@ -0,0 +1,42 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found src the LICENSE file.
+
+package chacha20
+
+import "runtime"
+
+// Platforms that have fast unaligned 32-bit little endian accesses.
+const unaligned = runtime.GOARCH == "386" ||
+	runtime.GOARCH == "amd64" ||
+	runtime.GOARCH == "arm64" ||
+	runtime.GOARCH == "ppc64le" ||
+	runtime.GOARCH == "s390x"
+
+// addXor reads a little endian uint32 from src, XORs it with (a + b) and
+// places the result in little endian byte order in dst.
+func addXor(dst, src []byte, a, b uint32) {
+	_, _ = src[3], dst[3] // bounds check elimination hint
+	if unaligned {
+		// The compiler should optimize this code into
+		// 32-bit unaligned little endian loads and stores.
+		// TODO: delete once the compiler does a reliably
+		// good job with the generic code below.
+		// See issue #25111 for more details.
+		v := uint32(src[0])
+		v |= uint32(src[1]) << 8
+		v |= uint32(src[2]) << 16
+		v |= uint32(src[3]) << 24
+		v ^= a + b
+		dst[0] = byte(v)
+		dst[1] = byte(v >> 8)
+		dst[2] = byte(v >> 16)
+		dst[3] = byte(v >> 24)
+	} else {
+		a += b
+		dst[0] = src[0] ^ byte(a)
+		dst[1] = src[1] ^ byte(a>>8)
+		dst[2] = src[2] ^ byte(a>>16)
+		dst[3] = src[3] ^ byte(a>>24)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go
new file mode 100644
index 0000000..4b9a655
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go
@@ -0,0 +1,95 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package curve25519 provides an implementation of the X25519 function, which
+// performs scalar multiplication on the elliptic curve known as Curve25519.
+// See RFC 7748.
+package curve25519 // import "golang.org/x/crypto/curve25519"
+
+import (
+	"crypto/subtle"
+	"fmt"
+)
+
+// ScalarMult sets dst to the product scalar * point.
+//
+// Deprecated: when provided a low-order point, ScalarMult will set dst to all
+// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
+// will return an error.
+func ScalarMult(dst, scalar, point *[32]byte) {
+	scalarMult(dst, scalar, point)
+}
+
+// ScalarBaseMult sets dst to the product scalar * base where base is the
+// standard generator.
+//
+// It is recommended to use the X25519 function with Basepoint instead, as
+// copying into fixed size arrays can lead to unexpected bugs.
+func ScalarBaseMult(dst, scalar *[32]byte) {
+	ScalarMult(dst, scalar, &basePoint)
+}
+
+const (
+	// ScalarSize is the size of the scalar input to X25519.
+	ScalarSize = 32
+	// PointSize is the size of the point input to X25519.
+	PointSize = 32
+)
+
+// Basepoint is the canonical Curve25519 generator.
+var Basepoint []byte
+
+var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+func init() { Basepoint = basePoint[:] }
+
+func checkBasepoint() {
+	if subtle.ConstantTimeCompare(Basepoint, []byte{
+		0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}) != 1 {
+		panic("curve25519: global Basepoint value was modified")
+	}
+}
+
+// X25519 returns the result of the scalar multiplication (scalar * point),
+// according to RFC 7748, Section 5. scalar, point and the return value are
+// slices of 32 bytes.
+//
+// scalar can be generated at random, for example with crypto/rand. point should
+// be either Basepoint or the output of another X25519 call.
+//
+// If point is Basepoint (but not if it's a different slice with the same
+// contents) a precomputed implementation might be used for performance.
+func X25519(scalar, point []byte) ([]byte, error) {
+	// Outline the body of function, to let the allocation be inlined in the
+	// caller, and possibly avoid escaping to the heap.
+	var dst [32]byte
+	return x25519(&dst, scalar, point)
+}
+
+func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
+	var in [32]byte
+	if l := len(scalar); l != 32 {
+		return nil, fmt.Errorf("bad scalar length: %d, expected %d", l, 32)
+	}
+	if l := len(point); l != 32 {
+		return nil, fmt.Errorf("bad point length: %d, expected %d", l, 32)
+	}
+	copy(in[:], scalar)
+	if &point[0] == &Basepoint[0] {
+		checkBasepoint()
+		ScalarBaseMult(dst, &in)
+	} else {
+		var base, zero [32]byte
+		copy(base[:], point)
+		ScalarMult(dst, &in, &base)
+		if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
+			return nil, fmt.Errorf("bad input point: low order point")
+		}
+	}
+	return dst[:], nil
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go
new file mode 100644
index 0000000..5120b77
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.go
@@ -0,0 +1,240 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine,!purego
+
+package curve25519
+
+// These functions are implemented in the .s files. The names of the functions
+// in the rest of the file are also taken from the SUPERCOP sources to help
+// people following along.
+
+//go:noescape
+
+func cswap(inout *[5]uint64, v uint64)
+
+//go:noescape
+
+func ladderstep(inout *[5][5]uint64)
+
+//go:noescape
+
+func freeze(inout *[5]uint64)
+
+//go:noescape
+
+func mul(dest, a, b *[5]uint64)
+
+//go:noescape
+
+func square(out, in *[5]uint64)
+
+// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
+func mladder(xr, zr *[5]uint64, s *[32]byte) {
+	var work [5][5]uint64
+
+	work[0] = *xr
+	setint(&work[1], 1)
+	setint(&work[2], 0)
+	work[3] = *xr
+	setint(&work[4], 1)
+
+	j := uint(6)
+	var prevbit byte
+
+	for i := 31; i >= 0; i-- {
+		for j < 8 {
+			bit := ((*s)[i] >> j) & 1
+			swap := bit ^ prevbit
+			prevbit = bit
+			cswap(&work[1], uint64(swap))
+			ladderstep(&work)
+			j--
+		}
+		j = 7
+	}
+
+	*xr = work[1]
+	*zr = work[2]
+}
+
+func scalarMult(out, in, base *[32]byte) {
+	var e [32]byte
+	copy(e[:], (*in)[:])
+	e[0] &= 248
+	e[31] &= 127
+	e[31] |= 64
+
+	var t, z [5]uint64
+	unpack(&t, base)
+	mladder(&t, &z, &e)
+	invert(&z, &z)
+	mul(&t, &t, &z)
+	pack(out, &t)
+}
+
+func setint(r *[5]uint64, v uint64) {
+	r[0] = v
+	r[1] = 0
+	r[2] = 0
+	r[3] = 0
+	r[4] = 0
+}
+
+// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
+// order.
+func unpack(r *[5]uint64, x *[32]byte) {
+	r[0] = uint64(x[0]) |
+		uint64(x[1])<<8 |
+		uint64(x[2])<<16 |
+		uint64(x[3])<<24 |
+		uint64(x[4])<<32 |
+		uint64(x[5])<<40 |
+		uint64(x[6]&7)<<48
+
+	r[1] = uint64(x[6])>>3 |
+		uint64(x[7])<<5 |
+		uint64(x[8])<<13 |
+		uint64(x[9])<<21 |
+		uint64(x[10])<<29 |
+		uint64(x[11])<<37 |
+		uint64(x[12]&63)<<45
+
+	r[2] = uint64(x[12])>>6 |
+		uint64(x[13])<<2 |
+		uint64(x[14])<<10 |
+		uint64(x[15])<<18 |
+		uint64(x[16])<<26 |
+		uint64(x[17])<<34 |
+		uint64(x[18])<<42 |
+		uint64(x[19]&1)<<50
+
+	r[3] = uint64(x[19])>>1 |
+		uint64(x[20])<<7 |
+		uint64(x[21])<<15 |
+		uint64(x[22])<<23 |
+		uint64(x[23])<<31 |
+		uint64(x[24])<<39 |
+		uint64(x[25]&15)<<47
+
+	r[4] = uint64(x[25])>>4 |
+		uint64(x[26])<<4 |
+		uint64(x[27])<<12 |
+		uint64(x[28])<<20 |
+		uint64(x[29])<<28 |
+		uint64(x[30])<<36 |
+		uint64(x[31]&127)<<44
+}
+
+// pack sets out = x where out is the usual, little-endian form of the 5,
+// 51-bit limbs in x.
+func pack(out *[32]byte, x *[5]uint64) {
+	t := *x
+	freeze(&t)
+
+	out[0] = byte(t[0])
+	out[1] = byte(t[0] >> 8)
+	out[2] = byte(t[0] >> 16)
+	out[3] = byte(t[0] >> 24)
+	out[4] = byte(t[0] >> 32)
+	out[5] = byte(t[0] >> 40)
+	out[6] = byte(t[0] >> 48)
+
+	out[6] ^= byte(t[1]<<3) & 0xf8
+	out[7] = byte(t[1] >> 5)
+	out[8] = byte(t[1] >> 13)
+	out[9] = byte(t[1] >> 21)
+	out[10] = byte(t[1] >> 29)
+	out[11] = byte(t[1] >> 37)
+	out[12] = byte(t[1] >> 45)
+
+	out[12] ^= byte(t[2]<<6) & 0xc0
+	out[13] = byte(t[2] >> 2)
+	out[14] = byte(t[2] >> 10)
+	out[15] = byte(t[2] >> 18)
+	out[16] = byte(t[2] >> 26)
+	out[17] = byte(t[2] >> 34)
+	out[18] = byte(t[2] >> 42)
+	out[19] = byte(t[2] >> 50)
+
+	out[19] ^= byte(t[3]<<1) & 0xfe
+	out[20] = byte(t[3] >> 7)
+	out[21] = byte(t[3] >> 15)
+	out[22] = byte(t[3] >> 23)
+	out[23] = byte(t[3] >> 31)
+	out[24] = byte(t[3] >> 39)
+	out[25] = byte(t[3] >> 47)
+
+	out[25] ^= byte(t[4]<<4) & 0xf0
+	out[26] = byte(t[4] >> 4)
+	out[27] = byte(t[4] >> 12)
+	out[28] = byte(t[4] >> 20)
+	out[29] = byte(t[4] >> 28)
+	out[30] = byte(t[4] >> 36)
+	out[31] = byte(t[4] >> 44)
+}
+
+// invert calculates r = x^-1 mod p using Fermat's little theorem.
+func invert(r *[5]uint64, x *[5]uint64) {
+	var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
+
+	square(&z2, x)        /* 2 */
+	square(&t, &z2)       /* 4 */
+	square(&t, &t)        /* 8 */
+	mul(&z9, &t, x)       /* 9 */
+	mul(&z11, &z9, &z2)   /* 11 */
+	square(&t, &z11)      /* 22 */
+	mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
+
+	square(&t, &z2_5_0)      /* 2^6 - 2^1 */
+	for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
+		square(&t, &t)
+	}
+	mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
+
+	square(&t, &z2_10_0)      /* 2^11 - 2^1 */
+	for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
+		square(&t, &t)
+	}
+	mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
+
+	square(&t, &z2_20_0)      /* 2^21 - 2^1 */
+	for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
+		square(&t, &t)
+	}
+	mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
+
+	square(&t, &t)            /* 2^41 - 2^1 */
+	for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
+		square(&t, &t)
+	}
+	mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
+
+	square(&t, &z2_50_0)      /* 2^51 - 2^1 */
+	for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
+		square(&t, &t)
+	}
+	mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
+
+	square(&t, &z2_100_0)      /* 2^101 - 2^1 */
+	for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
+		square(&t, &t)
+	}
+	mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
+
+	square(&t, &t)            /* 2^201 - 2^1 */
+	for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
+		square(&t, &t)
+	}
+	mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
+
+	square(&t, &t) /* 2^251 - 2^1 */
+	square(&t, &t) /* 2^252 - 2^2 */
+	square(&t, &t) /* 2^253 - 2^3 */
+
+	square(&t, &t) /* 2^254 - 2^4 */
+
+	square(&t, &t)   /* 2^255 - 2^5 */
+	mul(r, &t, &z11) /* 2^255 - 21 */
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s
new file mode 100644
index 0000000..0250c88
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519_amd64.s
@@ -0,0 +1,1793 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+// +build amd64,!gccgo,!appengine,!purego
+
+#define REDMASK51     0x0007FFFFFFFFFFFF
+
+// These constants cannot be encoded in non-MOVQ immediates.
+// We access them directly from memory instead.
+
+DATA ·_121666_213(SB)/8, $996687872
+GLOBL ·_121666_213(SB), 8, $8
+
+DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
+GLOBL ·_2P0(SB), 8, $8
+
+DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
+GLOBL ·_2P1234(SB), 8, $8
+
+// func freeze(inout *[5]uint64)
+TEXT ·freeze(SB),7,$0-8
+	MOVQ inout+0(FP), DI
+
+	MOVQ 0(DI),SI
+	MOVQ 8(DI),DX
+	MOVQ 16(DI),CX
+	MOVQ 24(DI),R8
+	MOVQ 32(DI),R9
+	MOVQ $REDMASK51,AX
+	MOVQ AX,R10
+	SUBQ $18,R10
+	MOVQ $3,R11
+REDUCELOOP:
+	MOVQ SI,R12
+	SHRQ $51,R12
+	ANDQ AX,SI
+	ADDQ R12,DX
+	MOVQ DX,R12
+	SHRQ $51,R12
+	ANDQ AX,DX
+	ADDQ R12,CX
+	MOVQ CX,R12
+	SHRQ $51,R12
+	ANDQ AX,CX
+	ADDQ R12,R8
+	MOVQ R8,R12
+	SHRQ $51,R12
+	ANDQ AX,R8
+	ADDQ R12,R9
+	MOVQ R9,R12
+	SHRQ $51,R12
+	ANDQ AX,R9
+	IMUL3Q $19,R12,R12
+	ADDQ R12,SI
+	SUBQ $1,R11
+	JA REDUCELOOP
+	MOVQ $1,R12
+	CMPQ R10,SI
+	CMOVQLT R11,R12
+	CMPQ AX,DX
+	CMOVQNE R11,R12
+	CMPQ AX,CX
+	CMOVQNE R11,R12
+	CMPQ AX,R8
+	CMOVQNE R11,R12
+	CMPQ AX,R9
+	CMOVQNE R11,R12
+	NEGQ R12
+	ANDQ R12,AX
+	ANDQ R12,R10
+	SUBQ R10,SI
+	SUBQ AX,DX
+	SUBQ AX,CX
+	SUBQ AX,R8
+	SUBQ AX,R9
+	MOVQ SI,0(DI)
+	MOVQ DX,8(DI)
+	MOVQ CX,16(DI)
+	MOVQ R8,24(DI)
+	MOVQ R9,32(DI)
+	RET
+
+// func ladderstep(inout *[5][5]uint64)
+TEXT ·ladderstep(SB),0,$296-8
+	MOVQ inout+0(FP),DI
+
+	MOVQ 40(DI),SI
+	MOVQ 48(DI),DX
+	MOVQ 56(DI),CX
+	MOVQ 64(DI),R8
+	MOVQ 72(DI),R9
+	MOVQ SI,AX
+	MOVQ DX,R10
+	MOVQ CX,R11
+	MOVQ R8,R12
+	MOVQ R9,R13
+	ADDQ ·_2P0(SB),AX
+	ADDQ ·_2P1234(SB),R10
+	ADDQ ·_2P1234(SB),R11
+	ADDQ ·_2P1234(SB),R12
+	ADDQ ·_2P1234(SB),R13
+	ADDQ 80(DI),SI
+	ADDQ 88(DI),DX
+	ADDQ 96(DI),CX
+	ADDQ 104(DI),R8
+	ADDQ 112(DI),R9
+	SUBQ 80(DI),AX
+	SUBQ 88(DI),R10
+	SUBQ 96(DI),R11
+	SUBQ 104(DI),R12
+	SUBQ 112(DI),R13
+	MOVQ SI,0(SP)
+	MOVQ DX,8(SP)
+	MOVQ CX,16(SP)
+	MOVQ R8,24(SP)
+	MOVQ R9,32(SP)
+	MOVQ AX,40(SP)
+	MOVQ R10,48(SP)
+	MOVQ R11,56(SP)
+	MOVQ R12,64(SP)
+	MOVQ R13,72(SP)
+	MOVQ 40(SP),AX
+	MULQ 40(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 40(SP),AX
+	SHLQ $1,AX
+	MULQ 48(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 40(SP),AX
+	SHLQ $1,AX
+	MULQ 56(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 40(SP),AX
+	SHLQ $1,AX
+	MULQ 64(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 40(SP),AX
+	SHLQ $1,AX
+	MULQ 72(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 48(SP),AX
+	MULQ 48(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 48(SP),AX
+	SHLQ $1,AX
+	MULQ 56(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 48(SP),AX
+	SHLQ $1,AX
+	MULQ 64(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 48(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 72(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 56(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 56(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 64(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 56(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 72(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 64(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 64(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 64(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 72(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 72(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 72(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,80(SP)
+	MOVQ R8,88(SP)
+	MOVQ R9,96(SP)
+	MOVQ AX,104(SP)
+	MOVQ R10,112(SP)
+	MOVQ 0(SP),AX
+	MULQ 0(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 0(SP),AX
+	SHLQ $1,AX
+	MULQ 8(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 0(SP),AX
+	SHLQ $1,AX
+	MULQ 16(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 0(SP),AX
+	SHLQ $1,AX
+	MULQ 24(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 0(SP),AX
+	SHLQ $1,AX
+	MULQ 32(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 8(SP),AX
+	MULQ 8(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SP),AX
+	SHLQ $1,AX
+	MULQ 16(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 8(SP),AX
+	SHLQ $1,AX
+	MULQ 24(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 8(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 16(SP),AX
+	MULQ 16(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 16(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 24(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 16(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 24(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 24(SP),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 32(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,120(SP)
+	MOVQ R8,128(SP)
+	MOVQ R9,136(SP)
+	MOVQ AX,144(SP)
+	MOVQ R10,152(SP)
+	MOVQ SI,SI
+	MOVQ R8,DX
+	MOVQ R9,CX
+	MOVQ AX,R8
+	MOVQ R10,R9
+	ADDQ ·_2P0(SB),SI
+	ADDQ ·_2P1234(SB),DX
+	ADDQ ·_2P1234(SB),CX
+	ADDQ ·_2P1234(SB),R8
+	ADDQ ·_2P1234(SB),R9
+	SUBQ 80(SP),SI
+	SUBQ 88(SP),DX
+	SUBQ 96(SP),CX
+	SUBQ 104(SP),R8
+	SUBQ 112(SP),R9
+	MOVQ SI,160(SP)
+	MOVQ DX,168(SP)
+	MOVQ CX,176(SP)
+	MOVQ R8,184(SP)
+	MOVQ R9,192(SP)
+	MOVQ 120(DI),SI
+	MOVQ 128(DI),DX
+	MOVQ 136(DI),CX
+	MOVQ 144(DI),R8
+	MOVQ 152(DI),R9
+	MOVQ SI,AX
+	MOVQ DX,R10
+	MOVQ CX,R11
+	MOVQ R8,R12
+	MOVQ R9,R13
+	ADDQ ·_2P0(SB),AX
+	ADDQ ·_2P1234(SB),R10
+	ADDQ ·_2P1234(SB),R11
+	ADDQ ·_2P1234(SB),R12
+	ADDQ ·_2P1234(SB),R13
+	ADDQ 160(DI),SI
+	ADDQ 168(DI),DX
+	ADDQ 176(DI),CX
+	ADDQ 184(DI),R8
+	ADDQ 192(DI),R9
+	SUBQ 160(DI),AX
+	SUBQ 168(DI),R10
+	SUBQ 176(DI),R11
+	SUBQ 184(DI),R12
+	SUBQ 192(DI),R13
+	MOVQ SI,200(SP)
+	MOVQ DX,208(SP)
+	MOVQ CX,216(SP)
+	MOVQ R8,224(SP)
+	MOVQ R9,232(SP)
+	MOVQ AX,240(SP)
+	MOVQ R10,248(SP)
+	MOVQ R11,256(SP)
+	MOVQ R12,264(SP)
+	MOVQ R13,272(SP)
+	MOVQ 224(SP),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,280(SP)
+	MULQ 56(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 232(SP),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,288(SP)
+	MULQ 48(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 200(SP),AX
+	MULQ 40(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 200(SP),AX
+	MULQ 48(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 200(SP),AX
+	MULQ 56(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 200(SP),AX
+	MULQ 64(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 200(SP),AX
+	MULQ 72(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 208(SP),AX
+	MULQ 40(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 208(SP),AX
+	MULQ 48(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 208(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 208(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 208(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 72(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 216(SP),AX
+	MULQ 40(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 216(SP),AX
+	MULQ 48(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 216(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 216(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 64(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 216(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 72(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 224(SP),AX
+	MULQ 40(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 224(SP),AX
+	MULQ 48(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 280(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 280(SP),AX
+	MULQ 72(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 232(SP),AX
+	MULQ 40(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 288(SP),AX
+	MULQ 56(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 288(SP),AX
+	MULQ 64(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 288(SP),AX
+	MULQ 72(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,40(SP)
+	MOVQ R8,48(SP)
+	MOVQ R9,56(SP)
+	MOVQ AX,64(SP)
+	MOVQ R10,72(SP)
+	MOVQ 264(SP),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,200(SP)
+	MULQ 16(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 272(SP),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,208(SP)
+	MULQ 8(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 240(SP),AX
+	MULQ 0(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 240(SP),AX
+	MULQ 8(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 240(SP),AX
+	MULQ 16(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 240(SP),AX
+	MULQ 24(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 240(SP),AX
+	MULQ 32(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 248(SP),AX
+	MULQ 0(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 248(SP),AX
+	MULQ 8(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 248(SP),AX
+	MULQ 16(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 248(SP),AX
+	MULQ 24(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 248(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 256(SP),AX
+	MULQ 0(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 256(SP),AX
+	MULQ 8(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 256(SP),AX
+	MULQ 16(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 256(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 256(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 264(SP),AX
+	MULQ 0(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 264(SP),AX
+	MULQ 8(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 200(SP),AX
+	MULQ 24(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 200(SP),AX
+	MULQ 32(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 272(SP),AX
+	MULQ 0(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 208(SP),AX
+	MULQ 16(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 208(SP),AX
+	MULQ 24(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 208(SP),AX
+	MULQ 32(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,DX
+	MOVQ R8,CX
+	MOVQ R9,R11
+	MOVQ AX,R12
+	MOVQ R10,R13
+	ADDQ ·_2P0(SB),DX
+	ADDQ ·_2P1234(SB),CX
+	ADDQ ·_2P1234(SB),R11
+	ADDQ ·_2P1234(SB),R12
+	ADDQ ·_2P1234(SB),R13
+	ADDQ 40(SP),SI
+	ADDQ 48(SP),R8
+	ADDQ 56(SP),R9
+	ADDQ 64(SP),AX
+	ADDQ 72(SP),R10
+	SUBQ 40(SP),DX
+	SUBQ 48(SP),CX
+	SUBQ 56(SP),R11
+	SUBQ 64(SP),R12
+	SUBQ 72(SP),R13
+	MOVQ SI,120(DI)
+	MOVQ R8,128(DI)
+	MOVQ R9,136(DI)
+	MOVQ AX,144(DI)
+	MOVQ R10,152(DI)
+	MOVQ DX,160(DI)
+	MOVQ CX,168(DI)
+	MOVQ R11,176(DI)
+	MOVQ R12,184(DI)
+	MOVQ R13,192(DI)
+	MOVQ 120(DI),AX
+	MULQ 120(DI)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 128(DI)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 136(DI)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 144(DI)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 120(DI),AX
+	SHLQ $1,AX
+	MULQ 152(DI)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 128(DI),AX
+	MULQ 128(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 128(DI),AX
+	SHLQ $1,AX
+	MULQ 136(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 128(DI),AX
+	SHLQ $1,AX
+	MULQ 144(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 128(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 136(DI),AX
+	MULQ 136(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 136(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 144(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 136(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 144(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 144(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 144(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 152(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 152(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,120(DI)
+	MOVQ R8,128(DI)
+	MOVQ R9,136(DI)
+	MOVQ AX,144(DI)
+	MOVQ R10,152(DI)
+	MOVQ 160(DI),AX
+	MULQ 160(DI)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 168(DI)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 176(DI)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 184(DI)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 160(DI),AX
+	SHLQ $1,AX
+	MULQ 192(DI)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 168(DI),AX
+	MULQ 168(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 168(DI),AX
+	SHLQ $1,AX
+	MULQ 176(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 168(DI),AX
+	SHLQ $1,AX
+	MULQ 184(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 168(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),AX
+	MULQ 176(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 176(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 184(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 184(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(DI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 192(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 192(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	ANDQ DX,SI
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ADDQ R10,CX
+	ANDQ DX,R8
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ADDQ R12,CX
+	ANDQ DX,R9
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ADDQ R14,CX
+	ANDQ DX,AX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,160(DI)
+	MOVQ R8,168(DI)
+	MOVQ R9,176(DI)
+	MOVQ AX,184(DI)
+	MOVQ R10,192(DI)
+	MOVQ 184(DI),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,0(SP)
+	MULQ 16(DI)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 192(DI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,8(SP)
+	MULQ 8(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 160(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 160(DI),AX
+	MULQ 8(DI)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 160(DI),AX
+	MULQ 16(DI)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 160(DI),AX
+	MULQ 24(DI)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 160(DI),AX
+	MULQ 32(DI)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 168(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 168(DI),AX
+	MULQ 8(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 168(DI),AX
+	MULQ 16(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 168(DI),AX
+	MULQ 24(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 168(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 176(DI),AX
+	MULQ 8(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 176(DI),AX
+	MULQ 16(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 176(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(DI)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 176(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 184(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 184(DI),AX
+	MULQ 8(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 0(SP),AX
+	MULQ 24(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SP),AX
+	MULQ 32(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 192(DI),AX
+	MULQ 0(DI)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 8(SP),AX
+	MULQ 16(DI)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 8(SP),AX
+	MULQ 24(DI)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SP),AX
+	MULQ 32(DI)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,160(DI)
+	MOVQ R8,168(DI)
+	MOVQ R9,176(DI)
+	MOVQ AX,184(DI)
+	MOVQ R10,192(DI)
+	MOVQ 144(SP),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,0(SP)
+	MULQ 96(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 152(SP),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,8(SP)
+	MULQ 88(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 120(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 120(SP),AX
+	MULQ 88(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 120(SP),AX
+	MULQ 96(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 120(SP),AX
+	MULQ 104(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 120(SP),AX
+	MULQ 112(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 128(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 128(SP),AX
+	MULQ 88(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 128(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 128(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 128(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 112(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 136(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 136(SP),AX
+	MULQ 88(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 136(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 136(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 104(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 136(SP),DX
+	IMUL3Q $19,DX,AX
+	MULQ 112(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 144(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 144(SP),AX
+	MULQ 88(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 0(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SP),AX
+	MULQ 112(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 152(SP),AX
+	MULQ 80(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 8(SP),AX
+	MULQ 96(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 8(SP),AX
+	MULQ 104(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SP),AX
+	MULQ 112(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,40(DI)
+	MOVQ R8,48(DI)
+	MOVQ R9,56(DI)
+	MOVQ AX,64(DI)
+	MOVQ R10,72(DI)
+	MOVQ 160(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 168(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,CX
+	MOVQ DX,R8
+	MOVQ 176(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,R8
+	MOVQ DX,R9
+	MOVQ 184(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,R9
+	MOVQ DX,R10
+	MOVQ 192(SP),AX
+	MULQ ·_121666_213(SB)
+	SHRQ $13,AX
+	ADDQ AX,R10
+	IMUL3Q $19,DX,DX
+	ADDQ DX,SI
+	ADDQ 80(SP),SI
+	ADDQ 88(SP),CX
+	ADDQ 96(SP),R8
+	ADDQ 104(SP),R9
+	ADDQ 112(SP),R10
+	MOVQ SI,80(DI)
+	MOVQ CX,88(DI)
+	MOVQ R8,96(DI)
+	MOVQ R9,104(DI)
+	MOVQ R10,112(DI)
+	MOVQ 104(DI),SI
+	IMUL3Q $19,SI,AX
+	MOVQ AX,0(SP)
+	MULQ 176(SP)
+	MOVQ AX,SI
+	MOVQ DX,CX
+	MOVQ 112(DI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,8(SP)
+	MULQ 168(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 80(DI),AX
+	MULQ 160(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 80(DI),AX
+	MULQ 168(SP)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 80(DI),AX
+	MULQ 176(SP)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 80(DI),AX
+	MULQ 184(SP)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 80(DI),AX
+	MULQ 192(SP)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 88(DI),AX
+	MULQ 160(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 88(DI),AX
+	MULQ 168(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 88(DI),AX
+	MULQ 176(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 88(DI),AX
+	MULQ 184(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 88(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 192(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 96(DI),AX
+	MULQ 160(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 96(DI),AX
+	MULQ 168(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 96(DI),AX
+	MULQ 176(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 96(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 184(SP)
+	ADDQ AX,SI
+	ADCQ DX,CX
+	MOVQ 96(DI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 192(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 104(DI),AX
+	MULQ 160(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 104(DI),AX
+	MULQ 168(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 0(SP),AX
+	MULQ 184(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SP),AX
+	MULQ 192(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 112(DI),AX
+	MULQ 160(SP)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 8(SP),AX
+	MULQ 176(SP)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 8(SP),AX
+	MULQ 184(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SP),AX
+	MULQ 192(SP)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ $REDMASK51,DX
+	SHLQ $13,SI,CX
+	ANDQ DX,SI
+	SHLQ $13,R8,R9
+	ANDQ DX,R8
+	ADDQ CX,R8
+	SHLQ $13,R10,R11
+	ANDQ DX,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ DX,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ DX,R14
+	ADDQ R13,R14
+	IMUL3Q $19,R15,CX
+	ADDQ CX,SI
+	MOVQ SI,CX
+	SHRQ $51,CX
+	ADDQ R8,CX
+	MOVQ CX,R8
+	SHRQ $51,CX
+	ANDQ DX,SI
+	ADDQ R10,CX
+	MOVQ CX,R9
+	SHRQ $51,CX
+	ANDQ DX,R8
+	ADDQ R12,CX
+	MOVQ CX,AX
+	SHRQ $51,CX
+	ANDQ DX,R9
+	ADDQ R14,CX
+	MOVQ CX,R10
+	SHRQ $51,CX
+	ANDQ DX,AX
+	IMUL3Q $19,CX,CX
+	ADDQ CX,SI
+	ANDQ DX,R10
+	MOVQ SI,80(DI)
+	MOVQ R8,88(DI)
+	MOVQ R9,96(DI)
+	MOVQ AX,104(DI)
+	MOVQ R10,112(DI)
+	RET
+
+// func cswap(inout *[4][5]uint64, v uint64)
+TEXT ·cswap(SB),7,$0
+	MOVQ inout+0(FP),DI
+	MOVQ v+8(FP),SI
+
+	SUBQ $1, SI
+	NOTQ SI
+	MOVQ SI, X15
+	PSHUFD $0x44, X15, X15
+
+	MOVOU 0(DI), X0
+	MOVOU 16(DI), X2
+	MOVOU 32(DI), X4
+	MOVOU 48(DI), X6
+	MOVOU 64(DI), X8
+	MOVOU 80(DI), X1
+	MOVOU 96(DI), X3
+	MOVOU 112(DI), X5
+	MOVOU 128(DI), X7
+	MOVOU 144(DI), X9
+
+	MOVO X1, X10
+	MOVO X3, X11
+	MOVO X5, X12
+	MOVO X7, X13
+	MOVO X9, X14
+
+	PXOR X0, X10
+	PXOR X2, X11
+	PXOR X4, X12
+	PXOR X6, X13
+	PXOR X8, X14
+	PAND X15, X10
+	PAND X15, X11
+	PAND X15, X12
+	PAND X15, X13
+	PAND X15, X14
+	PXOR X10, X0
+	PXOR X10, X1
+	PXOR X11, X2
+	PXOR X11, X3
+	PXOR X12, X4
+	PXOR X12, X5
+	PXOR X13, X6
+	PXOR X13, X7
+	PXOR X14, X8
+	PXOR X14, X9
+
+	MOVOU X0, 0(DI)
+	MOVOU X2, 16(DI)
+	MOVOU X4, 32(DI)
+	MOVOU X6, 48(DI)
+	MOVOU X8, 64(DI)
+	MOVOU X1, 80(DI)
+	MOVOU X3, 96(DI)
+	MOVOU X5, 112(DI)
+	MOVOU X7, 128(DI)
+	MOVOU X9, 144(DI)
+	RET
+
+// func mul(dest, a, b *[5]uint64)
+TEXT ·mul(SB),0,$16-24
+	MOVQ dest+0(FP), DI
+	MOVQ a+8(FP), SI
+	MOVQ b+16(FP), DX
+
+	MOVQ DX,CX
+	MOVQ 24(SI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,0(SP)
+	MULQ 16(CX)
+	MOVQ AX,R8
+	MOVQ DX,R9
+	MOVQ 32(SI),DX
+	IMUL3Q $19,DX,AX
+	MOVQ AX,8(SP)
+	MULQ 8(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 0(SI),AX
+	MULQ 8(CX)
+	MOVQ AX,R10
+	MOVQ DX,R11
+	MOVQ 0(SI),AX
+	MULQ 16(CX)
+	MOVQ AX,R12
+	MOVQ DX,R13
+	MOVQ 0(SI),AX
+	MULQ 24(CX)
+	MOVQ AX,R14
+	MOVQ DX,R15
+	MOVQ 0(SI),AX
+	MULQ 32(CX)
+	MOVQ AX,BX
+	MOVQ DX,BP
+	MOVQ 8(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SI),AX
+	MULQ 8(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 8(SI),AX
+	MULQ 16(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 8(SI),AX
+	MULQ 24(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 8(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 16(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 16(SI),AX
+	MULQ 8(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 16(SI),AX
+	MULQ 16(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 16(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(CX)
+	ADDQ AX,R8
+	ADCQ DX,R9
+	MOVQ 16(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 24(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ 24(SI),AX
+	MULQ 8(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 0(SP),AX
+	MULQ 24(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 0(SP),AX
+	MULQ 32(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 32(SI),AX
+	MULQ 0(CX)
+	ADDQ AX,BX
+	ADCQ DX,BP
+	MOVQ 8(SP),AX
+	MULQ 16(CX)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 8(SP),AX
+	MULQ 24(CX)
+	ADDQ AX,R12
+	ADCQ DX,R13
+	MOVQ 8(SP),AX
+	MULQ 32(CX)
+	ADDQ AX,R14
+	ADCQ DX,R15
+	MOVQ $REDMASK51,SI
+	SHLQ $13,R8,R9
+	ANDQ SI,R8
+	SHLQ $13,R10,R11
+	ANDQ SI,R10
+	ADDQ R9,R10
+	SHLQ $13,R12,R13
+	ANDQ SI,R12
+	ADDQ R11,R12
+	SHLQ $13,R14,R15
+	ANDQ SI,R14
+	ADDQ R13,R14
+	SHLQ $13,BX,BP
+	ANDQ SI,BX
+	ADDQ R15,BX
+	IMUL3Q $19,BP,DX
+	ADDQ DX,R8
+	MOVQ R8,DX
+	SHRQ $51,DX
+	ADDQ R10,DX
+	MOVQ DX,CX
+	SHRQ $51,DX
+	ANDQ SI,R8
+	ADDQ R12,DX
+	MOVQ DX,R9
+	SHRQ $51,DX
+	ANDQ SI,CX
+	ADDQ R14,DX
+	MOVQ DX,AX
+	SHRQ $51,DX
+	ANDQ SI,R9
+	ADDQ BX,DX
+	MOVQ DX,R10
+	SHRQ $51,DX
+	ANDQ SI,AX
+	IMUL3Q $19,DX,DX
+	ADDQ DX,R8
+	ANDQ SI,R10
+	MOVQ R8,0(DI)
+	MOVQ CX,8(DI)
+	MOVQ R9,16(DI)
+	MOVQ AX,24(DI)
+	MOVQ R10,32(DI)
+	RET
+
+// func square(out, in *[5]uint64)
+TEXT ·square(SB),7,$0-16
+	MOVQ out+0(FP), DI
+	MOVQ in+8(FP), SI
+
+	MOVQ 0(SI),AX
+	MULQ 0(SI)
+	MOVQ AX,CX
+	MOVQ DX,R8
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 8(SI)
+	MOVQ AX,R9
+	MOVQ DX,R10
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 16(SI)
+	MOVQ AX,R11
+	MOVQ DX,R12
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 24(SI)
+	MOVQ AX,R13
+	MOVQ DX,R14
+	MOVQ 0(SI),AX
+	SHLQ $1,AX
+	MULQ 32(SI)
+	MOVQ AX,R15
+	MOVQ DX,BX
+	MOVQ 8(SI),AX
+	MULQ 8(SI)
+	ADDQ AX,R11
+	ADCQ DX,R12
+	MOVQ 8(SI),AX
+	SHLQ $1,AX
+	MULQ 16(SI)
+	ADDQ AX,R13
+	ADCQ DX,R14
+	MOVQ 8(SI),AX
+	SHLQ $1,AX
+	MULQ 24(SI)
+	ADDQ AX,R15
+	ADCQ DX,BX
+	MOVQ 8(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,CX
+	ADCQ DX,R8
+	MOVQ 16(SI),AX
+	MULQ 16(SI)
+	ADDQ AX,R15
+	ADCQ DX,BX
+	MOVQ 16(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 24(SI)
+	ADDQ AX,CX
+	ADCQ DX,R8
+	MOVQ 16(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,R9
+	ADCQ DX,R10
+	MOVQ 24(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 24(SI)
+	ADDQ AX,R9
+	ADCQ DX,R10
+	MOVQ 24(SI),DX
+	IMUL3Q $38,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,R11
+	ADCQ DX,R12
+	MOVQ 32(SI),DX
+	IMUL3Q $19,DX,AX
+	MULQ 32(SI)
+	ADDQ AX,R13
+	ADCQ DX,R14
+	MOVQ $REDMASK51,SI
+	SHLQ $13,CX,R8
+	ANDQ SI,CX
+	SHLQ $13,R9,R10
+	ANDQ SI,R9
+	ADDQ R8,R9
+	SHLQ $13,R11,R12
+	ANDQ SI,R11
+	ADDQ R10,R11
+	SHLQ $13,R13,R14
+	ANDQ SI,R13
+	ADDQ R12,R13
+	SHLQ $13,R15,BX
+	ANDQ SI,R15
+	ADDQ R14,R15
+	IMUL3Q $19,BX,DX
+	ADDQ DX,CX
+	MOVQ CX,DX
+	SHRQ $51,DX
+	ADDQ R9,DX
+	ANDQ SI,CX
+	MOVQ DX,R8
+	SHRQ $51,DX
+	ADDQ R11,DX
+	ANDQ SI,R8
+	MOVQ DX,R9
+	SHRQ $51,DX
+	ADDQ R13,DX
+	ANDQ SI,R9
+	MOVQ DX,AX
+	SHRQ $51,DX
+	ADDQ R15,DX
+	ANDQ SI,AX
+	MOVQ DX,R10
+	SHRQ $51,DX
+	IMUL3Q $19,DX,DX
+	ADDQ DX,CX
+	ANDQ SI,R10
+	MOVQ CX,0(DI)
+	MOVQ R8,8(DI)
+	MOVQ R9,16(DI)
+	MOVQ AX,24(DI)
+	MOVQ R10,32(DI)
+	RET
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go b/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go
new file mode 100644
index 0000000..c43b13f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519_generic.go
@@ -0,0 +1,828 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package curve25519
+
+import "encoding/binary"
+
+// This code is a port of the public domain, "ref10" implementation of
+// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
+
+// fieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type fieldElement [10]int32
+
+func feZero(fe *fieldElement) {
+	for i := range fe {
+		fe[i] = 0
+	}
+}
+
+func feOne(fe *fieldElement) {
+	feZero(fe)
+	fe[0] = 1
+}
+
+func feAdd(dst, a, b *fieldElement) {
+	for i := range dst {
+		dst[i] = a[i] + b[i]
+	}
+}
+
+func feSub(dst, a, b *fieldElement) {
+	for i := range dst {
+		dst[i] = a[i] - b[i]
+	}
+}
+
+func feCopy(dst, src *fieldElement) {
+	for i := range dst {
+		dst[i] = src[i]
+	}
+}
+
+// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func feCSwap(f, g *fieldElement, b int32) {
+	b = -b
+	for i := range f {
+		t := b & (f[i] ^ g[i])
+		f[i] ^= t
+		g[i] ^= t
+	}
+}
+
+// load3 reads a 24-bit, little-endian value from in.
+func load3(in []byte) int64 {
+	var r int64
+	r = int64(in[0])
+	r |= int64(in[1]) << 8
+	r |= int64(in[2]) << 16
+	return r
+}
+
+// load4 reads a 32-bit, little-endian value from in.
+func load4(in []byte) int64 {
+	return int64(binary.LittleEndian.Uint32(in))
+}
+
+func feFromBytes(dst *fieldElement, src *[32]byte) {
+	h0 := load4(src[:])
+	h1 := load3(src[4:]) << 6
+	h2 := load3(src[7:]) << 5
+	h3 := load3(src[10:]) << 3
+	h4 := load3(src[13:]) << 2
+	h5 := load4(src[16:])
+	h6 := load3(src[20:]) << 7
+	h7 := load3(src[23:]) << 5
+	h8 := load3(src[26:]) << 4
+	h9 := (load3(src[29:]) & 0x7fffff) << 2
+
+	var carry [10]int64
+	carry[9] = (h9 + 1<<24) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+	carry[1] = (h1 + 1<<24) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[3] = (h3 + 1<<24) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[5] = (h5 + 1<<24) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+	carry[7] = (h7 + 1<<24) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+
+	carry[0] = (h0 + 1<<25) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[2] = (h2 + 1<<25) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[4] = (h4 + 1<<25) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[6] = (h6 + 1<<25) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+	carry[8] = (h8 + 1<<25) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+
+	dst[0] = int32(h0)
+	dst[1] = int32(h1)
+	dst[2] = int32(h2)
+	dst[3] = int32(h3)
+	dst[4] = int32(h4)
+	dst[5] = int32(h5)
+	dst[6] = int32(h6)
+	dst[7] = int32(h7)
+	dst[8] = int32(h8)
+	dst[9] = int32(h9)
+}
+
+// feToBytes marshals h to s.
+// Preconditions:
+//   |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+//   Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+//   Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+//   Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+//   Then 0<y<1.
+//
+//   Write r=h-pq.
+//   Have 0<=r<=p-1=2^255-20.
+//   Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+//
+//   Write x=r+19(2^-255)r+y.
+//   Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+//
+//   Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+//   so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+func feToBytes(s *[32]byte, h *fieldElement) {
+	var carry [10]int32
+
+	q := (19*h[9] + (1 << 24)) >> 25
+	q = (h[0] + q) >> 26
+	q = (h[1] + q) >> 25
+	q = (h[2] + q) >> 26
+	q = (h[3] + q) >> 25
+	q = (h[4] + q) >> 26
+	q = (h[5] + q) >> 25
+	q = (h[6] + q) >> 26
+	q = (h[7] + q) >> 25
+	q = (h[8] + q) >> 26
+	q = (h[9] + q) >> 25
+
+	// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+	h[0] += 19 * q
+	// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+	carry[0] = h[0] >> 26
+	h[1] += carry[0]
+	h[0] -= carry[0] << 26
+	carry[1] = h[1] >> 25
+	h[2] += carry[1]
+	h[1] -= carry[1] << 25
+	carry[2] = h[2] >> 26
+	h[3] += carry[2]
+	h[2] -= carry[2] << 26
+	carry[3] = h[3] >> 25
+	h[4] += carry[3]
+	h[3] -= carry[3] << 25
+	carry[4] = h[4] >> 26
+	h[5] += carry[4]
+	h[4] -= carry[4] << 26
+	carry[5] = h[5] >> 25
+	h[6] += carry[5]
+	h[5] -= carry[5] << 25
+	carry[6] = h[6] >> 26
+	h[7] += carry[6]
+	h[6] -= carry[6] << 26
+	carry[7] = h[7] >> 25
+	h[8] += carry[7]
+	h[7] -= carry[7] << 25
+	carry[8] = h[8] >> 26
+	h[9] += carry[8]
+	h[8] -= carry[8] << 26
+	carry[9] = h[9] >> 25
+	h[9] -= carry[9] << 25
+	// h10 = carry9
+
+	// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+	// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+	// evidently 2^255 h10-2^255 q = 0.
+	// Goal: Output h[0]+...+2^230 h[9].
+
+	s[0] = byte(h[0] >> 0)
+	s[1] = byte(h[0] >> 8)
+	s[2] = byte(h[0] >> 16)
+	s[3] = byte((h[0] >> 24) | (h[1] << 2))
+	s[4] = byte(h[1] >> 6)
+	s[5] = byte(h[1] >> 14)
+	s[6] = byte((h[1] >> 22) | (h[2] << 3))
+	s[7] = byte(h[2] >> 5)
+	s[8] = byte(h[2] >> 13)
+	s[9] = byte((h[2] >> 21) | (h[3] << 5))
+	s[10] = byte(h[3] >> 3)
+	s[11] = byte(h[3] >> 11)
+	s[12] = byte((h[3] >> 19) | (h[4] << 6))
+	s[13] = byte(h[4] >> 2)
+	s[14] = byte(h[4] >> 10)
+	s[15] = byte(h[4] >> 18)
+	s[16] = byte(h[5] >> 0)
+	s[17] = byte(h[5] >> 8)
+	s[18] = byte(h[5] >> 16)
+	s[19] = byte((h[5] >> 24) | (h[6] << 1))
+	s[20] = byte(h[6] >> 7)
+	s[21] = byte(h[6] >> 15)
+	s[22] = byte((h[6] >> 23) | (h[7] << 3))
+	s[23] = byte(h[7] >> 5)
+	s[24] = byte(h[7] >> 13)
+	s[25] = byte((h[7] >> 21) | (h[8] << 4))
+	s[26] = byte(h[8] >> 4)
+	s[27] = byte(h[8] >> 12)
+	s[28] = byte((h[8] >> 20) | (h[9] << 6))
+	s[29] = byte(h[9] >> 2)
+	s[30] = byte(h[9] >> 10)
+	s[31] = byte(h[9] >> 18)
+}
+
+// feMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//    |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs can squeeze carries into int32.
+func feMul(h, f, g *fieldElement) {
+	f0 := f[0]
+	f1 := f[1]
+	f2 := f[2]
+	f3 := f[3]
+	f4 := f[4]
+	f5 := f[5]
+	f6 := f[6]
+	f7 := f[7]
+	f8 := f[8]
+	f9 := f[9]
+	g0 := g[0]
+	g1 := g[1]
+	g2 := g[2]
+	g3 := g[3]
+	g4 := g[4]
+	g5 := g[5]
+	g6 := g[6]
+	g7 := g[7]
+	g8 := g[8]
+	g9 := g[9]
+	g1_19 := 19 * g1 // 1.4*2^29
+	g2_19 := 19 * g2 // 1.4*2^30; still ok
+	g3_19 := 19 * g3
+	g4_19 := 19 * g4
+	g5_19 := 19 * g5
+	g6_19 := 19 * g6
+	g7_19 := 19 * g7
+	g8_19 := 19 * g8
+	g9_19 := 19 * g9
+	f1_2 := 2 * f1
+	f3_2 := 2 * f3
+	f5_2 := 2 * f5
+	f7_2 := 2 * f7
+	f9_2 := 2 * f9
+	f0g0 := int64(f0) * int64(g0)
+	f0g1 := int64(f0) * int64(g1)
+	f0g2 := int64(f0) * int64(g2)
+	f0g3 := int64(f0) * int64(g3)
+	f0g4 := int64(f0) * int64(g4)
+	f0g5 := int64(f0) * int64(g5)
+	f0g6 := int64(f0) * int64(g6)
+	f0g7 := int64(f0) * int64(g7)
+	f0g8 := int64(f0) * int64(g8)
+	f0g9 := int64(f0) * int64(g9)
+	f1g0 := int64(f1) * int64(g0)
+	f1g1_2 := int64(f1_2) * int64(g1)
+	f1g2 := int64(f1) * int64(g2)
+	f1g3_2 := int64(f1_2) * int64(g3)
+	f1g4 := int64(f1) * int64(g4)
+	f1g5_2 := int64(f1_2) * int64(g5)
+	f1g6 := int64(f1) * int64(g6)
+	f1g7_2 := int64(f1_2) * int64(g7)
+	f1g8 := int64(f1) * int64(g8)
+	f1g9_38 := int64(f1_2) * int64(g9_19)
+	f2g0 := int64(f2) * int64(g0)
+	f2g1 := int64(f2) * int64(g1)
+	f2g2 := int64(f2) * int64(g2)
+	f2g3 := int64(f2) * int64(g3)
+	f2g4 := int64(f2) * int64(g4)
+	f2g5 := int64(f2) * int64(g5)
+	f2g6 := int64(f2) * int64(g6)
+	f2g7 := int64(f2) * int64(g7)
+	f2g8_19 := int64(f2) * int64(g8_19)
+	f2g9_19 := int64(f2) * int64(g9_19)
+	f3g0 := int64(f3) * int64(g0)
+	f3g1_2 := int64(f3_2) * int64(g1)
+	f3g2 := int64(f3) * int64(g2)
+	f3g3_2 := int64(f3_2) * int64(g3)
+	f3g4 := int64(f3) * int64(g4)
+	f3g5_2 := int64(f3_2) * int64(g5)
+	f3g6 := int64(f3) * int64(g6)
+	f3g7_38 := int64(f3_2) * int64(g7_19)
+	f3g8_19 := int64(f3) * int64(g8_19)
+	f3g9_38 := int64(f3_2) * int64(g9_19)
+	f4g0 := int64(f4) * int64(g0)
+	f4g1 := int64(f4) * int64(g1)
+	f4g2 := int64(f4) * int64(g2)
+	f4g3 := int64(f4) * int64(g3)
+	f4g4 := int64(f4) * int64(g4)
+	f4g5 := int64(f4) * int64(g5)
+	f4g6_19 := int64(f4) * int64(g6_19)
+	f4g7_19 := int64(f4) * int64(g7_19)
+	f4g8_19 := int64(f4) * int64(g8_19)
+	f4g9_19 := int64(f4) * int64(g9_19)
+	f5g0 := int64(f5) * int64(g0)
+	f5g1_2 := int64(f5_2) * int64(g1)
+	f5g2 := int64(f5) * int64(g2)
+	f5g3_2 := int64(f5_2) * int64(g3)
+	f5g4 := int64(f5) * int64(g4)
+	f5g5_38 := int64(f5_2) * int64(g5_19)
+	f5g6_19 := int64(f5) * int64(g6_19)
+	f5g7_38 := int64(f5_2) * int64(g7_19)
+	f5g8_19 := int64(f5) * int64(g8_19)
+	f5g9_38 := int64(f5_2) * int64(g9_19)
+	f6g0 := int64(f6) * int64(g0)
+	f6g1 := int64(f6) * int64(g1)
+	f6g2 := int64(f6) * int64(g2)
+	f6g3 := int64(f6) * int64(g3)
+	f6g4_19 := int64(f6) * int64(g4_19)
+	f6g5_19 := int64(f6) * int64(g5_19)
+	f6g6_19 := int64(f6) * int64(g6_19)
+	f6g7_19 := int64(f6) * int64(g7_19)
+	f6g8_19 := int64(f6) * int64(g8_19)
+	f6g9_19 := int64(f6) * int64(g9_19)
+	f7g0 := int64(f7) * int64(g0)
+	f7g1_2 := int64(f7_2) * int64(g1)
+	f7g2 := int64(f7) * int64(g2)
+	f7g3_38 := int64(f7_2) * int64(g3_19)
+	f7g4_19 := int64(f7) * int64(g4_19)
+	f7g5_38 := int64(f7_2) * int64(g5_19)
+	f7g6_19 := int64(f7) * int64(g6_19)
+	f7g7_38 := int64(f7_2) * int64(g7_19)
+	f7g8_19 := int64(f7) * int64(g8_19)
+	f7g9_38 := int64(f7_2) * int64(g9_19)
+	f8g0 := int64(f8) * int64(g0)
+	f8g1 := int64(f8) * int64(g1)
+	f8g2_19 := int64(f8) * int64(g2_19)
+	f8g3_19 := int64(f8) * int64(g3_19)
+	f8g4_19 := int64(f8) * int64(g4_19)
+	f8g5_19 := int64(f8) * int64(g5_19)
+	f8g6_19 := int64(f8) * int64(g6_19)
+	f8g7_19 := int64(f8) * int64(g7_19)
+	f8g8_19 := int64(f8) * int64(g8_19)
+	f8g9_19 := int64(f8) * int64(g9_19)
+	f9g0 := int64(f9) * int64(g0)
+	f9g1_38 := int64(f9_2) * int64(g1_19)
+	f9g2_19 := int64(f9) * int64(g2_19)
+	f9g3_38 := int64(f9_2) * int64(g3_19)
+	f9g4_19 := int64(f9) * int64(g4_19)
+	f9g5_38 := int64(f9_2) * int64(g5_19)
+	f9g6_19 := int64(f9) * int64(g6_19)
+	f9g7_38 := int64(f9_2) * int64(g7_19)
+	f9g8_19 := int64(f9) * int64(g8_19)
+	f9g9_38 := int64(f9_2) * int64(g9_19)
+	h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
+	h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
+	h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
+	h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
+	h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
+	h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
+	h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
+	h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
+	h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
+	h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
+	var carry [10]int64
+
+	// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+	//   i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+	// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+	//   i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	// |h0| <= 2^25
+	// |h4| <= 2^25
+	// |h1| <= 1.51*2^58
+	// |h5| <= 1.51*2^58
+
+	carry[1] = (h1 + (1 << 24)) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[5] = (h5 + (1 << 24)) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+	// |h1| <= 2^24; from now on fits into int32
+	// |h5| <= 2^24; from now on fits into int32
+	// |h2| <= 1.21*2^59
+	// |h6| <= 1.21*2^59
+
+	carry[2] = (h2 + (1 << 25)) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[6] = (h6 + (1 << 25)) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+	// |h2| <= 2^25; from now on fits into int32 unchanged
+	// |h6| <= 2^25; from now on fits into int32 unchanged
+	// |h3| <= 1.51*2^58
+	// |h7| <= 1.51*2^58
+
+	carry[3] = (h3 + (1 << 24)) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[7] = (h7 + (1 << 24)) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+	// |h3| <= 2^24; from now on fits into int32 unchanged
+	// |h7| <= 2^24; from now on fits into int32 unchanged
+	// |h4| <= 1.52*2^33
+	// |h8| <= 1.52*2^33
+
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[8] = (h8 + (1 << 25)) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+	// |h4| <= 2^25; from now on fits into int32 unchanged
+	// |h8| <= 2^25; from now on fits into int32 unchanged
+	// |h5| <= 1.01*2^24
+	// |h9| <= 1.51*2^58
+
+	carry[9] = (h9 + (1 << 24)) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+	// |h9| <= 2^24; from now on fits into int32 unchanged
+	// |h0| <= 1.8*2^37
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	// |h0| <= 2^25; from now on fits into int32 unchanged
+	// |h1| <= 1.01*2^24
+
+	h[0] = int32(h0)
+	h[1] = int32(h1)
+	h[2] = int32(h2)
+	h[3] = int32(h3)
+	h[4] = int32(h4)
+	h[5] = int32(h5)
+	h[6] = int32(h6)
+	h[7] = int32(h7)
+	h[8] = int32(h8)
+	h[9] = int32(h9)
+}
+
+// feSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feSquare(h, f *fieldElement) {
+	f0 := f[0]
+	f1 := f[1]
+	f2 := f[2]
+	f3 := f[3]
+	f4 := f[4]
+	f5 := f[5]
+	f6 := f[6]
+	f7 := f[7]
+	f8 := f[8]
+	f9 := f[9]
+	f0_2 := 2 * f0
+	f1_2 := 2 * f1
+	f2_2 := 2 * f2
+	f3_2 := 2 * f3
+	f4_2 := 2 * f4
+	f5_2 := 2 * f5
+	f6_2 := 2 * f6
+	f7_2 := 2 * f7
+	f5_38 := 38 * f5 // 1.31*2^30
+	f6_19 := 19 * f6 // 1.31*2^30
+	f7_38 := 38 * f7 // 1.31*2^30
+	f8_19 := 19 * f8 // 1.31*2^30
+	f9_38 := 38 * f9 // 1.31*2^30
+	f0f0 := int64(f0) * int64(f0)
+	f0f1_2 := int64(f0_2) * int64(f1)
+	f0f2_2 := int64(f0_2) * int64(f2)
+	f0f3_2 := int64(f0_2) * int64(f3)
+	f0f4_2 := int64(f0_2) * int64(f4)
+	f0f5_2 := int64(f0_2) * int64(f5)
+	f0f6_2 := int64(f0_2) * int64(f6)
+	f0f7_2 := int64(f0_2) * int64(f7)
+	f0f8_2 := int64(f0_2) * int64(f8)
+	f0f9_2 := int64(f0_2) * int64(f9)
+	f1f1_2 := int64(f1_2) * int64(f1)
+	f1f2_2 := int64(f1_2) * int64(f2)
+	f1f3_4 := int64(f1_2) * int64(f3_2)
+	f1f4_2 := int64(f1_2) * int64(f4)
+	f1f5_4 := int64(f1_2) * int64(f5_2)
+	f1f6_2 := int64(f1_2) * int64(f6)
+	f1f7_4 := int64(f1_2) * int64(f7_2)
+	f1f8_2 := int64(f1_2) * int64(f8)
+	f1f9_76 := int64(f1_2) * int64(f9_38)
+	f2f2 := int64(f2) * int64(f2)
+	f2f3_2 := int64(f2_2) * int64(f3)
+	f2f4_2 := int64(f2_2) * int64(f4)
+	f2f5_2 := int64(f2_2) * int64(f5)
+	f2f6_2 := int64(f2_2) * int64(f6)
+	f2f7_2 := int64(f2_2) * int64(f7)
+	f2f8_38 := int64(f2_2) * int64(f8_19)
+	f2f9_38 := int64(f2) * int64(f9_38)
+	f3f3_2 := int64(f3_2) * int64(f3)
+	f3f4_2 := int64(f3_2) * int64(f4)
+	f3f5_4 := int64(f3_2) * int64(f5_2)
+	f3f6_2 := int64(f3_2) * int64(f6)
+	f3f7_76 := int64(f3_2) * int64(f7_38)
+	f3f8_38 := int64(f3_2) * int64(f8_19)
+	f3f9_76 := int64(f3_2) * int64(f9_38)
+	f4f4 := int64(f4) * int64(f4)
+	f4f5_2 := int64(f4_2) * int64(f5)
+	f4f6_38 := int64(f4_2) * int64(f6_19)
+	f4f7_38 := int64(f4) * int64(f7_38)
+	f4f8_38 := int64(f4_2) * int64(f8_19)
+	f4f9_38 := int64(f4) * int64(f9_38)
+	f5f5_38 := int64(f5) * int64(f5_38)
+	f5f6_38 := int64(f5_2) * int64(f6_19)
+	f5f7_76 := int64(f5_2) * int64(f7_38)
+	f5f8_38 := int64(f5_2) * int64(f8_19)
+	f5f9_76 := int64(f5_2) * int64(f9_38)
+	f6f6_19 := int64(f6) * int64(f6_19)
+	f6f7_38 := int64(f6) * int64(f7_38)
+	f6f8_38 := int64(f6_2) * int64(f8_19)
+	f6f9_38 := int64(f6) * int64(f9_38)
+	f7f7_38 := int64(f7) * int64(f7_38)
+	f7f8_38 := int64(f7_2) * int64(f8_19)
+	f7f9_76 := int64(f7_2) * int64(f9_38)
+	f8f8_19 := int64(f8) * int64(f8_19)
+	f8f9_38 := int64(f8) * int64(f9_38)
+	f9f9_38 := int64(f9) * int64(f9_38)
+	h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
+	h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
+	h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
+	h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
+	h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
+	h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
+	h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
+	h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
+	h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
+	h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
+	var carry [10]int64
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+
+	carry[1] = (h1 + (1 << 24)) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[5] = (h5 + (1 << 24)) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+
+	carry[2] = (h2 + (1 << 25)) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[6] = (h6 + (1 << 25)) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+
+	carry[3] = (h3 + (1 << 24)) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[7] = (h7 + (1 << 24)) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[8] = (h8 + (1 << 25)) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+
+	carry[9] = (h9 + (1 << 24)) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+
+	h[0] = int32(h0)
+	h[1] = int32(h1)
+	h[2] = int32(h2)
+	h[3] = int32(h3)
+	h[4] = int32(h4)
+	h[5] = int32(h5)
+	h[6] = int32(h6)
+	h[7] = int32(h7)
+	h[8] = int32(h8)
+	h[9] = int32(h9)
+}
+
+// feMul121666 calculates h = f * 121666. Can overlap h with f.
+//
+// Preconditions:
+//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feMul121666(h, f *fieldElement) {
+	h0 := int64(f[0]) * 121666
+	h1 := int64(f[1]) * 121666
+	h2 := int64(f[2]) * 121666
+	h3 := int64(f[3]) * 121666
+	h4 := int64(f[4]) * 121666
+	h5 := int64(f[5]) * 121666
+	h6 := int64(f[6]) * 121666
+	h7 := int64(f[7]) * 121666
+	h8 := int64(f[8]) * 121666
+	h9 := int64(f[9]) * 121666
+	var carry [10]int64
+
+	carry[9] = (h9 + (1 << 24)) >> 25
+	h0 += carry[9] * 19
+	h9 -= carry[9] << 25
+	carry[1] = (h1 + (1 << 24)) >> 25
+	h2 += carry[1]
+	h1 -= carry[1] << 25
+	carry[3] = (h3 + (1 << 24)) >> 25
+	h4 += carry[3]
+	h3 -= carry[3] << 25
+	carry[5] = (h5 + (1 << 24)) >> 25
+	h6 += carry[5]
+	h5 -= carry[5] << 25
+	carry[7] = (h7 + (1 << 24)) >> 25
+	h8 += carry[7]
+	h7 -= carry[7] << 25
+
+	carry[0] = (h0 + (1 << 25)) >> 26
+	h1 += carry[0]
+	h0 -= carry[0] << 26
+	carry[2] = (h2 + (1 << 25)) >> 26
+	h3 += carry[2]
+	h2 -= carry[2] << 26
+	carry[4] = (h4 + (1 << 25)) >> 26
+	h5 += carry[4]
+	h4 -= carry[4] << 26
+	carry[6] = (h6 + (1 << 25)) >> 26
+	h7 += carry[6]
+	h6 -= carry[6] << 26
+	carry[8] = (h8 + (1 << 25)) >> 26
+	h9 += carry[8]
+	h8 -= carry[8] << 26
+
+	h[0] = int32(h0)
+	h[1] = int32(h1)
+	h[2] = int32(h2)
+	h[3] = int32(h3)
+	h[4] = int32(h4)
+	h[5] = int32(h5)
+	h[6] = int32(h6)
+	h[7] = int32(h7)
+	h[8] = int32(h8)
+	h[9] = int32(h9)
+}
+
+// feInvert sets out = z^-1.
+func feInvert(out, z *fieldElement) {
+	var t0, t1, t2, t3 fieldElement
+	var i int
+
+	feSquare(&t0, z)
+	for i = 1; i < 1; i++ {
+		feSquare(&t0, &t0)
+	}
+	feSquare(&t1, &t0)
+	for i = 1; i < 2; i++ {
+		feSquare(&t1, &t1)
+	}
+	feMul(&t1, z, &t1)
+	feMul(&t0, &t0, &t1)
+	feSquare(&t2, &t0)
+	for i = 1; i < 1; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t1, &t2)
+	feSquare(&t2, &t1)
+	for i = 1; i < 5; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t2, &t1)
+	feSquare(&t2, &t1)
+	for i = 1; i < 10; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t2, &t2, &t1)
+	feSquare(&t3, &t2)
+	for i = 1; i < 20; i++ {
+		feSquare(&t3, &t3)
+	}
+	feMul(&t2, &t3, &t2)
+	feSquare(&t2, &t2)
+	for i = 1; i < 10; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t2, &t1)
+	feSquare(&t2, &t1)
+	for i = 1; i < 50; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t2, &t2, &t1)
+	feSquare(&t3, &t2)
+	for i = 1; i < 100; i++ {
+		feSquare(&t3, &t3)
+	}
+	feMul(&t2, &t3, &t2)
+	feSquare(&t2, &t2)
+	for i = 1; i < 50; i++ {
+		feSquare(&t2, &t2)
+	}
+	feMul(&t1, &t2, &t1)
+	feSquare(&t1, &t1)
+	for i = 1; i < 5; i++ {
+		feSquare(&t1, &t1)
+	}
+	feMul(out, &t1, &t0)
+}
+
+func scalarMultGeneric(out, in, base *[32]byte) {
+	var e [32]byte
+
+	copy(e[:], in[:])
+	e[0] &= 248
+	e[31] &= 127
+	e[31] |= 64
+
+	var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
+	feFromBytes(&x1, base)
+	feOne(&x2)
+	feCopy(&x3, &x1)
+	feOne(&z3)
+
+	swap := int32(0)
+	for pos := 254; pos >= 0; pos-- {
+		b := e[pos/8] >> uint(pos&7)
+		b &= 1
+		swap ^= int32(b)
+		feCSwap(&x2, &x3, swap)
+		feCSwap(&z2, &z3, swap)
+		swap = int32(b)
+
+		feSub(&tmp0, &x3, &z3)
+		feSub(&tmp1, &x2, &z2)
+		feAdd(&x2, &x2, &z2)
+		feAdd(&z2, &x3, &z3)
+		feMul(&z3, &tmp0, &x2)
+		feMul(&z2, &z2, &tmp1)
+		feSquare(&tmp0, &tmp1)
+		feSquare(&tmp1, &x2)
+		feAdd(&x3, &z3, &z2)
+		feSub(&z2, &z3, &z2)
+		feMul(&x2, &tmp1, &tmp0)
+		feSub(&tmp1, &tmp1, &tmp0)
+		feSquare(&z2, &z2)
+		feMul121666(&z3, &tmp1)
+		feSquare(&x3, &x3)
+		feAdd(&tmp0, &tmp0, &z3)
+		feMul(&z3, &x1, &z2)
+		feMul(&z2, &tmp1, &tmp0)
+	}
+
+	feCSwap(&x2, &x3, swap)
+	feCSwap(&z2, &z3, swap)
+
+	feInvert(&z2, &z2)
+	feMul(&x2, &x2, &z2)
+	feToBytes(out, &x2)
+}
diff --git a/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go
new file mode 100644
index 0000000..047d49a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519_noasm.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64 gccgo appengine purego
+
+package curve25519
+
+func scalarMult(out, in, base *[32]byte) {
+	scalarMultGeneric(out, in, base)
+}
diff --git a/vendor/golang.org/x/crypto/go.mod b/vendor/golang.org/x/crypto/go.mod
index 6a004e4..b8e0727 100644
--- a/vendor/golang.org/x/crypto/go.mod
+++ b/vendor/golang.org/x/crypto/go.mod
@@ -4,5 +4,6 @@
 
 require (
 	golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
-	golang.org/x/sys v0.0.0-20190412213103-97732733099d
+	golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
+	golang.org/x/term v0.0.0-20201117132131-f5c789dd3221
 )
diff --git a/vendor/golang.org/x/crypto/nacl/sign/sign.go b/vendor/golang.org/x/crypto/nacl/sign/sign.go
new file mode 100644
index 0000000..d076270
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/sign/sign.go
@@ -0,0 +1,90 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sign signs small messages using public-key cryptography.
+//
+// Sign uses Ed25519 to sign messages. The length of messages is not hidden.
+// Messages should be small because:
+// 1. The whole message needs to be held in memory to be processed.
+// 2. Using large messages pressures implementations on small machines to process
+// plaintext without verifying the signature. This is very dangerous, and this API
+// discourages it, but a protocol that uses excessive message sizes might present
+// some implementations with no other choice.
+// 3. Performance may be improved by working with messages that fit into data caches.
+// Thus large amounts of data should be chunked so that each message is small.
+//
+// This package is not interoperable with the current release of NaCl
+// (https://nacl.cr.yp.to/sign.html), which does not support Ed25519 yet. However,
+// it is compatible with the NaCl fork libsodium (https://www.libsodium.org), as well
+// as TweetNaCl (https://tweetnacl.cr.yp.to/).
+package sign
+
+import (
+	"io"
+
+	"golang.org/x/crypto/ed25519"
+	"golang.org/x/crypto/internal/subtle"
+)
+
+// Overhead is the number of bytes of overhead when signing a message.
+const Overhead = 64
+
+// GenerateKey generates a new public/private key pair suitable for use with
+// Sign and Open.
+func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err error) {
+	pub, priv, err := ed25519.GenerateKey(rand)
+	if err != nil {
+		return nil, nil, err
+	}
+	publicKey, privateKey = new([32]byte), new([64]byte)
+	copy((*publicKey)[:], pub)
+	copy((*privateKey)[:], priv)
+	return publicKey, privateKey, nil
+}
+
+// Sign appends a signed copy of message to out, which will be Overhead bytes
+// longer than the original and must not overlap it.
+func Sign(out, message []byte, privateKey *[64]byte) []byte {
+	sig := ed25519.Sign(ed25519.PrivateKey((*privateKey)[:]), message)
+	ret, out := sliceForAppend(out, Overhead+len(message))
+	if subtle.AnyOverlap(out, message) {
+		panic("nacl: invalid buffer overlap")
+	}
+	copy(out, sig)
+	copy(out[Overhead:], message)
+	return ret
+}
+
+// Open verifies a signed message produced by Sign and appends the message to
+// out, which must not overlap the signed message. The output will be Overhead
+// bytes smaller than the signed message.
+func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool) {
+	if len(signedMessage) < Overhead {
+		return nil, false
+	}
+	if !ed25519.Verify(ed25519.PublicKey((*publicKey)[:]), signedMessage[Overhead:], signedMessage[:Overhead]) {
+		return nil, false
+	}
+	ret, out := sliceForAppend(out, len(signedMessage)-Overhead)
+	if subtle.AnyOverlap(out, signedMessage) {
+		panic("nacl: invalid buffer overlap")
+	}
+	copy(out, signedMessage[Overhead:])
+	return ret, true
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+	if total := len(in) + n; cap(in) >= total {
+		head = in[:total]
+	} else {
+		head = make([]byte, total)
+		copy(head, in)
+	}
+	tail = head[len(in):]
+	return
+}
diff --git a/vendor/golang.org/x/crypto/ocsp/ocsp.go b/vendor/golang.org/x/crypto/ocsp/ocsp.go
index d297ac9..9d3fffa 100644
--- a/vendor/golang.org/x/crypto/ocsp/ocsp.go
+++ b/vendor/golang.org/x/crypto/ocsp/ocsp.go
@@ -445,10 +445,18 @@
 	}, nil
 }
 
-// ParseResponse parses an OCSP response in DER form. It only supports
-// responses for a single certificate. If the response contains a certificate
-// then the signature over the response is checked. If issuer is not nil then
-// it will be used to validate the signature or embedded certificate.
+// ParseResponse parses an OCSP response in DER form. The response must contain
+// only one certificate status. To parse the status of a specific certificate
+// from a response which may contain multiple statuses, use ParseResponseForCert
+// instead.
+//
+// If the response contains an embedded certificate, then that certificate will
+// be used to verify the response signature. If the response contains an
+// embedded certificate and issuer is not nil, then issuer will be used to verify
+// the signature on the embedded certificate.
+//
+// If the response does not contain an embedded certificate and issuer is not
+// nil, then issuer will be used to verify the response signature.
 //
 // Invalid responses and parse failures will result in a ParseError.
 // Error responses will result in a ResponseError.
@@ -456,14 +464,11 @@
 	return ParseResponseForCert(bytes, nil, issuer)
 }
 
-// ParseResponseForCert parses an OCSP response in DER form and searches for a
-// Response relating to cert. If such a Response is found and the OCSP response
-// contains a certificate then the signature over the response is checked. If
-// issuer is not nil then it will be used to validate the signature or embedded
-// certificate.
-//
-// Invalid responses and parse failures will result in a ParseError.
-// Error responses will result in a ResponseError.
+// ParseResponseForCert acts identically to ParseResponse, except it supports
+// parsing responses that contain multiple statuses. If the response contains
+// multiple statuses and cert is not nil, then ParseResponseForCert will return
+// the first status which contains a matching serial, otherwise it will return an
+// error. If cert is nil, then the first status in the response will be returned.
 func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) {
 	var resp responseASN1
 	rest, err := asn1.Unmarshal(bytes, &resp)
diff --git a/vendor/golang.org/x/crypto/pkcs12/pkcs12.go b/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
index 3e2ce69..3a89bdb 100644
--- a/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
+++ b/vendor/golang.org/x/crypto/pkcs12/pkcs12.go
@@ -30,6 +30,8 @@
 	oidFriendlyName     = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20})
 	oidLocalKeyID       = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21})
 	oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1})
+
+	errUnknownAttributeOID = errors.New("pkcs12: unknown attribute OID")
 )
 
 type pfxPdu struct {
@@ -104,6 +106,11 @@
 }
 
 // ToPEM converts all "safe bags" contained in pfxData to PEM blocks.
+// Unknown attributes are discarded.
+//
+// Note that although the returned PEM blocks for private keys have type
+// "PRIVATE KEY", the bytes are not encoded according to PKCS #8, but according
+// to PKCS #1 for RSA keys and SEC 1 for ECDSA keys.
 func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) {
 	encodedPassword, err := bmpString(password)
 	if err != nil {
@@ -135,6 +142,9 @@
 
 	for _, attribute := range bag.Attributes {
 		k, v, err := convertAttribute(&attribute)
+		if err == errUnknownAttributeOID {
+			continue
+		}
 		if err != nil {
 			return nil, err
 		}
@@ -188,7 +198,7 @@
 		key = "Microsoft CSP Name"
 		isString = true
 	default:
-		return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String())
+		return "", "", errUnknownAttributeOID
 	}
 
 	if isString {
diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go
new file mode 100644
index 0000000..1ab07d0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/buffer.go
@@ -0,0 +1,97 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"io"
+	"sync"
+)
+
+// buffer provides a linked list buffer for data exchange
+// between producer and consumer. Theoretically the buffer is
+// of unlimited capacity as it does no allocation of its own.
+type buffer struct {
+	// protects concurrent access to head, tail and closed
+	*sync.Cond
+
+	head *element // the buffer that will be read first
+	tail *element // the buffer that will be read last
+
+	closed bool
+}
+
+// An element represents a single link in a linked list.
+type element struct {
+	buf  []byte
+	next *element
+}
+
+// newBuffer returns an empty buffer that is not closed.
+func newBuffer() *buffer {
+	e := new(element)
+	b := &buffer{
+		Cond: newCond(),
+		head: e,
+		tail: e,
+	}
+	return b
+}
+
+// write makes buf available for Read to receive.
+// buf must not be modified after the call to write.
+func (b *buffer) write(buf []byte) {
+	b.Cond.L.Lock()
+	e := &element{buf: buf}
+	b.tail.next = e
+	b.tail = e
+	b.Cond.Signal()
+	b.Cond.L.Unlock()
+}
+
+// eof closes the buffer. Reads from the buffer once all
+// the data has been consumed will receive io.EOF.
+func (b *buffer) eof() {
+	b.Cond.L.Lock()
+	b.closed = true
+	b.Cond.Signal()
+	b.Cond.L.Unlock()
+}
+
+// Read reads data from the internal buffer in buf.  Reads will block
+// if no data is available, or until the buffer is closed.
+func (b *buffer) Read(buf []byte) (n int, err error) {
+	b.Cond.L.Lock()
+	defer b.Cond.L.Unlock()
+
+	for len(buf) > 0 {
+		// if there is data in b.head, copy it
+		if len(b.head.buf) > 0 {
+			r := copy(buf, b.head.buf)
+			buf, b.head.buf = buf[r:], b.head.buf[r:]
+			n += r
+			continue
+		}
+		// if there is a next buffer, make it the head
+		if len(b.head.buf) == 0 && b.head != b.tail {
+			b.head = b.head.next
+			continue
+		}
+
+		// if at least one byte has been copied, return
+		if n > 0 {
+			break
+		}
+
+		// if nothing was read, and there is nothing outstanding
+		// check to see if the buffer is closed.
+		if b.closed {
+			err = io.EOF
+			break
+		}
+		// out of buffers, wait for producer
+		b.Cond.Wait()
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
new file mode 100644
index 0000000..916c840
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -0,0 +1,546 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"sort"
+	"time"
+)
+
+// These constants from [PROTOCOL.certkeys] represent the algorithm names
+// for certificate types supported by this package.
+const (
+	CertAlgoRSAv01        = "ssh-rsa-cert-v01@openssh.com"
+	CertAlgoDSAv01        = "ssh-dss-cert-v01@openssh.com"
+	CertAlgoECDSA256v01   = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
+	CertAlgoECDSA384v01   = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
+	CertAlgoECDSA521v01   = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
+	CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
+	CertAlgoED25519v01    = "ssh-ed25519-cert-v01@openssh.com"
+	CertAlgoSKED25519v01  = "sk-ssh-ed25519-cert-v01@openssh.com"
+)
+
+// Certificate types distinguish between host and user
+// certificates. The values can be set in the CertType field of
+// Certificate.
+const (
+	UserCert = 1
+	HostCert = 2
+)
+
+// Signature represents a cryptographic signature.
+type Signature struct {
+	Format string
+	Blob   []byte
+	Rest   []byte `ssh:"rest"`
+}
+
+// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
+// a certificate does not expire.
+const CertTimeInfinity = 1<<64 - 1
+
+// An Certificate represents an OpenSSH certificate as defined in
+// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the
+// PublicKey interface, so it can be unmarshaled using
+// ParsePublicKey.
+type Certificate struct {
+	Nonce           []byte
+	Key             PublicKey
+	Serial          uint64
+	CertType        uint32
+	KeyId           string
+	ValidPrincipals []string
+	ValidAfter      uint64
+	ValidBefore     uint64
+	Permissions
+	Reserved     []byte
+	SignatureKey PublicKey
+	Signature    *Signature
+}
+
+// genericCertData holds the key-independent part of the certificate data.
+// Overall, certificates contain an nonce, public key fields and
+// key-independent fields.
+type genericCertData struct {
+	Serial          uint64
+	CertType        uint32
+	KeyId           string
+	ValidPrincipals []byte
+	ValidAfter      uint64
+	ValidBefore     uint64
+	CriticalOptions []byte
+	Extensions      []byte
+	Reserved        []byte
+	SignatureKey    []byte
+	Signature       []byte
+}
+
+func marshalStringList(namelist []string) []byte {
+	var to []byte
+	for _, name := range namelist {
+		s := struct{ N string }{name}
+		to = append(to, Marshal(&s)...)
+	}
+	return to
+}
+
+type optionsTuple struct {
+	Key   string
+	Value []byte
+}
+
+type optionsTupleValue struct {
+	Value string
+}
+
+// serialize a map of critical options or extensions
+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
+// we need two length prefixes for a non-empty string value
+func marshalTuples(tups map[string]string) []byte {
+	keys := make([]string, 0, len(tups))
+	for key := range tups {
+		keys = append(keys, key)
+	}
+	sort.Strings(keys)
+
+	var ret []byte
+	for _, key := range keys {
+		s := optionsTuple{Key: key}
+		if value := tups[key]; len(value) > 0 {
+			s.Value = Marshal(&optionsTupleValue{value})
+		}
+		ret = append(ret, Marshal(&s)...)
+	}
+	return ret
+}
+
+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
+// we need two length prefixes for a non-empty option value
+func parseTuples(in []byte) (map[string]string, error) {
+	tups := map[string]string{}
+	var lastKey string
+	var haveLastKey bool
+
+	for len(in) > 0 {
+		var key, val, extra []byte
+		var ok bool
+
+		if key, in, ok = parseString(in); !ok {
+			return nil, errShortRead
+		}
+		keyStr := string(key)
+		// according to [PROTOCOL.certkeys], the names must be in
+		// lexical order.
+		if haveLastKey && keyStr <= lastKey {
+			return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
+		}
+		lastKey, haveLastKey = keyStr, true
+		// the next field is a data field, which if non-empty has a string embedded
+		if val, in, ok = parseString(in); !ok {
+			return nil, errShortRead
+		}
+		if len(val) > 0 {
+			val, extra, ok = parseString(val)
+			if !ok {
+				return nil, errShortRead
+			}
+			if len(extra) > 0 {
+				return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
+			}
+			tups[keyStr] = string(val)
+		} else {
+			tups[keyStr] = ""
+		}
+	}
+	return tups, nil
+}
+
+func parseCert(in []byte, privAlgo string) (*Certificate, error) {
+	nonce, rest, ok := parseString(in)
+	if !ok {
+		return nil, errShortRead
+	}
+
+	key, rest, err := parsePubKey(rest, privAlgo)
+	if err != nil {
+		return nil, err
+	}
+
+	var g genericCertData
+	if err := Unmarshal(rest, &g); err != nil {
+		return nil, err
+	}
+
+	c := &Certificate{
+		Nonce:       nonce,
+		Key:         key,
+		Serial:      g.Serial,
+		CertType:    g.CertType,
+		KeyId:       g.KeyId,
+		ValidAfter:  g.ValidAfter,
+		ValidBefore: g.ValidBefore,
+	}
+
+	for principals := g.ValidPrincipals; len(principals) > 0; {
+		principal, rest, ok := parseString(principals)
+		if !ok {
+			return nil, errShortRead
+		}
+		c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
+		principals = rest
+	}
+
+	c.CriticalOptions, err = parseTuples(g.CriticalOptions)
+	if err != nil {
+		return nil, err
+	}
+	c.Extensions, err = parseTuples(g.Extensions)
+	if err != nil {
+		return nil, err
+	}
+	c.Reserved = g.Reserved
+	k, err := ParsePublicKey(g.SignatureKey)
+	if err != nil {
+		return nil, err
+	}
+
+	c.SignatureKey = k
+	c.Signature, rest, ok = parseSignatureBody(g.Signature)
+	if !ok || len(rest) > 0 {
+		return nil, errors.New("ssh: signature parse error")
+	}
+
+	return c, nil
+}
+
+type openSSHCertSigner struct {
+	pub    *Certificate
+	signer Signer
+}
+
+type algorithmOpenSSHCertSigner struct {
+	*openSSHCertSigner
+	algorithmSigner AlgorithmSigner
+}
+
+// NewCertSigner returns a Signer that signs with the given Certificate, whose
+// private key is held by signer. It returns an error if the public key in cert
+// doesn't match the key used by signer.
+func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
+	if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+		return nil, errors.New("ssh: signer and cert have different public key")
+	}
+
+	if algorithmSigner, ok := signer.(AlgorithmSigner); ok {
+		return &algorithmOpenSSHCertSigner{
+			&openSSHCertSigner{cert, signer}, algorithmSigner}, nil
+	} else {
+		return &openSSHCertSigner{cert, signer}, nil
+	}
+}
+
+func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	return s.signer.Sign(rand, data)
+}
+
+func (s *openSSHCertSigner) PublicKey() PublicKey {
+	return s.pub
+}
+
+func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
+	return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm)
+}
+
+const sourceAddressCriticalOption = "source-address"
+
+// CertChecker does the work of verifying a certificate. Its methods
+// can be plugged into ClientConfig.HostKeyCallback and
+// ServerConfig.PublicKeyCallback. For the CertChecker to work,
+// minimally, the IsAuthority callback should be set.
+type CertChecker struct {
+	// SupportedCriticalOptions lists the CriticalOptions that the
+	// server application layer understands. These are only used
+	// for user certificates.
+	SupportedCriticalOptions []string
+
+	// IsUserAuthority should return true if the key is recognized as an
+	// authority for the given user certificate. This allows for
+	// certificates to be signed by other certificates. This must be set
+	// if this CertChecker will be checking user certificates.
+	IsUserAuthority func(auth PublicKey) bool
+
+	// IsHostAuthority should report whether the key is recognized as
+	// an authority for this host. This allows for certificates to be
+	// signed by other keys, and for those other keys to only be valid
+	// signers for particular hostnames. This must be set if this
+	// CertChecker will be checking host certificates.
+	IsHostAuthority func(auth PublicKey, address string) bool
+
+	// Clock is used for verifying time stamps. If nil, time.Now
+	// is used.
+	Clock func() time.Time
+
+	// UserKeyFallback is called when CertChecker.Authenticate encounters a
+	// public key that is not a certificate. It must implement validation
+	// of user keys or else, if nil, all such keys are rejected.
+	UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+	// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
+	// public key that is not a certificate. It must implement host key
+	// validation or else, if nil, all such keys are rejected.
+	HostKeyFallback HostKeyCallback
+
+	// IsRevoked is called for each certificate so that revocation checking
+	// can be implemented. It should return true if the given certificate
+	// is revoked and false otherwise. If nil, no certificates are
+	// considered to have been revoked.
+	IsRevoked func(cert *Certificate) bool
+}
+
+// CheckHostKey checks a host key certificate. This method can be
+// plugged into ClientConfig.HostKeyCallback.
+func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
+	cert, ok := key.(*Certificate)
+	if !ok {
+		if c.HostKeyFallback != nil {
+			return c.HostKeyFallback(addr, remote, key)
+		}
+		return errors.New("ssh: non-certificate host key")
+	}
+	if cert.CertType != HostCert {
+		return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
+	}
+	if !c.IsHostAuthority(cert.SignatureKey, addr) {
+		return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
+	}
+
+	hostname, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return err
+	}
+
+	// Pass hostname only as principal for host certificates (consistent with OpenSSH)
+	return c.CheckCert(hostname, cert)
+}
+
+// Authenticate checks a user certificate. Authenticate can be used as
+// a value for ServerConfig.PublicKeyCallback.
+func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
+	cert, ok := pubKey.(*Certificate)
+	if !ok {
+		if c.UserKeyFallback != nil {
+			return c.UserKeyFallback(conn, pubKey)
+		}
+		return nil, errors.New("ssh: normal key pairs not accepted")
+	}
+
+	if cert.CertType != UserCert {
+		return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
+	}
+	if !c.IsUserAuthority(cert.SignatureKey) {
+		return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
+	}
+
+	if err := c.CheckCert(conn.User(), cert); err != nil {
+		return nil, err
+	}
+
+	return &cert.Permissions, nil
+}
+
+// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
+// the signature of the certificate.
+func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
+	if c.IsRevoked != nil && c.IsRevoked(cert) {
+		return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial)
+	}
+
+	for opt := range cert.CriticalOptions {
+		// sourceAddressCriticalOption will be enforced by
+		// serverAuthenticate
+		if opt == sourceAddressCriticalOption {
+			continue
+		}
+
+		found := false
+		for _, supp := range c.SupportedCriticalOptions {
+			if supp == opt {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
+		}
+	}
+
+	if len(cert.ValidPrincipals) > 0 {
+		// By default, certs are valid for all users/hosts.
+		found := false
+		for _, p := range cert.ValidPrincipals {
+			if p == principal {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
+		}
+	}
+
+	clock := c.Clock
+	if clock == nil {
+		clock = time.Now
+	}
+
+	unixNow := clock().Unix()
+	if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
+		return fmt.Errorf("ssh: cert is not yet valid")
+	}
+	if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
+		return fmt.Errorf("ssh: cert has expired")
+	}
+	if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
+		return fmt.Errorf("ssh: certificate signature does not verify")
+	}
+
+	return nil
+}
+
+// SignCert signs the certificate with an authority, setting the Nonce,
+// SignatureKey, and Signature fields.
+func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
+	c.Nonce = make([]byte, 32)
+	if _, err := io.ReadFull(rand, c.Nonce); err != nil {
+		return err
+	}
+	c.SignatureKey = authority.PublicKey()
+
+	sig, err := authority.Sign(rand, c.bytesForSigning())
+	if err != nil {
+		return err
+	}
+	c.Signature = sig
+	return nil
+}
+
+var certAlgoNames = map[string]string{
+	KeyAlgoRSA:        CertAlgoRSAv01,
+	KeyAlgoDSA:        CertAlgoDSAv01,
+	KeyAlgoECDSA256:   CertAlgoECDSA256v01,
+	KeyAlgoECDSA384:   CertAlgoECDSA384v01,
+	KeyAlgoECDSA521:   CertAlgoECDSA521v01,
+	KeyAlgoSKECDSA256: CertAlgoSKECDSA256v01,
+	KeyAlgoED25519:    CertAlgoED25519v01,
+	KeyAlgoSKED25519:  CertAlgoSKED25519v01,
+}
+
+// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
+// Panics if a non-certificate algorithm is passed.
+func certToPrivAlgo(algo string) string {
+	for privAlgo, pubAlgo := range certAlgoNames {
+		if pubAlgo == algo {
+			return privAlgo
+		}
+	}
+	panic("unknown cert algorithm")
+}
+
+func (cert *Certificate) bytesForSigning() []byte {
+	c2 := *cert
+	c2.Signature = nil
+	out := c2.Marshal()
+	// Drop trailing signature length.
+	return out[:len(out)-4]
+}
+
+// Marshal serializes c into OpenSSH's wire format. It is part of the
+// PublicKey interface.
+func (c *Certificate) Marshal() []byte {
+	generic := genericCertData{
+		Serial:          c.Serial,
+		CertType:        c.CertType,
+		KeyId:           c.KeyId,
+		ValidPrincipals: marshalStringList(c.ValidPrincipals),
+		ValidAfter:      uint64(c.ValidAfter),
+		ValidBefore:     uint64(c.ValidBefore),
+		CriticalOptions: marshalTuples(c.CriticalOptions),
+		Extensions:      marshalTuples(c.Extensions),
+		Reserved:        c.Reserved,
+		SignatureKey:    c.SignatureKey.Marshal(),
+	}
+	if c.Signature != nil {
+		generic.Signature = Marshal(c.Signature)
+	}
+	genericBytes := Marshal(&generic)
+	keyBytes := c.Key.Marshal()
+	_, keyBytes, _ = parseString(keyBytes)
+	prefix := Marshal(&struct {
+		Name  string
+		Nonce []byte
+		Key   []byte `ssh:"rest"`
+	}{c.Type(), c.Nonce, keyBytes})
+
+	result := make([]byte, 0, len(prefix)+len(genericBytes))
+	result = append(result, prefix...)
+	result = append(result, genericBytes...)
+	return result
+}
+
+// Type returns the key name. It is part of the PublicKey interface.
+func (c *Certificate) Type() string {
+	algo, ok := certAlgoNames[c.Key.Type()]
+	if !ok {
+		panic("unknown cert key type " + c.Key.Type())
+	}
+	return algo
+}
+
+// Verify verifies a signature against the certificate's public
+// key. It is part of the PublicKey interface.
+func (c *Certificate) Verify(data []byte, sig *Signature) error {
+	return c.Key.Verify(data, sig)
+}
+
+func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
+	format, in, ok := parseString(in)
+	if !ok {
+		return
+	}
+
+	out = &Signature{
+		Format: string(format),
+	}
+
+	if out.Blob, in, ok = parseString(in); !ok {
+		return
+	}
+
+	switch out.Format {
+	case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01:
+		out.Rest = in
+		return out, nil, ok
+	}
+
+	return out, in, ok
+}
+
+func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
+	sigBytes, rest, ok := parseString(in)
+	if !ok {
+		return
+	}
+
+	out, trailing, ok := parseSignatureBody(sigBytes)
+	if !ok || len(trailing) > 0 {
+		return nil, nil, false
+	}
+	return
+}
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
new file mode 100644
index 0000000..c0834c0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -0,0 +1,633 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"sync"
+)
+
+const (
+	minPacketLength = 9
+	// channelMaxPacket contains the maximum number of bytes that will be
+	// sent in a single packet. As per RFC 4253, section 6.1, 32k is also
+	// the minimum.
+	channelMaxPacket = 1 << 15
+	// We follow OpenSSH here.
+	channelWindowSize = 64 * channelMaxPacket
+)
+
+// NewChannel represents an incoming request to a channel. It must either be
+// accepted for use by calling Accept, or rejected by calling Reject.
+type NewChannel interface {
+	// Accept accepts the channel creation request. It returns the Channel
+	// and a Go channel containing SSH requests. The Go channel must be
+	// serviced otherwise the Channel will hang.
+	Accept() (Channel, <-chan *Request, error)
+
+	// Reject rejects the channel creation request. After calling
+	// this, no other methods on the Channel may be called.
+	Reject(reason RejectionReason, message string) error
+
+	// ChannelType returns the type of the channel, as supplied by the
+	// client.
+	ChannelType() string
+
+	// ExtraData returns the arbitrary payload for this channel, as supplied
+	// by the client. This data is specific to the channel type.
+	ExtraData() []byte
+}
+
+// A Channel is an ordered, reliable, flow-controlled, duplex stream
+// that is multiplexed over an SSH connection.
+type Channel interface {
+	// Read reads up to len(data) bytes from the channel.
+	Read(data []byte) (int, error)
+
+	// Write writes len(data) bytes to the channel.
+	Write(data []byte) (int, error)
+
+	// Close signals end of channel use. No data may be sent after this
+	// call.
+	Close() error
+
+	// CloseWrite signals the end of sending in-band
+	// data. Requests may still be sent, and the other side may
+	// still send data
+	CloseWrite() error
+
+	// SendRequest sends a channel request.  If wantReply is true,
+	// it will wait for a reply and return the result as a
+	// boolean, otherwise the return value will be false. Channel
+	// requests are out-of-band messages so they may be sent even
+	// if the data stream is closed or blocked by flow control.
+	// If the channel is closed before a reply is returned, io.EOF
+	// is returned.
+	SendRequest(name string, wantReply bool, payload []byte) (bool, error)
+
+	// Stderr returns an io.ReadWriter that writes to this channel
+	// with the extended data type set to stderr. Stderr may
+	// safely be read and written from a different goroutine than
+	// Read and Write respectively.
+	Stderr() io.ReadWriter
+}
+
+// Request is a request sent outside of the normal stream of
+// data. Requests can either be specific to an SSH channel, or they
+// can be global.
+type Request struct {
+	Type      string
+	WantReply bool
+	Payload   []byte
+
+	ch  *channel
+	mux *mux
+}
+
+// Reply sends a response to a request. It must be called for all requests
+// where WantReply is true and is a no-op otherwise. The payload argument is
+// ignored for replies to channel-specific requests.
+func (r *Request) Reply(ok bool, payload []byte) error {
+	if !r.WantReply {
+		return nil
+	}
+
+	if r.ch == nil {
+		return r.mux.ackRequest(ok, payload)
+	}
+
+	return r.ch.ackRequest(ok)
+}
+
+// RejectionReason is an enumeration used when rejecting channel creation
+// requests. See RFC 4254, section 5.1.
+type RejectionReason uint32
+
+const (
+	Prohibited RejectionReason = iota + 1
+	ConnectionFailed
+	UnknownChannelType
+	ResourceShortage
+)
+
+// String converts the rejection reason to human readable form.
+func (r RejectionReason) String() string {
+	switch r {
+	case Prohibited:
+		return "administratively prohibited"
+	case ConnectionFailed:
+		return "connect failed"
+	case UnknownChannelType:
+		return "unknown channel type"
+	case ResourceShortage:
+		return "resource shortage"
+	}
+	return fmt.Sprintf("unknown reason %d", int(r))
+}
+
+func min(a uint32, b int) uint32 {
+	if a < uint32(b) {
+		return a
+	}
+	return uint32(b)
+}
+
+type channelDirection uint8
+
+const (
+	channelInbound channelDirection = iota
+	channelOutbound
+)
+
+// channel is an implementation of the Channel interface that works
+// with the mux class.
+type channel struct {
+	// R/O after creation
+	chanType          string
+	extraData         []byte
+	localId, remoteId uint32
+
+	// maxIncomingPayload and maxRemotePayload are the maximum
+	// payload sizes of normal and extended data packets for
+	// receiving and sending, respectively. The wire packet will
+	// be 9 or 13 bytes larger (excluding encryption overhead).
+	maxIncomingPayload uint32
+	maxRemotePayload   uint32
+
+	mux *mux
+
+	// decided is set to true if an accept or reject message has been sent
+	// (for outbound channels) or received (for inbound channels).
+	decided bool
+
+	// direction contains either channelOutbound, for channels created
+	// locally, or channelInbound, for channels created by the peer.
+	direction channelDirection
+
+	// Pending internal channel messages.
+	msg chan interface{}
+
+	// Since requests have no ID, there can be only one request
+	// with WantReply=true outstanding.  This lock is held by a
+	// goroutine that has such an outgoing request pending.
+	sentRequestMu sync.Mutex
+
+	incomingRequests chan *Request
+
+	sentEOF bool
+
+	// thread-safe data
+	remoteWin  window
+	pending    *buffer
+	extPending *buffer
+
+	// windowMu protects myWindow, the flow-control window.
+	windowMu sync.Mutex
+	myWindow uint32
+
+	// writeMu serializes calls to mux.conn.writePacket() and
+	// protects sentClose and packetPool. This mutex must be
+	// different from windowMu, as writePacket can block if there
+	// is a key exchange pending.
+	writeMu   sync.Mutex
+	sentClose bool
+
+	// packetPool has a buffer for each extended channel ID to
+	// save allocations during writes.
+	packetPool map[uint32][]byte
+}
+
+// writePacket sends a packet. If the packet is a channel close, it updates
+// sentClose. This method takes the lock c.writeMu.
+func (ch *channel) writePacket(packet []byte) error {
+	ch.writeMu.Lock()
+	if ch.sentClose {
+		ch.writeMu.Unlock()
+		return io.EOF
+	}
+	ch.sentClose = (packet[0] == msgChannelClose)
+	err := ch.mux.conn.writePacket(packet)
+	ch.writeMu.Unlock()
+	return err
+}
+
+func (ch *channel) sendMessage(msg interface{}) error {
+	if debugMux {
+		log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg)
+	}
+
+	p := Marshal(msg)
+	binary.BigEndian.PutUint32(p[1:], ch.remoteId)
+	return ch.writePacket(p)
+}
+
+// WriteExtended writes data to a specific extended stream. These streams are
+// used, for example, for stderr.
+func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
+	if ch.sentEOF {
+		return 0, io.EOF
+	}
+	// 1 byte message type, 4 bytes remoteId, 4 bytes data length
+	opCode := byte(msgChannelData)
+	headerLength := uint32(9)
+	if extendedCode > 0 {
+		headerLength += 4
+		opCode = msgChannelExtendedData
+	}
+
+	ch.writeMu.Lock()
+	packet := ch.packetPool[extendedCode]
+	// We don't remove the buffer from packetPool, so
+	// WriteExtended calls from different goroutines will be
+	// flagged as errors by the race detector.
+	ch.writeMu.Unlock()
+
+	for len(data) > 0 {
+		space := min(ch.maxRemotePayload, len(data))
+		if space, err = ch.remoteWin.reserve(space); err != nil {
+			return n, err
+		}
+		if want := headerLength + space; uint32(cap(packet)) < want {
+			packet = make([]byte, want)
+		} else {
+			packet = packet[:want]
+		}
+
+		todo := data[:space]
+
+		packet[0] = opCode
+		binary.BigEndian.PutUint32(packet[1:], ch.remoteId)
+		if extendedCode > 0 {
+			binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))
+		}
+		binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))
+		copy(packet[headerLength:], todo)
+		if err = ch.writePacket(packet); err != nil {
+			return n, err
+		}
+
+		n += len(todo)
+		data = data[len(todo):]
+	}
+
+	ch.writeMu.Lock()
+	ch.packetPool[extendedCode] = packet
+	ch.writeMu.Unlock()
+
+	return n, err
+}
+
+func (ch *channel) handleData(packet []byte) error {
+	headerLen := 9
+	isExtendedData := packet[0] == msgChannelExtendedData
+	if isExtendedData {
+		headerLen = 13
+	}
+	if len(packet) < headerLen {
+		// malformed data packet
+		return parseError(packet[0])
+	}
+
+	var extended uint32
+	if isExtendedData {
+		extended = binary.BigEndian.Uint32(packet[5:])
+	}
+
+	length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen])
+	if length == 0 {
+		return nil
+	}
+	if length > ch.maxIncomingPayload {
+		// TODO(hanwen): should send Disconnect?
+		return errors.New("ssh: incoming packet exceeds maximum payload size")
+	}
+
+	data := packet[headerLen:]
+	if length != uint32(len(data)) {
+		return errors.New("ssh: wrong packet length")
+	}
+
+	ch.windowMu.Lock()
+	if ch.myWindow < length {
+		ch.windowMu.Unlock()
+		// TODO(hanwen): should send Disconnect with reason?
+		return errors.New("ssh: remote side wrote too much")
+	}
+	ch.myWindow -= length
+	ch.windowMu.Unlock()
+
+	if extended == 1 {
+		ch.extPending.write(data)
+	} else if extended > 0 {
+		// discard other extended data.
+	} else {
+		ch.pending.write(data)
+	}
+	return nil
+}
+
+func (c *channel) adjustWindow(n uint32) error {
+	c.windowMu.Lock()
+	// Since myWindow is managed on our side, and can never exceed
+	// the initial window setting, we don't worry about overflow.
+	c.myWindow += uint32(n)
+	c.windowMu.Unlock()
+	return c.sendMessage(windowAdjustMsg{
+		AdditionalBytes: uint32(n),
+	})
+}
+
+func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) {
+	switch extended {
+	case 1:
+		n, err = c.extPending.Read(data)
+	case 0:
+		n, err = c.pending.Read(data)
+	default:
+		return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended)
+	}
+
+	if n > 0 {
+		err = c.adjustWindow(uint32(n))
+		// sendWindowAdjust can return io.EOF if the remote
+		// peer has closed the connection, however we want to
+		// defer forwarding io.EOF to the caller of Read until
+		// the buffer has been drained.
+		if n > 0 && err == io.EOF {
+			err = nil
+		}
+	}
+
+	return n, err
+}
+
+func (c *channel) close() {
+	c.pending.eof()
+	c.extPending.eof()
+	close(c.msg)
+	close(c.incomingRequests)
+	c.writeMu.Lock()
+	// This is not necessary for a normal channel teardown, but if
+	// there was another error, it is.
+	c.sentClose = true
+	c.writeMu.Unlock()
+	// Unblock writers.
+	c.remoteWin.close()
+}
+
+// responseMessageReceived is called when a success or failure message is
+// received on a channel to check that such a message is reasonable for the
+// given channel.
+func (ch *channel) responseMessageReceived() error {
+	if ch.direction == channelInbound {
+		return errors.New("ssh: channel response message received on inbound channel")
+	}
+	if ch.decided {
+		return errors.New("ssh: duplicate response received for channel")
+	}
+	ch.decided = true
+	return nil
+}
+
+func (ch *channel) handlePacket(packet []byte) error {
+	switch packet[0] {
+	case msgChannelData, msgChannelExtendedData:
+		return ch.handleData(packet)
+	case msgChannelClose:
+		ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId})
+		ch.mux.chanList.remove(ch.localId)
+		ch.close()
+		return nil
+	case msgChannelEOF:
+		// RFC 4254 is mute on how EOF affects dataExt messages but
+		// it is logical to signal EOF at the same time.
+		ch.extPending.eof()
+		ch.pending.eof()
+		return nil
+	}
+
+	decoded, err := decode(packet)
+	if err != nil {
+		return err
+	}
+
+	switch msg := decoded.(type) {
+	case *channelOpenFailureMsg:
+		if err := ch.responseMessageReceived(); err != nil {
+			return err
+		}
+		ch.mux.chanList.remove(msg.PeersID)
+		ch.msg <- msg
+	case *channelOpenConfirmMsg:
+		if err := ch.responseMessageReceived(); err != nil {
+			return err
+		}
+		if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+			return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)
+		}
+		ch.remoteId = msg.MyID
+		ch.maxRemotePayload = msg.MaxPacketSize
+		ch.remoteWin.add(msg.MyWindow)
+		ch.msg <- msg
+	case *windowAdjustMsg:
+		if !ch.remoteWin.add(msg.AdditionalBytes) {
+			return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)
+		}
+	case *channelRequestMsg:
+		req := Request{
+			Type:      msg.Request,
+			WantReply: msg.WantReply,
+			Payload:   msg.RequestSpecificData,
+			ch:        ch,
+		}
+
+		ch.incomingRequests <- &req
+	default:
+		ch.msg <- msg
+	}
+	return nil
+}
+
+func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
+	ch := &channel{
+		remoteWin:        window{Cond: newCond()},
+		myWindow:         channelWindowSize,
+		pending:          newBuffer(),
+		extPending:       newBuffer(),
+		direction:        direction,
+		incomingRequests: make(chan *Request, chanSize),
+		msg:              make(chan interface{}, chanSize),
+		chanType:         chanType,
+		extraData:        extraData,
+		mux:              m,
+		packetPool:       make(map[uint32][]byte),
+	}
+	ch.localId = m.chanList.add(ch)
+	return ch
+}
+
+var errUndecided = errors.New("ssh: must Accept or Reject channel")
+var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once")
+
+type extChannel struct {
+	code uint32
+	ch   *channel
+}
+
+func (e *extChannel) Write(data []byte) (n int, err error) {
+	return e.ch.WriteExtended(data, e.code)
+}
+
+func (e *extChannel) Read(data []byte) (n int, err error) {
+	return e.ch.ReadExtended(data, e.code)
+}
+
+func (ch *channel) Accept() (Channel, <-chan *Request, error) {
+	if ch.decided {
+		return nil, nil, errDecidedAlready
+	}
+	ch.maxIncomingPayload = channelMaxPacket
+	confirm := channelOpenConfirmMsg{
+		PeersID:       ch.remoteId,
+		MyID:          ch.localId,
+		MyWindow:      ch.myWindow,
+		MaxPacketSize: ch.maxIncomingPayload,
+	}
+	ch.decided = true
+	if err := ch.sendMessage(confirm); err != nil {
+		return nil, nil, err
+	}
+
+	return ch, ch.incomingRequests, nil
+}
+
+func (ch *channel) Reject(reason RejectionReason, message string) error {
+	if ch.decided {
+		return errDecidedAlready
+	}
+	reject := channelOpenFailureMsg{
+		PeersID:  ch.remoteId,
+		Reason:   reason,
+		Message:  message,
+		Language: "en",
+	}
+	ch.decided = true
+	return ch.sendMessage(reject)
+}
+
+func (ch *channel) Read(data []byte) (int, error) {
+	if !ch.decided {
+		return 0, errUndecided
+	}
+	return ch.ReadExtended(data, 0)
+}
+
+func (ch *channel) Write(data []byte) (int, error) {
+	if !ch.decided {
+		return 0, errUndecided
+	}
+	return ch.WriteExtended(data, 0)
+}
+
+func (ch *channel) CloseWrite() error {
+	if !ch.decided {
+		return errUndecided
+	}
+	ch.sentEOF = true
+	return ch.sendMessage(channelEOFMsg{
+		PeersID: ch.remoteId})
+}
+
+func (ch *channel) Close() error {
+	if !ch.decided {
+		return errUndecided
+	}
+
+	return ch.sendMessage(channelCloseMsg{
+		PeersID: ch.remoteId})
+}
+
+// Extended returns an io.ReadWriter that sends and receives data on the given,
+// SSH extended stream. Such streams are used, for example, for stderr.
+func (ch *channel) Extended(code uint32) io.ReadWriter {
+	if !ch.decided {
+		return nil
+	}
+	return &extChannel{code, ch}
+}
+
+func (ch *channel) Stderr() io.ReadWriter {
+	return ch.Extended(1)
+}
+
+func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+	if !ch.decided {
+		return false, errUndecided
+	}
+
+	if wantReply {
+		ch.sentRequestMu.Lock()
+		defer ch.sentRequestMu.Unlock()
+	}
+
+	msg := channelRequestMsg{
+		PeersID:             ch.remoteId,
+		Request:             name,
+		WantReply:           wantReply,
+		RequestSpecificData: payload,
+	}
+
+	if err := ch.sendMessage(msg); err != nil {
+		return false, err
+	}
+
+	if wantReply {
+		m, ok := (<-ch.msg)
+		if !ok {
+			return false, io.EOF
+		}
+		switch m.(type) {
+		case *channelRequestFailureMsg:
+			return false, nil
+		case *channelRequestSuccessMsg:
+			return true, nil
+		default:
+			return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m)
+		}
+	}
+
+	return false, nil
+}
+
+// ackRequest either sends an ack or nack to the channel request.
+func (ch *channel) ackRequest(ok bool) error {
+	if !ch.decided {
+		return errUndecided
+	}
+
+	var msg interface{}
+	if !ok {
+		msg = channelRequestFailureMsg{
+			PeersID: ch.remoteId,
+		}
+	} else {
+		msg = channelRequestSuccessMsg{
+			PeersID: ch.remoteId,
+		}
+	}
+	return ch.sendMessage(msg)
+}
+
+func (ch *channel) ChannelType() string {
+	return ch.chanType
+}
+
+func (ch *channel) ExtraData() []byte {
+	return ch.extraData
+}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
new file mode 100644
index 0000000..8bd6b3d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -0,0 +1,781 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"crypto/rc4"
+	"crypto/subtle"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"hash"
+	"io"
+	"io/ioutil"
+
+	"golang.org/x/crypto/chacha20"
+	"golang.org/x/crypto/poly1305"
+)
+
+const (
+	packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
+
+	// RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations
+	// MUST be able to process (plus a few more kilobytes for padding and mac). The RFC
+	// indicates implementations SHOULD be able to handle larger packet sizes, but then
+	// waffles on about reasonable limits.
+	//
+	// OpenSSH caps their maxPacket at 256kB so we choose to do
+	// the same. maxPacket is also used to ensure that uint32
+	// length fields do not overflow, so it should remain well
+	// below 4G.
+	maxPacket = 256 * 1024
+)
+
+// noneCipher implements cipher.Stream and provides no encryption. It is used
+// by the transport before the first key-exchange.
+type noneCipher struct{}
+
+func (c noneCipher) XORKeyStream(dst, src []byte) {
+	copy(dst, src)
+}
+
+func newAESCTR(key, iv []byte) (cipher.Stream, error) {
+	c, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	return cipher.NewCTR(c, iv), nil
+}
+
+func newRC4(key, iv []byte) (cipher.Stream, error) {
+	return rc4.NewCipher(key)
+}
+
+type cipherMode struct {
+	keySize int
+	ivSize  int
+	create  func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)
+}
+
+func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+	return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+		stream, err := createFunc(key, iv)
+		if err != nil {
+			return nil, err
+		}
+
+		var streamDump []byte
+		if skip > 0 {
+			streamDump = make([]byte, 512)
+		}
+
+		for remainingToDump := skip; remainingToDump > 0; {
+			dumpThisTime := remainingToDump
+			if dumpThisTime > len(streamDump) {
+				dumpThisTime = len(streamDump)
+			}
+			stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
+			remainingToDump -= dumpThisTime
+		}
+
+		mac := macModes[algs.MAC].new(macKey)
+		return &streamPacketCipher{
+			mac:       mac,
+			etm:       macModes[algs.MAC].etm,
+			macResult: make([]byte, mac.Size()),
+			cipher:    stream,
+		}, nil
+	}
+}
+
+// cipherModes documents properties of supported ciphers. Ciphers not included
+// are not supported and will not be negotiated, even if explicitly requested in
+// ClientConfig.Crypto.Ciphers.
+var cipherModes = map[string]*cipherMode{
+	// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
+	// are defined in the order specified in the RFC.
+	"aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
+	"aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
+	"aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
+
+	// Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
+	// They are defined in the order specified in the RFC.
+	"arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
+	"arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
+
+	// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
+	// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
+	// RC4) has problems with weak keys, and should be used with caution."
+	// RFC4345 introduces improved versions of Arcfour.
+	"arcfour": {16, 0, streamCipherMode(0, newRC4)},
+
+	// AEAD ciphers
+	gcmCipherID:        {16, 12, newGCMCipher},
+	chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
+
+	// CBC mode is insecure and so is not included in the default config.
+	// (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely
+	// needed, it's possible to specify a custom Config to enable it.
+	// You should expect that an active attacker can recover plaintext if
+	// you do.
+	aes128cbcID: {16, aes.BlockSize, newAESCBCCipher},
+
+	// 3des-cbc is insecure and is not included in the default
+	// config.
+	tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher},
+}
+
+// prefixLen is the length of the packet prefix that contains the packet length
+// and number of padding bytes.
+const prefixLen = 5
+
+// streamPacketCipher is a packetCipher using a stream cipher.
+type streamPacketCipher struct {
+	mac    hash.Hash
+	cipher cipher.Stream
+	etm    bool
+
+	// The following members are to avoid per-packet allocations.
+	prefix      [prefixLen]byte
+	seqNumBytes [4]byte
+	padding     [2 * packetSizeMultiple]byte
+	packetData  []byte
+	macResult   []byte
+}
+
+// readCipherPacket reads and decrypt a single packet from the reader argument.
+func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+	if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
+		return nil, err
+	}
+
+	var encryptedPaddingLength [1]byte
+	if s.mac != nil && s.etm {
+		copy(encryptedPaddingLength[:], s.prefix[4:5])
+		s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+	} else {
+		s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+	}
+
+	length := binary.BigEndian.Uint32(s.prefix[0:4])
+	paddingLength := uint32(s.prefix[4])
+
+	var macSize uint32
+	if s.mac != nil {
+		s.mac.Reset()
+		binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+		s.mac.Write(s.seqNumBytes[:])
+		if s.etm {
+			s.mac.Write(s.prefix[:4])
+			s.mac.Write(encryptedPaddingLength[:])
+		} else {
+			s.mac.Write(s.prefix[:])
+		}
+		macSize = uint32(s.mac.Size())
+	}
+
+	if length <= paddingLength+1 {
+		return nil, errors.New("ssh: invalid packet length, packet too small")
+	}
+
+	if length > maxPacket {
+		return nil, errors.New("ssh: invalid packet length, packet too large")
+	}
+
+	// the maxPacket check above ensures that length-1+macSize
+	// does not overflow.
+	if uint32(cap(s.packetData)) < length-1+macSize {
+		s.packetData = make([]byte, length-1+macSize)
+	} else {
+		s.packetData = s.packetData[:length-1+macSize]
+	}
+
+	if _, err := io.ReadFull(r, s.packetData); err != nil {
+		return nil, err
+	}
+	mac := s.packetData[length-1:]
+	data := s.packetData[:length-1]
+
+	if s.mac != nil && s.etm {
+		s.mac.Write(data)
+	}
+
+	s.cipher.XORKeyStream(data, data)
+
+	if s.mac != nil {
+		if !s.etm {
+			s.mac.Write(data)
+		}
+		s.macResult = s.mac.Sum(s.macResult[:0])
+		if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
+			return nil, errors.New("ssh: MAC failure")
+		}
+	}
+
+	return s.packetData[:length-paddingLength-1], nil
+}
+
+// writeCipherPacket encrypts and sends a packet of data to the writer argument
+func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+	if len(packet) > maxPacket {
+		return errors.New("ssh: packet too large")
+	}
+
+	aadlen := 0
+	if s.mac != nil && s.etm {
+		// packet length is not encrypted for EtM modes
+		aadlen = 4
+	}
+
+	paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
+	if paddingLength < 4 {
+		paddingLength += packetSizeMultiple
+	}
+
+	length := len(packet) + 1 + paddingLength
+	binary.BigEndian.PutUint32(s.prefix[:], uint32(length))
+	s.prefix[4] = byte(paddingLength)
+	padding := s.padding[:paddingLength]
+	if _, err := io.ReadFull(rand, padding); err != nil {
+		return err
+	}
+
+	if s.mac != nil {
+		s.mac.Reset()
+		binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+		s.mac.Write(s.seqNumBytes[:])
+
+		if s.etm {
+			// For EtM algorithms, the packet length must stay unencrypted,
+			// but the following data (padding length) must be encrypted
+			s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+		}
+
+		s.mac.Write(s.prefix[:])
+
+		if !s.etm {
+			// For non-EtM algorithms, the algorithm is applied on unencrypted data
+			s.mac.Write(packet)
+			s.mac.Write(padding)
+		}
+	}
+
+	if !(s.mac != nil && s.etm) {
+		// For EtM algorithms, the padding length has already been encrypted
+		// and the packet length must remain unencrypted
+		s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+	}
+
+	s.cipher.XORKeyStream(packet, packet)
+	s.cipher.XORKeyStream(padding, padding)
+
+	if s.mac != nil && s.etm {
+		// For EtM algorithms, packet and padding must be encrypted
+		s.mac.Write(packet)
+		s.mac.Write(padding)
+	}
+
+	if _, err := w.Write(s.prefix[:]); err != nil {
+		return err
+	}
+	if _, err := w.Write(packet); err != nil {
+		return err
+	}
+	if _, err := w.Write(padding); err != nil {
+		return err
+	}
+
+	if s.mac != nil {
+		s.macResult = s.mac.Sum(s.macResult[:0])
+		if _, err := w.Write(s.macResult); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+type gcmCipher struct {
+	aead   cipher.AEAD
+	prefix [4]byte
+	iv     []byte
+	buf    []byte
+}
+
+func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
+	c, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	aead, err := cipher.NewGCM(c)
+	if err != nil {
+		return nil, err
+	}
+
+	return &gcmCipher{
+		aead: aead,
+		iv:   iv,
+	}, nil
+}
+
+const gcmTagSize = 16
+
+func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+	// Pad out to multiple of 16 bytes. This is different from the
+	// stream cipher because that encrypts the length too.
+	padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
+	if padding < 4 {
+		padding += packetSizeMultiple
+	}
+
+	length := uint32(len(packet) + int(padding) + 1)
+	binary.BigEndian.PutUint32(c.prefix[:], length)
+	if _, err := w.Write(c.prefix[:]); err != nil {
+		return err
+	}
+
+	if cap(c.buf) < int(length) {
+		c.buf = make([]byte, length)
+	} else {
+		c.buf = c.buf[:length]
+	}
+
+	c.buf[0] = padding
+	copy(c.buf[1:], packet)
+	if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil {
+		return err
+	}
+	c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:])
+	if _, err := w.Write(c.buf); err != nil {
+		return err
+	}
+	c.incIV()
+
+	return nil
+}
+
+func (c *gcmCipher) incIV() {
+	for i := 4 + 7; i >= 4; i-- {
+		c.iv[i]++
+		if c.iv[i] != 0 {
+			break
+		}
+	}
+}
+
+func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+	if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
+		return nil, err
+	}
+	length := binary.BigEndian.Uint32(c.prefix[:])
+	if length > maxPacket {
+		return nil, errors.New("ssh: max packet length exceeded")
+	}
+
+	if cap(c.buf) < int(length+gcmTagSize) {
+		c.buf = make([]byte, length+gcmTagSize)
+	} else {
+		c.buf = c.buf[:length+gcmTagSize]
+	}
+
+	if _, err := io.ReadFull(r, c.buf); err != nil {
+		return nil, err
+	}
+
+	plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:])
+	if err != nil {
+		return nil, err
+	}
+	c.incIV()
+
+	padding := plain[0]
+	if padding < 4 {
+		// padding is a byte, so it automatically satisfies
+		// the maximum size, which is 255.
+		return nil, fmt.Errorf("ssh: illegal padding %d", padding)
+	}
+
+	if int(padding+1) >= len(plain) {
+		return nil, fmt.Errorf("ssh: padding %d too large", padding)
+	}
+	plain = plain[1 : length-uint32(padding)]
+	return plain, nil
+}
+
+// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1
+type cbcCipher struct {
+	mac       hash.Hash
+	macSize   uint32
+	decrypter cipher.BlockMode
+	encrypter cipher.BlockMode
+
+	// The following members are to avoid per-packet allocations.
+	seqNumBytes [4]byte
+	packetData  []byte
+	macResult   []byte
+
+	// Amount of data we should still read to hide which
+	// verification error triggered.
+	oracleCamouflage uint32
+}
+
+func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+	cbc := &cbcCipher{
+		mac:        macModes[algs.MAC].new(macKey),
+		decrypter:  cipher.NewCBCDecrypter(c, iv),
+		encrypter:  cipher.NewCBCEncrypter(c, iv),
+		packetData: make([]byte, 1024),
+	}
+	if cbc.mac != nil {
+		cbc.macSize = uint32(cbc.mac.Size())
+	}
+
+	return cbc, nil
+}
+
+func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+	c, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	cbc, err := newCBCCipher(c, key, iv, macKey, algs)
+	if err != nil {
+		return nil, err
+	}
+
+	return cbc, nil
+}
+
+func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+	c, err := des.NewTripleDESCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	cbc, err := newCBCCipher(c, key, iv, macKey, algs)
+	if err != nil {
+		return nil, err
+	}
+
+	return cbc, nil
+}
+
+func maxUInt32(a, b int) uint32 {
+	if a > b {
+		return uint32(a)
+	}
+	return uint32(b)
+}
+
+const (
+	cbcMinPacketSizeMultiple = 8
+	cbcMinPacketSize         = 16
+	cbcMinPaddingSize        = 4
+)
+
+// cbcError represents a verification error that may leak information.
+type cbcError string
+
+func (e cbcError) Error() string { return string(e) }
+
+func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+	p, err := c.readCipherPacketLeaky(seqNum, r)
+	if err != nil {
+		if _, ok := err.(cbcError); ok {
+			// Verification error: read a fixed amount of
+			// data, to make distinguishing between
+			// failing MAC and failing length check more
+			// difficult.
+			io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage))
+		}
+	}
+	return p, err
+}
+
+func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
+	blockSize := c.decrypter.BlockSize()
+
+	// Read the header, which will include some of the subsequent data in the
+	// case of block ciphers - this is copied back to the payload later.
+	// How many bytes of payload/padding will be read with this first read.
+	firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize)
+	firstBlock := c.packetData[:firstBlockLength]
+	if _, err := io.ReadFull(r, firstBlock); err != nil {
+		return nil, err
+	}
+
+	c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength
+
+	c.decrypter.CryptBlocks(firstBlock, firstBlock)
+	length := binary.BigEndian.Uint32(firstBlock[:4])
+	if length > maxPacket {
+		return nil, cbcError("ssh: packet too large")
+	}
+	if length+4 < maxUInt32(cbcMinPacketSize, blockSize) {
+		// The minimum size of a packet is 16 (or the cipher block size, whichever
+		// is larger) bytes.
+		return nil, cbcError("ssh: packet too small")
+	}
+	// The length of the packet (including the length field but not the MAC) must
+	// be a multiple of the block size or 8, whichever is larger.
+	if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 {
+		return nil, cbcError("ssh: invalid packet length multiple")
+	}
+
+	paddingLength := uint32(firstBlock[4])
+	if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 {
+		return nil, cbcError("ssh: invalid packet length")
+	}
+
+	// Positions within the c.packetData buffer:
+	macStart := 4 + length
+	paddingStart := macStart - paddingLength
+
+	// Entire packet size, starting before length, ending at end of mac.
+	entirePacketSize := macStart + c.macSize
+
+	// Ensure c.packetData is large enough for the entire packet data.
+	if uint32(cap(c.packetData)) < entirePacketSize {
+		// Still need to upsize and copy, but this should be rare at runtime, only
+		// on upsizing the packetData buffer.
+		c.packetData = make([]byte, entirePacketSize)
+		copy(c.packetData, firstBlock)
+	} else {
+		c.packetData = c.packetData[:entirePacketSize]
+	}
+
+	n, err := io.ReadFull(r, c.packetData[firstBlockLength:])
+	if err != nil {
+		return nil, err
+	}
+	c.oracleCamouflage -= uint32(n)
+
+	remainingCrypted := c.packetData[firstBlockLength:macStart]
+	c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted)
+
+	mac := c.packetData[macStart:]
+	if c.mac != nil {
+		c.mac.Reset()
+		binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
+		c.mac.Write(c.seqNumBytes[:])
+		c.mac.Write(c.packetData[:macStart])
+		c.macResult = c.mac.Sum(c.macResult[:0])
+		if subtle.ConstantTimeCompare(c.macResult, mac) != 1 {
+			return nil, cbcError("ssh: MAC failure")
+		}
+	}
+
+	return c.packetData[prefixLen:paddingStart], nil
+}
+
+func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+	effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize())
+
+	// Length of encrypted portion of the packet (header, payload, padding).
+	// Enforce minimum padding and packet size.
+	encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize)
+	// Enforce block size.
+	encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize
+
+	length := encLength - 4
+	paddingLength := int(length) - (1 + len(packet))
+
+	// Overall buffer contains: header, payload, padding, mac.
+	// Space for the MAC is reserved in the capacity but not the slice length.
+	bufferSize := encLength + c.macSize
+	if uint32(cap(c.packetData)) < bufferSize {
+		c.packetData = make([]byte, encLength, bufferSize)
+	} else {
+		c.packetData = c.packetData[:encLength]
+	}
+
+	p := c.packetData
+
+	// Packet header.
+	binary.BigEndian.PutUint32(p, length)
+	p = p[4:]
+	p[0] = byte(paddingLength)
+
+	// Payload.
+	p = p[1:]
+	copy(p, packet)
+
+	// Padding.
+	p = p[len(packet):]
+	if _, err := io.ReadFull(rand, p); err != nil {
+		return err
+	}
+
+	if c.mac != nil {
+		c.mac.Reset()
+		binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
+		c.mac.Write(c.seqNumBytes[:])
+		c.mac.Write(c.packetData)
+		// The MAC is now appended into the capacity reserved for it earlier.
+		c.packetData = c.mac.Sum(c.packetData)
+	}
+
+	c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength])
+
+	if _, err := w.Write(c.packetData); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
+
+// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com
+// AEAD, which is described here:
+//
+//   https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00
+//
+// the methods here also implement padding, which RFC4253 Section 6
+// also requires of stream ciphers.
+type chacha20Poly1305Cipher struct {
+	lengthKey  [32]byte
+	contentKey [32]byte
+	buf        []byte
+}
+
+func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
+	if len(key) != 64 {
+		panic(len(key))
+	}
+
+	c := &chacha20Poly1305Cipher{
+		buf: make([]byte, 256),
+	}
+
+	copy(c.contentKey[:], key[:32])
+	copy(c.lengthKey[:], key[32:])
+	return c, nil
+}
+
+func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+	nonce := make([]byte, 12)
+	binary.BigEndian.PutUint32(nonce[8:], seqNum)
+	s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce)
+	if err != nil {
+		return nil, err
+	}
+	var polyKey, discardBuf [32]byte
+	s.XORKeyStream(polyKey[:], polyKey[:])
+	s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes
+
+	encryptedLength := c.buf[:4]
+	if _, err := io.ReadFull(r, encryptedLength); err != nil {
+		return nil, err
+	}
+
+	var lenBytes [4]byte
+	ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce)
+	if err != nil {
+		return nil, err
+	}
+	ls.XORKeyStream(lenBytes[:], encryptedLength)
+
+	length := binary.BigEndian.Uint32(lenBytes[:])
+	if length > maxPacket {
+		return nil, errors.New("ssh: invalid packet length, packet too large")
+	}
+
+	contentEnd := 4 + length
+	packetEnd := contentEnd + poly1305.TagSize
+	if uint32(cap(c.buf)) < packetEnd {
+		c.buf = make([]byte, packetEnd)
+		copy(c.buf[:], encryptedLength)
+	} else {
+		c.buf = c.buf[:packetEnd]
+	}
+
+	if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil {
+		return nil, err
+	}
+
+	var mac [poly1305.TagSize]byte
+	copy(mac[:], c.buf[contentEnd:packetEnd])
+	if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) {
+		return nil, errors.New("ssh: MAC failure")
+	}
+
+	plain := c.buf[4:contentEnd]
+	s.XORKeyStream(plain, plain)
+
+	padding := plain[0]
+	if padding < 4 {
+		// padding is a byte, so it automatically satisfies
+		// the maximum size, which is 255.
+		return nil, fmt.Errorf("ssh: illegal padding %d", padding)
+	}
+
+	if int(padding)+1 >= len(plain) {
+		return nil, fmt.Errorf("ssh: padding %d too large", padding)
+	}
+
+	plain = plain[1 : len(plain)-int(padding)]
+
+	return plain, nil
+}
+
+func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
+	nonce := make([]byte, 12)
+	binary.BigEndian.PutUint32(nonce[8:], seqNum)
+	s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce)
+	if err != nil {
+		return err
+	}
+	var polyKey, discardBuf [32]byte
+	s.XORKeyStream(polyKey[:], polyKey[:])
+	s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes
+
+	// There is no blocksize, so fall back to multiple of 8 byte
+	// padding, as described in RFC 4253, Sec 6.
+	const packetSizeMultiple = 8
+
+	padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple
+	if padding < 4 {
+		padding += packetSizeMultiple
+	}
+
+	// size (4 bytes), padding (1), payload, padding, tag.
+	totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize
+	if cap(c.buf) < totalLength {
+		c.buf = make([]byte, totalLength)
+	} else {
+		c.buf = c.buf[:totalLength]
+	}
+
+	binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
+	ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce)
+	if err != nil {
+		return err
+	}
+	ls.XORKeyStream(c.buf, c.buf[:4])
+	c.buf[4] = byte(padding)
+	copy(c.buf[5:], payload)
+	packetEnd := 5 + len(payload) + padding
+	if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil {
+		return err
+	}
+
+	s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd])
+
+	var mac [poly1305.TagSize]byte
+	poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey)
+
+	copy(c.buf[packetEnd:], mac[:])
+
+	if _, err := w.Write(c.buf); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
new file mode 100644
index 0000000..7b00bff
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -0,0 +1,278 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"net"
+	"os"
+	"sync"
+	"time"
+)
+
+// Client implements a traditional SSH client that supports shells,
+// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
+type Client struct {
+	Conn
+
+	handleForwardsOnce sync.Once // guards calling (*Client).handleForwards
+
+	forwards        forwardList // forwarded tcpip connections from the remote side
+	mu              sync.Mutex
+	channelHandlers map[string]chan NewChannel
+}
+
+// HandleChannelOpen returns a channel on which NewChannel requests
+// for the given type are sent. If the type already is being handled,
+// nil is returned. The channel is closed when the connection is closed.
+func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.channelHandlers == nil {
+		// The SSH channel has been closed.
+		c := make(chan NewChannel)
+		close(c)
+		return c
+	}
+
+	ch := c.channelHandlers[channelType]
+	if ch != nil {
+		return nil
+	}
+
+	ch = make(chan NewChannel, chanSize)
+	c.channelHandlers[channelType] = ch
+	return ch
+}
+
+// NewClient creates a Client on top of the given connection.
+func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
+	conn := &Client{
+		Conn:            c,
+		channelHandlers: make(map[string]chan NewChannel, 1),
+	}
+
+	go conn.handleGlobalRequests(reqs)
+	go conn.handleChannelOpens(chans)
+	go func() {
+		conn.Wait()
+		conn.forwards.closeAll()
+	}()
+	return conn
+}
+
+// NewClientConn establishes an authenticated SSH connection using c
+// as the underlying transport.  The Request and NewChannel channels
+// must be serviced or the connection will hang.
+func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
+	fullConf := *config
+	fullConf.SetDefaults()
+	if fullConf.HostKeyCallback == nil {
+		c.Close()
+		return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
+	}
+
+	conn := &connection{
+		sshConn: sshConn{conn: c},
+	}
+
+	if err := conn.clientHandshake(addr, &fullConf); err != nil {
+		c.Close()
+		return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
+	}
+	conn.mux = newMux(conn.transport)
+	return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
+}
+
+// clientHandshake performs the client side key exchange. See RFC 4253 Section
+// 7.
+func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error {
+	if config.ClientVersion != "" {
+		c.clientVersion = []byte(config.ClientVersion)
+	} else {
+		c.clientVersion = []byte(packageVersion)
+	}
+	var err error
+	c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion)
+	if err != nil {
+		return err
+	}
+
+	c.transport = newClientTransport(
+		newTransport(c.sshConn.conn, config.Rand, true /* is client */),
+		c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
+	if err := c.transport.waitSession(); err != nil {
+		return err
+	}
+
+	c.sessionID = c.transport.getSessionID()
+	return c.clientAuthenticate(config)
+}
+
+// verifyHostKeySignature verifies the host key obtained in the key
+// exchange.
+func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
+	sig, rest, ok := parseSignatureBody(result.Signature)
+	if len(rest) > 0 || !ok {
+		return errors.New("ssh: signature parse error")
+	}
+
+	return hostKey.Verify(result.H, sig)
+}
+
+// NewSession opens a new Session for this client. (A session is a remote
+// execution of a program.)
+func (c *Client) NewSession() (*Session, error) {
+	ch, in, err := c.OpenChannel("session", nil)
+	if err != nil {
+		return nil, err
+	}
+	return newSession(ch, in)
+}
+
+func (c *Client) handleGlobalRequests(incoming <-chan *Request) {
+	for r := range incoming {
+		// This handles keepalive messages and matches
+		// the behaviour of OpenSSH.
+		r.Reply(false, nil)
+	}
+}
+
+// handleChannelOpens channel open messages from the remote side.
+func (c *Client) handleChannelOpens(in <-chan NewChannel) {
+	for ch := range in {
+		c.mu.Lock()
+		handler := c.channelHandlers[ch.ChannelType()]
+		c.mu.Unlock()
+
+		if handler != nil {
+			handler <- ch
+		} else {
+			ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType()))
+		}
+	}
+
+	c.mu.Lock()
+	for _, ch := range c.channelHandlers {
+		close(ch)
+	}
+	c.channelHandlers = nil
+	c.mu.Unlock()
+}
+
+// Dial starts a client connection to the given SSH server. It is a
+// convenience function that connects to the given network address,
+// initiates the SSH handshake, and then sets up a Client.  For access
+// to incoming channels and requests, use net.Dial with NewClientConn
+// instead.
+func Dial(network, addr string, config *ClientConfig) (*Client, error) {
+	conn, err := net.DialTimeout(network, addr, config.Timeout)
+	if err != nil {
+		return nil, err
+	}
+	c, chans, reqs, err := NewClientConn(conn, addr, config)
+	if err != nil {
+		return nil, err
+	}
+	return NewClient(c, chans, reqs), nil
+}
+
+// HostKeyCallback is the function type used for verifying server
+// keys.  A HostKeyCallback must return nil if the host key is OK, or
+// an error to reject it. It receives the hostname as passed to Dial
+// or NewClientConn. The remote address is the RemoteAddr of the
+// net.Conn underlying the SSH connection.
+type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+
+// BannerCallback is the function type used for treat the banner sent by
+// the server. A BannerCallback receives the message sent by the remote server.
+type BannerCallback func(message string) error
+
+// A ClientConfig structure is used to configure a Client. It must not be
+// modified after having been passed to an SSH function.
+type ClientConfig struct {
+	// Config contains configuration that is shared between clients and
+	// servers.
+	Config
+
+	// User contains the username to authenticate as.
+	User string
+
+	// Auth contains possible authentication methods to use with the
+	// server. Only the first instance of a particular RFC 4252 method will
+	// be used during authentication.
+	Auth []AuthMethod
+
+	// HostKeyCallback is called during the cryptographic
+	// handshake to validate the server's host key. The client
+	// configuration must supply this callback for the connection
+	// to succeed. The functions InsecureIgnoreHostKey or
+	// FixedHostKey can be used for simplistic host key checks.
+	HostKeyCallback HostKeyCallback
+
+	// BannerCallback is called during the SSH dance to display a custom
+	// server's message. The client configuration can supply this callback to
+	// handle it as wished. The function BannerDisplayStderr can be used for
+	// simplistic display on Stderr.
+	BannerCallback BannerCallback
+
+	// ClientVersion contains the version identification string that will
+	// be used for the connection. If empty, a reasonable default is used.
+	ClientVersion string
+
+	// HostKeyAlgorithms lists the key types that the client will
+	// accept from the server as host key, in order of
+	// preference. If empty, a reasonable default is used. Any
+	// string returned from PublicKey.Type method may be used, or
+	// any of the CertAlgoXxxx and KeyAlgoXxxx constants.
+	HostKeyAlgorithms []string
+
+	// Timeout is the maximum amount of time for the TCP connection to establish.
+	//
+	// A Timeout of zero means no timeout.
+	Timeout time.Duration
+}
+
+// InsecureIgnoreHostKey returns a function that can be used for
+// ClientConfig.HostKeyCallback to accept any host key. It should
+// not be used for production code.
+func InsecureIgnoreHostKey() HostKeyCallback {
+	return func(hostname string, remote net.Addr, key PublicKey) error {
+		return nil
+	}
+}
+
+type fixedHostKey struct {
+	key PublicKey
+}
+
+func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
+	if f.key == nil {
+		return fmt.Errorf("ssh: required host key was nil")
+	}
+	if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
+		return fmt.Errorf("ssh: host key mismatch")
+	}
+	return nil
+}
+
+// FixedHostKey returns a function for use in
+// ClientConfig.HostKeyCallback to accept only a specific host key.
+func FixedHostKey(key PublicKey) HostKeyCallback {
+	hk := &fixedHostKey{key}
+	return hk.check
+}
+
+// BannerDisplayStderr returns a function that can be used for
+// ClientConfig.BannerCallback to display banners on os.Stderr.
+func BannerDisplayStderr() BannerCallback {
+	return func(banner string) error {
+		_, err := os.Stderr.WriteString(banner)
+
+		return err
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
new file mode 100644
index 0000000..c611aeb
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -0,0 +1,641 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+)
+
+type authResult int
+
+const (
+	authFailure authResult = iota
+	authPartialSuccess
+	authSuccess
+)
+
+// clientAuthenticate authenticates with the remote server. See RFC 4252.
+func (c *connection) clientAuthenticate(config *ClientConfig) error {
+	// initiate user auth session
+	if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
+		return err
+	}
+	packet, err := c.transport.readPacket()
+	if err != nil {
+		return err
+	}
+	var serviceAccept serviceAcceptMsg
+	if err := Unmarshal(packet, &serviceAccept); err != nil {
+		return err
+	}
+
+	// during the authentication phase the client first attempts the "none" method
+	// then any untried methods suggested by the server.
+	var tried []string
+	var lastMethods []string
+
+	sessionID := c.transport.getSessionID()
+	for auth := AuthMethod(new(noneAuth)); auth != nil; {
+		ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
+		if err != nil {
+			return err
+		}
+		if ok == authSuccess {
+			// success
+			return nil
+		} else if ok == authFailure {
+			if m := auth.method(); !contains(tried, m) {
+				tried = append(tried, m)
+			}
+		}
+		if methods == nil {
+			methods = lastMethods
+		}
+		lastMethods = methods
+
+		auth = nil
+
+	findNext:
+		for _, a := range config.Auth {
+			candidateMethod := a.method()
+			if contains(tried, candidateMethod) {
+				continue
+			}
+			for _, meth := range methods {
+				if meth == candidateMethod {
+					auth = a
+					break findNext
+				}
+			}
+		}
+	}
+	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried)
+}
+
+func contains(list []string, e string) bool {
+	for _, s := range list {
+		if s == e {
+			return true
+		}
+	}
+	return false
+}
+
+// An AuthMethod represents an instance of an RFC 4252 authentication method.
+type AuthMethod interface {
+	// auth authenticates user over transport t.
+	// Returns true if authentication is successful.
+	// If authentication is not successful, a []string of alternative
+	// method names is returned. If the slice is nil, it will be ignored
+	// and the previous set of possible methods will be reused.
+	auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error)
+
+	// method returns the RFC 4252 method name.
+	method() string
+}
+
+// "none" authentication, RFC 4252 section 5.2.
+type noneAuth int
+
+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+	if err := c.writePacket(Marshal(&userAuthRequestMsg{
+		User:    user,
+		Service: serviceSSH,
+		Method:  "none",
+	})); err != nil {
+		return authFailure, nil, err
+	}
+
+	return handleAuthResponse(c)
+}
+
+func (n *noneAuth) method() string {
+	return "none"
+}
+
+// passwordCallback is an AuthMethod that fetches the password through
+// a function call, e.g. by prompting the user.
+type passwordCallback func() (password string, err error)
+
+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+	type passwordAuthMsg struct {
+		User     string `sshtype:"50"`
+		Service  string
+		Method   string
+		Reply    bool
+		Password string
+	}
+
+	pw, err := cb()
+	// REVIEW NOTE: is there a need to support skipping a password attempt?
+	// The program may only find out that the user doesn't have a password
+	// when prompting.
+	if err != nil {
+		return authFailure, nil, err
+	}
+
+	if err := c.writePacket(Marshal(&passwordAuthMsg{
+		User:     user,
+		Service:  serviceSSH,
+		Method:   cb.method(),
+		Reply:    false,
+		Password: pw,
+	})); err != nil {
+		return authFailure, nil, err
+	}
+
+	return handleAuthResponse(c)
+}
+
+func (cb passwordCallback) method() string {
+	return "password"
+}
+
+// Password returns an AuthMethod using the given password.
+func Password(secret string) AuthMethod {
+	return passwordCallback(func() (string, error) { return secret, nil })
+}
+
+// PasswordCallback returns an AuthMethod that uses a callback for
+// fetching a password.
+func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
+	return passwordCallback(prompt)
+}
+
+type publickeyAuthMsg struct {
+	User    string `sshtype:"50"`
+	Service string
+	Method  string
+	// HasSig indicates to the receiver packet that the auth request is signed and
+	// should be used for authentication of the request.
+	HasSig   bool
+	Algoname string
+	PubKey   []byte
+	// Sig is tagged with "rest" so Marshal will exclude it during
+	// validateKey
+	Sig []byte `ssh:"rest"`
+}
+
+// publicKeyCallback is an AuthMethod that uses a set of key
+// pairs for authentication.
+type publicKeyCallback func() ([]Signer, error)
+
+func (cb publicKeyCallback) method() string {
+	return "publickey"
+}
+
+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+	// Authentication is performed by sending an enquiry to test if a key is
+	// acceptable to the remote. If the key is acceptable, the client will
+	// attempt to authenticate with the valid key.  If not the client will repeat
+	// the process with the remaining keys.
+
+	signers, err := cb()
+	if err != nil {
+		return authFailure, nil, err
+	}
+	var methods []string
+	for _, signer := range signers {
+		ok, err := validateKey(signer.PublicKey(), user, c)
+		if err != nil {
+			return authFailure, nil, err
+		}
+		if !ok {
+			continue
+		}
+
+		pub := signer.PublicKey()
+		pubKey := pub.Marshal()
+		sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
+			User:    user,
+			Service: serviceSSH,
+			Method:  cb.method(),
+		}, []byte(pub.Type()), pubKey))
+		if err != nil {
+			return authFailure, nil, err
+		}
+
+		// manually wrap the serialized signature in a string
+		s := Marshal(sign)
+		sig := make([]byte, stringLength(len(s)))
+		marshalString(sig, s)
+		msg := publickeyAuthMsg{
+			User:     user,
+			Service:  serviceSSH,
+			Method:   cb.method(),
+			HasSig:   true,
+			Algoname: pub.Type(),
+			PubKey:   pubKey,
+			Sig:      sig,
+		}
+		p := Marshal(&msg)
+		if err := c.writePacket(p); err != nil {
+			return authFailure, nil, err
+		}
+		var success authResult
+		success, methods, err = handleAuthResponse(c)
+		if err != nil {
+			return authFailure, nil, err
+		}
+
+		// If authentication succeeds or the list of available methods does not
+		// contain the "publickey" method, do not attempt to authenticate with any
+		// other keys.  According to RFC 4252 Section 7, the latter can occur when
+		// additional authentication methods are required.
+		if success == authSuccess || !containsMethod(methods, cb.method()) {
+			return success, methods, err
+		}
+	}
+
+	return authFailure, methods, nil
+}
+
+func containsMethod(methods []string, method string) bool {
+	for _, m := range methods {
+		if m == method {
+			return true
+		}
+	}
+
+	return false
+}
+
+// validateKey validates the key provided is acceptable to the server.
+func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
+	pubKey := key.Marshal()
+	msg := publickeyAuthMsg{
+		User:     user,
+		Service:  serviceSSH,
+		Method:   "publickey",
+		HasSig:   false,
+		Algoname: key.Type(),
+		PubKey:   pubKey,
+	}
+	if err := c.writePacket(Marshal(&msg)); err != nil {
+		return false, err
+	}
+
+	return confirmKeyAck(key, c)
+}
+
+func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
+	pubKey := key.Marshal()
+	algoname := key.Type()
+
+	for {
+		packet, err := c.readPacket()
+		if err != nil {
+			return false, err
+		}
+		switch packet[0] {
+		case msgUserAuthBanner:
+			if err := handleBannerResponse(c, packet); err != nil {
+				return false, err
+			}
+		case msgUserAuthPubKeyOk:
+			var msg userAuthPubKeyOkMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return false, err
+			}
+			if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
+				return false, nil
+			}
+			return true, nil
+		case msgUserAuthFailure:
+			return false, nil
+		default:
+			return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+		}
+	}
+}
+
+// PublicKeys returns an AuthMethod that uses the given key
+// pairs.
+func PublicKeys(signers ...Signer) AuthMethod {
+	return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
+}
+
+// PublicKeysCallback returns an AuthMethod that runs the given
+// function to obtain a list of key pairs.
+func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
+	return publicKeyCallback(getSigners)
+}
+
+// handleAuthResponse returns whether the preceding authentication request succeeded
+// along with a list of remaining authentication methods to try next and
+// an error if an unexpected response was received.
+func handleAuthResponse(c packetConn) (authResult, []string, error) {
+	for {
+		packet, err := c.readPacket()
+		if err != nil {
+			return authFailure, nil, err
+		}
+
+		switch packet[0] {
+		case msgUserAuthBanner:
+			if err := handleBannerResponse(c, packet); err != nil {
+				return authFailure, nil, err
+			}
+		case msgUserAuthFailure:
+			var msg userAuthFailureMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return authFailure, nil, err
+			}
+			if msg.PartialSuccess {
+				return authPartialSuccess, msg.Methods, nil
+			}
+			return authFailure, msg.Methods, nil
+		case msgUserAuthSuccess:
+			return authSuccess, nil, nil
+		default:
+			return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+		}
+	}
+}
+
+func handleBannerResponse(c packetConn, packet []byte) error {
+	var msg userAuthBannerMsg
+	if err := Unmarshal(packet, &msg); err != nil {
+		return err
+	}
+
+	transport, ok := c.(*handshakeTransport)
+	if !ok {
+		return nil
+	}
+
+	if transport.bannerCallback != nil {
+		return transport.bannerCallback(msg.Message)
+	}
+
+	return nil
+}
+
+// KeyboardInteractiveChallenge should print questions, optionally
+// disabling echoing (e.g. for passwords), and return all the answers.
+// Challenge may be called multiple times in a single session. After
+// successful authentication, the server may send a challenge with no
+// questions, for which the user and instruction messages should be
+// printed.  RFC 4256 section 3.3 details how the UI should behave for
+// both CLI and GUI environments.
+type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
+
+// KeyboardInteractive returns an AuthMethod using a prompt/response
+// sequence controlled by the server.
+func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
+	return challenge
+}
+
+func (cb KeyboardInteractiveChallenge) method() string {
+	return "keyboard-interactive"
+}
+
+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+	type initiateMsg struct {
+		User       string `sshtype:"50"`
+		Service    string
+		Method     string
+		Language   string
+		Submethods string
+	}
+
+	if err := c.writePacket(Marshal(&initiateMsg{
+		User:    user,
+		Service: serviceSSH,
+		Method:  "keyboard-interactive",
+	})); err != nil {
+		return authFailure, nil, err
+	}
+
+	for {
+		packet, err := c.readPacket()
+		if err != nil {
+			return authFailure, nil, err
+		}
+
+		// like handleAuthResponse, but with less options.
+		switch packet[0] {
+		case msgUserAuthBanner:
+			if err := handleBannerResponse(c, packet); err != nil {
+				return authFailure, nil, err
+			}
+			continue
+		case msgUserAuthInfoRequest:
+			// OK
+		case msgUserAuthFailure:
+			var msg userAuthFailureMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return authFailure, nil, err
+			}
+			if msg.PartialSuccess {
+				return authPartialSuccess, msg.Methods, nil
+			}
+			return authFailure, msg.Methods, nil
+		case msgUserAuthSuccess:
+			return authSuccess, nil, nil
+		default:
+			return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+		}
+
+		var msg userAuthInfoRequestMsg
+		if err := Unmarshal(packet, &msg); err != nil {
+			return authFailure, nil, err
+		}
+
+		// Manually unpack the prompt/echo pairs.
+		rest := msg.Prompts
+		var prompts []string
+		var echos []bool
+		for i := 0; i < int(msg.NumPrompts); i++ {
+			prompt, r, ok := parseString(rest)
+			if !ok || len(r) == 0 {
+				return authFailure, nil, errors.New("ssh: prompt format error")
+			}
+			prompts = append(prompts, string(prompt))
+			echos = append(echos, r[0] != 0)
+			rest = r[1:]
+		}
+
+		if len(rest) != 0 {
+			return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
+		}
+
+		answers, err := cb(msg.User, msg.Instruction, prompts, echos)
+		if err != nil {
+			return authFailure, nil, err
+		}
+
+		if len(answers) != len(prompts) {
+			return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts))
+		}
+		responseLength := 1 + 4
+		for _, a := range answers {
+			responseLength += stringLength(len(a))
+		}
+		serialized := make([]byte, responseLength)
+		p := serialized
+		p[0] = msgUserAuthInfoResponse
+		p = p[1:]
+		p = marshalUint32(p, uint32(len(answers)))
+		for _, a := range answers {
+			p = marshalString(p, []byte(a))
+		}
+
+		if err := c.writePacket(serialized); err != nil {
+			return authFailure, nil, err
+		}
+	}
+}
+
+type retryableAuthMethod struct {
+	authMethod AuthMethod
+	maxTries   int
+}
+
+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) {
+	for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
+		ok, methods, err = r.authMethod.auth(session, user, c, rand)
+		if ok != authFailure || err != nil { // either success, partial success or error terminate
+			return ok, methods, err
+		}
+	}
+	return ok, methods, err
+}
+
+func (r *retryableAuthMethod) method() string {
+	return r.authMethod.method()
+}
+
+// RetryableAuthMethod is a decorator for other auth methods enabling them to
+// be retried up to maxTries before considering that AuthMethod itself failed.
+// If maxTries is <= 0, will retry indefinitely
+//
+// This is useful for interactive clients using challenge/response type
+// authentication (e.g. Keyboard-Interactive, Password, etc) where the user
+// could mistype their response resulting in the server issuing a
+// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4
+// [keyboard-interactive]); Without this decorator, the non-retryable
+// AuthMethod would be removed from future consideration, and never tried again
+// (and so the user would never be able to retry their entry).
+func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
+	return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}
+}
+
+// GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication.
+// See RFC 4462 section 3
+// gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details.
+// target is the server host you want to log in to.
+func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod {
+	if gssAPIClient == nil {
+		panic("gss-api client must be not nil with enable gssapi-with-mic")
+	}
+	return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target}
+}
+
+type gssAPIWithMICCallback struct {
+	gssAPIClient GSSAPIClient
+	target       string
+}
+
+func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
+	m := &userAuthRequestMsg{
+		User:    user,
+		Service: serviceSSH,
+		Method:  g.method(),
+	}
+	// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST.
+	// See RFC 4462 section 3.2.
+	m.Payload = appendU32(m.Payload, 1)
+	m.Payload = appendString(m.Payload, string(krb5OID))
+	if err := c.writePacket(Marshal(m)); err != nil {
+		return authFailure, nil, err
+	}
+	// The server responds to the SSH_MSG_USERAUTH_REQUEST with either an
+	// SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or
+	// with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE.
+	// See RFC 4462 section 3.3.
+	// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check
+	// selected mech if it is valid.
+	packet, err := c.readPacket()
+	if err != nil {
+		return authFailure, nil, err
+	}
+	userAuthGSSAPIResp := &userAuthGSSAPIResponse{}
+	if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil {
+		return authFailure, nil, err
+	}
+	// Start the loop into the exchange token.
+	// See RFC 4462 section 3.4.
+	var token []byte
+	defer g.gssAPIClient.DeleteSecContext()
+	for {
+		// Initiates the establishment of a security context between the application and a remote peer.
+		nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false)
+		if err != nil {
+			return authFailure, nil, err
+		}
+		if len(nextToken) > 0 {
+			if err := c.writePacket(Marshal(&userAuthGSSAPIToken{
+				Token: nextToken,
+			})); err != nil {
+				return authFailure, nil, err
+			}
+		}
+		if !needContinue {
+			break
+		}
+		packet, err = c.readPacket()
+		if err != nil {
+			return authFailure, nil, err
+		}
+		switch packet[0] {
+		case msgUserAuthFailure:
+			var msg userAuthFailureMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return authFailure, nil, err
+			}
+			if msg.PartialSuccess {
+				return authPartialSuccess, msg.Methods, nil
+			}
+			return authFailure, msg.Methods, nil
+		case msgUserAuthGSSAPIError:
+			userAuthGSSAPIErrorResp := &userAuthGSSAPIError{}
+			if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil {
+				return authFailure, nil, err
+			}
+			return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+
+				"Major Status: %d\n"+
+				"Minor Status: %d\n"+
+				"Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus,
+				userAuthGSSAPIErrorResp.Message)
+		case msgUserAuthGSSAPIToken:
+			userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
+			if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
+				return authFailure, nil, err
+			}
+			token = userAuthGSSAPITokenReq.Token
+		}
+	}
+	// Binding Encryption Keys.
+	// See RFC 4462 section 3.5.
+	micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic")
+	micToken, err := g.gssAPIClient.GetMIC(micField)
+	if err != nil {
+		return authFailure, nil, err
+	}
+	if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{
+		MIC: micToken,
+	})); err != nil {
+		return authFailure, nil, err
+	}
+	return handleAuthResponse(c)
+}
+
+func (g *gssAPIWithMICCallback) method() string {
+	return "gssapi-with-mic"
+}
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
new file mode 100644
index 0000000..290382d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -0,0 +1,404 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto"
+	"crypto/rand"
+	"fmt"
+	"io"
+	"math"
+	"sync"
+
+	_ "crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+)
+
+// These are string constants in the SSH protocol.
+const (
+	compressionNone = "none"
+	serviceUserAuth = "ssh-userauth"
+	serviceSSH      = "ssh-connection"
+)
+
+// supportedCiphers lists ciphers we support but might not recommend.
+var supportedCiphers = []string{
+	"aes128-ctr", "aes192-ctr", "aes256-ctr",
+	"aes128-gcm@openssh.com",
+	chacha20Poly1305ID,
+	"arcfour256", "arcfour128", "arcfour",
+	aes128cbcID,
+	tripledescbcID,
+}
+
+// preferredCiphers specifies the default preference for ciphers.
+var preferredCiphers = []string{
+	"aes128-gcm@openssh.com",
+	chacha20Poly1305ID,
+	"aes128-ctr", "aes192-ctr", "aes256-ctr",
+}
+
+// supportedKexAlgos specifies the supported key-exchange algorithms in
+// preference order.
+var supportedKexAlgos = []string{
+	kexAlgoCurve25519SHA256,
+	// P384 and P521 are not constant-time yet, but since we don't
+	// reuse ephemeral keys, using them for ECDH should be OK.
+	kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
+	kexAlgoDH14SHA1, kexAlgoDH1SHA1,
+}
+
+// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
+// for the server half.
+var serverForbiddenKexAlgos = map[string]struct{}{
+	kexAlgoDHGEXSHA1:   {}, // server half implementation is only minimal to satisfy the automated tests
+	kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
+}
+
+// preferredKexAlgos specifies the default preference for key-exchange algorithms
+// in preference order.
+var preferredKexAlgos = []string{
+	kexAlgoCurve25519SHA256,
+	kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
+	kexAlgoDH14SHA1,
+}
+
+// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
+// of authenticating servers) in preference order.
+var supportedHostKeyAlgos = []string{
+	CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
+	CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
+
+	KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
+	KeyAlgoRSA, KeyAlgoDSA,
+
+	KeyAlgoED25519,
+}
+
+// supportedMACs specifies a default set of MAC algorithms in preference order.
+// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
+// because they have reached the end of their useful life.
+var supportedMACs = []string{
+	"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
+}
+
+var supportedCompressions = []string{compressionNone}
+
+// hashFuncs keeps the mapping of supported algorithms to their respective
+// hashes needed for signature verification.
+var hashFuncs = map[string]crypto.Hash{
+	KeyAlgoRSA:          crypto.SHA1,
+	KeyAlgoDSA:          crypto.SHA1,
+	KeyAlgoECDSA256:     crypto.SHA256,
+	KeyAlgoECDSA384:     crypto.SHA384,
+	KeyAlgoECDSA521:     crypto.SHA512,
+	CertAlgoRSAv01:      crypto.SHA1,
+	CertAlgoDSAv01:      crypto.SHA1,
+	CertAlgoECDSA256v01: crypto.SHA256,
+	CertAlgoECDSA384v01: crypto.SHA384,
+	CertAlgoECDSA521v01: crypto.SHA512,
+}
+
+// unexpectedMessageError results when the SSH message that we received didn't
+// match what we wanted.
+func unexpectedMessageError(expected, got uint8) error {
+	return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected)
+}
+
+// parseError results from a malformed SSH message.
+func parseError(tag uint8) error {
+	return fmt.Errorf("ssh: parse error in message type %d", tag)
+}
+
+func findCommon(what string, client []string, server []string) (common string, err error) {
+	for _, c := range client {
+		for _, s := range server {
+			if c == s {
+				return c, nil
+			}
+		}
+	}
+	return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server)
+}
+
+// directionAlgorithms records algorithm choices in one direction (either read or write)
+type directionAlgorithms struct {
+	Cipher      string
+	MAC         string
+	Compression string
+}
+
+// rekeyBytes returns a rekeying intervals in bytes.
+func (a *directionAlgorithms) rekeyBytes() int64 {
+	// According to RFC4344 block ciphers should rekey after
+	// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
+	// 128.
+	switch a.Cipher {
+	case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
+		return 16 * (1 << 32)
+
+	}
+
+	// For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
+	return 1 << 30
+}
+
+type algorithms struct {
+	kex     string
+	hostKey string
+	w       directionAlgorithms
+	r       directionAlgorithms
+}
+
+func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
+	result := &algorithms{}
+
+	result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
+	if err != nil {
+		return
+	}
+
+	result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
+	if err != nil {
+		return
+	}
+
+	stoc, ctos := &result.w, &result.r
+	if isClient {
+		ctos, stoc = stoc, ctos
+	}
+
+	ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
+	if err != nil {
+		return
+	}
+
+	stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
+	if err != nil {
+		return
+	}
+
+	ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+	if err != nil {
+		return
+	}
+
+	stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+	if err != nil {
+		return
+	}
+
+	ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
+	if err != nil {
+		return
+	}
+
+	stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
+	if err != nil {
+		return
+	}
+
+	return result, nil
+}
+
+// If rekeythreshold is too small, we can't make any progress sending
+// stuff.
+const minRekeyThreshold uint64 = 256
+
+// Config contains configuration data common to both ServerConfig and
+// ClientConfig.
+type Config struct {
+	// Rand provides the source of entropy for cryptographic
+	// primitives. If Rand is nil, the cryptographic random reader
+	// in package crypto/rand will be used.
+	Rand io.Reader
+
+	// The maximum number of bytes sent or received after which a
+	// new key is negotiated. It must be at least 256. If
+	// unspecified, a size suitable for the chosen cipher is used.
+	RekeyThreshold uint64
+
+	// The allowed key exchanges algorithms. If unspecified then a
+	// default set of algorithms is used.
+	KeyExchanges []string
+
+	// The allowed cipher algorithms. If unspecified then a sensible
+	// default is used.
+	Ciphers []string
+
+	// The allowed MAC algorithms. If unspecified then a sensible default
+	// is used.
+	MACs []string
+}
+
+// SetDefaults sets sensible values for unset fields in config. This is
+// exported for testing: Configs passed to SSH functions are copied and have
+// default values set automatically.
+func (c *Config) SetDefaults() {
+	if c.Rand == nil {
+		c.Rand = rand.Reader
+	}
+	if c.Ciphers == nil {
+		c.Ciphers = preferredCiphers
+	}
+	var ciphers []string
+	for _, c := range c.Ciphers {
+		if cipherModes[c] != nil {
+			// reject the cipher if we have no cipherModes definition
+			ciphers = append(ciphers, c)
+		}
+	}
+	c.Ciphers = ciphers
+
+	if c.KeyExchanges == nil {
+		c.KeyExchanges = preferredKexAlgos
+	}
+
+	if c.MACs == nil {
+		c.MACs = supportedMACs
+	}
+
+	if c.RekeyThreshold == 0 {
+		// cipher specific default
+	} else if c.RekeyThreshold < minRekeyThreshold {
+		c.RekeyThreshold = minRekeyThreshold
+	} else if c.RekeyThreshold >= math.MaxInt64 {
+		// Avoid weirdness if somebody uses -1 as a threshold.
+		c.RekeyThreshold = math.MaxInt64
+	}
+}
+
+// buildDataSignedForAuth returns the data that is signed in order to prove
+// possession of a private key. See RFC 4252, section 7.
+func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+	data := struct {
+		Session []byte
+		Type    byte
+		User    string
+		Service string
+		Method  string
+		Sign    bool
+		Algo    []byte
+		PubKey  []byte
+	}{
+		sessionID,
+		msgUserAuthRequest,
+		req.User,
+		req.Service,
+		req.Method,
+		true,
+		algo,
+		pubKey,
+	}
+	return Marshal(data)
+}
+
+func appendU16(buf []byte, n uint16) []byte {
+	return append(buf, byte(n>>8), byte(n))
+}
+
+func appendU32(buf []byte, n uint32) []byte {
+	return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendU64(buf []byte, n uint64) []byte {
+	return append(buf,
+		byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32),
+		byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendInt(buf []byte, n int) []byte {
+	return appendU32(buf, uint32(n))
+}
+
+func appendString(buf []byte, s string) []byte {
+	buf = appendU32(buf, uint32(len(s)))
+	buf = append(buf, s...)
+	return buf
+}
+
+func appendBool(buf []byte, b bool) []byte {
+	if b {
+		return append(buf, 1)
+	}
+	return append(buf, 0)
+}
+
+// newCond is a helper to hide the fact that there is no usable zero
+// value for sync.Cond.
+func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) }
+
+// window represents the buffer available to clients
+// wishing to write to a channel.
+type window struct {
+	*sync.Cond
+	win          uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1
+	writeWaiters int
+	closed       bool
+}
+
+// add adds win to the amount of window available
+// for consumers.
+func (w *window) add(win uint32) bool {
+	// a zero sized window adjust is a noop.
+	if win == 0 {
+		return true
+	}
+	w.L.Lock()
+	if w.win+win < win {
+		w.L.Unlock()
+		return false
+	}
+	w.win += win
+	// It is unusual that multiple goroutines would be attempting to reserve
+	// window space, but not guaranteed. Use broadcast to notify all waiters
+	// that additional window is available.
+	w.Broadcast()
+	w.L.Unlock()
+	return true
+}
+
+// close sets the window to closed, so all reservations fail
+// immediately.
+func (w *window) close() {
+	w.L.Lock()
+	w.closed = true
+	w.Broadcast()
+	w.L.Unlock()
+}
+
+// reserve reserves win from the available window capacity.
+// If no capacity remains, reserve will block. reserve may
+// return less than requested.
+func (w *window) reserve(win uint32) (uint32, error) {
+	var err error
+	w.L.Lock()
+	w.writeWaiters++
+	w.Broadcast()
+	for w.win == 0 && !w.closed {
+		w.Wait()
+	}
+	w.writeWaiters--
+	if w.win < win {
+		win = w.win
+	}
+	w.win -= win
+	if w.closed {
+		err = io.EOF
+	}
+	w.L.Unlock()
+	return win, err
+}
+
+// waitWriterBlocked waits until some goroutine is blocked for further
+// writes. It is used in tests only.
+func (w *window) waitWriterBlocked() {
+	w.Cond.L.Lock()
+	for w.writeWaiters == 0 {
+		w.Cond.Wait()
+	}
+	w.Cond.L.Unlock()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
new file mode 100644
index 0000000..fd6b068
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -0,0 +1,143 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"fmt"
+	"net"
+)
+
+// OpenChannelError is returned if the other side rejects an
+// OpenChannel request.
+type OpenChannelError struct {
+	Reason  RejectionReason
+	Message string
+}
+
+func (e *OpenChannelError) Error() string {
+	return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
+}
+
+// ConnMetadata holds metadata for the connection.
+type ConnMetadata interface {
+	// User returns the user ID for this connection.
+	User() string
+
+	// SessionID returns the session hash, also denoted by H.
+	SessionID() []byte
+
+	// ClientVersion returns the client's version string as hashed
+	// into the session ID.
+	ClientVersion() []byte
+
+	// ServerVersion returns the server's version string as hashed
+	// into the session ID.
+	ServerVersion() []byte
+
+	// RemoteAddr returns the remote address for this connection.
+	RemoteAddr() net.Addr
+
+	// LocalAddr returns the local address for this connection.
+	LocalAddr() net.Addr
+}
+
+// Conn represents an SSH connection for both server and client roles.
+// Conn is the basis for implementing an application layer, such
+// as ClientConn, which implements the traditional shell access for
+// clients.
+type Conn interface {
+	ConnMetadata
+
+	// SendRequest sends a global request, and returns the
+	// reply. If wantReply is true, it returns the response status
+	// and payload. See also RFC4254, section 4.
+	SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
+
+	// OpenChannel tries to open an channel. If the request is
+	// rejected, it returns *OpenChannelError. On success it returns
+	// the SSH Channel and a Go channel for incoming, out-of-band
+	// requests. The Go channel must be serviced, or the
+	// connection will hang.
+	OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
+
+	// Close closes the underlying network connection
+	Close() error
+
+	// Wait blocks until the connection has shut down, and returns the
+	// error causing the shutdown.
+	Wait() error
+
+	// TODO(hanwen): consider exposing:
+	//   RequestKeyChange
+	//   Disconnect
+}
+
+// DiscardRequests consumes and rejects all requests from the
+// passed-in channel.
+func DiscardRequests(in <-chan *Request) {
+	for req := range in {
+		if req.WantReply {
+			req.Reply(false, nil)
+		}
+	}
+}
+
+// A connection represents an incoming connection.
+type connection struct {
+	transport *handshakeTransport
+	sshConn
+
+	// The connection protocol.
+	*mux
+}
+
+func (c *connection) Close() error {
+	return c.sshConn.conn.Close()
+}
+
+// sshconn provides net.Conn metadata, but disallows direct reads and
+// writes.
+type sshConn struct {
+	conn net.Conn
+
+	user          string
+	sessionID     []byte
+	clientVersion []byte
+	serverVersion []byte
+}
+
+func dup(src []byte) []byte {
+	dst := make([]byte, len(src))
+	copy(dst, src)
+	return dst
+}
+
+func (c *sshConn) User() string {
+	return c.user
+}
+
+func (c *sshConn) RemoteAddr() net.Addr {
+	return c.conn.RemoteAddr()
+}
+
+func (c *sshConn) Close() error {
+	return c.conn.Close()
+}
+
+func (c *sshConn) LocalAddr() net.Addr {
+	return c.conn.LocalAddr()
+}
+
+func (c *sshConn) SessionID() []byte {
+	return dup(c.sessionID)
+}
+
+func (c *sshConn) ClientVersion() []byte {
+	return dup(c.clientVersion)
+}
+
+func (c *sshConn) ServerVersion() []byte {
+	return dup(c.serverVersion)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go
new file mode 100644
index 0000000..67b7322
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/doc.go
@@ -0,0 +1,21 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package ssh implements an SSH client and server.
+
+SSH is a transport security protocol, an authentication protocol and a
+family of application protocols. The most typical application level
+protocol is a remote shell and this is specifically implemented.  However,
+the multiplexed nature of SSH is exposed to users that wish to support
+others.
+
+References:
+  [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
+  [SSH-PARAMETERS]:    http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+
+This package does not fall under the stability promise of the Go language itself,
+so its API may be changed when pressing needs arise.
+*/
+package ssh // import "golang.org/x/crypto/ssh"
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
new file mode 100644
index 0000000..2b10b05
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -0,0 +1,647 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"sync"
+)
+
+// debugHandshake, if set, prints messages sent and received.  Key
+// exchange messages are printed as if DH were used, so the debug
+// messages are wrong when using ECDH.
+const debugHandshake = false
+
+// chanSize sets the amount of buffering SSH connections. This is
+// primarily for testing: setting chanSize=0 uncovers deadlocks more
+// quickly.
+const chanSize = 16
+
+// keyingTransport is a packet based transport that supports key
+// changes. It need not be thread-safe. It should pass through
+// msgNewKeys in both directions.
+type keyingTransport interface {
+	packetConn
+
+	// prepareKeyChange sets up a key change. The key change for a
+	// direction will be effected if a msgNewKeys message is sent
+	// or received.
+	prepareKeyChange(*algorithms, *kexResult) error
+}
+
+// handshakeTransport implements rekeying on top of a keyingTransport
+// and offers a thread-safe writePacket() interface.
+type handshakeTransport struct {
+	conn   keyingTransport
+	config *Config
+
+	serverVersion []byte
+	clientVersion []byte
+
+	// hostKeys is non-empty if we are the server. In that case,
+	// it contains all host keys that can be used to sign the
+	// connection.
+	hostKeys []Signer
+
+	// hostKeyAlgorithms is non-empty if we are the client. In that case,
+	// we accept these key types from the server as host key.
+	hostKeyAlgorithms []string
+
+	// On read error, incoming is closed, and readError is set.
+	incoming  chan []byte
+	readError error
+
+	mu             sync.Mutex
+	writeError     error
+	sentInitPacket []byte
+	sentInitMsg    *kexInitMsg
+	pendingPackets [][]byte // Used when a key exchange is in progress.
+
+	// If the read loop wants to schedule a kex, it pings this
+	// channel, and the write loop will send out a kex
+	// message.
+	requestKex chan struct{}
+
+	// If the other side requests or confirms a kex, its kexInit
+	// packet is sent here for the write loop to find it.
+	startKex chan *pendingKex
+
+	// data for host key checking
+	hostKeyCallback HostKeyCallback
+	dialAddress     string
+	remoteAddr      net.Addr
+
+	// bannerCallback is non-empty if we are the client and it has been set in
+	// ClientConfig. In that case it is called during the user authentication
+	// dance to handle a custom server's message.
+	bannerCallback BannerCallback
+
+	// Algorithms agreed in the last key exchange.
+	algorithms *algorithms
+
+	readPacketsLeft uint32
+	readBytesLeft   int64
+
+	writePacketsLeft uint32
+	writeBytesLeft   int64
+
+	// The session ID or nil if first kex did not complete yet.
+	sessionID []byte
+}
+
+type pendingKex struct {
+	otherInit []byte
+	done      chan error
+}
+
+func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
+	t := &handshakeTransport{
+		conn:          conn,
+		serverVersion: serverVersion,
+		clientVersion: clientVersion,
+		incoming:      make(chan []byte, chanSize),
+		requestKex:    make(chan struct{}, 1),
+		startKex:      make(chan *pendingKex, 1),
+
+		config: config,
+	}
+	t.resetReadThresholds()
+	t.resetWriteThresholds()
+
+	// We always start with a mandatory key exchange.
+	t.requestKex <- struct{}{}
+	return t
+}
+
+func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport {
+	t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+	t.dialAddress = dialAddr
+	t.remoteAddr = addr
+	t.hostKeyCallback = config.HostKeyCallback
+	t.bannerCallback = config.BannerCallback
+	if config.HostKeyAlgorithms != nil {
+		t.hostKeyAlgorithms = config.HostKeyAlgorithms
+	} else {
+		t.hostKeyAlgorithms = supportedHostKeyAlgos
+	}
+	go t.readLoop()
+	go t.kexLoop()
+	return t
+}
+
+func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport {
+	t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+	t.hostKeys = config.hostKeys
+	go t.readLoop()
+	go t.kexLoop()
+	return t
+}
+
+func (t *handshakeTransport) getSessionID() []byte {
+	return t.sessionID
+}
+
+// waitSession waits for the session to be established. This should be
+// the first thing to call after instantiating handshakeTransport.
+func (t *handshakeTransport) waitSession() error {
+	p, err := t.readPacket()
+	if err != nil {
+		return err
+	}
+	if p[0] != msgNewKeys {
+		return fmt.Errorf("ssh: first packet should be msgNewKeys")
+	}
+
+	return nil
+}
+
+func (t *handshakeTransport) id() string {
+	if len(t.hostKeys) > 0 {
+		return "server"
+	}
+	return "client"
+}
+
+func (t *handshakeTransport) printPacket(p []byte, write bool) {
+	action := "got"
+	if write {
+		action = "sent"
+	}
+
+	if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
+		log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
+	} else {
+		msg, err := decode(p)
+		log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
+	}
+}
+
+func (t *handshakeTransport) readPacket() ([]byte, error) {
+	p, ok := <-t.incoming
+	if !ok {
+		return nil, t.readError
+	}
+	return p, nil
+}
+
+func (t *handshakeTransport) readLoop() {
+	first := true
+	for {
+		p, err := t.readOnePacket(first)
+		first = false
+		if err != nil {
+			t.readError = err
+			close(t.incoming)
+			break
+		}
+		if p[0] == msgIgnore || p[0] == msgDebug {
+			continue
+		}
+		t.incoming <- p
+	}
+
+	// Stop writers too.
+	t.recordWriteError(t.readError)
+
+	// Unblock the writer should it wait for this.
+	close(t.startKex)
+
+	// Don't close t.requestKex; it's also written to from writePacket.
+}
+
+func (t *handshakeTransport) pushPacket(p []byte) error {
+	if debugHandshake {
+		t.printPacket(p, true)
+	}
+	return t.conn.writePacket(p)
+}
+
+func (t *handshakeTransport) getWriteError() error {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	return t.writeError
+}
+
+func (t *handshakeTransport) recordWriteError(err error) {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	if t.writeError == nil && err != nil {
+		t.writeError = err
+	}
+}
+
+func (t *handshakeTransport) requestKeyExchange() {
+	select {
+	case t.requestKex <- struct{}{}:
+	default:
+		// something already requested a kex, so do nothing.
+	}
+}
+
+func (t *handshakeTransport) resetWriteThresholds() {
+	t.writePacketsLeft = packetRekeyThreshold
+	if t.config.RekeyThreshold > 0 {
+		t.writeBytesLeft = int64(t.config.RekeyThreshold)
+	} else if t.algorithms != nil {
+		t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+	} else {
+		t.writeBytesLeft = 1 << 30
+	}
+}
+
+func (t *handshakeTransport) kexLoop() {
+
+write:
+	for t.getWriteError() == nil {
+		var request *pendingKex
+		var sent bool
+
+		for request == nil || !sent {
+			var ok bool
+			select {
+			case request, ok = <-t.startKex:
+				if !ok {
+					break write
+				}
+			case <-t.requestKex:
+				break
+			}
+
+			if !sent {
+				if err := t.sendKexInit(); err != nil {
+					t.recordWriteError(err)
+					break
+				}
+				sent = true
+			}
+		}
+
+		if err := t.getWriteError(); err != nil {
+			if request != nil {
+				request.done <- err
+			}
+			break
+		}
+
+		// We're not servicing t.requestKex, but that is OK:
+		// we never block on sending to t.requestKex.
+
+		// We're not servicing t.startKex, but the remote end
+		// has just sent us a kexInitMsg, so it can't send
+		// another key change request, until we close the done
+		// channel on the pendingKex request.
+
+		err := t.enterKeyExchange(request.otherInit)
+
+		t.mu.Lock()
+		t.writeError = err
+		t.sentInitPacket = nil
+		t.sentInitMsg = nil
+
+		t.resetWriteThresholds()
+
+		// we have completed the key exchange. Since the
+		// reader is still blocked, it is safe to clear out
+		// the requestKex channel. This avoids the situation
+		// where: 1) we consumed our own request for the
+		// initial kex, and 2) the kex from the remote side
+		// caused another send on the requestKex channel,
+	clear:
+		for {
+			select {
+			case <-t.requestKex:
+				//
+			default:
+				break clear
+			}
+		}
+
+		request.done <- t.writeError
+
+		// kex finished. Push packets that we received while
+		// the kex was in progress. Don't look at t.startKex
+		// and don't increment writtenSinceKex: if we trigger
+		// another kex while we are still busy with the last
+		// one, things will become very confusing.
+		for _, p := range t.pendingPackets {
+			t.writeError = t.pushPacket(p)
+			if t.writeError != nil {
+				break
+			}
+		}
+		t.pendingPackets = t.pendingPackets[:0]
+		t.mu.Unlock()
+	}
+
+	// drain startKex channel. We don't service t.requestKex
+	// because nobody does blocking sends there.
+	go func() {
+		for init := range t.startKex {
+			init.done <- t.writeError
+		}
+	}()
+
+	// Unblock reader.
+	t.conn.Close()
+}
+
+// The protocol uses uint32 for packet counters, so we can't let them
+// reach 1<<32.  We will actually read and write more packets than
+// this, though: the other side may send more packets, and after we
+// hit this limit on writing we will send a few more packets for the
+// key exchange itself.
+const packetRekeyThreshold = (1 << 31)
+
+func (t *handshakeTransport) resetReadThresholds() {
+	t.readPacketsLeft = packetRekeyThreshold
+	if t.config.RekeyThreshold > 0 {
+		t.readBytesLeft = int64(t.config.RekeyThreshold)
+	} else if t.algorithms != nil {
+		t.readBytesLeft = t.algorithms.r.rekeyBytes()
+	} else {
+		t.readBytesLeft = 1 << 30
+	}
+}
+
+func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
+	p, err := t.conn.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	if t.readPacketsLeft > 0 {
+		t.readPacketsLeft--
+	} else {
+		t.requestKeyExchange()
+	}
+
+	if t.readBytesLeft > 0 {
+		t.readBytesLeft -= int64(len(p))
+	} else {
+		t.requestKeyExchange()
+	}
+
+	if debugHandshake {
+		t.printPacket(p, false)
+	}
+
+	if first && p[0] != msgKexInit {
+		return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
+	}
+
+	if p[0] != msgKexInit {
+		return p, nil
+	}
+
+	firstKex := t.sessionID == nil
+
+	kex := pendingKex{
+		done:      make(chan error, 1),
+		otherInit: p,
+	}
+	t.startKex <- &kex
+	err = <-kex.done
+
+	if debugHandshake {
+		log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
+	}
+
+	if err != nil {
+		return nil, err
+	}
+
+	t.resetReadThresholds()
+
+	// By default, a key exchange is hidden from higher layers by
+	// translating it into msgIgnore.
+	successPacket := []byte{msgIgnore}
+	if firstKex {
+		// sendKexInit() for the first kex waits for
+		// msgNewKeys so the authentication process is
+		// guaranteed to happen over an encrypted transport.
+		successPacket = []byte{msgNewKeys}
+	}
+
+	return successPacket, nil
+}
+
+// sendKexInit sends a key change message.
+func (t *handshakeTransport) sendKexInit() error {
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	if t.sentInitMsg != nil {
+		// kexInits may be sent either in response to the other side,
+		// or because our side wants to initiate a key change, so we
+		// may have already sent a kexInit. In that case, don't send a
+		// second kexInit.
+		return nil
+	}
+
+	msg := &kexInitMsg{
+		KexAlgos:                t.config.KeyExchanges,
+		CiphersClientServer:     t.config.Ciphers,
+		CiphersServerClient:     t.config.Ciphers,
+		MACsClientServer:        t.config.MACs,
+		MACsServerClient:        t.config.MACs,
+		CompressionClientServer: supportedCompressions,
+		CompressionServerClient: supportedCompressions,
+	}
+	io.ReadFull(rand.Reader, msg.Cookie[:])
+
+	if len(t.hostKeys) > 0 {
+		for _, k := range t.hostKeys {
+			msg.ServerHostKeyAlgos = append(
+				msg.ServerHostKeyAlgos, k.PublicKey().Type())
+		}
+	} else {
+		msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
+	}
+	packet := Marshal(msg)
+
+	// writePacket destroys the contents, so save a copy.
+	packetCopy := make([]byte, len(packet))
+	copy(packetCopy, packet)
+
+	if err := t.pushPacket(packetCopy); err != nil {
+		return err
+	}
+
+	t.sentInitMsg = msg
+	t.sentInitPacket = packet
+
+	return nil
+}
+
+func (t *handshakeTransport) writePacket(p []byte) error {
+	switch p[0] {
+	case msgKexInit:
+		return errors.New("ssh: only handshakeTransport can send kexInit")
+	case msgNewKeys:
+		return errors.New("ssh: only handshakeTransport can send newKeys")
+	}
+
+	t.mu.Lock()
+	defer t.mu.Unlock()
+	if t.writeError != nil {
+		return t.writeError
+	}
+
+	if t.sentInitMsg != nil {
+		// Copy the packet so the writer can reuse the buffer.
+		cp := make([]byte, len(p))
+		copy(cp, p)
+		t.pendingPackets = append(t.pendingPackets, cp)
+		return nil
+	}
+
+	if t.writeBytesLeft > 0 {
+		t.writeBytesLeft -= int64(len(p))
+	} else {
+		t.requestKeyExchange()
+	}
+
+	if t.writePacketsLeft > 0 {
+		t.writePacketsLeft--
+	} else {
+		t.requestKeyExchange()
+	}
+
+	if err := t.pushPacket(p); err != nil {
+		t.writeError = err
+	}
+
+	return nil
+}
+
+func (t *handshakeTransport) Close() error {
+	return t.conn.Close()
+}
+
+func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
+	if debugHandshake {
+		log.Printf("%s entered key exchange", t.id())
+	}
+
+	otherInit := &kexInitMsg{}
+	if err := Unmarshal(otherInitPacket, otherInit); err != nil {
+		return err
+	}
+
+	magics := handshakeMagics{
+		clientVersion: t.clientVersion,
+		serverVersion: t.serverVersion,
+		clientKexInit: otherInitPacket,
+		serverKexInit: t.sentInitPacket,
+	}
+
+	clientInit := otherInit
+	serverInit := t.sentInitMsg
+	isClient := len(t.hostKeys) == 0
+	if isClient {
+		clientInit, serverInit = serverInit, clientInit
+
+		magics.clientKexInit = t.sentInitPacket
+		magics.serverKexInit = otherInitPacket
+	}
+
+	var err error
+	t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit)
+	if err != nil {
+		return err
+	}
+
+	// We don't send FirstKexFollows, but we handle receiving it.
+	//
+	// RFC 4253 section 7 defines the kex and the agreement method for
+	// first_kex_packet_follows. It states that the guessed packet
+	// should be ignored if the "kex algorithm and/or the host
+	// key algorithm is guessed wrong (server and client have
+	// different preferred algorithm), or if any of the other
+	// algorithms cannot be agreed upon". The other algorithms have
+	// already been checked above so the kex algorithm and host key
+	// algorithm are checked here.
+	if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) {
+		// other side sent a kex message for the wrong algorithm,
+		// which we have to ignore.
+		if _, err := t.conn.readPacket(); err != nil {
+			return err
+		}
+	}
+
+	kex, ok := kexAlgoMap[t.algorithms.kex]
+	if !ok {
+		return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
+	}
+
+	var result *kexResult
+	if len(t.hostKeys) > 0 {
+		result, err = t.server(kex, t.algorithms, &magics)
+	} else {
+		result, err = t.client(kex, t.algorithms, &magics)
+	}
+
+	if err != nil {
+		return err
+	}
+
+	if t.sessionID == nil {
+		t.sessionID = result.H
+	}
+	result.SessionID = t.sessionID
+
+	if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
+		return err
+	}
+	if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
+		return err
+	}
+	if packet, err := t.conn.readPacket(); err != nil {
+		return err
+	} else if packet[0] != msgNewKeys {
+		return unexpectedMessageError(msgNewKeys, packet[0])
+	}
+
+	return nil
+}
+
+func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+	var hostKey Signer
+	for _, k := range t.hostKeys {
+		if algs.hostKey == k.PublicKey().Type() {
+			hostKey = k
+		}
+	}
+
+	r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey)
+	return r, err
+}
+
+func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+	result, err := kex.Client(t.conn, t.config.Rand, magics)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKey, err := ParsePublicKey(result.HostKey)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := verifyHostKeySignature(hostKey, result); err != nil {
+		return nil, err
+	}
+
+	err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go b/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
new file mode 100644
index 0000000..af81d26
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf/bcrypt_pbkdf.go
@@ -0,0 +1,93 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD.
+//
+// See https://flak.tedunangst.com/post/bcrypt-pbkdf and
+// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c.
+package bcrypt_pbkdf
+
+import (
+	"crypto/sha512"
+	"errors"
+	"golang.org/x/crypto/blowfish"
+)
+
+const blockSize = 32
+
+// Key derives a key from the password, salt and rounds count, returning a
+// []byte of length keyLen that can be used as cryptographic key.
+func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) {
+	if rounds < 1 {
+		return nil, errors.New("bcrypt_pbkdf: number of rounds is too small")
+	}
+	if len(password) == 0 {
+		return nil, errors.New("bcrypt_pbkdf: empty password")
+	}
+	if len(salt) == 0 || len(salt) > 1<<20 {
+		return nil, errors.New("bcrypt_pbkdf: bad salt length")
+	}
+	if keyLen > 1024 {
+		return nil, errors.New("bcrypt_pbkdf: keyLen is too large")
+	}
+
+	numBlocks := (keyLen + blockSize - 1) / blockSize
+	key := make([]byte, numBlocks*blockSize)
+
+	h := sha512.New()
+	h.Write(password)
+	shapass := h.Sum(nil)
+
+	shasalt := make([]byte, 0, sha512.Size)
+	cnt, tmp := make([]byte, 4), make([]byte, blockSize)
+	for block := 1; block <= numBlocks; block++ {
+		h.Reset()
+		h.Write(salt)
+		cnt[0] = byte(block >> 24)
+		cnt[1] = byte(block >> 16)
+		cnt[2] = byte(block >> 8)
+		cnt[3] = byte(block)
+		h.Write(cnt)
+		bcryptHash(tmp, shapass, h.Sum(shasalt))
+
+		out := make([]byte, blockSize)
+		copy(out, tmp)
+		for i := 2; i <= rounds; i++ {
+			h.Reset()
+			h.Write(tmp)
+			bcryptHash(tmp, shapass, h.Sum(shasalt))
+			for j := 0; j < len(out); j++ {
+				out[j] ^= tmp[j]
+			}
+		}
+
+		for i, v := range out {
+			key[i*numBlocks+(block-1)] = v
+		}
+	}
+	return key[:keyLen], nil
+}
+
+var magic = []byte("OxychromaticBlowfishSwatDynamite")
+
+func bcryptHash(out, shapass, shasalt []byte) {
+	c, err := blowfish.NewSaltedCipher(shapass, shasalt)
+	if err != nil {
+		panic(err)
+	}
+	for i := 0; i < 64; i++ {
+		blowfish.ExpandKey(shasalt, c)
+		blowfish.ExpandKey(shapass, c)
+	}
+	copy(out, magic)
+	for i := 0; i < 32; i += 8 {
+		for j := 0; j < 64; j++ {
+			c.Encrypt(out[i:i+8], out[i:i+8])
+		}
+	}
+	// Swap bytes due to different endianness.
+	for i := 0; i < 32; i += 4 {
+		out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3]
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
new file mode 100644
index 0000000..766e929
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -0,0 +1,782 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/subtle"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+
+	"golang.org/x/crypto/curve25519"
+)
+
+const (
+	kexAlgoDH1SHA1          = "diffie-hellman-group1-sha1"
+	kexAlgoDH14SHA1         = "diffie-hellman-group14-sha1"
+	kexAlgoECDH256          = "ecdh-sha2-nistp256"
+	kexAlgoECDH384          = "ecdh-sha2-nistp384"
+	kexAlgoECDH521          = "ecdh-sha2-nistp521"
+	kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
+
+	// For the following kex only the client half contains a production
+	// ready implementation. The server half only consists of a minimal
+	// implementation to satisfy the automated tests.
+	kexAlgoDHGEXSHA1   = "diffie-hellman-group-exchange-sha1"
+	kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
+)
+
+// kexResult captures the outcome of a key exchange.
+type kexResult struct {
+	// Session hash. See also RFC 4253, section 8.
+	H []byte
+
+	// Shared secret. See also RFC 4253, section 8.
+	K []byte
+
+	// Host key as hashed into H.
+	HostKey []byte
+
+	// Signature of H.
+	Signature []byte
+
+	// A cryptographic hash function that matches the security
+	// level of the key exchange algorithm. It is used for
+	// calculating H, and for deriving keys from H and K.
+	Hash crypto.Hash
+
+	// The session ID, which is the first H computed. This is used
+	// to derive key material inside the transport.
+	SessionID []byte
+}
+
+// handshakeMagics contains data that is always included in the
+// session hash.
+type handshakeMagics struct {
+	clientVersion, serverVersion []byte
+	clientKexInit, serverKexInit []byte
+}
+
+func (m *handshakeMagics) write(w io.Writer) {
+	writeString(w, m.clientVersion)
+	writeString(w, m.serverVersion)
+	writeString(w, m.clientKexInit)
+	writeString(w, m.serverKexInit)
+}
+
+// kexAlgorithm abstracts different key exchange algorithms.
+type kexAlgorithm interface {
+	// Server runs server-side key agreement, signing the result
+	// with a hostkey.
+	Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
+
+	// Client runs the client-side key agreement. Caller is
+	// responsible for verifying the host key signature.
+	Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
+}
+
+// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
+type dhGroup struct {
+	g, p, pMinus1 *big.Int
+}
+
+func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
+	if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
+		return nil, errors.New("ssh: DH parameter out of bounds")
+	}
+	return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
+}
+
+func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
+	hashFunc := crypto.SHA1
+
+	var x *big.Int
+	for {
+		var err error
+		if x, err = rand.Int(randSource, group.pMinus1); err != nil {
+			return nil, err
+		}
+		if x.Sign() > 0 {
+			break
+		}
+	}
+
+	X := new(big.Int).Exp(group.g, x, group.p)
+	kexDHInit := kexDHInitMsg{
+		X: X,
+	}
+	if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var kexDHReply kexDHReplyMsg
+	if err = Unmarshal(packet, &kexDHReply); err != nil {
+		return nil, err
+	}
+
+	ki, err := group.diffieHellman(kexDHReply.Y, x)
+	if err != nil {
+		return nil, err
+	}
+
+	h := hashFunc.New()
+	magics.write(h)
+	writeString(h, kexDHReply.HostKey)
+	writeInt(h, X)
+	writeInt(h, kexDHReply.Y)
+	K := make([]byte, intLength(ki))
+	marshalInt(K, ki)
+	h.Write(K)
+
+	return &kexResult{
+		H:         h.Sum(nil),
+		K:         K,
+		HostKey:   kexDHReply.HostKey,
+		Signature: kexDHReply.Signature,
+		Hash:      crypto.SHA1,
+	}, nil
+}
+
+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+	hashFunc := crypto.SHA1
+	packet, err := c.readPacket()
+	if err != nil {
+		return
+	}
+	var kexDHInit kexDHInitMsg
+	if err = Unmarshal(packet, &kexDHInit); err != nil {
+		return
+	}
+
+	var y *big.Int
+	for {
+		if y, err = rand.Int(randSource, group.pMinus1); err != nil {
+			return
+		}
+		if y.Sign() > 0 {
+			break
+		}
+	}
+
+	Y := new(big.Int).Exp(group.g, y, group.p)
+	ki, err := group.diffieHellman(kexDHInit.X, y)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKeyBytes := priv.PublicKey().Marshal()
+
+	h := hashFunc.New()
+	magics.write(h)
+	writeString(h, hostKeyBytes)
+	writeInt(h, kexDHInit.X)
+	writeInt(h, Y)
+
+	K := make([]byte, intLength(ki))
+	marshalInt(K, ki)
+	h.Write(K)
+
+	H := h.Sum(nil)
+
+	// H is already a hash, but the hostkey signing will apply its
+	// own key-specific hash algorithm.
+	sig, err := signAndMarshal(priv, randSource, H)
+	if err != nil {
+		return nil, err
+	}
+
+	kexDHReply := kexDHReplyMsg{
+		HostKey:   hostKeyBytes,
+		Y:         Y,
+		Signature: sig,
+	}
+	packet = Marshal(&kexDHReply)
+
+	err = c.writePacket(packet)
+	return &kexResult{
+		H:         H,
+		K:         K,
+		HostKey:   hostKeyBytes,
+		Signature: sig,
+		Hash:      crypto.SHA1,
+	}, err
+}
+
+// ecdh performs Elliptic Curve Diffie-Hellman key exchange as
+// described in RFC 5656, section 4.
+type ecdh struct {
+	curve elliptic.Curve
+}
+
+func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+	ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+	if err != nil {
+		return nil, err
+	}
+
+	kexInit := kexECDHInitMsg{
+		ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
+	}
+
+	serialized := Marshal(&kexInit)
+	if err := c.writePacket(serialized); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var reply kexECDHReplyMsg
+	if err = Unmarshal(packet, &reply); err != nil {
+		return nil, err
+	}
+
+	x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
+	if err != nil {
+		return nil, err
+	}
+
+	// generate shared secret
+	secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
+
+	h := ecHash(kex.curve).New()
+	magics.write(h)
+	writeString(h, reply.HostKey)
+	writeString(h, kexInit.ClientPubKey)
+	writeString(h, reply.EphemeralPubKey)
+	K := make([]byte, intLength(secret))
+	marshalInt(K, secret)
+	h.Write(K)
+
+	return &kexResult{
+		H:         h.Sum(nil),
+		K:         K,
+		HostKey:   reply.HostKey,
+		Signature: reply.Signature,
+		Hash:      ecHash(kex.curve),
+	}, nil
+}
+
+// unmarshalECKey parses and checks an EC key.
+func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
+	x, y = elliptic.Unmarshal(curve, pubkey)
+	if x == nil {
+		return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
+	}
+	if !validateECPublicKey(curve, x, y) {
+		return nil, nil, errors.New("ssh: public key not on curve")
+	}
+	return x, y, nil
+}
+
+// validateECPublicKey checks that the point is a valid public key for
+// the given curve. See [SEC1], 3.2.2
+func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
+	if x.Sign() == 0 && y.Sign() == 0 {
+		return false
+	}
+
+	if x.Cmp(curve.Params().P) >= 0 {
+		return false
+	}
+
+	if y.Cmp(curve.Params().P) >= 0 {
+		return false
+	}
+
+	if !curve.IsOnCurve(x, y) {
+		return false
+	}
+
+	// We don't check if N * PubKey == 0, since
+	//
+	// - the NIST curves have cofactor = 1, so this is implicit.
+	// (We don't foresee an implementation that supports non NIST
+	// curves)
+	//
+	// - for ephemeral keys, we don't need to worry about small
+	// subgroup attacks.
+	return true
+}
+
+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var kexECDHInit kexECDHInitMsg
+	if err = Unmarshal(packet, &kexECDHInit); err != nil {
+		return nil, err
+	}
+
+	clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
+	if err != nil {
+		return nil, err
+	}
+
+	// We could cache this key across multiple users/multiple
+	// connection attempts, but the benefit is small. OpenSSH
+	// generates a new key for each incoming connection.
+	ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKeyBytes := priv.PublicKey().Marshal()
+
+	serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
+
+	// generate shared secret
+	secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
+
+	h := ecHash(kex.curve).New()
+	magics.write(h)
+	writeString(h, hostKeyBytes)
+	writeString(h, kexECDHInit.ClientPubKey)
+	writeString(h, serializedEphKey)
+
+	K := make([]byte, intLength(secret))
+	marshalInt(K, secret)
+	h.Write(K)
+
+	H := h.Sum(nil)
+
+	// H is already a hash, but the hostkey signing will apply its
+	// own key-specific hash algorithm.
+	sig, err := signAndMarshal(priv, rand, H)
+	if err != nil {
+		return nil, err
+	}
+
+	reply := kexECDHReplyMsg{
+		EphemeralPubKey: serializedEphKey,
+		HostKey:         hostKeyBytes,
+		Signature:       sig,
+	}
+
+	serialized := Marshal(&reply)
+	if err := c.writePacket(serialized); err != nil {
+		return nil, err
+	}
+
+	return &kexResult{
+		H:         H,
+		K:         K,
+		HostKey:   reply.HostKey,
+		Signature: sig,
+		Hash:      ecHash(kex.curve),
+	}, nil
+}
+
+var kexAlgoMap = map[string]kexAlgorithm{}
+
+func init() {
+	// This is the group called diffie-hellman-group1-sha1 in RFC
+	// 4253 and Oakley Group 2 in RFC 2409.
+	p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
+	kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
+		g:       new(big.Int).SetInt64(2),
+		p:       p,
+		pMinus1: new(big.Int).Sub(p, bigOne),
+	}
+
+	// This is the group called diffie-hellman-group14-sha1 in RFC
+	// 4253 and Oakley Group 14 in RFC 3526.
+	p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+
+	kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
+		g:       new(big.Int).SetInt64(2),
+		p:       p,
+		pMinus1: new(big.Int).Sub(p, bigOne),
+	}
+
+	kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
+	kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
+	kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
+	kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
+	kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
+	kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
+}
+
+// curve25519sha256 implements the curve25519-sha256@libssh.org key
+// agreement protocol, as described in
+// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt
+type curve25519sha256 struct{}
+
+type curve25519KeyPair struct {
+	priv [32]byte
+	pub  [32]byte
+}
+
+func (kp *curve25519KeyPair) generate(rand io.Reader) error {
+	if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
+		return err
+	}
+	curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
+	return nil
+}
+
+// curve25519Zeros is just an array of 32 zero bytes so that we have something
+// convenient to compare against in order to reject curve25519 points with the
+// wrong order.
+var curve25519Zeros [32]byte
+
+func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+	var kp curve25519KeyPair
+	if err := kp.generate(rand); err != nil {
+		return nil, err
+	}
+	if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var reply kexECDHReplyMsg
+	if err = Unmarshal(packet, &reply); err != nil {
+		return nil, err
+	}
+	if len(reply.EphemeralPubKey) != 32 {
+		return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
+	}
+
+	var servPub, secret [32]byte
+	copy(servPub[:], reply.EphemeralPubKey)
+	curve25519.ScalarMult(&secret, &kp.priv, &servPub)
+	if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
+		return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
+	}
+
+	h := crypto.SHA256.New()
+	magics.write(h)
+	writeString(h, reply.HostKey)
+	writeString(h, kp.pub[:])
+	writeString(h, reply.EphemeralPubKey)
+
+	ki := new(big.Int).SetBytes(secret[:])
+	K := make([]byte, intLength(ki))
+	marshalInt(K, ki)
+	h.Write(K)
+
+	return &kexResult{
+		H:         h.Sum(nil),
+		K:         K,
+		HostKey:   reply.HostKey,
+		Signature: reply.Signature,
+		Hash:      crypto.SHA256,
+	}, nil
+}
+
+func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+	packet, err := c.readPacket()
+	if err != nil {
+		return
+	}
+	var kexInit kexECDHInitMsg
+	if err = Unmarshal(packet, &kexInit); err != nil {
+		return
+	}
+
+	if len(kexInit.ClientPubKey) != 32 {
+		return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
+	}
+
+	var kp curve25519KeyPair
+	if err := kp.generate(rand); err != nil {
+		return nil, err
+	}
+
+	var clientPub, secret [32]byte
+	copy(clientPub[:], kexInit.ClientPubKey)
+	curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
+	if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
+		return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
+	}
+
+	hostKeyBytes := priv.PublicKey().Marshal()
+
+	h := crypto.SHA256.New()
+	magics.write(h)
+	writeString(h, hostKeyBytes)
+	writeString(h, kexInit.ClientPubKey)
+	writeString(h, kp.pub[:])
+
+	ki := new(big.Int).SetBytes(secret[:])
+	K := make([]byte, intLength(ki))
+	marshalInt(K, ki)
+	h.Write(K)
+
+	H := h.Sum(nil)
+
+	sig, err := signAndMarshal(priv, rand, H)
+	if err != nil {
+		return nil, err
+	}
+
+	reply := kexECDHReplyMsg{
+		EphemeralPubKey: kp.pub[:],
+		HostKey:         hostKeyBytes,
+		Signature:       sig,
+	}
+	if err := c.writePacket(Marshal(&reply)); err != nil {
+		return nil, err
+	}
+	return &kexResult{
+		H:         H,
+		K:         K,
+		HostKey:   hostKeyBytes,
+		Signature: sig,
+		Hash:      crypto.SHA256,
+	}, nil
+}
+
+// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and
+// diffie-hellman-group-exchange-sha256 key agreement protocols,
+// as described in RFC 4419
+type dhGEXSHA struct {
+	g, p     *big.Int
+	hashFunc crypto.Hash
+}
+
+const (
+	dhGroupExchangeMinimumBits   = 2048
+	dhGroupExchangePreferredBits = 2048
+	dhGroupExchangeMaximumBits   = 8192
+)
+
+func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
+	if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 {
+		return nil, fmt.Errorf("ssh: DH parameter out of bounds")
+	}
+	return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
+}
+
+func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
+	// Send GexRequest
+	kexDHGexRequest := kexDHGexRequestMsg{
+		MinBits:      dhGroupExchangeMinimumBits,
+		PreferedBits: dhGroupExchangePreferredBits,
+		MaxBits:      dhGroupExchangeMaximumBits,
+	}
+	if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
+		return nil, err
+	}
+
+	// Receive GexGroup
+	packet, err := c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var kexDHGexGroup kexDHGexGroupMsg
+	if err = Unmarshal(packet, &kexDHGexGroup); err != nil {
+		return nil, err
+	}
+
+	// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
+	if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits {
+		return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen())
+	}
+
+	gex.p = kexDHGexGroup.P
+	gex.g = kexDHGexGroup.G
+
+	// Check if g is safe by verifing that g > 1 and g < p - 1
+	one := big.NewInt(1)
+	var pMinusOne = &big.Int{}
+	pMinusOne.Sub(gex.p, one)
+	if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
+		return nil, fmt.Errorf("ssh: server provided gex g is not safe")
+	}
+
+	// Send GexInit
+	var pHalf = &big.Int{}
+	pHalf.Rsh(gex.p, 1)
+	x, err := rand.Int(randSource, pHalf)
+	if err != nil {
+		return nil, err
+	}
+	X := new(big.Int).Exp(gex.g, x, gex.p)
+	kexDHGexInit := kexDHGexInitMsg{
+		X: X,
+	}
+	if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil {
+		return nil, err
+	}
+
+	// Receive GexReply
+	packet, err = c.readPacket()
+	if err != nil {
+		return nil, err
+	}
+
+	var kexDHGexReply kexDHGexReplyMsg
+	if err = Unmarshal(packet, &kexDHGexReply); err != nil {
+		return nil, err
+	}
+
+	kInt, err := gex.diffieHellman(kexDHGexReply.Y, x)
+	if err != nil {
+		return nil, err
+	}
+
+	// Check if k is safe by verifing that k > 1 and k < p - 1
+	if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 {
+		return nil, fmt.Errorf("ssh: derived k is not safe")
+	}
+
+	h := gex.hashFunc.New()
+	magics.write(h)
+	writeString(h, kexDHGexReply.HostKey)
+	binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
+	binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
+	binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
+	writeInt(h, gex.p)
+	writeInt(h, gex.g)
+	writeInt(h, X)
+	writeInt(h, kexDHGexReply.Y)
+	K := make([]byte, intLength(kInt))
+	marshalInt(K, kInt)
+	h.Write(K)
+
+	return &kexResult{
+		H:         h.Sum(nil),
+		K:         K,
+		HostKey:   kexDHGexReply.HostKey,
+		Signature: kexDHGexReply.Signature,
+		Hash:      gex.hashFunc,
+	}, nil
+}
+
+// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
+//
+// This is a minimal implementation to satisfy the automated tests.
+func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+	// Receive GexRequest
+	packet, err := c.readPacket()
+	if err != nil {
+		return
+	}
+	var kexDHGexRequest kexDHGexRequestMsg
+	if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
+		return
+	}
+
+	// smoosh the user's preferred size into our own limits
+	if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits {
+		kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits
+	}
+	if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits {
+		kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits
+	}
+	// fix min/max if they're inconsistent.  technically, we could just pout
+	// and hang up, but there's no harm in giving them the benefit of the
+	// doubt and just picking a bitsize for them.
+	if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits {
+		kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits
+	}
+	if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits {
+		kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits
+	}
+
+	// Send GexGroup
+	// This is the group called diffie-hellman-group14-sha1 in RFC
+	// 4253 and Oakley Group 14 in RFC 3526.
+	p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+	gex.p = p
+	gex.g = big.NewInt(2)
+
+	kexDHGexGroup := kexDHGexGroupMsg{
+		P: gex.p,
+		G: gex.g,
+	}
+	if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil {
+		return nil, err
+	}
+
+	// Receive GexInit
+	packet, err = c.readPacket()
+	if err != nil {
+		return
+	}
+	var kexDHGexInit kexDHGexInitMsg
+	if err = Unmarshal(packet, &kexDHGexInit); err != nil {
+		return
+	}
+
+	var pHalf = &big.Int{}
+	pHalf.Rsh(gex.p, 1)
+
+	y, err := rand.Int(randSource, pHalf)
+	if err != nil {
+		return
+	}
+
+	Y := new(big.Int).Exp(gex.g, y, gex.p)
+	kInt, err := gex.diffieHellman(kexDHGexInit.X, y)
+	if err != nil {
+		return nil, err
+	}
+
+	hostKeyBytes := priv.PublicKey().Marshal()
+
+	h := gex.hashFunc.New()
+	magics.write(h)
+	writeString(h, hostKeyBytes)
+	binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
+	binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
+	binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
+	writeInt(h, gex.p)
+	writeInt(h, gex.g)
+	writeInt(h, kexDHGexInit.X)
+	writeInt(h, Y)
+
+	K := make([]byte, intLength(kInt))
+	marshalInt(K, kInt)
+	h.Write(K)
+
+	H := h.Sum(nil)
+
+	// H is already a hash, but the hostkey signing will apply its
+	// own key-specific hash algorithm.
+	sig, err := signAndMarshal(priv, randSource, H)
+	if err != nil {
+		return nil, err
+	}
+
+	kexDHGexReply := kexDHGexReplyMsg{
+		HostKey:   hostKeyBytes,
+		Y:         Y,
+		Signature: sig,
+	}
+	packet = Marshal(&kexDHGexReply)
+
+	err = c.writePacket(packet)
+
+	return &kexResult{
+		H:         H,
+		K:         K,
+		HostKey:   hostKeyBytes,
+		Signature: sig,
+		Hash:      gex.hashFunc,
+	}, err
+}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
new file mode 100644
index 0000000..31f2634
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -0,0 +1,1474 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/dsa"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/md5"
+	"crypto/rsa"
+	"crypto/sha256"
+	"crypto/x509"
+	"encoding/asn1"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/pem"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"strings"
+
+	"golang.org/x/crypto/ed25519"
+	"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
+)
+
+// These constants represent the algorithm names for key types supported by this
+// package.
+const (
+	KeyAlgoRSA        = "ssh-rsa"
+	KeyAlgoDSA        = "ssh-dss"
+	KeyAlgoECDSA256   = "ecdsa-sha2-nistp256"
+	KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
+	KeyAlgoECDSA384   = "ecdsa-sha2-nistp384"
+	KeyAlgoECDSA521   = "ecdsa-sha2-nistp521"
+	KeyAlgoED25519    = "ssh-ed25519"
+	KeyAlgoSKED25519  = "sk-ssh-ed25519@openssh.com"
+)
+
+// These constants represent non-default signature algorithms that are supported
+// as algorithm parameters to AlgorithmSigner.SignWithAlgorithm methods. See
+// [PROTOCOL.agent] section 4.5.1 and
+// https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-10
+const (
+	SigAlgoRSA        = "ssh-rsa"
+	SigAlgoRSASHA2256 = "rsa-sha2-256"
+	SigAlgoRSASHA2512 = "rsa-sha2-512"
+)
+
+// parsePubKey parses a public key of the given algorithm.
+// Use ParsePublicKey for keys with prepended algorithm.
+func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
+	switch algo {
+	case KeyAlgoRSA:
+		return parseRSA(in)
+	case KeyAlgoDSA:
+		return parseDSA(in)
+	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+		return parseECDSA(in)
+	case KeyAlgoSKECDSA256:
+		return parseSKECDSA(in)
+	case KeyAlgoED25519:
+		return parseED25519(in)
+	case KeyAlgoSKED25519:
+		return parseSKEd25519(in)
+	case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
+		cert, err := parseCert(in, certToPrivAlgo(algo))
+		if err != nil {
+			return nil, nil, err
+		}
+		return cert, nil, nil
+	}
+	return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
+}
+
+// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
+// (see sshd(8) manual page) once the options and key type fields have been
+// removed.
+func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
+	in = bytes.TrimSpace(in)
+
+	i := bytes.IndexAny(in, " \t")
+	if i == -1 {
+		i = len(in)
+	}
+	base64Key := in[:i]
+
+	key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
+	n, err := base64.StdEncoding.Decode(key, base64Key)
+	if err != nil {
+		return nil, "", err
+	}
+	key = key[:n]
+	out, err = ParsePublicKey(key)
+	if err != nil {
+		return nil, "", err
+	}
+	comment = string(bytes.TrimSpace(in[i:]))
+	return out, comment, nil
+}
+
+// ParseKnownHosts parses an entry in the format of the known_hosts file.
+//
+// The known_hosts format is documented in the sshd(8) manual page. This
+// function will parse a single entry from in. On successful return, marker
+// will contain the optional marker value (i.e. "cert-authority" or "revoked")
+// or else be empty, hosts will contain the hosts that this entry matches,
+// pubKey will contain the public key and comment will contain any trailing
+// comment at the end of the line. See the sshd(8) manual page for the various
+// forms that a host string can take.
+//
+// The unparsed remainder of the input will be returned in rest. This function
+// can be called repeatedly to parse multiple entries.
+//
+// If no entries were found in the input then err will be io.EOF. Otherwise a
+// non-nil err value indicates a parse error.
+func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
+	for len(in) > 0 {
+		end := bytes.IndexByte(in, '\n')
+		if end != -1 {
+			rest = in[end+1:]
+			in = in[:end]
+		} else {
+			rest = nil
+		}
+
+		end = bytes.IndexByte(in, '\r')
+		if end != -1 {
+			in = in[:end]
+		}
+
+		in = bytes.TrimSpace(in)
+		if len(in) == 0 || in[0] == '#' {
+			in = rest
+			continue
+		}
+
+		i := bytes.IndexAny(in, " \t")
+		if i == -1 {
+			in = rest
+			continue
+		}
+
+		// Strip out the beginning of the known_host key.
+		// This is either an optional marker or a (set of) hostname(s).
+		keyFields := bytes.Fields(in)
+		if len(keyFields) < 3 || len(keyFields) > 5 {
+			return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
+		}
+
+		// keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
+		// list of hosts
+		marker := ""
+		if keyFields[0][0] == '@' {
+			marker = string(keyFields[0][1:])
+			keyFields = keyFields[1:]
+		}
+
+		hosts := string(keyFields[0])
+		// keyFields[1] contains the key type (e.g. “ssh-rsa”).
+		// However, that information is duplicated inside the
+		// base64-encoded key and so is ignored here.
+
+		key := bytes.Join(keyFields[2:], []byte(" "))
+		if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
+			return "", nil, nil, "", nil, err
+		}
+
+		return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
+	}
+
+	return "", nil, nil, "", nil, io.EOF
+}
+
+// ParseAuthorizedKeys parses a public key from an authorized_keys
+// file used in OpenSSH according to the sshd(8) manual page.
+func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
+	for len(in) > 0 {
+		end := bytes.IndexByte(in, '\n')
+		if end != -1 {
+			rest = in[end+1:]
+			in = in[:end]
+		} else {
+			rest = nil
+		}
+
+		end = bytes.IndexByte(in, '\r')
+		if end != -1 {
+			in = in[:end]
+		}
+
+		in = bytes.TrimSpace(in)
+		if len(in) == 0 || in[0] == '#' {
+			in = rest
+			continue
+		}
+
+		i := bytes.IndexAny(in, " \t")
+		if i == -1 {
+			in = rest
+			continue
+		}
+
+		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+			return out, comment, options, rest, nil
+		}
+
+		// No key type recognised. Maybe there's an options field at
+		// the beginning.
+		var b byte
+		inQuote := false
+		var candidateOptions []string
+		optionStart := 0
+		for i, b = range in {
+			isEnd := !inQuote && (b == ' ' || b == '\t')
+			if (b == ',' && !inQuote) || isEnd {
+				if i-optionStart > 0 {
+					candidateOptions = append(candidateOptions, string(in[optionStart:i]))
+				}
+				optionStart = i + 1
+			}
+			if isEnd {
+				break
+			}
+			if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
+				inQuote = !inQuote
+			}
+		}
+		for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
+			i++
+		}
+		if i == len(in) {
+			// Invalid line: unmatched quote
+			in = rest
+			continue
+		}
+
+		in = in[i:]
+		i = bytes.IndexAny(in, " \t")
+		if i == -1 {
+			in = rest
+			continue
+		}
+
+		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+			options = candidateOptions
+			return out, comment, options, rest, nil
+		}
+
+		in = rest
+		continue
+	}
+
+	return nil, "", nil, nil, errors.New("ssh: no key found")
+}
+
+// ParsePublicKey parses an SSH public key formatted for use in
+// the SSH wire protocol according to RFC 4253, section 6.6.
+func ParsePublicKey(in []byte) (out PublicKey, err error) {
+	algo, in, ok := parseString(in)
+	if !ok {
+		return nil, errShortRead
+	}
+	var rest []byte
+	out, rest, err = parsePubKey(in, string(algo))
+	if len(rest) > 0 {
+		return nil, errors.New("ssh: trailing junk in public key")
+	}
+
+	return out, err
+}
+
+// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
+// authorized_keys file. The return value ends with newline.
+func MarshalAuthorizedKey(key PublicKey) []byte {
+	b := &bytes.Buffer{}
+	b.WriteString(key.Type())
+	b.WriteByte(' ')
+	e := base64.NewEncoder(base64.StdEncoding, b)
+	e.Write(key.Marshal())
+	e.Close()
+	b.WriteByte('\n')
+	return b.Bytes()
+}
+
+// PublicKey is an abstraction of different types of public keys.
+type PublicKey interface {
+	// Type returns the key's type, e.g. "ssh-rsa".
+	Type() string
+
+	// Marshal returns the serialized key data in SSH wire format,
+	// with the name prefix. To unmarshal the returned data, use
+	// the ParsePublicKey function.
+	Marshal() []byte
+
+	// Verify that sig is a signature on the given data using this
+	// key. This function will hash the data appropriately first.
+	Verify(data []byte, sig *Signature) error
+}
+
+// CryptoPublicKey, if implemented by a PublicKey,
+// returns the underlying crypto.PublicKey form of the key.
+type CryptoPublicKey interface {
+	CryptoPublicKey() crypto.PublicKey
+}
+
+// A Signer can create signatures that verify against a public key.
+type Signer interface {
+	// PublicKey returns an associated PublicKey instance.
+	PublicKey() PublicKey
+
+	// Sign returns raw signature for the given data. This method
+	// will apply the hash specified for the keytype to the data.
+	Sign(rand io.Reader, data []byte) (*Signature, error)
+}
+
+// A AlgorithmSigner is a Signer that also supports specifying a specific
+// algorithm to use for signing.
+type AlgorithmSigner interface {
+	Signer
+
+	// SignWithAlgorithm is like Signer.Sign, but allows specification of a
+	// non-default signing algorithm. See the SigAlgo* constants in this
+	// package for signature algorithms supported by this package. Callers may
+	// pass an empty string for the algorithm in which case the AlgorithmSigner
+	// will use its default algorithm.
+	SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
+}
+
+type rsaPublicKey rsa.PublicKey
+
+func (r *rsaPublicKey) Type() string {
+	return "ssh-rsa"
+}
+
+// parseRSA parses an RSA key according to RFC 4253, section 6.6.
+func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		E    *big.Int
+		N    *big.Int
+		Rest []byte `ssh:"rest"`
+	}
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	if w.E.BitLen() > 24 {
+		return nil, nil, errors.New("ssh: exponent too large")
+	}
+	e := w.E.Int64()
+	if e < 3 || e&1 == 0 {
+		return nil, nil, errors.New("ssh: incorrect exponent")
+	}
+
+	var key rsa.PublicKey
+	key.E = int(e)
+	key.N = w.N
+	return (*rsaPublicKey)(&key), w.Rest, nil
+}
+
+func (r *rsaPublicKey) Marshal() []byte {
+	e := new(big.Int).SetInt64(int64(r.E))
+	// RSA publickey struct layout should match the struct used by
+	// parseRSACert in the x/crypto/ssh/agent package.
+	wirekey := struct {
+		Name string
+		E    *big.Int
+		N    *big.Int
+	}{
+		KeyAlgoRSA,
+		e,
+		r.N,
+	}
+	return Marshal(&wirekey)
+}
+
+func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
+	var hash crypto.Hash
+	switch sig.Format {
+	case SigAlgoRSA:
+		hash = crypto.SHA1
+	case SigAlgoRSASHA2256:
+		hash = crypto.SHA256
+	case SigAlgoRSASHA2512:
+		hash = crypto.SHA512
+	default:
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
+	}
+	h := hash.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+	return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, sig.Blob)
+}
+
+func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+	return (*rsa.PublicKey)(r)
+}
+
+type dsaPublicKey dsa.PublicKey
+
+func (k *dsaPublicKey) Type() string {
+	return "ssh-dss"
+}
+
+func checkDSAParams(param *dsa.Parameters) error {
+	// SSH specifies FIPS 186-2, which only provided a single size
+	// (1024 bits) DSA key. FIPS 186-3 allows for larger key
+	// sizes, which would confuse SSH.
+	if l := param.P.BitLen(); l != 1024 {
+		return fmt.Errorf("ssh: unsupported DSA key size %d", l)
+	}
+
+	return nil
+}
+
+// parseDSA parses an DSA key according to RFC 4253, section 6.6.
+func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		P, Q, G, Y *big.Int
+		Rest       []byte `ssh:"rest"`
+	}
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	param := dsa.Parameters{
+		P: w.P,
+		Q: w.Q,
+		G: w.G,
+	}
+	if err := checkDSAParams(&param); err != nil {
+		return nil, nil, err
+	}
+
+	key := &dsaPublicKey{
+		Parameters: param,
+		Y:          w.Y,
+	}
+	return key, w.Rest, nil
+}
+
+func (k *dsaPublicKey) Marshal() []byte {
+	// DSA publickey struct layout should match the struct used by
+	// parseDSACert in the x/crypto/ssh/agent package.
+	w := struct {
+		Name       string
+		P, Q, G, Y *big.Int
+	}{
+		k.Type(),
+		k.P,
+		k.Q,
+		k.G,
+		k.Y,
+	}
+
+	return Marshal(&w)
+}
+
+func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != k.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+	}
+	h := crypto.SHA1.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+
+	// Per RFC 4253, section 6.6,
+	// The value for 'dss_signature_blob' is encoded as a string containing
+	// r, followed by s (which are 160-bit integers, without lengths or
+	// padding, unsigned, and in network byte order).
+	// For DSS purposes, sig.Blob should be exactly 40 bytes in length.
+	if len(sig.Blob) != 40 {
+		return errors.New("ssh: DSA signature parse error")
+	}
+	r := new(big.Int).SetBytes(sig.Blob[:20])
+	s := new(big.Int).SetBytes(sig.Blob[20:])
+	if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
+		return nil
+	}
+	return errors.New("ssh: signature did not verify")
+}
+
+func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+	return (*dsa.PublicKey)(k)
+}
+
+type dsaPrivateKey struct {
+	*dsa.PrivateKey
+}
+
+func (k *dsaPrivateKey) PublicKey() PublicKey {
+	return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
+}
+
+func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	return k.SignWithAlgorithm(rand, data, "")
+}
+
+func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
+	if algorithm != "" && algorithm != k.PublicKey().Type() {
+		return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
+	}
+
+	h := crypto.SHA1.New()
+	h.Write(data)
+	digest := h.Sum(nil)
+	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
+	if err != nil {
+		return nil, err
+	}
+
+	sig := make([]byte, 40)
+	rb := r.Bytes()
+	sb := s.Bytes()
+
+	copy(sig[20-len(rb):20], rb)
+	copy(sig[40-len(sb):], sb)
+
+	return &Signature{
+		Format: k.PublicKey().Type(),
+		Blob:   sig,
+	}, nil
+}
+
+type ecdsaPublicKey ecdsa.PublicKey
+
+func (k *ecdsaPublicKey) Type() string {
+	return "ecdsa-sha2-" + k.nistID()
+}
+
+func (k *ecdsaPublicKey) nistID() string {
+	switch k.Params().BitSize {
+	case 256:
+		return "nistp256"
+	case 384:
+		return "nistp384"
+	case 521:
+		return "nistp521"
+	}
+	panic("ssh: unsupported ecdsa key size")
+}
+
+type ed25519PublicKey ed25519.PublicKey
+
+func (k ed25519PublicKey) Type() string {
+	return KeyAlgoED25519
+}
+
+func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		KeyBytes []byte
+		Rest     []byte `ssh:"rest"`
+	}
+
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
+		return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
+	}
+
+	return ed25519PublicKey(w.KeyBytes), w.Rest, nil
+}
+
+func (k ed25519PublicKey) Marshal() []byte {
+	w := struct {
+		Name     string
+		KeyBytes []byte
+	}{
+		KeyAlgoED25519,
+		[]byte(k),
+	}
+	return Marshal(&w)
+}
+
+func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
+	if sig.Format != k.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+	}
+	if l := len(k); l != ed25519.PublicKeySize {
+		return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
+	}
+
+	if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok {
+		return errors.New("ssh: signature did not verify")
+	}
+
+	return nil
+}
+
+func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
+	return ed25519.PublicKey(k)
+}
+
+func supportedEllipticCurve(curve elliptic.Curve) bool {
+	return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
+}
+
+// ecHash returns the hash to match the given elliptic curve, see RFC
+// 5656, section 6.2.1
+func ecHash(curve elliptic.Curve) crypto.Hash {
+	bitSize := curve.Params().BitSize
+	switch {
+	case bitSize <= 256:
+		return crypto.SHA256
+	case bitSize <= 384:
+		return crypto.SHA384
+	}
+	return crypto.SHA512
+}
+
+// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
+func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		Curve    string
+		KeyBytes []byte
+		Rest     []byte `ssh:"rest"`
+	}
+
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	key := new(ecdsa.PublicKey)
+
+	switch w.Curve {
+	case "nistp256":
+		key.Curve = elliptic.P256()
+	case "nistp384":
+		key.Curve = elliptic.P384()
+	case "nistp521":
+		key.Curve = elliptic.P521()
+	default:
+		return nil, nil, errors.New("ssh: unsupported curve")
+	}
+
+	key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
+	if key.X == nil || key.Y == nil {
+		return nil, nil, errors.New("ssh: invalid curve point")
+	}
+	return (*ecdsaPublicKey)(key), w.Rest, nil
+}
+
+func (k *ecdsaPublicKey) Marshal() []byte {
+	// See RFC 5656, section 3.1.
+	keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
+	// ECDSA publickey struct layout should match the struct used by
+	// parseECDSACert in the x/crypto/ssh/agent package.
+	w := struct {
+		Name string
+		ID   string
+		Key  []byte
+	}{
+		k.Type(),
+		k.nistID(),
+		keyBytes,
+	}
+
+	return Marshal(&w)
+}
+
+func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != k.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+	}
+
+	h := ecHash(k.Curve).New()
+	h.Write(data)
+	digest := h.Sum(nil)
+
+	// Per RFC 5656, section 3.1.2,
+	// The ecdsa_signature_blob value has the following specific encoding:
+	//    mpint    r
+	//    mpint    s
+	var ecSig struct {
+		R *big.Int
+		S *big.Int
+	}
+
+	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
+		return err
+	}
+
+	if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) {
+		return nil
+	}
+	return errors.New("ssh: signature did not verify")
+}
+
+func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+	return (*ecdsa.PublicKey)(k)
+}
+
+// skFields holds the additional fields present in U2F/FIDO2 signatures.
+// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details.
+type skFields struct {
+	// Flags contains U2F/FIDO2 flags such as 'user present'
+	Flags byte
+	// Counter is a monotonic signature counter which can be
+	// used to detect concurrent use of a private key, should
+	// it be extracted from hardware.
+	Counter uint32
+}
+
+type skECDSAPublicKey struct {
+	// application is a URL-like string, typically "ssh:" for SSH.
+	// see openssh/PROTOCOL.u2f for details.
+	application string
+	ecdsa.PublicKey
+}
+
+func (k *skECDSAPublicKey) Type() string {
+	return KeyAlgoSKECDSA256
+}
+
+func (k *skECDSAPublicKey) nistID() string {
+	return "nistp256"
+}
+
+func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		Curve       string
+		KeyBytes    []byte
+		Application string
+		Rest        []byte `ssh:"rest"`
+	}
+
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	key := new(skECDSAPublicKey)
+	key.application = w.Application
+
+	if w.Curve != "nistp256" {
+		return nil, nil, errors.New("ssh: unsupported curve")
+	}
+	key.Curve = elliptic.P256()
+
+	key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
+	if key.X == nil || key.Y == nil {
+		return nil, nil, errors.New("ssh: invalid curve point")
+	}
+
+	return key, w.Rest, nil
+}
+
+func (k *skECDSAPublicKey) Marshal() []byte {
+	// See RFC 5656, section 3.1.
+	keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
+	w := struct {
+		Name        string
+		ID          string
+		Key         []byte
+		Application string
+	}{
+		k.Type(),
+		k.nistID(),
+		keyBytes,
+		k.application,
+	}
+
+	return Marshal(&w)
+}
+
+func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != k.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+	}
+
+	h := ecHash(k.Curve).New()
+	h.Write([]byte(k.application))
+	appDigest := h.Sum(nil)
+
+	h.Reset()
+	h.Write(data)
+	dataDigest := h.Sum(nil)
+
+	var ecSig struct {
+		R *big.Int
+		S *big.Int
+	}
+	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
+		return err
+	}
+
+	var skf skFields
+	if err := Unmarshal(sig.Rest, &skf); err != nil {
+		return err
+	}
+
+	blob := struct {
+		ApplicationDigest []byte `ssh:"rest"`
+		Flags             byte
+		Counter           uint32
+		MessageDigest     []byte `ssh:"rest"`
+	}{
+		appDigest,
+		skf.Flags,
+		skf.Counter,
+		dataDigest,
+	}
+
+	original := Marshal(blob)
+
+	h.Reset()
+	h.Write(original)
+	digest := h.Sum(nil)
+
+	if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) {
+		return nil
+	}
+	return errors.New("ssh: signature did not verify")
+}
+
+type skEd25519PublicKey struct {
+	// application is a URL-like string, typically "ssh:" for SSH.
+	// see openssh/PROTOCOL.u2f for details.
+	application string
+	ed25519.PublicKey
+}
+
+func (k *skEd25519PublicKey) Type() string {
+	return KeyAlgoSKED25519
+}
+
+func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) {
+	var w struct {
+		KeyBytes    []byte
+		Application string
+		Rest        []byte `ssh:"rest"`
+	}
+
+	if err := Unmarshal(in, &w); err != nil {
+		return nil, nil, err
+	}
+
+	if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
+		return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
+	}
+
+	key := new(skEd25519PublicKey)
+	key.application = w.Application
+	key.PublicKey = ed25519.PublicKey(w.KeyBytes)
+
+	return key, w.Rest, nil
+}
+
+func (k *skEd25519PublicKey) Marshal() []byte {
+	w := struct {
+		Name        string
+		KeyBytes    []byte
+		Application string
+	}{
+		KeyAlgoSKED25519,
+		[]byte(k.PublicKey),
+		k.application,
+	}
+	return Marshal(&w)
+}
+
+func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
+	if sig.Format != k.Type() {
+		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+	}
+	if l := len(k.PublicKey); l != ed25519.PublicKeySize {
+		return fmt.Errorf("invalid size %d for Ed25519 public key", l)
+	}
+
+	h := sha256.New()
+	h.Write([]byte(k.application))
+	appDigest := h.Sum(nil)
+
+	h.Reset()
+	h.Write(data)
+	dataDigest := h.Sum(nil)
+
+	var edSig struct {
+		Signature []byte `ssh:"rest"`
+	}
+
+	if err := Unmarshal(sig.Blob, &edSig); err != nil {
+		return err
+	}
+
+	var skf skFields
+	if err := Unmarshal(sig.Rest, &skf); err != nil {
+		return err
+	}
+
+	blob := struct {
+		ApplicationDigest []byte `ssh:"rest"`
+		Flags             byte
+		Counter           uint32
+		MessageDigest     []byte `ssh:"rest"`
+	}{
+		appDigest,
+		skf.Flags,
+		skf.Counter,
+		dataDigest,
+	}
+
+	original := Marshal(blob)
+
+	if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok {
+		return errors.New("ssh: signature did not verify")
+	}
+
+	return nil
+}
+
+// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
+// *ecdsa.PrivateKey or any other crypto.Signer and returns a
+// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
+// P-521. DSA keys must use parameter size L1024N160.
+func NewSignerFromKey(key interface{}) (Signer, error) {
+	switch key := key.(type) {
+	case crypto.Signer:
+		return NewSignerFromSigner(key)
+	case *dsa.PrivateKey:
+		return newDSAPrivateKey(key)
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+	}
+}
+
+func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
+	if err := checkDSAParams(&key.PublicKey.Parameters); err != nil {
+		return nil, err
+	}
+
+	return &dsaPrivateKey{key}, nil
+}
+
+type wrappedSigner struct {
+	signer crypto.Signer
+	pubKey PublicKey
+}
+
+// NewSignerFromSigner takes any crypto.Signer implementation and
+// returns a corresponding Signer interface. This can be used, for
+// example, with keys kept in hardware modules.
+func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
+	pubKey, err := NewPublicKey(signer.Public())
+	if err != nil {
+		return nil, err
+	}
+
+	return &wrappedSigner{signer, pubKey}, nil
+}
+
+func (s *wrappedSigner) PublicKey() PublicKey {
+	return s.pubKey
+}
+
+func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+	return s.SignWithAlgorithm(rand, data, "")
+}
+
+func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
+	var hashFunc crypto.Hash
+
+	if _, ok := s.pubKey.(*rsaPublicKey); ok {
+		// RSA keys support a few hash functions determined by the requested signature algorithm
+		switch algorithm {
+		case "", SigAlgoRSA:
+			algorithm = SigAlgoRSA
+			hashFunc = crypto.SHA1
+		case SigAlgoRSASHA2256:
+			hashFunc = crypto.SHA256
+		case SigAlgoRSASHA2512:
+			hashFunc = crypto.SHA512
+		default:
+			return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
+		}
+	} else {
+		// The only supported algorithm for all other key types is the same as the type of the key
+		if algorithm == "" {
+			algorithm = s.pubKey.Type()
+		} else if algorithm != s.pubKey.Type() {
+			return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
+		}
+
+		switch key := s.pubKey.(type) {
+		case *dsaPublicKey:
+			hashFunc = crypto.SHA1
+		case *ecdsaPublicKey:
+			hashFunc = ecHash(key.Curve)
+		case ed25519PublicKey:
+		default:
+			return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+		}
+	}
+
+	var digest []byte
+	if hashFunc != 0 {
+		h := hashFunc.New()
+		h.Write(data)
+		digest = h.Sum(nil)
+	} else {
+		digest = data
+	}
+
+	signature, err := s.signer.Sign(rand, digest, hashFunc)
+	if err != nil {
+		return nil, err
+	}
+
+	// crypto.Signer.Sign is expected to return an ASN.1-encoded signature
+	// for ECDSA and DSA, but that's not the encoding expected by SSH, so
+	// re-encode.
+	switch s.pubKey.(type) {
+	case *ecdsaPublicKey, *dsaPublicKey:
+		type asn1Signature struct {
+			R, S *big.Int
+		}
+		asn1Sig := new(asn1Signature)
+		_, err := asn1.Unmarshal(signature, asn1Sig)
+		if err != nil {
+			return nil, err
+		}
+
+		switch s.pubKey.(type) {
+		case *ecdsaPublicKey:
+			signature = Marshal(asn1Sig)
+
+		case *dsaPublicKey:
+			signature = make([]byte, 40)
+			r := asn1Sig.R.Bytes()
+			s := asn1Sig.S.Bytes()
+			copy(signature[20-len(r):20], r)
+			copy(signature[40-len(s):40], s)
+		}
+	}
+
+	return &Signature{
+		Format: algorithm,
+		Blob:   signature,
+	}, nil
+}
+
+// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
+// or ed25519.PublicKey returns a corresponding PublicKey instance.
+// ECDSA keys must use P-256, P-384 or P-521.
+func NewPublicKey(key interface{}) (PublicKey, error) {
+	switch key := key.(type) {
+	case *rsa.PublicKey:
+		return (*rsaPublicKey)(key), nil
+	case *ecdsa.PublicKey:
+		if !supportedEllipticCurve(key.Curve) {
+			return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")
+		}
+		return (*ecdsaPublicKey)(key), nil
+	case *dsa.PublicKey:
+		return (*dsaPublicKey)(key), nil
+	case ed25519.PublicKey:
+		if l := len(key); l != ed25519.PublicKeySize {
+			return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
+		}
+		return ed25519PublicKey(key), nil
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+	}
+}
+
+// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
+// the same keys as ParseRawPrivateKey. If the private key is encrypted, it
+// will return a PassphraseMissingError.
+func ParsePrivateKey(pemBytes []byte) (Signer, error) {
+	key, err := ParseRawPrivateKey(pemBytes)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewSignerFromKey(key)
+}
+
+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
+// key and passphrase. It supports the same keys as
+// ParseRawPrivateKeyWithPassphrase.
+func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) {
+	key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewSignerFromKey(key)
+}
+
+// encryptedBlock tells whether a private key is
+// encrypted by examining its Proc-Type header
+// for a mention of ENCRYPTED
+// according to RFC 1421 Section 4.6.1.1.
+func encryptedBlock(block *pem.Block) bool {
+	return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
+}
+
+// A PassphraseMissingError indicates that parsing this private key requires a
+// passphrase. Use ParsePrivateKeyWithPassphrase.
+type PassphraseMissingError struct {
+	// PublicKey will be set if the private key format includes an unencrypted
+	// public key along with the encrypted private key.
+	PublicKey PublicKey
+}
+
+func (*PassphraseMissingError) Error() string {
+	return "ssh: this private key is passphrase protected"
+}
+
+// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
+// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the
+// private key is encrypted, it will return a PassphraseMissingError.
+func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
+	block, _ := pem.Decode(pemBytes)
+	if block == nil {
+		return nil, errors.New("ssh: no key found")
+	}
+
+	if encryptedBlock(block) {
+		return nil, &PassphraseMissingError{}
+	}
+
+	switch block.Type {
+	case "RSA PRIVATE KEY":
+		return x509.ParsePKCS1PrivateKey(block.Bytes)
+	// RFC5208 - https://tools.ietf.org/html/rfc5208
+	case "PRIVATE KEY":
+		return x509.ParsePKCS8PrivateKey(block.Bytes)
+	case "EC PRIVATE KEY":
+		return x509.ParseECPrivateKey(block.Bytes)
+	case "DSA PRIVATE KEY":
+		return ParseDSAPrivateKey(block.Bytes)
+	case "OPENSSH PRIVATE KEY":
+		return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey)
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+	}
+}
+
+// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
+// passphrase from a PEM encoded private key. If the passphrase is wrong, it
+// will return x509.IncorrectPasswordError.
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) {
+	block, _ := pem.Decode(pemBytes)
+	if block == nil {
+		return nil, errors.New("ssh: no key found")
+	}
+
+	if block.Type == "OPENSSH PRIVATE KEY" {
+		return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase))
+	}
+
+	if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) {
+		return nil, errors.New("ssh: not an encrypted key")
+	}
+
+	buf, err := x509.DecryptPEMBlock(block, passphrase)
+	if err != nil {
+		if err == x509.IncorrectPasswordError {
+			return nil, err
+		}
+		return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
+	}
+
+	switch block.Type {
+	case "RSA PRIVATE KEY":
+		return x509.ParsePKCS1PrivateKey(buf)
+	case "EC PRIVATE KEY":
+		return x509.ParseECPrivateKey(buf)
+	case "DSA PRIVATE KEY":
+		return ParseDSAPrivateKey(buf)
+	default:
+		return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+	}
+}
+
+// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
+// specified by the OpenSSL DSA man page.
+func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
+	var k struct {
+		Version int
+		P       *big.Int
+		Q       *big.Int
+		G       *big.Int
+		Pub     *big.Int
+		Priv    *big.Int
+	}
+	rest, err := asn1.Unmarshal(der, &k)
+	if err != nil {
+		return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
+	}
+	if len(rest) > 0 {
+		return nil, errors.New("ssh: garbage after DSA key")
+	}
+
+	return &dsa.PrivateKey{
+		PublicKey: dsa.PublicKey{
+			Parameters: dsa.Parameters{
+				P: k.P,
+				Q: k.Q,
+				G: k.G,
+			},
+			Y: k.Pub,
+		},
+		X: k.Priv,
+	}, nil
+}
+
+func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
+	if kdfName != "none" || cipherName != "none" {
+		return nil, &PassphraseMissingError{}
+	}
+	if kdfOpts != "" {
+		return nil, errors.New("ssh: invalid openssh private key")
+	}
+	return privKeyBlock, nil
+}
+
+func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
+	return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
+		if kdfName == "none" || cipherName == "none" {
+			return nil, errors.New("ssh: key is not password protected")
+		}
+		if kdfName != "bcrypt" {
+			return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt")
+		}
+
+		var opts struct {
+			Salt   string
+			Rounds uint32
+		}
+		if err := Unmarshal([]byte(kdfOpts), &opts); err != nil {
+			return nil, err
+		}
+
+		k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16)
+		if err != nil {
+			return nil, err
+		}
+		key, iv := k[:32], k[32:]
+
+		c, err := aes.NewCipher(key)
+		if err != nil {
+			return nil, err
+		}
+		switch cipherName {
+		case "aes256-ctr":
+			ctr := cipher.NewCTR(c, iv)
+			ctr.XORKeyStream(privKeyBlock, privKeyBlock)
+		case "aes256-cbc":
+			if len(privKeyBlock)%c.BlockSize() != 0 {
+				return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size")
+			}
+			cbc := cipher.NewCBCDecrypter(c, iv)
+			cbc.CryptBlocks(privKeyBlock, privKeyBlock)
+		default:
+			return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc")
+		}
+
+		return privKeyBlock, nil
+	}
+}
+
+type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
+
+// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt
+// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used
+// as the decrypt function to parse an unencrypted private key. See
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.
+func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) {
+	const magic = "openssh-key-v1\x00"
+	if len(key) < len(magic) || string(key[:len(magic)]) != magic {
+		return nil, errors.New("ssh: invalid openssh private key format")
+	}
+	remaining := key[len(magic):]
+
+	var w struct {
+		CipherName   string
+		KdfName      string
+		KdfOpts      string
+		NumKeys      uint32
+		PubKey       []byte
+		PrivKeyBlock []byte
+	}
+
+	if err := Unmarshal(remaining, &w); err != nil {
+		return nil, err
+	}
+	if w.NumKeys != 1 {
+		// We only support single key files, and so does OpenSSH.
+		// https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171
+		return nil, errors.New("ssh: multi-key files are not supported")
+	}
+
+	privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock)
+	if err != nil {
+		if err, ok := err.(*PassphraseMissingError); ok {
+			pub, errPub := ParsePublicKey(w.PubKey)
+			if errPub != nil {
+				return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub)
+			}
+			err.PublicKey = pub
+		}
+		return nil, err
+	}
+
+	pk1 := struct {
+		Check1  uint32
+		Check2  uint32
+		Keytype string
+		Rest    []byte `ssh:"rest"`
+	}{}
+
+	if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 {
+		if w.CipherName != "none" {
+			return nil, x509.IncorrectPasswordError
+		}
+		return nil, errors.New("ssh: malformed OpenSSH key")
+	}
+
+	switch pk1.Keytype {
+	case KeyAlgoRSA:
+		// https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
+		key := struct {
+			N       *big.Int
+			E       *big.Int
+			D       *big.Int
+			Iqmp    *big.Int
+			P       *big.Int
+			Q       *big.Int
+			Comment string
+			Pad     []byte `ssh:"rest"`
+		}{}
+
+		if err := Unmarshal(pk1.Rest, &key); err != nil {
+			return nil, err
+		}
+
+		if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+			return nil, err
+		}
+
+		pk := &rsa.PrivateKey{
+			PublicKey: rsa.PublicKey{
+				N: key.N,
+				E: int(key.E.Int64()),
+			},
+			D:      key.D,
+			Primes: []*big.Int{key.P, key.Q},
+		}
+
+		if err := pk.Validate(); err != nil {
+			return nil, err
+		}
+
+		pk.Precompute()
+
+		return pk, nil
+	case KeyAlgoED25519:
+		key := struct {
+			Pub     []byte
+			Priv    []byte
+			Comment string
+			Pad     []byte `ssh:"rest"`
+		}{}
+
+		if err := Unmarshal(pk1.Rest, &key); err != nil {
+			return nil, err
+		}
+
+		if len(key.Priv) != ed25519.PrivateKeySize {
+			return nil, errors.New("ssh: private key unexpected length")
+		}
+
+		if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+			return nil, err
+		}
+
+		pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
+		copy(pk, key.Priv)
+		return &pk, nil
+	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+		key := struct {
+			Curve   string
+			Pub     []byte
+			D       *big.Int
+			Comment string
+			Pad     []byte `ssh:"rest"`
+		}{}
+
+		if err := Unmarshal(pk1.Rest, &key); err != nil {
+			return nil, err
+		}
+
+		if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
+			return nil, err
+		}
+
+		var curve elliptic.Curve
+		switch key.Curve {
+		case "nistp256":
+			curve = elliptic.P256()
+		case "nistp384":
+			curve = elliptic.P384()
+		case "nistp521":
+			curve = elliptic.P521()
+		default:
+			return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve)
+		}
+
+		X, Y := elliptic.Unmarshal(curve, key.Pub)
+		if X == nil || Y == nil {
+			return nil, errors.New("ssh: failed to unmarshal public key")
+		}
+
+		if key.D.Cmp(curve.Params().N) >= 0 {
+			return nil, errors.New("ssh: scalar is out of range")
+		}
+
+		x, y := curve.ScalarBaseMult(key.D.Bytes())
+		if x.Cmp(X) != 0 || y.Cmp(Y) != 0 {
+			return nil, errors.New("ssh: public key does not match private key")
+		}
+
+		return &ecdsa.PrivateKey{
+			PublicKey: ecdsa.PublicKey{
+				Curve: curve,
+				X:     X,
+				Y:     Y,
+			},
+			D: key.D,
+		}, nil
+	default:
+		return nil, errors.New("ssh: unhandled key type")
+	}
+}
+
+func checkOpenSSHKeyPadding(pad []byte) error {
+	for i, b := range pad {
+		if int(b) != i+1 {
+			return errors.New("ssh: padding not as expected")
+		}
+	}
+	return nil
+}
+
+// FingerprintLegacyMD5 returns the user presentation of the key's
+// fingerprint as described by RFC 4716 section 4.
+func FingerprintLegacyMD5(pubKey PublicKey) string {
+	md5sum := md5.Sum(pubKey.Marshal())
+	hexarray := make([]string, len(md5sum))
+	for i, c := range md5sum {
+		hexarray[i] = hex.EncodeToString([]byte{c})
+	}
+	return strings.Join(hexarray, ":")
+}
+
+// FingerprintSHA256 returns the user presentation of the key's
+// fingerprint as unpadded base64 encoded sha256 hash.
+// This format was introduced from OpenSSH 6.8.
+// https://www.openssh.com/txt/release-6.8
+// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
+func FingerprintSHA256(pubKey PublicKey) string {
+	sha256sum := sha256.Sum256(pubKey.Marshal())
+	hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
+	return "SHA256:" + hash
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
new file mode 100644
index 0000000..c07a062
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -0,0 +1,61 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Message authentication support
+
+import (
+	"crypto/hmac"
+	"crypto/sha1"
+	"crypto/sha256"
+	"hash"
+)
+
+type macMode struct {
+	keySize int
+	etm     bool
+	new     func(key []byte) hash.Hash
+}
+
+// truncatingMAC wraps around a hash.Hash and truncates the output digest to
+// a given size.
+type truncatingMAC struct {
+	length int
+	hmac   hash.Hash
+}
+
+func (t truncatingMAC) Write(data []byte) (int, error) {
+	return t.hmac.Write(data)
+}
+
+func (t truncatingMAC) Sum(in []byte) []byte {
+	out := t.hmac.Sum(in)
+	return out[:len(in)+t.length]
+}
+
+func (t truncatingMAC) Reset() {
+	t.hmac.Reset()
+}
+
+func (t truncatingMAC) Size() int {
+	return t.length
+}
+
+func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
+
+var macModes = map[string]*macMode{
+	"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
+		return hmac.New(sha256.New, key)
+	}},
+	"hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
+		return hmac.New(sha256.New, key)
+	}},
+	"hmac-sha1": {20, false, func(key []byte) hash.Hash {
+		return hmac.New(sha1.New, key)
+	}},
+	"hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
+		return truncatingMAC{12, hmac.New(sha1.New, key)}
+	}},
+}
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
new file mode 100644
index 0000000..ac41a41
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -0,0 +1,866 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// These are SSH message type numbers. They are scattered around several
+// documents but many were taken from [SSH-PARAMETERS].
+const (
+	msgIgnore        = 2
+	msgUnimplemented = 3
+	msgDebug         = 4
+	msgNewKeys       = 21
+)
+
+// SSH messages:
+//
+// These structures mirror the wire format of the corresponding SSH messages.
+// They are marshaled using reflection with the marshal and unmarshal functions
+// in this file. The only wrinkle is that a final member of type []byte with a
+// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
+
+// See RFC 4253, section 11.1.
+const msgDisconnect = 1
+
+// disconnectMsg is the message that signals a disconnect. It is also
+// the error type returned from mux.Wait()
+type disconnectMsg struct {
+	Reason   uint32 `sshtype:"1"`
+	Message  string
+	Language string
+}
+
+func (d *disconnectMsg) Error() string {
+	return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message)
+}
+
+// See RFC 4253, section 7.1.
+const msgKexInit = 20
+
+type kexInitMsg struct {
+	Cookie                  [16]byte `sshtype:"20"`
+	KexAlgos                []string
+	ServerHostKeyAlgos      []string
+	CiphersClientServer     []string
+	CiphersServerClient     []string
+	MACsClientServer        []string
+	MACsServerClient        []string
+	CompressionClientServer []string
+	CompressionServerClient []string
+	LanguagesClientServer   []string
+	LanguagesServerClient   []string
+	FirstKexFollows         bool
+	Reserved                uint32
+}
+
+// See RFC 4253, section 8.
+
+// Diffie-Helman
+const msgKexDHInit = 30
+
+type kexDHInitMsg struct {
+	X *big.Int `sshtype:"30"`
+}
+
+const msgKexECDHInit = 30
+
+type kexECDHInitMsg struct {
+	ClientPubKey []byte `sshtype:"30"`
+}
+
+const msgKexECDHReply = 31
+
+type kexECDHReplyMsg struct {
+	HostKey         []byte `sshtype:"31"`
+	EphemeralPubKey []byte
+	Signature       []byte
+}
+
+const msgKexDHReply = 31
+
+type kexDHReplyMsg struct {
+	HostKey   []byte `sshtype:"31"`
+	Y         *big.Int
+	Signature []byte
+}
+
+// See RFC 4419, section 5.
+const msgKexDHGexGroup = 31
+
+type kexDHGexGroupMsg struct {
+	P *big.Int `sshtype:"31"`
+	G *big.Int
+}
+
+const msgKexDHGexInit = 32
+
+type kexDHGexInitMsg struct {
+	X *big.Int `sshtype:"32"`
+}
+
+const msgKexDHGexReply = 33
+
+type kexDHGexReplyMsg struct {
+	HostKey   []byte `sshtype:"33"`
+	Y         *big.Int
+	Signature []byte
+}
+
+const msgKexDHGexRequest = 34
+
+type kexDHGexRequestMsg struct {
+	MinBits      uint32 `sshtype:"34"`
+	PreferedBits uint32
+	MaxBits      uint32
+}
+
+// See RFC 4253, section 10.
+const msgServiceRequest = 5
+
+type serviceRequestMsg struct {
+	Service string `sshtype:"5"`
+}
+
+// See RFC 4253, section 10.
+const msgServiceAccept = 6
+
+type serviceAcceptMsg struct {
+	Service string `sshtype:"6"`
+}
+
+// See RFC 4252, section 5.
+const msgUserAuthRequest = 50
+
+type userAuthRequestMsg struct {
+	User    string `sshtype:"50"`
+	Service string
+	Method  string
+	Payload []byte `ssh:"rest"`
+}
+
+// Used for debug printouts of packets.
+type userAuthSuccessMsg struct {
+}
+
+// See RFC 4252, section 5.1
+const msgUserAuthFailure = 51
+
+type userAuthFailureMsg struct {
+	Methods        []string `sshtype:"51"`
+	PartialSuccess bool
+}
+
+// See RFC 4252, section 5.1
+const msgUserAuthSuccess = 52
+
+// See RFC 4252, section 5.4
+const msgUserAuthBanner = 53
+
+type userAuthBannerMsg struct {
+	Message string `sshtype:"53"`
+	// unused, but required to allow message parsing
+	Language string
+}
+
+// See RFC 4256, section 3.2
+const msgUserAuthInfoRequest = 60
+const msgUserAuthInfoResponse = 61
+
+type userAuthInfoRequestMsg struct {
+	User               string `sshtype:"60"`
+	Instruction        string
+	DeprecatedLanguage string
+	NumPrompts         uint32
+	Prompts            []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpen = 90
+
+type channelOpenMsg struct {
+	ChanType         string `sshtype:"90"`
+	PeersID          uint32
+	PeersWindow      uint32
+	MaxPacketSize    uint32
+	TypeSpecificData []byte `ssh:"rest"`
+}
+
+const msgChannelExtendedData = 95
+const msgChannelData = 94
+
+// Used for debug print outs of packets.
+type channelDataMsg struct {
+	PeersID uint32 `sshtype:"94"`
+	Length  uint32
+	Rest    []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenConfirm = 91
+
+type channelOpenConfirmMsg struct {
+	PeersID          uint32 `sshtype:"91"`
+	MyID             uint32
+	MyWindow         uint32
+	MaxPacketSize    uint32
+	TypeSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenFailure = 92
+
+type channelOpenFailureMsg struct {
+	PeersID  uint32 `sshtype:"92"`
+	Reason   RejectionReason
+	Message  string
+	Language string
+}
+
+const msgChannelRequest = 98
+
+type channelRequestMsg struct {
+	PeersID             uint32 `sshtype:"98"`
+	Request             string
+	WantReply           bool
+	RequestSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelSuccess = 99
+
+type channelRequestSuccessMsg struct {
+	PeersID uint32 `sshtype:"99"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelFailure = 100
+
+type channelRequestFailureMsg struct {
+	PeersID uint32 `sshtype:"100"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelClose = 97
+
+type channelCloseMsg struct {
+	PeersID uint32 `sshtype:"97"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelEOF = 96
+
+type channelEOFMsg struct {
+	PeersID uint32 `sshtype:"96"`
+}
+
+// See RFC 4254, section 4
+const msgGlobalRequest = 80
+
+type globalRequestMsg struct {
+	Type      string `sshtype:"80"`
+	WantReply bool
+	Data      []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 4
+const msgRequestSuccess = 81
+
+type globalRequestSuccessMsg struct {
+	Data []byte `ssh:"rest" sshtype:"81"`
+}
+
+// See RFC 4254, section 4
+const msgRequestFailure = 82
+
+type globalRequestFailureMsg struct {
+	Data []byte `ssh:"rest" sshtype:"82"`
+}
+
+// See RFC 4254, section 5.2
+const msgChannelWindowAdjust = 93
+
+type windowAdjustMsg struct {
+	PeersID         uint32 `sshtype:"93"`
+	AdditionalBytes uint32
+}
+
+// See RFC 4252, section 7
+const msgUserAuthPubKeyOk = 60
+
+type userAuthPubKeyOkMsg struct {
+	Algo   string `sshtype:"60"`
+	PubKey []byte
+}
+
+// See RFC 4462, section 3
+const msgUserAuthGSSAPIResponse = 60
+
+type userAuthGSSAPIResponse struct {
+	SupportMech []byte `sshtype:"60"`
+}
+
+const msgUserAuthGSSAPIToken = 61
+
+type userAuthGSSAPIToken struct {
+	Token []byte `sshtype:"61"`
+}
+
+const msgUserAuthGSSAPIMIC = 66
+
+type userAuthGSSAPIMIC struct {
+	MIC []byte `sshtype:"66"`
+}
+
+// See RFC 4462, section 3.9
+const msgUserAuthGSSAPIErrTok = 64
+
+type userAuthGSSAPIErrTok struct {
+	ErrorToken []byte `sshtype:"64"`
+}
+
+// See RFC 4462, section 3.8
+const msgUserAuthGSSAPIError = 65
+
+type userAuthGSSAPIError struct {
+	MajorStatus uint32 `sshtype:"65"`
+	MinorStatus uint32
+	Message     string
+	LanguageTag string
+}
+
+// typeTags returns the possible type bytes for the given reflect.Type, which
+// should be a struct. The possible values are separated by a '|' character.
+func typeTags(structType reflect.Type) (tags []byte) {
+	tagStr := structType.Field(0).Tag.Get("sshtype")
+
+	for _, tag := range strings.Split(tagStr, "|") {
+		i, err := strconv.Atoi(tag)
+		if err == nil {
+			tags = append(tags, byte(i))
+		}
+	}
+
+	return tags
+}
+
+func fieldError(t reflect.Type, field int, problem string) error {
+	if problem != "" {
+		problem = ": " + problem
+	}
+	return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
+}
+
+var errShortRead = errors.New("ssh: short read")
+
+// Unmarshal parses data in SSH wire format into a structure. The out
+// argument should be a pointer to struct. If the first member of the
+// struct has the "sshtype" tag set to a '|'-separated set of numbers
+// in decimal, the packet must start with one of those numbers. In
+// case of error, Unmarshal returns a ParseError or
+// UnexpectedMessageError.
+func Unmarshal(data []byte, out interface{}) error {
+	v := reflect.ValueOf(out).Elem()
+	structType := v.Type()
+	expectedTypes := typeTags(structType)
+
+	var expectedType byte
+	if len(expectedTypes) > 0 {
+		expectedType = expectedTypes[0]
+	}
+
+	if len(data) == 0 {
+		return parseError(expectedType)
+	}
+
+	if len(expectedTypes) > 0 {
+		goodType := false
+		for _, e := range expectedTypes {
+			if e > 0 && data[0] == e {
+				goodType = true
+				break
+			}
+		}
+		if !goodType {
+			return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes)
+		}
+		data = data[1:]
+	}
+
+	var ok bool
+	for i := 0; i < v.NumField(); i++ {
+		field := v.Field(i)
+		t := field.Type()
+		switch t.Kind() {
+		case reflect.Bool:
+			if len(data) < 1 {
+				return errShortRead
+			}
+			field.SetBool(data[0] != 0)
+			data = data[1:]
+		case reflect.Array:
+			if t.Elem().Kind() != reflect.Uint8 {
+				return fieldError(structType, i, "array of unsupported type")
+			}
+			if len(data) < t.Len() {
+				return errShortRead
+			}
+			for j, n := 0, t.Len(); j < n; j++ {
+				field.Index(j).Set(reflect.ValueOf(data[j]))
+			}
+			data = data[t.Len():]
+		case reflect.Uint64:
+			var u64 uint64
+			if u64, data, ok = parseUint64(data); !ok {
+				return errShortRead
+			}
+			field.SetUint(u64)
+		case reflect.Uint32:
+			var u32 uint32
+			if u32, data, ok = parseUint32(data); !ok {
+				return errShortRead
+			}
+			field.SetUint(uint64(u32))
+		case reflect.Uint8:
+			if len(data) < 1 {
+				return errShortRead
+			}
+			field.SetUint(uint64(data[0]))
+			data = data[1:]
+		case reflect.String:
+			var s []byte
+			if s, data, ok = parseString(data); !ok {
+				return fieldError(structType, i, "")
+			}
+			field.SetString(string(s))
+		case reflect.Slice:
+			switch t.Elem().Kind() {
+			case reflect.Uint8:
+				if structType.Field(i).Tag.Get("ssh") == "rest" {
+					field.Set(reflect.ValueOf(data))
+					data = nil
+				} else {
+					var s []byte
+					if s, data, ok = parseString(data); !ok {
+						return errShortRead
+					}
+					field.Set(reflect.ValueOf(s))
+				}
+			case reflect.String:
+				var nl []string
+				if nl, data, ok = parseNameList(data); !ok {
+					return errShortRead
+				}
+				field.Set(reflect.ValueOf(nl))
+			default:
+				return fieldError(structType, i, "slice of unsupported type")
+			}
+		case reflect.Ptr:
+			if t == bigIntType {
+				var n *big.Int
+				if n, data, ok = parseInt(data); !ok {
+					return errShortRead
+				}
+				field.Set(reflect.ValueOf(n))
+			} else {
+				return fieldError(structType, i, "pointer to unsupported type")
+			}
+		default:
+			return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t))
+		}
+	}
+
+	if len(data) != 0 {
+		return parseError(expectedType)
+	}
+
+	return nil
+}
+
+// Marshal serializes the message in msg to SSH wire format.  The msg
+// argument should be a struct or pointer to struct. If the first
+// member has the "sshtype" tag set to a number in decimal, that
+// number is prepended to the result. If the last of member has the
+// "ssh" tag set to "rest", its contents are appended to the output.
+func Marshal(msg interface{}) []byte {
+	out := make([]byte, 0, 64)
+	return marshalStruct(out, msg)
+}
+
+func marshalStruct(out []byte, msg interface{}) []byte {
+	v := reflect.Indirect(reflect.ValueOf(msg))
+	msgTypes := typeTags(v.Type())
+	if len(msgTypes) > 0 {
+		out = append(out, msgTypes[0])
+	}
+
+	for i, n := 0, v.NumField(); i < n; i++ {
+		field := v.Field(i)
+		switch t := field.Type(); t.Kind() {
+		case reflect.Bool:
+			var v uint8
+			if field.Bool() {
+				v = 1
+			}
+			out = append(out, v)
+		case reflect.Array:
+			if t.Elem().Kind() != reflect.Uint8 {
+				panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
+			}
+			for j, l := 0, t.Len(); j < l; j++ {
+				out = append(out, uint8(field.Index(j).Uint()))
+			}
+		case reflect.Uint32:
+			out = appendU32(out, uint32(field.Uint()))
+		case reflect.Uint64:
+			out = appendU64(out, uint64(field.Uint()))
+		case reflect.Uint8:
+			out = append(out, uint8(field.Uint()))
+		case reflect.String:
+			s := field.String()
+			out = appendInt(out, len(s))
+			out = append(out, s...)
+		case reflect.Slice:
+			switch t.Elem().Kind() {
+			case reflect.Uint8:
+				if v.Type().Field(i).Tag.Get("ssh") != "rest" {
+					out = appendInt(out, field.Len())
+				}
+				out = append(out, field.Bytes()...)
+			case reflect.String:
+				offset := len(out)
+				out = appendU32(out, 0)
+				if n := field.Len(); n > 0 {
+					for j := 0; j < n; j++ {
+						f := field.Index(j)
+						if j != 0 {
+							out = append(out, ',')
+						}
+						out = append(out, f.String()...)
+					}
+					// overwrite length value
+					binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
+				}
+			default:
+				panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
+			}
+		case reflect.Ptr:
+			if t == bigIntType {
+				var n *big.Int
+				nValue := reflect.ValueOf(&n)
+				nValue.Elem().Set(field)
+				needed := intLength(n)
+				oldLength := len(out)
+
+				if cap(out)-len(out) < needed {
+					newOut := make([]byte, len(out), 2*(len(out)+needed))
+					copy(newOut, out)
+					out = newOut
+				}
+				out = out[:oldLength+needed]
+				marshalInt(out[oldLength:], n)
+			} else {
+				panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
+			}
+		}
+	}
+
+	return out
+}
+
+var bigOne = big.NewInt(1)
+
+func parseString(in []byte) (out, rest []byte, ok bool) {
+	if len(in) < 4 {
+		return
+	}
+	length := binary.BigEndian.Uint32(in)
+	in = in[4:]
+	if uint32(len(in)) < length {
+		return
+	}
+	out = in[:length]
+	rest = in[length:]
+	ok = true
+	return
+}
+
+var (
+	comma         = []byte{','}
+	emptyNameList = []string{}
+)
+
+func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
+	contents, rest, ok := parseString(in)
+	if !ok {
+		return
+	}
+	if len(contents) == 0 {
+		out = emptyNameList
+		return
+	}
+	parts := bytes.Split(contents, comma)
+	out = make([]string, len(parts))
+	for i, part := range parts {
+		out[i] = string(part)
+	}
+	return
+}
+
+func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
+	contents, rest, ok := parseString(in)
+	if !ok {
+		return
+	}
+	out = new(big.Int)
+
+	if len(contents) > 0 && contents[0]&0x80 == 0x80 {
+		// This is a negative number
+		notBytes := make([]byte, len(contents))
+		for i := range notBytes {
+			notBytes[i] = ^contents[i]
+		}
+		out.SetBytes(notBytes)
+		out.Add(out, bigOne)
+		out.Neg(out)
+	} else {
+		// Positive number
+		out.SetBytes(contents)
+	}
+	ok = true
+	return
+}
+
+func parseUint32(in []byte) (uint32, []byte, bool) {
+	if len(in) < 4 {
+		return 0, nil, false
+	}
+	return binary.BigEndian.Uint32(in), in[4:], true
+}
+
+func parseUint64(in []byte) (uint64, []byte, bool) {
+	if len(in) < 8 {
+		return 0, nil, false
+	}
+	return binary.BigEndian.Uint64(in), in[8:], true
+}
+
+func intLength(n *big.Int) int {
+	length := 4 /* length bytes */
+	if n.Sign() < 0 {
+		nMinus1 := new(big.Int).Neg(n)
+		nMinus1.Sub(nMinus1, bigOne)
+		bitLen := nMinus1.BitLen()
+		if bitLen%8 == 0 {
+			// The number will need 0xff padding
+			length++
+		}
+		length += (bitLen + 7) / 8
+	} else if n.Sign() == 0 {
+		// A zero is the zero length string
+	} else {
+		bitLen := n.BitLen()
+		if bitLen%8 == 0 {
+			// The number will need 0x00 padding
+			length++
+		}
+		length += (bitLen + 7) / 8
+	}
+
+	return length
+}
+
+func marshalUint32(to []byte, n uint32) []byte {
+	binary.BigEndian.PutUint32(to, n)
+	return to[4:]
+}
+
+func marshalUint64(to []byte, n uint64) []byte {
+	binary.BigEndian.PutUint64(to, n)
+	return to[8:]
+}
+
+func marshalInt(to []byte, n *big.Int) []byte {
+	lengthBytes := to
+	to = to[4:]
+	length := 0
+
+	if n.Sign() < 0 {
+		// A negative number has to be converted to two's-complement
+		// form. So we'll subtract 1 and invert. If the
+		// most-significant-bit isn't set then we'll need to pad the
+		// beginning with 0xff in order to keep the number negative.
+		nMinus1 := new(big.Int).Neg(n)
+		nMinus1.Sub(nMinus1, bigOne)
+		bytes := nMinus1.Bytes()
+		for i := range bytes {
+			bytes[i] ^= 0xff
+		}
+		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+			to[0] = 0xff
+			to = to[1:]
+			length++
+		}
+		nBytes := copy(to, bytes)
+		to = to[nBytes:]
+		length += nBytes
+	} else if n.Sign() == 0 {
+		// A zero is the zero length string
+	} else {
+		bytes := n.Bytes()
+		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+			// We'll have to pad this with a 0x00 in order to
+			// stop it looking like a negative number.
+			to[0] = 0
+			to = to[1:]
+			length++
+		}
+		nBytes := copy(to, bytes)
+		to = to[nBytes:]
+		length += nBytes
+	}
+
+	lengthBytes[0] = byte(length >> 24)
+	lengthBytes[1] = byte(length >> 16)
+	lengthBytes[2] = byte(length >> 8)
+	lengthBytes[3] = byte(length)
+	return to
+}
+
+func writeInt(w io.Writer, n *big.Int) {
+	length := intLength(n)
+	buf := make([]byte, length)
+	marshalInt(buf, n)
+	w.Write(buf)
+}
+
+func writeString(w io.Writer, s []byte) {
+	var lengthBytes [4]byte
+	lengthBytes[0] = byte(len(s) >> 24)
+	lengthBytes[1] = byte(len(s) >> 16)
+	lengthBytes[2] = byte(len(s) >> 8)
+	lengthBytes[3] = byte(len(s))
+	w.Write(lengthBytes[:])
+	w.Write(s)
+}
+
+func stringLength(n int) int {
+	return 4 + n
+}
+
+func marshalString(to []byte, s []byte) []byte {
+	to[0] = byte(len(s) >> 24)
+	to[1] = byte(len(s) >> 16)
+	to[2] = byte(len(s) >> 8)
+	to[3] = byte(len(s))
+	to = to[4:]
+	copy(to, s)
+	return to[len(s):]
+}
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil))
+
+// Decode a packet into its corresponding message.
+func decode(packet []byte) (interface{}, error) {
+	var msg interface{}
+	switch packet[0] {
+	case msgDisconnect:
+		msg = new(disconnectMsg)
+	case msgServiceRequest:
+		msg = new(serviceRequestMsg)
+	case msgServiceAccept:
+		msg = new(serviceAcceptMsg)
+	case msgKexInit:
+		msg = new(kexInitMsg)
+	case msgKexDHInit:
+		msg = new(kexDHInitMsg)
+	case msgKexDHReply:
+		msg = new(kexDHReplyMsg)
+	case msgUserAuthRequest:
+		msg = new(userAuthRequestMsg)
+	case msgUserAuthSuccess:
+		return new(userAuthSuccessMsg), nil
+	case msgUserAuthFailure:
+		msg = new(userAuthFailureMsg)
+	case msgUserAuthPubKeyOk:
+		msg = new(userAuthPubKeyOkMsg)
+	case msgGlobalRequest:
+		msg = new(globalRequestMsg)
+	case msgRequestSuccess:
+		msg = new(globalRequestSuccessMsg)
+	case msgRequestFailure:
+		msg = new(globalRequestFailureMsg)
+	case msgChannelOpen:
+		msg = new(channelOpenMsg)
+	case msgChannelData:
+		msg = new(channelDataMsg)
+	case msgChannelOpenConfirm:
+		msg = new(channelOpenConfirmMsg)
+	case msgChannelOpenFailure:
+		msg = new(channelOpenFailureMsg)
+	case msgChannelWindowAdjust:
+		msg = new(windowAdjustMsg)
+	case msgChannelEOF:
+		msg = new(channelEOFMsg)
+	case msgChannelClose:
+		msg = new(channelCloseMsg)
+	case msgChannelRequest:
+		msg = new(channelRequestMsg)
+	case msgChannelSuccess:
+		msg = new(channelRequestSuccessMsg)
+	case msgChannelFailure:
+		msg = new(channelRequestFailureMsg)
+	case msgUserAuthGSSAPIToken:
+		msg = new(userAuthGSSAPIToken)
+	case msgUserAuthGSSAPIMIC:
+		msg = new(userAuthGSSAPIMIC)
+	case msgUserAuthGSSAPIErrTok:
+		msg = new(userAuthGSSAPIErrTok)
+	case msgUserAuthGSSAPIError:
+		msg = new(userAuthGSSAPIError)
+	default:
+		return nil, unexpectedMessageError(0, packet[0])
+	}
+	if err := Unmarshal(packet, msg); err != nil {
+		return nil, err
+	}
+	return msg, nil
+}
+
+var packetTypeNames = map[byte]string{
+	msgDisconnect:          "disconnectMsg",
+	msgServiceRequest:      "serviceRequestMsg",
+	msgServiceAccept:       "serviceAcceptMsg",
+	msgKexInit:             "kexInitMsg",
+	msgKexDHInit:           "kexDHInitMsg",
+	msgKexDHReply:          "kexDHReplyMsg",
+	msgUserAuthRequest:     "userAuthRequestMsg",
+	msgUserAuthSuccess:     "userAuthSuccessMsg",
+	msgUserAuthFailure:     "userAuthFailureMsg",
+	msgUserAuthPubKeyOk:    "userAuthPubKeyOkMsg",
+	msgGlobalRequest:       "globalRequestMsg",
+	msgRequestSuccess:      "globalRequestSuccessMsg",
+	msgRequestFailure:      "globalRequestFailureMsg",
+	msgChannelOpen:         "channelOpenMsg",
+	msgChannelData:         "channelDataMsg",
+	msgChannelOpenConfirm:  "channelOpenConfirmMsg",
+	msgChannelOpenFailure:  "channelOpenFailureMsg",
+	msgChannelWindowAdjust: "windowAdjustMsg",
+	msgChannelEOF:          "channelEOFMsg",
+	msgChannelClose:        "channelCloseMsg",
+	msgChannelRequest:      "channelRequestMsg",
+	msgChannelSuccess:      "channelRequestSuccessMsg",
+	msgChannelFailure:      "channelRequestFailureMsg",
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go
new file mode 100644
index 0000000..9654c01
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mux.go
@@ -0,0 +1,351 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"log"
+	"sync"
+	"sync/atomic"
+)
+
+// debugMux, if set, causes messages in the connection protocol to be
+// logged.
+const debugMux = false
+
+// chanList is a thread safe channel list.
+type chanList struct {
+	// protects concurrent access to chans
+	sync.Mutex
+
+	// chans are indexed by the local id of the channel, which the
+	// other side should send in the PeersId field.
+	chans []*channel
+
+	// This is a debugging aid: it offsets all IDs by this
+	// amount. This helps distinguish otherwise identical
+	// server/client muxes
+	offset uint32
+}
+
+// Assigns a channel ID to the given channel.
+func (c *chanList) add(ch *channel) uint32 {
+	c.Lock()
+	defer c.Unlock()
+	for i := range c.chans {
+		if c.chans[i] == nil {
+			c.chans[i] = ch
+			return uint32(i) + c.offset
+		}
+	}
+	c.chans = append(c.chans, ch)
+	return uint32(len(c.chans)-1) + c.offset
+}
+
+// getChan returns the channel for the given ID.
+func (c *chanList) getChan(id uint32) *channel {
+	id -= c.offset
+
+	c.Lock()
+	defer c.Unlock()
+	if id < uint32(len(c.chans)) {
+		return c.chans[id]
+	}
+	return nil
+}
+
+func (c *chanList) remove(id uint32) {
+	id -= c.offset
+	c.Lock()
+	if id < uint32(len(c.chans)) {
+		c.chans[id] = nil
+	}
+	c.Unlock()
+}
+
+// dropAll forgets all channels it knows, returning them in a slice.
+func (c *chanList) dropAll() []*channel {
+	c.Lock()
+	defer c.Unlock()
+	var r []*channel
+
+	for _, ch := range c.chans {
+		if ch == nil {
+			continue
+		}
+		r = append(r, ch)
+	}
+	c.chans = nil
+	return r
+}
+
+// mux represents the state for the SSH connection protocol, which
+// multiplexes many channels onto a single packet transport.
+type mux struct {
+	conn     packetConn
+	chanList chanList
+
+	incomingChannels chan NewChannel
+
+	globalSentMu     sync.Mutex
+	globalResponses  chan interface{}
+	incomingRequests chan *Request
+
+	errCond *sync.Cond
+	err     error
+}
+
+// When debugging, each new chanList instantiation has a different
+// offset.
+var globalOff uint32
+
+func (m *mux) Wait() error {
+	m.errCond.L.Lock()
+	defer m.errCond.L.Unlock()
+	for m.err == nil {
+		m.errCond.Wait()
+	}
+	return m.err
+}
+
+// newMux returns a mux that runs over the given connection.
+func newMux(p packetConn) *mux {
+	m := &mux{
+		conn:             p,
+		incomingChannels: make(chan NewChannel, chanSize),
+		globalResponses:  make(chan interface{}, 1),
+		incomingRequests: make(chan *Request, chanSize),
+		errCond:          newCond(),
+	}
+	if debugMux {
+		m.chanList.offset = atomic.AddUint32(&globalOff, 1)
+	}
+
+	go m.loop()
+	return m
+}
+
+func (m *mux) sendMessage(msg interface{}) error {
+	p := Marshal(msg)
+	if debugMux {
+		log.Printf("send global(%d): %#v", m.chanList.offset, msg)
+	}
+	return m.conn.writePacket(p)
+}
+
+func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
+	if wantReply {
+		m.globalSentMu.Lock()
+		defer m.globalSentMu.Unlock()
+	}
+
+	if err := m.sendMessage(globalRequestMsg{
+		Type:      name,
+		WantReply: wantReply,
+		Data:      payload,
+	}); err != nil {
+		return false, nil, err
+	}
+
+	if !wantReply {
+		return false, nil, nil
+	}
+
+	msg, ok := <-m.globalResponses
+	if !ok {
+		return false, nil, io.EOF
+	}
+	switch msg := msg.(type) {
+	case *globalRequestFailureMsg:
+		return false, msg.Data, nil
+	case *globalRequestSuccessMsg:
+		return true, msg.Data, nil
+	default:
+		return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg)
+	}
+}
+
+// ackRequest must be called after processing a global request that
+// has WantReply set.
+func (m *mux) ackRequest(ok bool, data []byte) error {
+	if ok {
+		return m.sendMessage(globalRequestSuccessMsg{Data: data})
+	}
+	return m.sendMessage(globalRequestFailureMsg{Data: data})
+}
+
+func (m *mux) Close() error {
+	return m.conn.Close()
+}
+
+// loop runs the connection machine. It will process packets until an
+// error is encountered. To synchronize on loop exit, use mux.Wait.
+func (m *mux) loop() {
+	var err error
+	for err == nil {
+		err = m.onePacket()
+	}
+
+	for _, ch := range m.chanList.dropAll() {
+		ch.close()
+	}
+
+	close(m.incomingChannels)
+	close(m.incomingRequests)
+	close(m.globalResponses)
+
+	m.conn.Close()
+
+	m.errCond.L.Lock()
+	m.err = err
+	m.errCond.Broadcast()
+	m.errCond.L.Unlock()
+
+	if debugMux {
+		log.Println("loop exit", err)
+	}
+}
+
+// onePacket reads and processes one packet.
+func (m *mux) onePacket() error {
+	packet, err := m.conn.readPacket()
+	if err != nil {
+		return err
+	}
+
+	if debugMux {
+		if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData {
+			log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet))
+		} else {
+			p, _ := decode(packet)
+			log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet))
+		}
+	}
+
+	switch packet[0] {
+	case msgChannelOpen:
+		return m.handleChannelOpen(packet)
+	case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
+		return m.handleGlobalPacket(packet)
+	}
+
+	// assume a channel packet.
+	if len(packet) < 5 {
+		return parseError(packet[0])
+	}
+	id := binary.BigEndian.Uint32(packet[1:])
+	ch := m.chanList.getChan(id)
+	if ch == nil {
+		return m.handleUnknownChannelPacket(id, packet)
+	}
+
+	return ch.handlePacket(packet)
+}
+
+func (m *mux) handleGlobalPacket(packet []byte) error {
+	msg, err := decode(packet)
+	if err != nil {
+		return err
+	}
+
+	switch msg := msg.(type) {
+	case *globalRequestMsg:
+		m.incomingRequests <- &Request{
+			Type:      msg.Type,
+			WantReply: msg.WantReply,
+			Payload:   msg.Data,
+			mux:       m,
+		}
+	case *globalRequestSuccessMsg, *globalRequestFailureMsg:
+		m.globalResponses <- msg
+	default:
+		panic(fmt.Sprintf("not a global message %#v", msg))
+	}
+
+	return nil
+}
+
+// handleChannelOpen schedules a channel to be Accept()ed.
+func (m *mux) handleChannelOpen(packet []byte) error {
+	var msg channelOpenMsg
+	if err := Unmarshal(packet, &msg); err != nil {
+		return err
+	}
+
+	if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+		failMsg := channelOpenFailureMsg{
+			PeersID:  msg.PeersID,
+			Reason:   ConnectionFailed,
+			Message:  "invalid request",
+			Language: "en_US.UTF-8",
+		}
+		return m.sendMessage(failMsg)
+	}
+
+	c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData)
+	c.remoteId = msg.PeersID
+	c.maxRemotePayload = msg.MaxPacketSize
+	c.remoteWin.add(msg.PeersWindow)
+	m.incomingChannels <- c
+	return nil
+}
+
+func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) {
+	ch, err := m.openChannel(chanType, extra)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return ch, ch.incomingRequests, nil
+}
+
+func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
+	ch := m.newChannel(chanType, channelOutbound, extra)
+
+	ch.maxIncomingPayload = channelMaxPacket
+
+	open := channelOpenMsg{
+		ChanType:         chanType,
+		PeersWindow:      ch.myWindow,
+		MaxPacketSize:    ch.maxIncomingPayload,
+		TypeSpecificData: extra,
+		PeersID:          ch.localId,
+	}
+	if err := m.sendMessage(open); err != nil {
+		return nil, err
+	}
+
+	switch msg := (<-ch.msg).(type) {
+	case *channelOpenConfirmMsg:
+		return ch, nil
+	case *channelOpenFailureMsg:
+		return nil, &OpenChannelError{msg.Reason, msg.Message}
+	default:
+		return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg)
+	}
+}
+
+func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) error {
+	msg, err := decode(packet)
+	if err != nil {
+		return err
+	}
+
+	switch msg := msg.(type) {
+	// RFC 4254 section 5.4 says unrecognized channel requests should
+	// receive a failure response.
+	case *channelRequestMsg:
+		if msg.WantReply {
+			return m.sendMessage(channelRequestFailureMsg{
+				PeersID: msg.PeersID,
+			})
+		}
+		return nil
+	default:
+		return fmt.Errorf("ssh: invalid channel %d", id)
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
new file mode 100644
index 0000000..7d42a8c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -0,0 +1,716 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"strings"
+)
+
+// The Permissions type holds fine-grained permissions that are
+// specific to a user or a specific authentication method for a user.
+// The Permissions value for a successful authentication attempt is
+// available in ServerConn, so it can be used to pass information from
+// the user-authentication phase to the application layer.
+type Permissions struct {
+	// CriticalOptions indicate restrictions to the default
+	// permissions, and are typically used in conjunction with
+	// user certificates. The standard for SSH certificates
+	// defines "force-command" (only allow the given command to
+	// execute) and "source-address" (only allow connections from
+	// the given address). The SSH package currently only enforces
+	// the "source-address" critical option. It is up to server
+	// implementations to enforce other critical options, such as
+	// "force-command", by checking them after the SSH handshake
+	// is successful. In general, SSH servers should reject
+	// connections that specify critical options that are unknown
+	// or not supported.
+	CriticalOptions map[string]string
+
+	// Extensions are extra functionality that the server may
+	// offer on authenticated connections. Lack of support for an
+	// extension does not preclude authenticating a user. Common
+	// extensions are "permit-agent-forwarding",
+	// "permit-X11-forwarding". The Go SSH library currently does
+	// not act on any extension, and it is up to server
+	// implementations to honor them. Extensions can be used to
+	// pass data from the authentication callbacks to the server
+	// application layer.
+	Extensions map[string]string
+}
+
+type GSSAPIWithMICConfig struct {
+	// AllowLogin, must be set, is called when gssapi-with-mic
+	// authentication is selected (RFC 4462 section 3). The srcName is from the
+	// results of the GSS-API authentication. The format is username@DOMAIN.
+	// GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions.
+	// This callback is called after the user identity is established with GSSAPI to decide if the user can login with
+	// which permissions. If the user is allowed to login, it should return a nil error.
+	AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error)
+
+	// Server must be set. It's the implementation
+	// of the GSSAPIServer interface. See GSSAPIServer interface for details.
+	Server GSSAPIServer
+}
+
+// ServerConfig holds server specific configuration data.
+type ServerConfig struct {
+	// Config contains configuration shared between client and server.
+	Config
+
+	hostKeys []Signer
+
+	// NoClientAuth is true if clients are allowed to connect without
+	// authenticating.
+	NoClientAuth bool
+
+	// MaxAuthTries specifies the maximum number of authentication attempts
+	// permitted per connection. If set to a negative number, the number of
+	// attempts are unlimited. If set to zero, the number of attempts are limited
+	// to 6.
+	MaxAuthTries int
+
+	// PasswordCallback, if non-nil, is called when a user
+	// attempts to authenticate using a password.
+	PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
+
+	// PublicKeyCallback, if non-nil, is called when a client
+	// offers a public key for authentication. It must return a nil error
+	// if the given public key can be used to authenticate the
+	// given user. For example, see CertChecker.Authenticate. A
+	// call to this function does not guarantee that the key
+	// offered is in fact used to authenticate. To record any data
+	// depending on the public key, store it inside a
+	// Permissions.Extensions entry.
+	PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+	// KeyboardInteractiveCallback, if non-nil, is called when
+	// keyboard-interactive authentication is selected (RFC
+	// 4256). The client object's Challenge function should be
+	// used to query the user. The callback may offer multiple
+	// Challenge rounds. To avoid information leaks, the client
+	// should be presented a challenge even if the user is
+	// unknown.
+	KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
+
+	// AuthLogCallback, if non-nil, is called to log all authentication
+	// attempts.
+	AuthLogCallback func(conn ConnMetadata, method string, err error)
+
+	// ServerVersion is the version identification string to announce in
+	// the public handshake.
+	// If empty, a reasonable default is used.
+	// Note that RFC 4253 section 4.2 requires that this string start with
+	// "SSH-2.0-".
+	ServerVersion string
+
+	// BannerCallback, if present, is called and the return string is sent to
+	// the client after key exchange completed but before authentication.
+	BannerCallback func(conn ConnMetadata) string
+
+	// GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used
+	// when gssapi-with-mic authentication is selected (RFC 4462 section 3).
+	GSSAPIWithMICConfig *GSSAPIWithMICConfig
+}
+
+// AddHostKey adds a private key as a host key. If an existing host
+// key exists with the same algorithm, it is overwritten. Each server
+// config must have at least one host key.
+func (s *ServerConfig) AddHostKey(key Signer) {
+	for i, k := range s.hostKeys {
+		if k.PublicKey().Type() == key.PublicKey().Type() {
+			s.hostKeys[i] = key
+			return
+		}
+	}
+
+	s.hostKeys = append(s.hostKeys, key)
+}
+
+// cachedPubKey contains the results of querying whether a public key is
+// acceptable for a user.
+type cachedPubKey struct {
+	user       string
+	pubKeyData []byte
+	result     error
+	perms      *Permissions
+}
+
+const maxCachedPubKeys = 16
+
+// pubKeyCache caches tests for public keys.  Since SSH clients
+// will query whether a public key is acceptable before attempting to
+// authenticate with it, we end up with duplicate queries for public
+// key validity.  The cache only applies to a single ServerConn.
+type pubKeyCache struct {
+	keys []cachedPubKey
+}
+
+// get returns the result for a given user/algo/key tuple.
+func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
+	for _, k := range c.keys {
+		if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
+			return k, true
+		}
+	}
+	return cachedPubKey{}, false
+}
+
+// add adds the given tuple to the cache.
+func (c *pubKeyCache) add(candidate cachedPubKey) {
+	if len(c.keys) < maxCachedPubKeys {
+		c.keys = append(c.keys, candidate)
+	}
+}
+
+// ServerConn is an authenticated SSH connection, as seen from the
+// server
+type ServerConn struct {
+	Conn
+
+	// If the succeeding authentication callback returned a
+	// non-nil Permissions pointer, it is stored here.
+	Permissions *Permissions
+}
+
+// NewServerConn starts a new SSH server with c as the underlying
+// transport.  It starts with a handshake and, if the handshake is
+// unsuccessful, it closes the connection and returns an error.  The
+// Request and NewChannel channels must be serviced, or the connection
+// will hang.
+//
+// The returned error may be of type *ServerAuthError for
+// authentication errors.
+func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
+	fullConf := *config
+	fullConf.SetDefaults()
+	if fullConf.MaxAuthTries == 0 {
+		fullConf.MaxAuthTries = 6
+	}
+	// Check if the config contains any unsupported key exchanges
+	for _, kex := range fullConf.KeyExchanges {
+		if _, ok := serverForbiddenKexAlgos[kex]; ok {
+			return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
+		}
+	}
+
+	s := &connection{
+		sshConn: sshConn{conn: c},
+	}
+	perms, err := s.serverHandshake(&fullConf)
+	if err != nil {
+		c.Close()
+		return nil, nil, nil, err
+	}
+	return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
+}
+
+// signAndMarshal signs the data with the appropriate algorithm,
+// and serializes the result in SSH wire format.
+func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
+	sig, err := k.Sign(rand, data)
+	if err != nil {
+		return nil, err
+	}
+
+	return Marshal(sig), nil
+}
+
+// handshake performs key exchange and user authentication.
+func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
+	if len(config.hostKeys) == 0 {
+		return nil, errors.New("ssh: server has no host keys")
+	}
+
+	if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil &&
+		config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil ||
+		config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) {
+		return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+	}
+
+	if config.ServerVersion != "" {
+		s.serverVersion = []byte(config.ServerVersion)
+	} else {
+		s.serverVersion = []byte(packageVersion)
+	}
+	var err error
+	s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
+	if err != nil {
+		return nil, err
+	}
+
+	tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
+	s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
+
+	if err := s.transport.waitSession(); err != nil {
+		return nil, err
+	}
+
+	// We just did the key change, so the session ID is established.
+	s.sessionID = s.transport.getSessionID()
+
+	var packet []byte
+	if packet, err = s.transport.readPacket(); err != nil {
+		return nil, err
+	}
+
+	var serviceRequest serviceRequestMsg
+	if err = Unmarshal(packet, &serviceRequest); err != nil {
+		return nil, err
+	}
+	if serviceRequest.Service != serviceUserAuth {
+		return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
+	}
+	serviceAccept := serviceAcceptMsg{
+		Service: serviceUserAuth,
+	}
+	if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
+		return nil, err
+	}
+
+	perms, err := s.serverAuthenticate(config)
+	if err != nil {
+		return nil, err
+	}
+	s.mux = newMux(s.transport)
+	return perms, err
+}
+
+func isAcceptableAlgo(algo string) bool {
+	switch algo {
+	case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
+		CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
+		return true
+	}
+	return false
+}
+
+func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
+	if addr == nil {
+		return errors.New("ssh: no address known for client, but source-address match required")
+	}
+
+	tcpAddr, ok := addr.(*net.TCPAddr)
+	if !ok {
+		return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
+	}
+
+	for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
+		if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+			if allowedIP.Equal(tcpAddr.IP) {
+				return nil
+			}
+		} else {
+			_, ipNet, err := net.ParseCIDR(sourceAddr)
+			if err != nil {
+				return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+			}
+
+			if ipNet.Contains(tcpAddr.IP) {
+				return nil
+			}
+		}
+	}
+
+	return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
+}
+
+func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection,
+	sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) {
+	gssAPIServer := gssapiConfig.Server
+	defer gssAPIServer.DeleteSecContext()
+	var srcName string
+	for {
+		var (
+			outToken     []byte
+			needContinue bool
+		)
+		outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken)
+		if err != nil {
+			return err, nil, nil
+		}
+		if len(outToken) != 0 {
+			if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{
+				Token: outToken,
+			})); err != nil {
+				return nil, nil, err
+			}
+		}
+		if !needContinue {
+			break
+		}
+		packet, err := s.transport.readPacket()
+		if err != nil {
+			return nil, nil, err
+		}
+		userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
+		if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
+			return nil, nil, err
+		}
+	}
+	packet, err := s.transport.readPacket()
+	if err != nil {
+		return nil, nil, err
+	}
+	userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{}
+	if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil {
+		return nil, nil, err
+	}
+	mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method)
+	if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil {
+		return err, nil, nil
+	}
+	perms, authErr = gssapiConfig.AllowLogin(s, srcName)
+	return authErr, perms, nil
+}
+
+// ServerAuthError represents server authentication errors and is
+// sometimes returned by NewServerConn. It appends any authentication
+// errors that may occur, and is returned if all of the authentication
+// methods provided by the user failed to authenticate.
+type ServerAuthError struct {
+	// Errors contains authentication errors returned by the authentication
+	// callback methods. The first entry is typically ErrNoAuth.
+	Errors []error
+}
+
+func (l ServerAuthError) Error() string {
+	var errs []string
+	for _, err := range l.Errors {
+		errs = append(errs, err.Error())
+	}
+	return "[" + strings.Join(errs, ", ") + "]"
+}
+
+// ErrNoAuth is the error value returned if no
+// authentication method has been passed yet. This happens as a normal
+// part of the authentication loop, since the client first tries
+// 'none' authentication to discover available methods.
+// It is returned in ServerAuthError.Errors from NewServerConn.
+var ErrNoAuth = errors.New("ssh: no auth passed yet")
+
+func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
+	sessionID := s.transport.getSessionID()
+	var cache pubKeyCache
+	var perms *Permissions
+
+	authFailures := 0
+	var authErrs []error
+	var displayedBanner bool
+
+userAuthLoop:
+	for {
+		if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
+			discMsg := &disconnectMsg{
+				Reason:  2,
+				Message: "too many authentication failures",
+			}
+
+			if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
+				return nil, err
+			}
+
+			return nil, discMsg
+		}
+
+		var userAuthReq userAuthRequestMsg
+		if packet, err := s.transport.readPacket(); err != nil {
+			if err == io.EOF {
+				return nil, &ServerAuthError{Errors: authErrs}
+			}
+			return nil, err
+		} else if err = Unmarshal(packet, &userAuthReq); err != nil {
+			return nil, err
+		}
+
+		if userAuthReq.Service != serviceSSH {
+			return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
+		}
+
+		s.user = userAuthReq.User
+
+		if !displayedBanner && config.BannerCallback != nil {
+			displayedBanner = true
+			msg := config.BannerCallback(s)
+			if msg != "" {
+				bannerMsg := &userAuthBannerMsg{
+					Message: msg,
+				}
+				if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil {
+					return nil, err
+				}
+			}
+		}
+
+		perms = nil
+		authErr := ErrNoAuth
+
+		switch userAuthReq.Method {
+		case "none":
+			if config.NoClientAuth {
+				authErr = nil
+			}
+
+			// allow initial attempt of 'none' without penalty
+			if authFailures == 0 {
+				authFailures--
+			}
+		case "password":
+			if config.PasswordCallback == nil {
+				authErr = errors.New("ssh: password auth not configured")
+				break
+			}
+			payload := userAuthReq.Payload
+			if len(payload) < 1 || payload[0] != 0 {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			payload = payload[1:]
+			password, payload, ok := parseString(payload)
+			if !ok || len(payload) > 0 {
+				return nil, parseError(msgUserAuthRequest)
+			}
+
+			perms, authErr = config.PasswordCallback(s, password)
+		case "keyboard-interactive":
+			if config.KeyboardInteractiveCallback == nil {
+				authErr = errors.New("ssh: keyboard-interactive auth not configured")
+				break
+			}
+
+			prompter := &sshClientKeyboardInteractive{s}
+			perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge)
+		case "publickey":
+			if config.PublicKeyCallback == nil {
+				authErr = errors.New("ssh: publickey auth not configured")
+				break
+			}
+			payload := userAuthReq.Payload
+			if len(payload) < 1 {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			isQuery := payload[0] == 0
+			payload = payload[1:]
+			algoBytes, payload, ok := parseString(payload)
+			if !ok {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			algo := string(algoBytes)
+			if !isAcceptableAlgo(algo) {
+				authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
+				break
+			}
+
+			pubKeyData, payload, ok := parseString(payload)
+			if !ok {
+				return nil, parseError(msgUserAuthRequest)
+			}
+
+			pubKey, err := ParsePublicKey(pubKeyData)
+			if err != nil {
+				return nil, err
+			}
+
+			candidate, ok := cache.get(s.user, pubKeyData)
+			if !ok {
+				candidate.user = s.user
+				candidate.pubKeyData = pubKeyData
+				candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
+				if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
+					candidate.result = checkSourceAddress(
+						s.RemoteAddr(),
+						candidate.perms.CriticalOptions[sourceAddressCriticalOption])
+				}
+				cache.add(candidate)
+			}
+
+			if isQuery {
+				// The client can query if the given public key
+				// would be okay.
+
+				if len(payload) > 0 {
+					return nil, parseError(msgUserAuthRequest)
+				}
+
+				if candidate.result == nil {
+					okMsg := userAuthPubKeyOkMsg{
+						Algo:   algo,
+						PubKey: pubKeyData,
+					}
+					if err = s.transport.writePacket(Marshal(&okMsg)); err != nil {
+						return nil, err
+					}
+					continue userAuthLoop
+				}
+				authErr = candidate.result
+			} else {
+				sig, payload, ok := parseSignature(payload)
+				if !ok || len(payload) > 0 {
+					return nil, parseError(msgUserAuthRequest)
+				}
+				// Ensure the public key algo and signature algo
+				// are supported.  Compare the private key
+				// algorithm name that corresponds to algo with
+				// sig.Format.  This is usually the same, but
+				// for certs, the names differ.
+				if !isAcceptableAlgo(sig.Format) {
+					authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
+					break
+				}
+				signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
+
+				if err := pubKey.Verify(signedData, sig); err != nil {
+					return nil, err
+				}
+
+				authErr = candidate.result
+				perms = candidate.perms
+			}
+		case "gssapi-with-mic":
+			gssapiConfig := config.GSSAPIWithMICConfig
+			userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload)
+			if err != nil {
+				return nil, parseError(msgUserAuthRequest)
+			}
+			// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication.
+			if userAuthRequestGSSAPI.N == 0 {
+				authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported")
+				break
+			}
+			var i uint32
+			present := false
+			for i = 0; i < userAuthRequestGSSAPI.N; i++ {
+				if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) {
+					present = true
+					break
+				}
+			}
+			if !present {
+				authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism")
+				break
+			}
+			// Initial server response, see RFC 4462 section 3.3.
+			if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{
+				SupportMech: krb5OID,
+			})); err != nil {
+				return nil, err
+			}
+			// Exchange token, see RFC 4462 section 3.4.
+			packet, err := s.transport.readPacket()
+			if err != nil {
+				return nil, err
+			}
+			userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
+			if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
+				return nil, err
+			}
+			authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID,
+				userAuthReq)
+			if err != nil {
+				return nil, err
+			}
+		default:
+			authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
+		}
+
+		authErrs = append(authErrs, authErr)
+
+		if config.AuthLogCallback != nil {
+			config.AuthLogCallback(s, userAuthReq.Method, authErr)
+		}
+
+		if authErr == nil {
+			break userAuthLoop
+		}
+
+		authFailures++
+
+		var failureMsg userAuthFailureMsg
+		if config.PasswordCallback != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "password")
+		}
+		if config.PublicKeyCallback != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "publickey")
+		}
+		if config.KeyboardInteractiveCallback != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
+		}
+		if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil &&
+			config.GSSAPIWithMICConfig.AllowLogin != nil {
+			failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic")
+		}
+
+		if len(failureMsg.Methods) == 0 {
+			return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+		}
+
+		if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
+			return nil, err
+		}
+	}
+
+	if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
+		return nil, err
+	}
+	return perms, nil
+}
+
+// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
+// asking the client on the other side of a ServerConn.
+type sshClientKeyboardInteractive struct {
+	*connection
+}
+
+func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
+	if len(questions) != len(echos) {
+		return nil, errors.New("ssh: echos and questions must have equal length")
+	}
+
+	var prompts []byte
+	for i := range questions {
+		prompts = appendString(prompts, questions[i])
+		prompts = appendBool(prompts, echos[i])
+	}
+
+	if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
+		Instruction: instruction,
+		NumPrompts:  uint32(len(questions)),
+		Prompts:     prompts,
+	})); err != nil {
+		return nil, err
+	}
+
+	packet, err := c.transport.readPacket()
+	if err != nil {
+		return nil, err
+	}
+	if packet[0] != msgUserAuthInfoResponse {
+		return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0])
+	}
+	packet = packet[1:]
+
+	n, packet, ok := parseUint32(packet)
+	if !ok || int(n) != len(questions) {
+		return nil, parseError(msgUserAuthInfoResponse)
+	}
+
+	for i := uint32(0); i < n; i++ {
+		ans, rest, ok := parseString(packet)
+		if !ok {
+			return nil, parseError(msgUserAuthInfoResponse)
+		}
+
+		answers = append(answers, string(ans))
+		packet = rest
+	}
+	if len(packet) != 0 {
+		return nil, errors.New("ssh: junk at end of message")
+	}
+
+	return answers, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
new file mode 100644
index 0000000..d3321f6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -0,0 +1,647 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Session implements an interactive session described in
+// "RFC 4254, section 6".
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"sync"
+)
+
+type Signal string
+
+// POSIX signals as listed in RFC 4254 Section 6.10.
+const (
+	SIGABRT Signal = "ABRT"
+	SIGALRM Signal = "ALRM"
+	SIGFPE  Signal = "FPE"
+	SIGHUP  Signal = "HUP"
+	SIGILL  Signal = "ILL"
+	SIGINT  Signal = "INT"
+	SIGKILL Signal = "KILL"
+	SIGPIPE Signal = "PIPE"
+	SIGQUIT Signal = "QUIT"
+	SIGSEGV Signal = "SEGV"
+	SIGTERM Signal = "TERM"
+	SIGUSR1 Signal = "USR1"
+	SIGUSR2 Signal = "USR2"
+)
+
+var signals = map[Signal]int{
+	SIGABRT: 6,
+	SIGALRM: 14,
+	SIGFPE:  8,
+	SIGHUP:  1,
+	SIGILL:  4,
+	SIGINT:  2,
+	SIGKILL: 9,
+	SIGPIPE: 13,
+	SIGQUIT: 3,
+	SIGSEGV: 11,
+	SIGTERM: 15,
+}
+
+type TerminalModes map[uint8]uint32
+
+// POSIX terminal mode flags as listed in RFC 4254 Section 8.
+const (
+	tty_OP_END    = 0
+	VINTR         = 1
+	VQUIT         = 2
+	VERASE        = 3
+	VKILL         = 4
+	VEOF          = 5
+	VEOL          = 6
+	VEOL2         = 7
+	VSTART        = 8
+	VSTOP         = 9
+	VSUSP         = 10
+	VDSUSP        = 11
+	VREPRINT      = 12
+	VWERASE       = 13
+	VLNEXT        = 14
+	VFLUSH        = 15
+	VSWTCH        = 16
+	VSTATUS       = 17
+	VDISCARD      = 18
+	IGNPAR        = 30
+	PARMRK        = 31
+	INPCK         = 32
+	ISTRIP        = 33
+	INLCR         = 34
+	IGNCR         = 35
+	ICRNL         = 36
+	IUCLC         = 37
+	IXON          = 38
+	IXANY         = 39
+	IXOFF         = 40
+	IMAXBEL       = 41
+	ISIG          = 50
+	ICANON        = 51
+	XCASE         = 52
+	ECHO          = 53
+	ECHOE         = 54
+	ECHOK         = 55
+	ECHONL        = 56
+	NOFLSH        = 57
+	TOSTOP        = 58
+	IEXTEN        = 59
+	ECHOCTL       = 60
+	ECHOKE        = 61
+	PENDIN        = 62
+	OPOST         = 70
+	OLCUC         = 71
+	ONLCR         = 72
+	OCRNL         = 73
+	ONOCR         = 74
+	ONLRET        = 75
+	CS7           = 90
+	CS8           = 91
+	PARENB        = 92
+	PARODD        = 93
+	TTY_OP_ISPEED = 128
+	TTY_OP_OSPEED = 129
+)
+
+// A Session represents a connection to a remote command or shell.
+type Session struct {
+	// Stdin specifies the remote process's standard input.
+	// If Stdin is nil, the remote process reads from an empty
+	// bytes.Buffer.
+	Stdin io.Reader
+
+	// Stdout and Stderr specify the remote process's standard
+	// output and error.
+	//
+	// If either is nil, Run connects the corresponding file
+	// descriptor to an instance of ioutil.Discard. There is a
+	// fixed amount of buffering that is shared for the two streams.
+	// If either blocks it may eventually cause the remote
+	// command to block.
+	Stdout io.Writer
+	Stderr io.Writer
+
+	ch        Channel // the channel backing this session
+	started   bool    // true once Start, Run or Shell is invoked.
+	copyFuncs []func() error
+	errors    chan error // one send per copyFunc
+
+	// true if pipe method is active
+	stdinpipe, stdoutpipe, stderrpipe bool
+
+	// stdinPipeWriter is non-nil if StdinPipe has not been called
+	// and Stdin was specified by the user; it is the write end of
+	// a pipe connecting Session.Stdin to the stdin channel.
+	stdinPipeWriter io.WriteCloser
+
+	exitStatus chan error
+}
+
+// SendRequest sends an out-of-band channel request on the SSH channel
+// underlying the session.
+func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+	return s.ch.SendRequest(name, wantReply, payload)
+}
+
+func (s *Session) Close() error {
+	return s.ch.Close()
+}
+
+// RFC 4254 Section 6.4.
+type setenvRequest struct {
+	Name  string
+	Value string
+}
+
+// Setenv sets an environment variable that will be applied to any
+// command executed by Shell or Run.
+func (s *Session) Setenv(name, value string) error {
+	msg := setenvRequest{
+		Name:  name,
+		Value: value,
+	}
+	ok, err := s.ch.SendRequest("env", true, Marshal(&msg))
+	if err == nil && !ok {
+		err = errors.New("ssh: setenv failed")
+	}
+	return err
+}
+
+// RFC 4254 Section 6.2.
+type ptyRequestMsg struct {
+	Term     string
+	Columns  uint32
+	Rows     uint32
+	Width    uint32
+	Height   uint32
+	Modelist string
+}
+
+// RequestPty requests the association of a pty with the session on the remote host.
+func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error {
+	var tm []byte
+	for k, v := range termmodes {
+		kv := struct {
+			Key byte
+			Val uint32
+		}{k, v}
+
+		tm = append(tm, Marshal(&kv)...)
+	}
+	tm = append(tm, tty_OP_END)
+	req := ptyRequestMsg{
+		Term:     term,
+		Columns:  uint32(w),
+		Rows:     uint32(h),
+		Width:    uint32(w * 8),
+		Height:   uint32(h * 8),
+		Modelist: string(tm),
+	}
+	ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req))
+	if err == nil && !ok {
+		err = errors.New("ssh: pty-req failed")
+	}
+	return err
+}
+
+// RFC 4254 Section 6.5.
+type subsystemRequestMsg struct {
+	Subsystem string
+}
+
+// RequestSubsystem requests the association of a subsystem with the session on the remote host.
+// A subsystem is a predefined command that runs in the background when the ssh session is initiated
+func (s *Session) RequestSubsystem(subsystem string) error {
+	msg := subsystemRequestMsg{
+		Subsystem: subsystem,
+	}
+	ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg))
+	if err == nil && !ok {
+		err = errors.New("ssh: subsystem request failed")
+	}
+	return err
+}
+
+// RFC 4254 Section 6.7.
+type ptyWindowChangeMsg struct {
+	Columns uint32
+	Rows    uint32
+	Width   uint32
+	Height  uint32
+}
+
+// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
+func (s *Session) WindowChange(h, w int) error {
+	req := ptyWindowChangeMsg{
+		Columns: uint32(w),
+		Rows:    uint32(h),
+		Width:   uint32(w * 8),
+		Height:  uint32(h * 8),
+	}
+	_, err := s.ch.SendRequest("window-change", false, Marshal(&req))
+	return err
+}
+
+// RFC 4254 Section 6.9.
+type signalMsg struct {
+	Signal string
+}
+
+// Signal sends the given signal to the remote process.
+// sig is one of the SIG* constants.
+func (s *Session) Signal(sig Signal) error {
+	msg := signalMsg{
+		Signal: string(sig),
+	}
+
+	_, err := s.ch.SendRequest("signal", false, Marshal(&msg))
+	return err
+}
+
+// RFC 4254 Section 6.5.
+type execMsg struct {
+	Command string
+}
+
+// Start runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start or Shell.
+func (s *Session) Start(cmd string) error {
+	if s.started {
+		return errors.New("ssh: session already started")
+	}
+	req := execMsg{
+		Command: cmd,
+	}
+
+	ok, err := s.ch.SendRequest("exec", true, Marshal(&req))
+	if err == nil && !ok {
+		err = fmt.Errorf("ssh: command %v failed", cmd)
+	}
+	if err != nil {
+		return err
+	}
+	return s.start()
+}
+
+// Run runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start, Shell, Output,
+// or CombinedOutput.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the remote server does not send an exit status, an error of type
+// *ExitMissingError is returned. If the command completes
+// unsuccessfully or is interrupted by a signal, the error is of type
+// *ExitError. Other error types may be returned for I/O problems.
+func (s *Session) Run(cmd string) error {
+	err := s.Start(cmd)
+	if err != nil {
+		return err
+	}
+	return s.Wait()
+}
+
+// Output runs cmd on the remote host and returns its standard output.
+func (s *Session) Output(cmd string) ([]byte, error) {
+	if s.Stdout != nil {
+		return nil, errors.New("ssh: Stdout already set")
+	}
+	var b bytes.Buffer
+	s.Stdout = &b
+	err := s.Run(cmd)
+	return b.Bytes(), err
+}
+
+type singleWriter struct {
+	b  bytes.Buffer
+	mu sync.Mutex
+}
+
+func (w *singleWriter) Write(p []byte) (int, error) {
+	w.mu.Lock()
+	defer w.mu.Unlock()
+	return w.b.Write(p)
+}
+
+// CombinedOutput runs cmd on the remote host and returns its combined
+// standard output and standard error.
+func (s *Session) CombinedOutput(cmd string) ([]byte, error) {
+	if s.Stdout != nil {
+		return nil, errors.New("ssh: Stdout already set")
+	}
+	if s.Stderr != nil {
+		return nil, errors.New("ssh: Stderr already set")
+	}
+	var b singleWriter
+	s.Stdout = &b
+	s.Stderr = &b
+	err := s.Run(cmd)
+	return b.b.Bytes(), err
+}
+
+// Shell starts a login shell on the remote host. A Session only
+// accepts one call to Run, Start, Shell, Output, or CombinedOutput.
+func (s *Session) Shell() error {
+	if s.started {
+		return errors.New("ssh: session already started")
+	}
+
+	ok, err := s.ch.SendRequest("shell", true, nil)
+	if err == nil && !ok {
+		return errors.New("ssh: could not start shell")
+	}
+	if err != nil {
+		return err
+	}
+	return s.start()
+}
+
+func (s *Session) start() error {
+	s.started = true
+
+	type F func(*Session)
+	for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} {
+		setupFd(s)
+	}
+
+	s.errors = make(chan error, len(s.copyFuncs))
+	for _, fn := range s.copyFuncs {
+		go func(fn func() error) {
+			s.errors <- fn()
+		}(fn)
+	}
+	return nil
+}
+
+// Wait waits for the remote command to exit.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the remote server does not send an exit status, an error of type
+// *ExitMissingError is returned. If the command completes
+// unsuccessfully or is interrupted by a signal, the error is of type
+// *ExitError. Other error types may be returned for I/O problems.
+func (s *Session) Wait() error {
+	if !s.started {
+		return errors.New("ssh: session not started")
+	}
+	waitErr := <-s.exitStatus
+
+	if s.stdinPipeWriter != nil {
+		s.stdinPipeWriter.Close()
+	}
+	var copyError error
+	for range s.copyFuncs {
+		if err := <-s.errors; err != nil && copyError == nil {
+			copyError = err
+		}
+	}
+	if waitErr != nil {
+		return waitErr
+	}
+	return copyError
+}
+
+func (s *Session) wait(reqs <-chan *Request) error {
+	wm := Waitmsg{status: -1}
+	// Wait for msg channel to be closed before returning.
+	for msg := range reqs {
+		switch msg.Type {
+		case "exit-status":
+			wm.status = int(binary.BigEndian.Uint32(msg.Payload))
+		case "exit-signal":
+			var sigval struct {
+				Signal     string
+				CoreDumped bool
+				Error      string
+				Lang       string
+			}
+			if err := Unmarshal(msg.Payload, &sigval); err != nil {
+				return err
+			}
+
+			// Must sanitize strings?
+			wm.signal = sigval.Signal
+			wm.msg = sigval.Error
+			wm.lang = sigval.Lang
+		default:
+			// This handles keepalives and matches
+			// OpenSSH's behaviour.
+			if msg.WantReply {
+				msg.Reply(false, nil)
+			}
+		}
+	}
+	if wm.status == 0 {
+		return nil
+	}
+	if wm.status == -1 {
+		// exit-status was never sent from server
+		if wm.signal == "" {
+			// signal was not sent either.  RFC 4254
+			// section 6.10 recommends against this
+			// behavior, but it is allowed, so we let
+			// clients handle it.
+			return &ExitMissingError{}
+		}
+		wm.status = 128
+		if _, ok := signals[Signal(wm.signal)]; ok {
+			wm.status += signals[Signal(wm.signal)]
+		}
+	}
+
+	return &ExitError{wm}
+}
+
+// ExitMissingError is returned if a session is torn down cleanly, but
+// the server sends no confirmation of the exit status.
+type ExitMissingError struct{}
+
+func (e *ExitMissingError) Error() string {
+	return "wait: remote command exited without exit status or exit signal"
+}
+
+func (s *Session) stdin() {
+	if s.stdinpipe {
+		return
+	}
+	var stdin io.Reader
+	if s.Stdin == nil {
+		stdin = new(bytes.Buffer)
+	} else {
+		r, w := io.Pipe()
+		go func() {
+			_, err := io.Copy(w, s.Stdin)
+			w.CloseWithError(err)
+		}()
+		stdin, s.stdinPipeWriter = r, w
+	}
+	s.copyFuncs = append(s.copyFuncs, func() error {
+		_, err := io.Copy(s.ch, stdin)
+		if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF {
+			err = err1
+		}
+		return err
+	})
+}
+
+func (s *Session) stdout() {
+	if s.stdoutpipe {
+		return
+	}
+	if s.Stdout == nil {
+		s.Stdout = ioutil.Discard
+	}
+	s.copyFuncs = append(s.copyFuncs, func() error {
+		_, err := io.Copy(s.Stdout, s.ch)
+		return err
+	})
+}
+
+func (s *Session) stderr() {
+	if s.stderrpipe {
+		return
+	}
+	if s.Stderr == nil {
+		s.Stderr = ioutil.Discard
+	}
+	s.copyFuncs = append(s.copyFuncs, func() error {
+		_, err := io.Copy(s.Stderr, s.ch.Stderr())
+		return err
+	})
+}
+
+// sessionStdin reroutes Close to CloseWrite.
+type sessionStdin struct {
+	io.Writer
+	ch Channel
+}
+
+func (s *sessionStdin) Close() error {
+	return s.ch.CloseWrite()
+}
+
+// StdinPipe returns a pipe that will be connected to the
+// remote command's standard input when the command starts.
+func (s *Session) StdinPipe() (io.WriteCloser, error) {
+	if s.Stdin != nil {
+		return nil, errors.New("ssh: Stdin already set")
+	}
+	if s.started {
+		return nil, errors.New("ssh: StdinPipe after process started")
+	}
+	s.stdinpipe = true
+	return &sessionStdin{s.ch, s.ch}, nil
+}
+
+// StdoutPipe returns a pipe that will be connected to the
+// remote command's standard output when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StdoutPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StdoutPipe() (io.Reader, error) {
+	if s.Stdout != nil {
+		return nil, errors.New("ssh: Stdout already set")
+	}
+	if s.started {
+		return nil, errors.New("ssh: StdoutPipe after process started")
+	}
+	s.stdoutpipe = true
+	return s.ch, nil
+}
+
+// StderrPipe returns a pipe that will be connected to the
+// remote command's standard error when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StderrPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StderrPipe() (io.Reader, error) {
+	if s.Stderr != nil {
+		return nil, errors.New("ssh: Stderr already set")
+	}
+	if s.started {
+		return nil, errors.New("ssh: StderrPipe after process started")
+	}
+	s.stderrpipe = true
+	return s.ch.Stderr(), nil
+}
+
+// newSession returns a new interactive session on the remote host.
+func newSession(ch Channel, reqs <-chan *Request) (*Session, error) {
+	s := &Session{
+		ch: ch,
+	}
+	s.exitStatus = make(chan error, 1)
+	go func() {
+		s.exitStatus <- s.wait(reqs)
+	}()
+
+	return s, nil
+}
+
+// An ExitError reports unsuccessful completion of a remote command.
+type ExitError struct {
+	Waitmsg
+}
+
+func (e *ExitError) Error() string {
+	return e.Waitmsg.String()
+}
+
+// Waitmsg stores the information about an exited remote command
+// as reported by Wait.
+type Waitmsg struct {
+	status int
+	signal string
+	msg    string
+	lang   string
+}
+
+// ExitStatus returns the exit status of the remote command.
+func (w Waitmsg) ExitStatus() int {
+	return w.status
+}
+
+// Signal returns the exit signal of the remote command if
+// it was terminated violently.
+func (w Waitmsg) Signal() string {
+	return w.signal
+}
+
+// Msg returns the exit message given by the remote command
+func (w Waitmsg) Msg() string {
+	return w.msg
+}
+
+// Lang returns the language tag. See RFC 3066
+func (w Waitmsg) Lang() string {
+	return w.lang
+}
+
+func (w Waitmsg) String() string {
+	str := fmt.Sprintf("Process exited with status %v", w.status)
+	if w.signal != "" {
+		str += fmt.Sprintf(" from signal %v", w.signal)
+	}
+	if w.msg != "" {
+		str += fmt.Sprintf(". Reason was: %v", w.msg)
+	}
+	return str
+}
diff --git a/vendor/golang.org/x/crypto/ssh/ssh_gss.go b/vendor/golang.org/x/crypto/ssh/ssh_gss.go
new file mode 100644
index 0000000..24bd7c8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/ssh_gss.go
@@ -0,0 +1,139 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"encoding/asn1"
+	"errors"
+)
+
+var krb5OID []byte
+
+func init() {
+	krb5OID, _ = asn1.Marshal(krb5Mesh)
+}
+
+// GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins.
+type GSSAPIClient interface {
+	// InitSecContext initiates the establishment of a security context for GSS-API between the
+	// ssh client and ssh server. Initially the token parameter should be specified as nil.
+	// The routine may return a outputToken which should be transferred to
+	// the ssh server, where the ssh server will present it to
+	// AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting
+	// needContinue to false. To complete the context
+	// establishment, one or more reply tokens may be required from the ssh
+	// server;if so, InitSecContext will return a needContinue which is true.
+	// In this case, InitSecContext should be called again when the
+	// reply token is received from the ssh server, passing the reply
+	// token to InitSecContext via the token parameters.
+	// See RFC 2743 section 2.2.1 and RFC 4462 section 3.4.
+	InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error)
+	// GetMIC generates a cryptographic MIC for the SSH2 message, and places
+	// the MIC in a token for transfer to the ssh server.
+	// The contents of the MIC field are obtained by calling GSS_GetMIC()
+	// over the following, using the GSS-API context that was just
+	// established:
+	//  string    session identifier
+	//  byte      SSH_MSG_USERAUTH_REQUEST
+	//  string    user name
+	//  string    service
+	//  string    "gssapi-with-mic"
+	// See RFC 2743 section 2.3.1 and RFC 4462 3.5.
+	GetMIC(micFiled []byte) ([]byte, error)
+	// Whenever possible, it should be possible for
+	// DeleteSecContext() calls to be successfully processed even
+	// if other calls cannot succeed, thereby enabling context-related
+	// resources to be released.
+	// In addition to deleting established security contexts,
+	// gss_delete_sec_context must also be able to delete "half-built"
+	// security contexts resulting from an incomplete sequence of
+	// InitSecContext()/AcceptSecContext() calls.
+	// See RFC 2743 section 2.2.3.
+	DeleteSecContext() error
+}
+
+// GSSAPIServer provides the API to plug in GSSAPI authentication for server logins.
+type GSSAPIServer interface {
+	// AcceptSecContext allows a remotely initiated security context between the application
+	// and a remote peer to be established by the ssh client. The routine may return a
+	// outputToken which should be transferred to the ssh client,
+	// where the ssh client will present it to InitSecContext.
+	// If no token need be sent, AcceptSecContext will indicate this
+	// by setting the needContinue to false. To
+	// complete the context establishment, one or more reply tokens may be
+	// required from the ssh client. if so, AcceptSecContext
+	// will return a needContinue which is true, in which case it
+	// should be called again when the reply token is received from the ssh
+	// client, passing the token to AcceptSecContext via the
+	// token parameters.
+	// The srcName return value is the authenticated username.
+	// See RFC 2743 section 2.2.2 and RFC 4462 section 3.4.
+	AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error)
+	// VerifyMIC verifies that a cryptographic MIC, contained in the token parameter,
+	// fits the supplied message is received from the ssh client.
+	// See RFC 2743 section 2.3.2.
+	VerifyMIC(micField []byte, micToken []byte) error
+	// Whenever possible, it should be possible for
+	// DeleteSecContext() calls to be successfully processed even
+	// if other calls cannot succeed, thereby enabling context-related
+	// resources to be released.
+	// In addition to deleting established security contexts,
+	// gss_delete_sec_context must also be able to delete "half-built"
+	// security contexts resulting from an incomplete sequence of
+	// InitSecContext()/AcceptSecContext() calls.
+	// See RFC 2743 section 2.2.3.
+	DeleteSecContext() error
+}
+
+var (
+	// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,
+	// so we also support the krb5 mechanism only.
+	// See RFC 1964 section 1.
+	krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2}
+)
+
+// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST
+// See RFC 4462 section 3.2.
+type userAuthRequestGSSAPI struct {
+	N    uint32
+	OIDS []asn1.ObjectIdentifier
+}
+
+func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
+	n, rest, ok := parseUint32(payload)
+	if !ok {
+		return nil, errors.New("parse uint32 failed")
+	}
+	s := &userAuthRequestGSSAPI{
+		N:    n,
+		OIDS: make([]asn1.ObjectIdentifier, n),
+	}
+	for i := 0; i < int(n); i++ {
+		var (
+			desiredMech []byte
+			err         error
+		)
+		desiredMech, rest, ok = parseString(rest)
+		if !ok {
+			return nil, errors.New("parse string failed")
+		}
+		if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil {
+			return nil, err
+		}
+
+	}
+	return s, nil
+}
+
+// See RFC 4462 section 3.6.
+func buildMIC(sessionID string, username string, service string, authMethod string) []byte {
+	out := make([]byte, 0, 0)
+	out = appendString(out, sessionID)
+	out = append(out, msgUserAuthRequest)
+	out = appendString(out, username)
+	out = appendString(out, service)
+	out = appendString(out, authMethod)
+	return out
+}
diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go
new file mode 100644
index 0000000..b171b33
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go
@@ -0,0 +1,116 @@
+package ssh
+
+import (
+	"errors"
+	"io"
+	"net"
+)
+
+// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "direct-streamlocal@openssh.com" string.
+//
+// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
+type streamLocalChannelOpenDirectMsg struct {
+	socketPath string
+	reserved0  string
+	reserved1  uint32
+}
+
+// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "forwarded-streamlocal@openssh.com" string.
+type forwardedStreamLocalPayload struct {
+	SocketPath string
+	Reserved0  string
+}
+
+// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
+// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
+type streamLocalChannelForwardMsg struct {
+	socketPath string
+}
+
+// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
+func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
+	c.handleForwardsOnce.Do(c.handleForwards)
+	m := streamLocalChannelForwardMsg{
+		socketPath,
+	}
+	// send message
+	ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
+	if err != nil {
+		return nil, err
+	}
+	if !ok {
+		return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
+	}
+	ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
+
+	return &unixListener{socketPath, c, ch}, nil
+}
+
+func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
+	msg := streamLocalChannelOpenDirectMsg{
+		socketPath: socketPath,
+	}
+	ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
+	if err != nil {
+		return nil, err
+	}
+	go DiscardRequests(in)
+	return ch, err
+}
+
+type unixListener struct {
+	socketPath string
+
+	conn *Client
+	in   <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *unixListener) Accept() (net.Conn, error) {
+	s, ok := <-l.in
+	if !ok {
+		return nil, io.EOF
+	}
+	ch, incoming, err := s.newCh.Accept()
+	if err != nil {
+		return nil, err
+	}
+	go DiscardRequests(incoming)
+
+	return &chanConn{
+		Channel: ch,
+		laddr: &net.UnixAddr{
+			Name: l.socketPath,
+			Net:  "unix",
+		},
+		raddr: &net.UnixAddr{
+			Name: "@",
+			Net:  "unix",
+		},
+	}, nil
+}
+
+// Close closes the listener.
+func (l *unixListener) Close() error {
+	// this also closes the listener.
+	l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
+	m := streamLocalChannelForwardMsg{
+		l.socketPath,
+	}
+	ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
+	if err == nil && !ok {
+		err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
+	}
+	return err
+}
+
+// Addr returns the listener's network address.
+func (l *unixListener) Addr() net.Addr {
+	return &net.UnixAddr{
+		Name: l.socketPath,
+		Net:  "unix",
+	}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go
new file mode 100644
index 0000000..80d35f5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/tcpip.go
@@ -0,0 +1,474 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"math/rand"
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+// Listen requests the remote peer open a listening socket on
+// addr. Incoming connections will be available by calling Accept on
+// the returned net.Listener. The listener must be serviced, or the
+// SSH connection may hang.
+// N must be "tcp", "tcp4", "tcp6", or "unix".
+func (c *Client) Listen(n, addr string) (net.Listener, error) {
+	switch n {
+	case "tcp", "tcp4", "tcp6":
+		laddr, err := net.ResolveTCPAddr(n, addr)
+		if err != nil {
+			return nil, err
+		}
+		return c.ListenTCP(laddr)
+	case "unix":
+		return c.ListenUnix(addr)
+	default:
+		return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
+	}
+}
+
+// Automatic port allocation is broken with OpenSSH before 6.0. See
+// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017.  In
+// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0,
+// rather than the actual port number. This means you can never open
+// two different listeners with auto allocated ports. We work around
+// this by trying explicit ports until we succeed.
+
+const openSSHPrefix = "OpenSSH_"
+
+var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+// isBrokenOpenSSHVersion returns true if the given version string
+// specifies a version of OpenSSH that is known to have a bug in port
+// forwarding.
+func isBrokenOpenSSHVersion(versionStr string) bool {
+	i := strings.Index(versionStr, openSSHPrefix)
+	if i < 0 {
+		return false
+	}
+	i += len(openSSHPrefix)
+	j := i
+	for ; j < len(versionStr); j++ {
+		if versionStr[j] < '0' || versionStr[j] > '9' {
+			break
+		}
+	}
+	version, _ := strconv.Atoi(versionStr[i:j])
+	return version < 6
+}
+
+// autoPortListenWorkaround simulates automatic port allocation by
+// trying random ports repeatedly.
+func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) {
+	var sshListener net.Listener
+	var err error
+	const tries = 10
+	for i := 0; i < tries; i++ {
+		addr := *laddr
+		addr.Port = 1024 + portRandomizer.Intn(60000)
+		sshListener, err = c.ListenTCP(&addr)
+		if err == nil {
+			laddr.Port = addr.Port
+			return sshListener, err
+		}
+	}
+	return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err)
+}
+
+// RFC 4254 7.1
+type channelForwardMsg struct {
+	addr  string
+	rport uint32
+}
+
+// handleForwards starts goroutines handling forwarded connections.
+// It's called on first use by (*Client).ListenTCP to not launch
+// goroutines until needed.
+func (c *Client) handleForwards() {
+	go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip"))
+	go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
+}
+
+// ListenTCP requests the remote peer open a listening socket
+// on laddr. Incoming connections will be available by calling
+// Accept on the returned net.Listener.
+func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
+	c.handleForwardsOnce.Do(c.handleForwards)
+	if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
+		return c.autoPortListenWorkaround(laddr)
+	}
+
+	m := channelForwardMsg{
+		laddr.IP.String(),
+		uint32(laddr.Port),
+	}
+	// send message
+	ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m))
+	if err != nil {
+		return nil, err
+	}
+	if !ok {
+		return nil, errors.New("ssh: tcpip-forward request denied by peer")
+	}
+
+	// If the original port was 0, then the remote side will
+	// supply a real port number in the response.
+	if laddr.Port == 0 {
+		var p struct {
+			Port uint32
+		}
+		if err := Unmarshal(resp, &p); err != nil {
+			return nil, err
+		}
+		laddr.Port = int(p.Port)
+	}
+
+	// Register this forward, using the port number we obtained.
+	ch := c.forwards.add(laddr)
+
+	return &tcpListener{laddr, c, ch}, nil
+}
+
+// forwardList stores a mapping between remote
+// forward requests and the tcpListeners.
+type forwardList struct {
+	sync.Mutex
+	entries []forwardEntry
+}
+
+// forwardEntry represents an established mapping of a laddr on a
+// remote ssh server to a channel connected to a tcpListener.
+type forwardEntry struct {
+	laddr net.Addr
+	c     chan forward
+}
+
+// forward represents an incoming forwarded tcpip connection. The
+// arguments to add/remove/lookup should be address as specified in
+// the original forward-request.
+type forward struct {
+	newCh NewChannel // the ssh client channel underlying this forward
+	raddr net.Addr   // the raddr of the incoming connection
+}
+
+func (l *forwardList) add(addr net.Addr) chan forward {
+	l.Lock()
+	defer l.Unlock()
+	f := forwardEntry{
+		laddr: addr,
+		c:     make(chan forward, 1),
+	}
+	l.entries = append(l.entries, f)
+	return f.c
+}
+
+// See RFC 4254, section 7.2
+type forwardedTCPPayload struct {
+	Addr       string
+	Port       uint32
+	OriginAddr string
+	OriginPort uint32
+}
+
+// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
+func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
+	if port == 0 || port > 65535 {
+		return nil, fmt.Errorf("ssh: port number out of range: %d", port)
+	}
+	ip := net.ParseIP(string(addr))
+	if ip == nil {
+		return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr)
+	}
+	return &net.TCPAddr{IP: ip, Port: int(port)}, nil
+}
+
+func (l *forwardList) handleChannels(in <-chan NewChannel) {
+	for ch := range in {
+		var (
+			laddr net.Addr
+			raddr net.Addr
+			err   error
+		)
+		switch channelType := ch.ChannelType(); channelType {
+		case "forwarded-tcpip":
+			var payload forwardedTCPPayload
+			if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+				ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
+				continue
+			}
+
+			// RFC 4254 section 7.2 specifies that incoming
+			// addresses should list the address, in string
+			// format. It is implied that this should be an IP
+			// address, as it would be impossible to connect to it
+			// otherwise.
+			laddr, err = parseTCPAddr(payload.Addr, payload.Port)
+			if err != nil {
+				ch.Reject(ConnectionFailed, err.Error())
+				continue
+			}
+			raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
+			if err != nil {
+				ch.Reject(ConnectionFailed, err.Error())
+				continue
+			}
+
+		case "forwarded-streamlocal@openssh.com":
+			var payload forwardedStreamLocalPayload
+			if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+				ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
+				continue
+			}
+			laddr = &net.UnixAddr{
+				Name: payload.SocketPath,
+				Net:  "unix",
+			}
+			raddr = &net.UnixAddr{
+				Name: "@",
+				Net:  "unix",
+			}
+		default:
+			panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
+		}
+		if ok := l.forward(laddr, raddr, ch); !ok {
+			// Section 7.2, implementations MUST reject spurious incoming
+			// connections.
+			ch.Reject(Prohibited, "no forward for address")
+			continue
+		}
+
+	}
+}
+
+// remove removes the forward entry, and the channel feeding its
+// listener.
+func (l *forwardList) remove(addr net.Addr) {
+	l.Lock()
+	defer l.Unlock()
+	for i, f := range l.entries {
+		if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
+			l.entries = append(l.entries[:i], l.entries[i+1:]...)
+			close(f.c)
+			return
+		}
+	}
+}
+
+// closeAll closes and clears all forwards.
+func (l *forwardList) closeAll() {
+	l.Lock()
+	defer l.Unlock()
+	for _, f := range l.entries {
+		close(f.c)
+	}
+	l.entries = nil
+}
+
+func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
+	l.Lock()
+	defer l.Unlock()
+	for _, f := range l.entries {
+		if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
+			f.c <- forward{newCh: ch, raddr: raddr}
+			return true
+		}
+	}
+	return false
+}
+
+type tcpListener struct {
+	laddr *net.TCPAddr
+
+	conn *Client
+	in   <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *tcpListener) Accept() (net.Conn, error) {
+	s, ok := <-l.in
+	if !ok {
+		return nil, io.EOF
+	}
+	ch, incoming, err := s.newCh.Accept()
+	if err != nil {
+		return nil, err
+	}
+	go DiscardRequests(incoming)
+
+	return &chanConn{
+		Channel: ch,
+		laddr:   l.laddr,
+		raddr:   s.raddr,
+	}, nil
+}
+
+// Close closes the listener.
+func (l *tcpListener) Close() error {
+	m := channelForwardMsg{
+		l.laddr.IP.String(),
+		uint32(l.laddr.Port),
+	}
+
+	// this also closes the listener.
+	l.conn.forwards.remove(l.laddr)
+	ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
+	if err == nil && !ok {
+		err = errors.New("ssh: cancel-tcpip-forward failed")
+	}
+	return err
+}
+
+// Addr returns the listener's network address.
+func (l *tcpListener) Addr() net.Addr {
+	return l.laddr
+}
+
+// Dial initiates a connection to the addr from the remote host.
+// The resulting connection has a zero LocalAddr() and RemoteAddr().
+func (c *Client) Dial(n, addr string) (net.Conn, error) {
+	var ch Channel
+	switch n {
+	case "tcp", "tcp4", "tcp6":
+		// Parse the address into host and numeric port.
+		host, portString, err := net.SplitHostPort(addr)
+		if err != nil {
+			return nil, err
+		}
+		port, err := strconv.ParseUint(portString, 10, 16)
+		if err != nil {
+			return nil, err
+		}
+		ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
+		if err != nil {
+			return nil, err
+		}
+		// Use a zero address for local and remote address.
+		zeroAddr := &net.TCPAddr{
+			IP:   net.IPv4zero,
+			Port: 0,
+		}
+		return &chanConn{
+			Channel: ch,
+			laddr:   zeroAddr,
+			raddr:   zeroAddr,
+		}, nil
+	case "unix":
+		var err error
+		ch, err = c.dialStreamLocal(addr)
+		if err != nil {
+			return nil, err
+		}
+		return &chanConn{
+			Channel: ch,
+			laddr: &net.UnixAddr{
+				Name: "@",
+				Net:  "unix",
+			},
+			raddr: &net.UnixAddr{
+				Name: addr,
+				Net:  "unix",
+			},
+		}, nil
+	default:
+		return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
+	}
+}
+
+// DialTCP connects to the remote address raddr on the network net,
+// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
+// as the local address for the connection.
+func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
+	if laddr == nil {
+		laddr = &net.TCPAddr{
+			IP:   net.IPv4zero,
+			Port: 0,
+		}
+	}
+	ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
+	if err != nil {
+		return nil, err
+	}
+	return &chanConn{
+		Channel: ch,
+		laddr:   laddr,
+		raddr:   raddr,
+	}, nil
+}
+
+// RFC 4254 7.2
+type channelOpenDirectMsg struct {
+	raddr string
+	rport uint32
+	laddr string
+	lport uint32
+}
+
+func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) {
+	msg := channelOpenDirectMsg{
+		raddr: raddr,
+		rport: uint32(rport),
+		laddr: laddr,
+		lport: uint32(lport),
+	}
+	ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg))
+	if err != nil {
+		return nil, err
+	}
+	go DiscardRequests(in)
+	return ch, err
+}
+
+type tcpChan struct {
+	Channel // the backing channel
+}
+
+// chanConn fulfills the net.Conn interface without
+// the tcpChan having to hold laddr or raddr directly.
+type chanConn struct {
+	Channel
+	laddr, raddr net.Addr
+}
+
+// LocalAddr returns the local network address.
+func (t *chanConn) LocalAddr() net.Addr {
+	return t.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (t *chanConn) RemoteAddr() net.Addr {
+	return t.raddr
+}
+
+// SetDeadline sets the read and write deadlines associated
+// with the connection.
+func (t *chanConn) SetDeadline(deadline time.Time) error {
+	if err := t.SetReadDeadline(deadline); err != nil {
+		return err
+	}
+	return t.SetWriteDeadline(deadline)
+}
+
+// SetReadDeadline sets the read deadline.
+// A zero value for t means Read will not time out.
+// After the deadline, the error from Read will implement net.Error
+// with Timeout() == true.
+func (t *chanConn) SetReadDeadline(deadline time.Time) error {
+	// for compatibility with previous version,
+	// the error message contains "tcpChan"
+	return errors.New("ssh: tcpChan: deadline not supported")
+}
+
+// SetWriteDeadline exists to satisfy the net.Conn interface
+// but is not implemented by this type.  It always returns an error.
+func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
+	return errors.New("ssh: tcpChan: deadline not supported")
+}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
new file mode 100644
index 0000000..49ddc2e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -0,0 +1,353 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"io"
+	"log"
+)
+
+// debugTransport if set, will print packet types as they go over the
+// wire. No message decoding is done, to minimize the impact on timing.
+const debugTransport = false
+
+const (
+	gcmCipherID    = "aes128-gcm@openssh.com"
+	aes128cbcID    = "aes128-cbc"
+	tripledescbcID = "3des-cbc"
+)
+
+// packetConn represents a transport that implements packet based
+// operations.
+type packetConn interface {
+	// Encrypt and send a packet of data to the remote peer.
+	writePacket(packet []byte) error
+
+	// Read a packet from the connection. The read is blocking,
+	// i.e. if error is nil, then the returned byte slice is
+	// always non-empty.
+	readPacket() ([]byte, error)
+
+	// Close closes the write-side of the connection.
+	Close() error
+}
+
+// transport is the keyingTransport that implements the SSH packet
+// protocol.
+type transport struct {
+	reader connectionState
+	writer connectionState
+
+	bufReader *bufio.Reader
+	bufWriter *bufio.Writer
+	rand      io.Reader
+	isClient  bool
+	io.Closer
+}
+
+// packetCipher represents a combination of SSH encryption/MAC
+// protocol.  A single instance should be used for one direction only.
+type packetCipher interface {
+	// writeCipherPacket encrypts the packet and writes it to w. The
+	// contents of the packet are generally scrambled.
+	writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
+
+	// readCipherPacket reads and decrypts a packet of data. The
+	// returned packet may be overwritten by future calls of
+	// readPacket.
+	readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error)
+}
+
+// connectionState represents one side (read or write) of the
+// connection. This is necessary because each direction has its own
+// keys, and can even have its own algorithms
+type connectionState struct {
+	packetCipher
+	seqNum           uint32
+	dir              direction
+	pendingKeyChange chan packetCipher
+}
+
+// prepareKeyChange sets up key material for a keychange. The key changes in
+// both directions are triggered by reading and writing a msgNewKey packet
+// respectively.
+func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error {
+	ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult)
+	if err != nil {
+		return err
+	}
+	t.reader.pendingKeyChange <- ciph
+
+	ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult)
+	if err != nil {
+		return err
+	}
+	t.writer.pendingKeyChange <- ciph
+
+	return nil
+}
+
+func (t *transport) printPacket(p []byte, write bool) {
+	if len(p) == 0 {
+		return
+	}
+	who := "server"
+	if t.isClient {
+		who = "client"
+	}
+	what := "read"
+	if write {
+		what = "write"
+	}
+
+	log.Println(what, who, p[0])
+}
+
+// Read and decrypt next packet.
+func (t *transport) readPacket() (p []byte, err error) {
+	for {
+		p, err = t.reader.readPacket(t.bufReader)
+		if err != nil {
+			break
+		}
+		if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
+			break
+		}
+	}
+	if debugTransport {
+		t.printPacket(p, false)
+	}
+
+	return p, err
+}
+
+func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
+	packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
+	s.seqNum++
+	if err == nil && len(packet) == 0 {
+		err = errors.New("ssh: zero length packet")
+	}
+
+	if len(packet) > 0 {
+		switch packet[0] {
+		case msgNewKeys:
+			select {
+			case cipher := <-s.pendingKeyChange:
+				s.packetCipher = cipher
+			default:
+				return nil, errors.New("ssh: got bogus newkeys message")
+			}
+
+		case msgDisconnect:
+			// Transform a disconnect message into an
+			// error. Since this is lowest level at which
+			// we interpret message types, doing it here
+			// ensures that we don't have to handle it
+			// elsewhere.
+			var msg disconnectMsg
+			if err := Unmarshal(packet, &msg); err != nil {
+				return nil, err
+			}
+			return nil, &msg
+		}
+	}
+
+	// The packet may point to an internal buffer, so copy the
+	// packet out here.
+	fresh := make([]byte, len(packet))
+	copy(fresh, packet)
+
+	return fresh, err
+}
+
+func (t *transport) writePacket(packet []byte) error {
+	if debugTransport {
+		t.printPacket(packet, true)
+	}
+	return t.writer.writePacket(t.bufWriter, t.rand, packet)
+}
+
+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
+	changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
+
+	err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
+	if err != nil {
+		return err
+	}
+	if err = w.Flush(); err != nil {
+		return err
+	}
+	s.seqNum++
+	if changeKeys {
+		select {
+		case cipher := <-s.pendingKeyChange:
+			s.packetCipher = cipher
+		default:
+			panic("ssh: no key material for msgNewKeys")
+		}
+	}
+	return err
+}
+
+func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport {
+	t := &transport{
+		bufReader: bufio.NewReader(rwc),
+		bufWriter: bufio.NewWriter(rwc),
+		rand:      rand,
+		reader: connectionState{
+			packetCipher:     &streamPacketCipher{cipher: noneCipher{}},
+			pendingKeyChange: make(chan packetCipher, 1),
+		},
+		writer: connectionState{
+			packetCipher:     &streamPacketCipher{cipher: noneCipher{}},
+			pendingKeyChange: make(chan packetCipher, 1),
+		},
+		Closer: rwc,
+	}
+	t.isClient = isClient
+
+	if isClient {
+		t.reader.dir = serverKeys
+		t.writer.dir = clientKeys
+	} else {
+		t.reader.dir = clientKeys
+		t.writer.dir = serverKeys
+	}
+
+	return t
+}
+
+type direction struct {
+	ivTag     []byte
+	keyTag    []byte
+	macKeyTag []byte
+}
+
+var (
+	serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
+	clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
+)
+
+// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
+// described in RFC 4253, section 6.4. direction should either be serverKeys
+// (to setup server->client keys) or clientKeys (for client->server keys).
+func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
+	cipherMode := cipherModes[algs.Cipher]
+	macMode := macModes[algs.MAC]
+
+	iv := make([]byte, cipherMode.ivSize)
+	key := make([]byte, cipherMode.keySize)
+	macKey := make([]byte, macMode.keySize)
+
+	generateKeyMaterial(iv, d.ivTag, kex)
+	generateKeyMaterial(key, d.keyTag, kex)
+	generateKeyMaterial(macKey, d.macKeyTag, kex)
+
+	return cipherModes[algs.Cipher].create(key, iv, macKey, algs)
+}
+
+// generateKeyMaterial fills out with key material generated from tag, K, H
+// and sessionId, as specified in RFC 4253, section 7.2.
+func generateKeyMaterial(out, tag []byte, r *kexResult) {
+	var digestsSoFar []byte
+
+	h := r.Hash.New()
+	for len(out) > 0 {
+		h.Reset()
+		h.Write(r.K)
+		h.Write(r.H)
+
+		if len(digestsSoFar) == 0 {
+			h.Write(tag)
+			h.Write(r.SessionID)
+		} else {
+			h.Write(digestsSoFar)
+		}
+
+		digest := h.Sum(nil)
+		n := copy(out, digest)
+		out = out[n:]
+		if len(out) > 0 {
+			digestsSoFar = append(digestsSoFar, digest...)
+		}
+	}
+}
+
+const packageVersion = "SSH-2.0-Go"
+
+// Sends and receives a version line.  The versionLine string should
+// be US ASCII, start with "SSH-2.0-", and should not include a
+// newline. exchangeVersions returns the other side's version line.
+func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) {
+	// Contrary to the RFC, we do not ignore lines that don't
+	// start with "SSH-2.0-" to make the library usable with
+	// nonconforming servers.
+	for _, c := range versionLine {
+		// The spec disallows non US-ASCII chars, and
+		// specifically forbids null chars.
+		if c < 32 {
+			return nil, errors.New("ssh: junk character in version line")
+		}
+	}
+	if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil {
+		return
+	}
+
+	them, err = readVersion(rw)
+	return them, err
+}
+
+// maxVersionStringBytes is the maximum number of bytes that we'll
+// accept as a version string. RFC 4253 section 4.2 limits this at 255
+// chars
+const maxVersionStringBytes = 255
+
+// Read version string as specified by RFC 4253, section 4.2.
+func readVersion(r io.Reader) ([]byte, error) {
+	versionString := make([]byte, 0, 64)
+	var ok bool
+	var buf [1]byte
+
+	for length := 0; length < maxVersionStringBytes; length++ {
+		_, err := io.ReadFull(r, buf[:])
+		if err != nil {
+			return nil, err
+		}
+		// The RFC says that the version should be terminated with \r\n
+		// but several SSH servers actually only send a \n.
+		if buf[0] == '\n' {
+			if !bytes.HasPrefix(versionString, []byte("SSH-")) {
+				// RFC 4253 says we need to ignore all version string lines
+				// except the one containing the SSH version (provided that
+				// all the lines do not exceed 255 bytes in total).
+				versionString = versionString[:0]
+				continue
+			}
+			ok = true
+			break
+		}
+
+		// non ASCII chars are disallowed, but we are lenient,
+		// since Go doesn't use null-terminated strings.
+
+		// The RFC allows a comment after a space, however,
+		// all of it (version and comments) goes into the
+		// session hash.
+		versionString = append(versionString, buf[0])
+	}
+
+	if !ok {
+		return nil, errors.New("ssh: overflow reading version string")
+	}
+
+	// There might be a '\r' on the end which we should remove.
+	if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' {
+		versionString = versionString[:len(versionString)-1]
+	}
+	return versionString, nil
+}