Sfoglia il codice sorgente

Merge pull request #39349 from tonistiigi/buildkit-userns-remap

builder-next: userns remap support
Sebastiaan van Stijn 6 anni fa
parent
commit
39c8e88068

+ 9 - 5
builder/builder-next/adapters/snapshot/snapshot.go

@@ -26,9 +26,10 @@ var keySize = []byte("size")
 
 // Opt defines options for creating the snapshotter
 type Opt struct {
-	GraphDriver graphdriver.Driver
-	LayerStore  layer.Store
-	Root        string
+	GraphDriver     graphdriver.Driver
+	LayerStore      layer.Store
+	Root            string
+	IdentityMapping *idtools.IdentityMapping
 }
 
 type graphIDRegistrar interface {
@@ -79,7 +80,7 @@ func (s *snapshotter) Name() string {
 }
 
 func (s *snapshotter) IdentityMapping() *idtools.IdentityMapping {
-	return nil
+	return s.opt.IdentityMapping
 }
 
 func (s *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) error {
@@ -253,6 +254,7 @@ func (s *snapshotter) Mounts(ctx context.Context, key string) (snapshot.Mountabl
 		id := identity.NewID()
 		var rwlayer layer.RWLayer
 		return &mountable{
+			idmap: s.opt.IdentityMapping,
 			acquire: func() ([]mount.Mount, error) {
 				rwlayer, err = s.opt.LayerStore.CreateRWLayer(id, l.ChainID(), nil)
 				if err != nil {
@@ -278,6 +280,7 @@ func (s *snapshotter) Mounts(ctx context.Context, key string) (snapshot.Mountabl
 	id, _ := s.getGraphDriverID(key)
 
 	return &mountable{
+		idmap: s.opt.IdentityMapping,
 		acquire: func() ([]mount.Mount, error) {
 			rootfs, err := s.opt.GraphDriver.Get(id, "")
 			if err != nil {
@@ -440,6 +443,7 @@ type mountable struct {
 	acquire  func() ([]mount.Mount, error)
 	release  func() error
 	refCount int
+	idmap    *idtools.IdentityMapping
 }
 
 func (m *mountable) Mount() ([]mount.Mount, error) {
@@ -480,5 +484,5 @@ func (m *mountable) Release() error {
 }
 
 func (m *mountable) IdentityMapping() *idtools.IdentityMapping {
-	return nil
+	return m.idmap
 }

+ 2 - 0
builder/builder-next/builder.go

@@ -17,6 +17,7 @@ import (
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/daemon/config"
 	"github.com/docker/docker/daemon/images"
+	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/libnetwork"
@@ -73,6 +74,7 @@ type Opt struct {
 	ResolverOpt         resolver.ResolveOptionsFunc
 	BuilderConfig       config.BuilderConfig
 	Rootless            bool
+	IdentityMapping     *idtools.IdentityMapping
 }
 
 // Builder can build using BuildKit backend

+ 6 - 5
builder/builder-next/controller.go

@@ -38,7 +38,7 @@ import (
 )
 
 func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
-	if err := os.MkdirAll(opt.Root, 0700); err != nil {
+	if err := os.MkdirAll(opt.Root, 0711); err != nil {
 		return nil, err
 	}
 
@@ -55,9 +55,10 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 	}
 
 	sbase, err := snapshot.NewSnapshotter(snapshot.Opt{
-		GraphDriver: driver,
-		LayerStore:  dist.LayerStore,
-		Root:        root,
+		GraphDriver:     driver,
+		LayerStore:      dist.LayerStore,
+		Root:            root,
+		IdentityMapping: opt.IdentityMapping,
 	})
 	if err != nil {
 		return nil, err
@@ -112,7 +113,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
 		return nil, err
 	}
 
-	exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, opt.Rootless)
+	exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, opt.Rootless, opt.IdentityMapping)
 	if err != nil {
 		return nil, err
 	}

+ 3 - 1
builder/builder-next/executor_unix.go

@@ -8,6 +8,7 @@ import (
 	"strconv"
 	"sync"
 
+	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/libnetwork"
 	"github.com/moby/buildkit/executor"
 	"github.com/moby/buildkit/executor/runcexecutor"
@@ -20,7 +21,7 @@ import (
 
 const networkName = "bridge"
 
-func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, rootless bool) (executor.Executor, error) {
+func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, rootless bool, idmap *idtools.IdentityMapping) (executor.Executor, error) {
 	networkProviders := map[pb.NetMode]network.Provider{
 		pb.NetMode_UNSET: &bridgeProvider{NetworkController: net, Root: filepath.Join(root, "net")},
 		pb.NetMode_HOST:  network.NewHostProvider(),
@@ -32,6 +33,7 @@ func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, ro
 		DefaultCgroupParent: cgroupParent,
 		Rootless:            rootless,
 		NoPivot:             os.Getenv("DOCKER_RAMDISK") != "",
+		IdentityMapping:     idmap,
 	}, networkProviders)
 }
 

+ 2 - 1
builder/builder-next/executor_windows.go

@@ -5,12 +5,13 @@ import (
 	"errors"
 	"io"
 
+	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/libnetwork"
 	"github.com/moby/buildkit/cache"
 	"github.com/moby/buildkit/executor"
 )
 
-func newExecutor(_, _ string, _ libnetwork.NetworkController, _ bool) (executor.Executor, error) {
+func newExecutor(_, _ string, _ libnetwork.NetworkController, _ bool, _ *idtools.IdentityMapping) (executor.Executor, error) {
 	return &winExecutor{}, nil
 }
 

+ 1 - 0
cmd/dockerd/daemon.go

@@ -318,6 +318,7 @@ func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, e
 		ResolverOpt:         d.NewResolveOptionsFunc(),
 		BuilderConfig:       config.Builder,
 		Rootless:            d.Rootless(),
+		IdentityMapping:     d.IdentityMapping(),
 	})
 	if err != nil {
 		return opts, err

+ 1 - 1
vendor.conf

@@ -27,7 +27,7 @@ github.com/imdario/mergo                            7c29201646fa3de8506f70121347
 golang.org/x/sync                                   e225da77a7e68af35c70ccbf71af2b83e6acac3c
 
 # buildkit
-github.com/moby/buildkit                            1f89ec125f84c097bdf3a063be622c4238dba5f8
+github.com/moby/buildkit                            c24275065aca6605bd83c57c6735510f4ebeb6d9
 github.com/tonistiigi/fsutil                        3bbb99cdbd76619ab717299830c60f6f2a533a6b
 github.com/grpc-ecosystem/grpc-opentracing          8e809c8a86450a29b90dcc9efbf062d0fe6d9746
 github.com/opentracing/opentracing-go               1361b9cd60be79c4c3a7fa9841b3c132e40066a7

+ 15 - 6
vendor/github.com/moby/buildkit/executor/oci/hosts.go

@@ -8,6 +8,7 @@ import (
 	"os"
 	"path/filepath"
 
+	"github.com/docker/docker/pkg/idtools"
 	"github.com/moby/buildkit/executor"
 	"github.com/moby/buildkit/identity"
 )
@@ -17,10 +18,10 @@ const hostsContent = `
 ::1	localhost ip6-localhost ip6-loopback
 `
 
-func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.HostIP) (string, func(), error) {
+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)
+			_, _, err := makeHostsFile(stateDir, nil, idmap)
 			return nil, err
 		})
 		if err != nil {
@@ -28,10 +29,10 @@ func GetHostsFile(ctx context.Context, stateDir string, extraHosts []executor.Ho
 		}
 		return filepath.Join(stateDir, "hosts"), func() {}, nil
 	}
-	return makeHostsFile(stateDir, extraHosts)
+	return makeHostsFile(stateDir, extraHosts, idmap)
 }
 
-func makeHostsFile(stateDir string, extraHosts []executor.HostIP) (string, func(), error) {
+func makeHostsFile(stateDir string, extraHosts []executor.HostIP, idmap *idtools.IdentityMapping) (string, func(), error) {
 	p := filepath.Join(stateDir, "hosts")
 	if len(extraHosts) != 0 {
 		p += "." + identity.NewID()
@@ -56,11 +57,19 @@ func makeHostsFile(stateDir string, extraHosts []executor.HostIP) (string, func(
 		}
 	}
 
-	if err := ioutil.WriteFile(p+".tmp", b.Bytes(), 0644); err != nil {
+	tmpPath := p + ".tmp"
+	if err := ioutil.WriteFile(tmpPath, b.Bytes(), 0644); err != nil {
 		return "", nil, err
 	}
 
-	if err := os.Rename(p+".tmp", p); err != nil {
+	if idmap != nil {
+		root := idmap.RootPair()
+		if err := os.Chown(tmpPath, root.UID, root.GID); err != nil {
+			return "", nil, err
+		}
+	}
+
+	if err := os.Rename(tmpPath, p); err != nil {
 		return "", nil, err
 	}
 	return p, func() {

+ 12 - 3
vendor/github.com/moby/buildkit/executor/oci/resolvconf.go

@@ -6,6 +6,7 @@ import (
 	"os"
 	"path/filepath"
 
+	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/libnetwork/resolvconf"
 	"github.com/moby/buildkit/util/flightcontrol"
 )
@@ -14,7 +15,7 @@ var g flightcontrol.Group
 var notFirstRun bool
 var lastNotEmpty bool
 
-func GetResolvConf(ctx context.Context, stateDir string) (string, error) {
+func GetResolvConf(ctx context.Context, stateDir string, idmap *idtools.IdentityMapping) (string, error) {
 	p := filepath.Join(stateDir, "resolv.conf")
 	_, err := g.Do(ctx, stateDir, func(ctx context.Context) (interface{}, error) {
 		generate := !notFirstRun
@@ -65,11 +66,19 @@ func GetResolvConf(ctx context.Context, stateDir string) (string, error) {
 			return "", err
 		}
 
-		if err := ioutil.WriteFile(p+".tmp", f.Content, 0644); err != nil {
+		tmpPath := p + ".tmp"
+		if err := ioutil.WriteFile(tmpPath, f.Content, 0644); err != nil {
 			return "", err
 		}
 
-		if err := os.Rename(p+".tmp", p); err != nil {
+		if idmap != nil {
+			root := idmap.RootPair()
+			if err := os.Chown(tmpPath, root.UID, root.GID); err != nil {
+				return "", err
+			}
+		}
+
+		if err := os.Rename(tmpPath, p); err != nil {
 			return "", err
 		}
 		return "", nil

+ 4 - 4
vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go

@@ -79,7 +79,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
 
 	root := opt.Root
 
-	if err := os.MkdirAll(root, 0700); err != nil {
+	if err := os.MkdirAll(root, 0711); err != nil {
 		return nil, errors.Wrapf(err, "failed to create %s", root)
 	}
 
@@ -134,12 +134,12 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
 		logrus.Info("enabling HostNetworking")
 	}
 
-	resolvConf, err := oci.GetResolvConf(ctx, w.root)
+	resolvConf, err := oci.GetResolvConf(ctx, w.root, w.idmap)
 	if err != nil {
 		return err
 	}
 
-	hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts)
+	hostsFile, clean, err := oci.GetHostsFile(ctx, w.root, meta.ExtraHosts, w.idmap)
 	if err != nil {
 		return err
 	}
@@ -161,7 +161,7 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
 	id := identity.NewID()
 	bundle := filepath.Join(w.root, id)
 
-	if err := os.Mkdir(bundle, 0700); err != nil {
+	if err := os.Mkdir(bundle, 0711); err != nil {
 		return err
 	}
 	defer os.RemoveAll(bundle)

+ 1 - 6
vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go

@@ -27,13 +27,9 @@ func timestampToTime(ts int64) *time.Time {
 }
 
 func mapUser(user *copy.ChownOpt, idmap *idtools.IdentityMapping) (*copy.ChownOpt, error) {
-	if idmap == nil {
+	if idmap == nil || user == nil {
 		return user, nil
 	}
-	if user == nil {
-		identity := idmap.RootPair()
-		return &copy.ChownOpt{Uid: identity.UID, Gid: identity.GID}, nil
-	}
 	identity, err := idmap.ToHost(idtools.Identity{
 		UID: user.Uid,
 		GID: user.Gid,
@@ -138,7 +134,6 @@ func docopy(ctx context.Context, src, dest string, action pb.FileActionCopy, u *
 		return nil
 	}
 
-	// TODO(tonistiigi): this is wrong. fsutil.Copy can't handle non-forced user
 	u, err := mapUser(u, idmap)
 	if err != nil {
 		return err