Browse code

vendor: github.com/moby/buildkit v0.12.5

full diff: https://github.com/moby/buildkit/compare/v0.12.4...v0.12.5

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>

Paweł Gronowski authored on 2024/02/01 01:18:20
Showing 32 changed files
... ...
@@ -142,8 +142,8 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
142 142
 		return nil, err
143 143
 	}
144 144
 	frontends := map[string]frontend.Frontend{
145
-		"dockerfile.v0": forwarder.NewGatewayForwarder(wc, dockerfile.Build),
146
-		"gateway.v0":    gateway.NewGatewayFrontend(wc),
145
+		"dockerfile.v0": forwarder.NewGatewayForwarder(wc.Infos(), dockerfile.Build),
146
+		"gateway.v0":    gateway.NewGatewayFrontend(wc.Infos()),
147 147
 	}
148 148
 
149 149
 	return control.NewController(control.Opt{
... ...
@@ -364,8 +364,8 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
364 364
 	wc.Add(w)
365 365
 
366 366
 	frontends := map[string]frontend.Frontend{
367
-		"dockerfile.v0": forwarder.NewGatewayForwarder(wc, dockerfile.Build),
368
-		"gateway.v0":    gateway.NewGatewayFrontend(wc),
367
+		"dockerfile.v0": forwarder.NewGatewayForwarder(wc.Infos(), dockerfile.Build),
368
+		"gateway.v0":    gateway.NewGatewayFrontend(wc.Infos()),
369 369
 	}
370 370
 
371 371
 	return control.NewController(control.Opt{
... ...
@@ -60,7 +60,7 @@ require (
60 60
 	github.com/miekg/dns v1.1.43
61 61
 	github.com/mistifyio/go-zfs/v3 v3.0.1
62 62
 	github.com/mitchellh/copystructure v1.2.0
63
-	github.com/moby/buildkit v0.12.5-0.20231208203051-3b6880d2a00f // v0.12 branch (v0.12.5-dev)
63
+	github.com/moby/buildkit v0.12.5
64 64
 	github.com/moby/ipvs v1.1.0
65 65
 	github.com/moby/locker v1.0.1
66 66
 	github.com/moby/patternmatcher v0.6.0
... ...
@@ -902,8 +902,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
902 902
 github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
903 903
 github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
904 904
 github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
905
-github.com/moby/buildkit v0.12.5-0.20231208203051-3b6880d2a00f h1:nYPkpfWrlQznHPLNrXxXIQMaTlmnsSBiiRTgnQ5hrZ0=
906
-github.com/moby/buildkit v0.12.5-0.20231208203051-3b6880d2a00f/go.mod h1:XG74uz06nPWQpnxYwgCryrVidvor0+ElUxGosbZPQG4=
905
+github.com/moby/buildkit v0.12.5 h1:RNHH1l3HDhYyZafr5EgstEu8aGNCwyfvMtrQDtjH9T0=
906
+github.com/moby/buildkit v0.12.5/go.mod h1:YGwjA2loqyiYfZeEo8FtI7z4x5XponAaIWsWcSjWwso=
907 907
 github.com/moby/ipvs v1.1.0 h1:ONN4pGaZQgAx+1Scz5RvWV4Q7Gb+mvfRh3NsPS+1XQQ=
908 908
 github.com/moby/ipvs v1.1.0/go.mod h1:4VJMWuf098bsUMmZEiD4Tjk/O7mOn3l1PTD3s4OoYAs=
909 909
 github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
... ...
@@ -405,6 +405,9 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
405 405
 
406 406
 	var cacheImports []frontend.CacheOptionsEntry
407 407
 	for _, im := range req.Cache.Imports {
408
+		if im == nil {
409
+			continue
410
+		}
408 411
 		cacheImports = append(cacheImports, frontend.CacheOptionsEntry{
409 412
 			Type:  im.Type,
410 413
 			Attrs: im.Attrs,
... ...
@@ -6,8 +6,9 @@ import (
6 6
 	"net"
7 7
 	"syscall"
8 8
 
9
+	"github.com/containerd/containerd/mount"
10
+	"github.com/docker/docker/pkg/idtools"
9 11
 	resourcestypes "github.com/moby/buildkit/executor/resources/types"
10
-	"github.com/moby/buildkit/snapshot"
11 12
 	"github.com/moby/buildkit/solver/pb"
12 13
 )
13 14
 
... ...
@@ -28,8 +29,13 @@ type Meta struct {
28 28
 	RemoveMountStubsRecursive bool
29 29
 }
30 30
 
31
+type MountableRef interface {
32
+	Mount() ([]mount.Mount, func() error, error)
33
+	IdentityMapping() *idtools.IdentityMapping
34
+}
35
+
31 36
 type Mountable interface {
32
-	Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error)
37
+	Mount(ctx context.Context, readonly bool) (MountableRef, error)
33 38
 }
34 39
 
35 40
 type Mount struct {
... ...
@@ -12,7 +12,6 @@ import (
12 12
 	"github.com/containerd/containerd/namespaces"
13 13
 	"github.com/containerd/containerd/oci"
14 14
 	"github.com/containerd/containerd/pkg/userns"
15
-	"github.com/containerd/continuity/fs"
16 15
 	"github.com/docker/docker/pkg/idtools"
17 16
 	"github.com/mitchellh/hashstructure/v2"
18 17
 	"github.com/moby/buildkit/executor"
... ...
@@ -215,6 +214,7 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
215 215
 type mountRef struct {
216 216
 	mount   mount.Mount
217 217
 	unmount func() error
218
+	subRefs map[string]mountRef
218 219
 }
219 220
 
220 221
 type submounts struct {
... ...
@@ -230,12 +230,19 @@ func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error)
230 230
 	}
231 231
 	h, err := hashstructure.Hash(m, hashstructure.FormatV2, nil)
232 232
 	if err != nil {
233
-		return mount.Mount{}, nil
233
+		return mount.Mount{}, err
234 234
 	}
235 235
 	if mr, ok := s.m[h]; ok {
236
-		sm, err := sub(mr.mount, subPath)
236
+		if sm, ok := mr.subRefs[subPath]; ok {
237
+			return sm.mount, nil
238
+		}
239
+		sm, unmount, err := sub(mr.mount, subPath)
237 240
 		if err != nil {
238
-			return mount.Mount{}, nil
241
+			return mount.Mount{}, err
242
+		}
243
+		mr.subRefs[subPath] = mountRef{
244
+			mount:   sm,
245
+			unmount: unmount,
239 246
 		}
240 247
 		return sm, nil
241 248
 	}
... ...
@@ -261,12 +268,17 @@ func (s *submounts) subMount(m mount.Mount, subPath string) (mount.Mount, error)
261 261
 			Options: opts,
262 262
 		},
263 263
 		unmount: lm.Unmount,
264
+		subRefs: map[string]mountRef{},
264 265
 	}
265 266
 
266
-	sm, err := sub(s.m[h].mount, subPath)
267
+	sm, unmount, err := sub(s.m[h].mount, subPath)
267 268
 	if err != nil {
268 269
 		return mount.Mount{}, err
269 270
 	}
271
+	s.m[h].subRefs[subPath] = mountRef{
272
+		mount:   sm,
273
+		unmount: unmount,
274
+	}
270 275
 	return sm, nil
271 276
 }
272 277
 
... ...
@@ -276,6 +288,9 @@ func (s *submounts) cleanup() {
276 276
 	for _, m := range s.m {
277 277
 		func(m mountRef) {
278 278
 			go func() {
279
+				for _, sm := range m.subRefs {
280
+					sm.unmount()
281
+				}
279 282
 				m.unmount()
280 283
 				wg.Done()
281 284
 			}()
... ...
@@ -284,15 +299,6 @@ func (s *submounts) cleanup() {
284 284
 	wg.Wait()
285 285
 }
286 286
 
287
-func sub(m mount.Mount, subPath string) (mount.Mount, error) {
288
-	src, err := fs.RootPath(m.Source, subPath)
289
-	if err != nil {
290
-		return mount.Mount{}, err
291
-	}
292
-	m.Source = src
293
-	return m, nil
294
-}
295
-
296 287
 func specMapping(s []idtools.IDMap) []specs.LinuxIDMapping {
297 288
 	var ids []specs.LinuxIDMapping
298 289
 	for _, item := range s {
299 290
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+package oci
1
+
2
+import (
3
+	"github.com/containerd/containerd/mount"
4
+	"github.com/containerd/continuity/fs"
5
+)
6
+
7
+func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) {
8
+	src, err := fs.RootPath(m.Source, subPath)
9
+	if err != nil {
10
+		return mount.Mount{}, nil, err
11
+	}
12
+	m.Source = src
13
+	return m, func() error { return nil }, nil
14
+}
0 15
new file mode 100644
... ...
@@ -0,0 +1,57 @@
0
+//go:build linux
1
+// +build linux
2
+
3
+package oci
4
+
5
+import (
6
+	"os"
7
+	"strconv"
8
+
9
+	"github.com/containerd/containerd/mount"
10
+	"github.com/containerd/continuity/fs"
11
+	"github.com/moby/buildkit/snapshot"
12
+	"github.com/pkg/errors"
13
+	"golang.org/x/sys/unix"
14
+)
15
+
16
+func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) {
17
+	var retries = 10
18
+	root := m.Source
19
+	for {
20
+		src, err := fs.RootPath(root, subPath)
21
+		if err != nil {
22
+			return mount.Mount{}, nil, err
23
+		}
24
+		// similar to runc.WithProcfd
25
+		fh, err := os.OpenFile(src, unix.O_PATH|unix.O_CLOEXEC, 0)
26
+		if err != nil {
27
+			return mount.Mount{}, nil, err
28
+		}
29
+
30
+		fdPath := "/proc/self/fd/" + strconv.Itoa(int(fh.Fd()))
31
+		if resolved, err := os.Readlink(fdPath); err != nil {
32
+			fh.Close()
33
+			return mount.Mount{}, nil, err
34
+		} else if resolved != src {
35
+			retries--
36
+			if retries <= 0 {
37
+				fh.Close()
38
+				return mount.Mount{}, nil, errors.Errorf("unable to safely resolve subpath %s", subPath)
39
+			}
40
+			fh.Close()
41
+			continue
42
+		}
43
+
44
+		m.Source = fdPath
45
+		lm := snapshot.LocalMounterWithMounts([]mount.Mount{m}, snapshot.ForceRemount())
46
+		mp, err := lm.Mount()
47
+		if err != nil {
48
+			fh.Close()
49
+			return mount.Mount{}, nil, err
50
+		}
51
+		m.Source = mp
52
+		fh.Close() // release the fd, we don't need it anymore
53
+
54
+		return m, lm.Unmount, nil
55
+	}
56
+}
... ...
@@ -7,7 +7,9 @@ import (
7 7
 	"fmt"
8 8
 	"path/filepath"
9 9
 
10
+	"github.com/containerd/containerd/mount"
10 11
 	"github.com/containerd/containerd/oci"
12
+	"github.com/containerd/continuity/fs"
11 13
 	"github.com/docker/docker/pkg/idtools"
12 14
 	"github.com/moby/buildkit/solver/pb"
13 15
 	specs "github.com/opencontainers/runtime-spec/specs-go"
... ...
@@ -67,3 +69,12 @@ func getTracingSocket() string {
67 67
 func cgroupV2NamespaceSupported() bool {
68 68
 	return false
69 69
 }
70
+
71
+func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) {
72
+	src, err := fs.RootPath(m.Source, subPath)
73
+	if err != nil {
74
+		return mount.Mount{}, nil, err
75
+	}
76
+	m.Source = src
77
+	return m, func() error { return nil }, nil
78
+}
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"errors"
6 6
 	"os"
7 7
 	"path/filepath"
8
+	"strings"
8 9
 	"syscall"
9 10
 
10 11
 	"github.com/containerd/continuity/fs"
... ...
@@ -43,7 +44,7 @@ func MountStubsCleaner(ctx context.Context, dir string, mounts []Mount, recursiv
43 43
 			}
44 44
 
45 45
 			realPathNext := filepath.Dir(realPath)
46
-			if realPath == realPathNext {
46
+			if realPath == realPathNext || realPathNext == dir {
47 47
 				break
48 48
 			}
49 49
 			realPath = realPathNext
... ...
@@ -52,6 +53,11 @@ func MountStubsCleaner(ctx context.Context, dir string, mounts []Mount, recursiv
52 52
 
53 53
 	return func() {
54 54
 		for _, p := range paths {
55
+			p, err := fs.RootPath(dir, strings.TrimPrefix(p, dir))
56
+			if err != nil {
57
+				continue
58
+			}
59
+
55 60
 			st, err := os.Lstat(p)
56 61
 			if err != nil {
57 62
 				continue
... ...
@@ -70,8 +76,12 @@ func MountStubsCleaner(ctx context.Context, dir string, mounts []Mount, recursiv
70 70
 
71 71
 			// Back up the timestamps of the dir for reproducible builds
72 72
 			// https://github.com/moby/buildkit/issues/3148
73
-			dir := filepath.Dir(p)
74
-			dirSt, err := os.Stat(dir)
73
+			parent := filepath.Dir(p)
74
+			if realPath, err := fs.RootPath(dir, strings.TrimPrefix(parent, dir)); err != nil || realPath != parent {
75
+				continue
76
+			}
77
+
78
+			dirSt, err := os.Stat(parent)
75 79
 			if err != nil {
76 80
 				bklog.G(ctx).WithError(err).Warnf("Failed to stat %q (parent of mount stub %q)", dir, p)
77 81
 				continue
... ...
@@ -88,7 +98,7 @@ func MountStubsCleaner(ctx context.Context, dir string, mounts []Mount, recursiv
88 88
 			}
89 89
 
90 90
 			// Restore the timestamps of the dir
91
-			if err := os.Chtimes(dir, atime, mtime); err != nil {
91
+			if err := os.Chtimes(parent, atime, mtime); err != nil {
92 92
 				bklog.G(ctx).WithError(err).Warnf("Failed to restore time time mount stub timestamp (os.Chtimes(%q, %v, %v))", dir, atime, mtime)
93 93
 			}
94 94
 		}
... ...
@@ -17,6 +17,18 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
17 17
 				return Platforms{}, errors.Wrapf(err, "failed to parse platforms passed to provenance processor")
18 18
 			}
19 19
 		}
20
+		if len(ps.Platforms) == 0 {
21
+			return Platforms{}, errors.Errorf("invalid empty platforms index for exporter")
22
+		}
23
+		for i, p := range ps.Platforms {
24
+			if p.ID == "" {
25
+				return Platforms{}, errors.Errorf("invalid empty platform key for exporter")
26
+			}
27
+			if p.Platform.OS == "" || p.Platform.Architecture == "" {
28
+				return Platforms{}, errors.Errorf("invalid platform value %v for exporter", p.Platform)
29
+			}
30
+			ps.Platforms[i].Platform = platforms.Normalize(p.Platform)
31
+		}
20 32
 		return ps, nil
21 33
 	}
22 34
 
... ...
@@ -36,6 +48,8 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
36 36
 				OSFeatures:   img.OSFeatures,
37 37
 				Variant:      img.Variant,
38 38
 			}
39
+		} else if img.OS != "" || img.Architecture != "" {
40
+			return Platforms{}, errors.Errorf("invalid image config: os and architecture must be specified together")
39 41
 		}
40 42
 	}
41 43
 	p = platforms.Normalize(p)
... ...
@@ -569,11 +569,27 @@ func parseHistoryFromConfig(dt []byte) ([]ocispecs.History, error) {
569 569
 }
570 570
 
571 571
 func patchImageConfig(dt []byte, descs []ocispecs.Descriptor, history []ocispecs.History, cache []byte, epoch *time.Time) ([]byte, error) {
572
+	var img ocispecs.Image
573
+	if err := json.Unmarshal(dt, &img); err != nil {
574
+		return nil, errors.Wrap(err, "invalid image config for export")
575
+	}
576
+
572 577
 	m := map[string]json.RawMessage{}
573 578
 	if err := json.Unmarshal(dt, &m); err != nil {
574 579
 		return nil, errors.Wrap(err, "failed to parse image config for patch")
575 580
 	}
576 581
 
582
+	if m == nil {
583
+		return nil, errors.Errorf("invalid null image config for export")
584
+	}
585
+
586
+	if img.OS == "" {
587
+		return nil, errors.Errorf("invalid image config for export: missing os")
588
+	}
589
+	if img.Architecture == "" {
590
+		return nil, errors.Errorf("invalid image config for export: missing architecture")
591
+	}
592
+
577 593
 	var rootFS ocispecs.RootFS
578 594
 	rootFS.Type = "layers"
579 595
 	for _, desc := range descs {
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"context"
5 5
 
6 6
 	"github.com/moby/buildkit/client/llb"
7
+	"github.com/moby/buildkit/executor"
7 8
 	gw "github.com/moby/buildkit/frontend/gateway/client"
8 9
 	"github.com/moby/buildkit/session"
9 10
 	"github.com/moby/buildkit/solver"
... ...
@@ -17,7 +18,7 @@ type Result = result.Result[solver.ResultProxy]
17 17
 type Attestation = result.Attestation[solver.ResultProxy]
18 18
 
19 19
 type Frontend interface {
20
-	Solve(ctx context.Context, llb FrontendLLBBridge, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error)
20
+	Solve(ctx context.Context, llb FrontendLLBBridge, exec executor.Executor, opt map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (*Result, error)
21 21
 }
22 22
 
23 23
 type FrontendLLBBridge interface {
... ...
@@ -30,8 +30,14 @@ func AttestationToPB[T any](a *result.Attestation[T]) (*pb.Attestation, error) {
30 30
 }
31 31
 
32 32
 func AttestationFromPB[T any](a *pb.Attestation) (*result.Attestation[T], error) {
33
+	if a == nil {
34
+		return nil, errors.Errorf("invalid nil attestation")
35
+	}
33 36
 	subjects := make([]result.InTotoSubject, len(a.InTotoSubjects))
34 37
 	for i, subject := range a.InTotoSubjects {
38
+		if subject == nil {
39
+			return nil, errors.Errorf("invalid nil attestation subject")
40
+		}
35 41
 		subjects[i] = result.InTotoSubject{
36 42
 			Kind:   subject.Kind,
37 43
 			Name:   subject.Name,
... ...
@@ -47,7 +47,7 @@ type Mount struct {
47 47
 	WorkerRef *worker.WorkerRef
48 48
 }
49 49
 
50
-func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) {
50
+func NewContainer(ctx context.Context, cm cache.Manager, exec executor.Executor, sm *session.Manager, g session.Group, req NewContainerRequest) (client.Container, error) {
51 51
 	ctx, cancel := context.WithCancel(ctx)
52 52
 	eg, ctx := errgroup.WithContext(ctx)
53 53
 	platform := opspb.Platform{
... ...
@@ -63,7 +63,7 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s
63 63
 		hostname:   req.Hostname,
64 64
 		extraHosts: req.ExtraHosts,
65 65
 		platform:   platform,
66
-		executor:   w.Executor(),
66
+		executor:   exec,
67 67
 		sm:         sm,
68 68
 		group:      g,
69 69
 		errGroup:   eg,
... ...
@@ -86,9 +86,8 @@ func NewContainer(ctx context.Context, w worker.Worker, sm *session.Manager, g s
86 86
 	}
87 87
 
88 88
 	name := fmt.Sprintf("container %s", req.ContainerID)
89
-	mm := mounts.NewMountManager(name, w.CacheManager(), sm)
90
-	p, err := PrepareMounts(ctx, mm, w.CacheManager(), g, "", mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) {
91
-		cm := w.CacheManager()
89
+	mm := mounts.NewMountManager(name, cm, sm)
90
+	p, err := PrepareMounts(ctx, mm, cm, g, "", mnts, refs, func(m *opspb.Mount, ref cache.ImmutableRef) (cache.MutableRef, error) {
92 91
 		if m.Input != opspb.Empty {
93 92
 			cm = refs[m.Input].Worker.CacheManager()
94 93
 		}
... ...
@@ -6,6 +6,7 @@ import (
6 6
 
7 7
 	cacheutil "github.com/moby/buildkit/cache/util"
8 8
 	"github.com/moby/buildkit/client/llb"
9
+	"github.com/moby/buildkit/executor"
9 10
 	"github.com/moby/buildkit/frontend"
10 11
 	"github.com/moby/buildkit/frontend/gateway/client"
11 12
 	"github.com/moby/buildkit/frontend/gateway/container"
... ...
@@ -26,7 +27,7 @@ import (
26 26
 	"golang.org/x/sync/errgroup"
27 27
 )
28 28
 
29
-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) {
29
+func LLBBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*opspb.Definition, w worker.Infos, sid string, sm *session.Manager) (*BridgeClient, error) {
30 30
 	bc := &BridgeClient{
31 31
 		opts:              opts,
32 32
 		inputs:            inputs,
... ...
@@ -35,6 +36,7 @@ func LLBBridgeToGatewayClient(ctx context.Context, llbBridge frontend.FrontendLL
35 35
 		sm:                sm,
36 36
 		workers:           w,
37 37
 		workerRefByID:     make(map[string]*worker.WorkerRef),
38
+		executor:          exec,
38 39
 	}
39 40
 	bc.buildOpts = bc.loadBuildOpts()
40 41
 	return bc, nil
... ...
@@ -52,6 +54,7 @@ type BridgeClient struct {
52 52
 	workerRefByID map[string]*worker.WorkerRef
53 53
 	buildOpts     client.BuildOpts
54 54
 	ctrs          []client.Container
55
+	executor      executor.Executor
55 56
 }
56 57
 
57 58
 func (c *BridgeClient) Solve(ctx context.Context, req client.SolveRequest) (*client.Result, error) {
... ...
@@ -293,13 +296,13 @@ func (c *BridgeClient) NewContainer(ctx context.Context, req client.NewContainer
293 293
 		return nil, err
294 294
 	}
295 295
 
296
-	w, err := c.workers.GetDefault()
296
+	cm, err := c.workers.DefaultCacheManager()
297 297
 	if err != nil {
298 298
 		return nil, err
299 299
 	}
300 300
 
301 301
 	group := session.NewGroup(c.sid)
302
-	ctr, err := container.NewContainer(ctx, w, c.sm, group, ctrReq)
302
+	ctr, err := container.NewContainer(ctx, cm, c.executor, c.sm, group, ctrReq)
303 303
 	if err != nil {
304 304
 		return nil, err
305 305
 	}
... ...
@@ -3,6 +3,7 @@ package forwarder
3 3
 import (
4 4
 	"context"
5 5
 
6
+	"github.com/moby/buildkit/executor"
6 7
 	"github.com/moby/buildkit/frontend"
7 8
 	"github.com/moby/buildkit/frontend/gateway/client"
8 9
 	"github.com/moby/buildkit/session"
... ...
@@ -22,8 +23,8 @@ type GatewayForwarder struct {
22 22
 	f       client.BuildFunc
23 23
 }
24 24
 
25
-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) {
26
-	c, err := LLBBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers, sid, sm)
25
+func (gf *GatewayForwarder) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*pb.Definition, sid string, sm *session.Manager) (retRes *frontend.Result, retErr error) {
26
+	c, err := LLBBridgeToGatewayClient(ctx, llbBridge, exec, opts, inputs, gf.workers, sid, sm)
27 27
 	if err != nil {
28 28
 		return nil, err
29 29
 	}
... ...
@@ -86,7 +86,7 @@ func filterPrefix(opts map[string]string, pfx string) map[string]string {
86 86
 	return m
87 87
 }
88 88
 
89
-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) {
89
+func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, opts map[string]string, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*frontend.Result, error) {
90 90
 	source, ok := opts[keySource]
91 91
 	if !ok {
92 92
 		return nil, errors.Errorf("no source specified for gateway")
... ...
@@ -141,7 +141,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
141 141
 			}
142 142
 		}
143 143
 	} else {
144
-		c, err := forwarder.LLBBridgeToGatewayClient(ctx, llbBridge, opts, inputs, gf.workers, sid, sm)
144
+		c, err := forwarder.LLBBridgeToGatewayClient(ctx, llbBridge, exec, opts, inputs, gf.workers, sid, sm)
145 145
 		if err != nil {
146 146
 			return nil, err
147 147
 		}
... ...
@@ -281,18 +281,13 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
281 281
 		}
282 282
 	}
283 283
 
284
-	lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, gf.workers, inputs, sid, sm)
284
+	lbf, ctx, err := serveLLBBridgeForwarder(ctx, llbBridge, exec, gf.workers, inputs, sid, sm)
285 285
 	defer lbf.conn.Close() //nolint
286 286
 	if err != nil {
287 287
 		return nil, err
288 288
 	}
289 289
 	defer lbf.Discard()
290 290
 
291
-	w, err := gf.workers.GetDefault()
292
-	if err != nil {
293
-		return nil, err
294
-	}
295
-
296 291
 	mdmnt, release, err := metadataMount(frontendDef)
297 292
 	if err != nil {
298 293
 		return nil, err
... ...
@@ -305,7 +300,7 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
305 305
 		mnts = append(mnts, *mdmnt)
306 306
 	}
307 307
 
308
-	_, err = w.Executor().Run(ctx, "", container.MountWithSession(rootFS, session.NewGroup(sid)), mnts, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil)
308
+	_, err = exec.Run(ctx, "", container.MountWithSession(rootFS, session.NewGroup(sid)), mnts, executor.ProcessInfo{Meta: meta, Stdin: lbf.Stdin, Stdout: lbf.Stdout, Stderr: os.Stderr}, nil)
309 309
 	if err != nil {
310 310
 		if errdefs.IsCanceled(ctx, err) && lbf.isErrServerClosed {
311 311
 			err = errors.Errorf("frontend grpc server closed unexpectedly")
... ...
@@ -434,11 +429,11 @@ func (lbf *llbBridgeForwarder) Result() (*frontend.Result, error) {
434 434
 	return lbf.result, nil
435 435
 }
436 436
 
437
-func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder {
438
-	return newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm)
437
+func NewBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) LLBBridgeForwarder {
438
+	return newBridgeForwarder(ctx, llbBridge, exec, workers, inputs, sid, sm)
439 439
 }
440 440
 
441
-func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder {
441
+func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) *llbBridgeForwarder {
442 442
 	lbf := &llbBridgeForwarder{
443 443
 		callCtx:       ctx,
444 444
 		llbBridge:     llbBridge,
... ...
@@ -451,13 +446,14 @@ func newBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridg
451 451
 		sid:           sid,
452 452
 		sm:            sm,
453 453
 		ctrs:          map[string]gwclient.Container{},
454
+		executor:      exec,
454 455
 	}
455 456
 	return lbf
456 457
 }
457 458
 
458
-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) {
459
+func serveLLBBridgeForwarder(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, workers worker.Infos, inputs map[string]*opspb.Definition, sid string, sm *session.Manager) (*llbBridgeForwarder, context.Context, error) {
459 460
 	ctx, cancel := context.WithCancel(ctx)
460
-	lbf := newBridgeForwarder(ctx, llbBridge, workers, inputs, sid, sm)
461
+	lbf := newBridgeForwarder(ctx, llbBridge, exec, workers, inputs, sid, sm)
461 462
 	server := grpc.NewServer(grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor), grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor))
462 463
 	grpc_health_v1.RegisterHealthServer(server, health.NewServer())
463 464
 	pb.RegisterLLBBridgeServer(server, lbf)
... ...
@@ -552,6 +548,7 @@ type llbBridgeForwarder struct {
552 552
 	isErrServerClosed bool
553 553
 	sid               string
554 554
 	sm                *session.Manager
555
+	executor          executor.Executor
555 556
 	*pipe
556 557
 	ctrs   map[string]gwclient.Container
557 558
 	ctrsMu sync.Mutex
... ...
@@ -646,12 +643,21 @@ func (lbf *llbBridgeForwarder) registerResultIDs(results ...solver.Result) (ids
646 646
 func (lbf *llbBridgeForwarder) Solve(ctx context.Context, req *pb.SolveRequest) (*pb.SolveResponse, error) {
647 647
 	var cacheImports []frontend.CacheOptionsEntry
648 648
 	for _, e := range req.CacheImports {
649
+		if e == nil {
650
+			return nil, errors.Errorf("invalid nil cache import")
651
+		}
649 652
 		cacheImports = append(cacheImports, frontend.CacheOptionsEntry{
650 653
 			Type:  e.Type,
651 654
 			Attrs: e.Attrs,
652 655
 		})
653 656
 	}
654 657
 
658
+	for _, p := range req.SourcePolicies {
659
+		if p == nil {
660
+			return nil, errors.Errorf("invalid nil source policy")
661
+		}
662
+	}
663
+
655 664
 	ctx = tracing.ContextWithSpanFromContext(ctx, lbf.callCtx)
656 665
 	res, err := lbf.llbBridge.Solve(ctx, frontend.SolveRequest{
657 666
 		Evaluate:       req.Evaluate,
... ...
@@ -1033,7 +1039,7 @@ func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewConta
1033 1033
 	// and we want the context to live for the duration of the container.
1034 1034
 	group := session.NewGroup(lbf.sid)
1035 1035
 
1036
-	w, err := lbf.workers.GetDefault()
1036
+	cm, err := lbf.workers.DefaultCacheManager()
1037 1037
 	if err != nil {
1038 1038
 		return nil, stack.Enable(err)
1039 1039
 	}
... ...
@@ -1043,7 +1049,7 @@ func (lbf *llbBridgeForwarder) NewContainer(ctx context.Context, in *pb.NewConta
1043 1043
 		return nil, stack.Enable(err)
1044 1044
 	}
1045 1045
 
1046
-	ctr, err := container.NewContainer(context.Background(), w, lbf.sm, group, ctrReq)
1046
+	ctr, err := container.NewContainer(context.Background(), cm, lbf.executor, lbf.sm, group, ctrReq)
1047 1047
 	if err != nil {
1048 1048
 		return nil, stack.Enable(err)
1049 1049
 	}
... ...
@@ -1077,6 +1083,12 @@ func (lbf *llbBridgeForwarder) ReleaseContainer(ctx context.Context, in *pb.Rele
1077 1077
 }
1078 1078
 
1079 1079
 func (lbf *llbBridgeForwarder) Warn(ctx context.Context, in *pb.WarnRequest) (*pb.WarnResponse, error) {
1080
+	// validate ranges are valid
1081
+	for _, r := range in.Ranges {
1082
+		if r == nil {
1083
+			return nil, status.Errorf(codes.InvalidArgument, "invalid source range")
1084
+		}
1085
+	}
1080 1086
 	err := lbf.llbBridge.Warn(ctx, in.Digest, string(in.Short), frontend.WarnOpts{
1081 1087
 		Level:      int(in.Level),
1082 1088
 		SourceInfo: in.Info,
... ...
@@ -11,22 +11,39 @@ type Mounter interface {
11 11
 	Unmount() error
12 12
 }
13 13
 
14
+type LocalMounterOpt func(*localMounter)
15
+
14 16
 // LocalMounter is a helper for mounting mountfactory to temporary path. In
15 17
 // addition it can mount binds without privileges
16
-func LocalMounter(mountable Mountable) Mounter {
17
-	return &localMounter{mountable: mountable}
18
+func LocalMounter(mountable Mountable, opts ...LocalMounterOpt) Mounter {
19
+	lm := &localMounter{mountable: mountable}
20
+	for _, opt := range opts {
21
+		opt(lm)
22
+	}
23
+	return lm
18 24
 }
19 25
 
20 26
 // LocalMounterWithMounts is a helper for mounting to temporary path. In
21 27
 // addition it can mount binds without privileges
22
-func LocalMounterWithMounts(mounts []mount.Mount) Mounter {
23
-	return &localMounter{mounts: mounts}
28
+func LocalMounterWithMounts(mounts []mount.Mount, opts ...LocalMounterOpt) Mounter {
29
+	lm := &localMounter{mounts: mounts}
30
+	for _, opt := range opts {
31
+		opt(lm)
32
+	}
33
+	return lm
24 34
 }
25 35
 
26 36
 type localMounter struct {
27
-	mu        sync.Mutex
28
-	mounts    []mount.Mount
29
-	mountable Mountable
30
-	target    string
31
-	release   func() error
37
+	mu           sync.Mutex
38
+	mounts       []mount.Mount
39
+	mountable    Mountable
40
+	target       string
41
+	release      func() error
42
+	forceRemount bool
43
+}
44
+
45
+func ForceRemount() LocalMounterOpt {
46
+	return func(lm *localMounter) {
47
+		lm.forceRemount = true
48
+	}
32 49
 }
... ...
@@ -5,6 +5,7 @@ package snapshot
5 5
 
6 6
 import (
7 7
 	"os"
8
+	"path/filepath"
8 9
 	"syscall"
9 10
 
10 11
 	"github.com/containerd/containerd/mount"
... ...
@@ -34,30 +35,48 @@ func (lm *localMounter) Mount() (string, error) {
34 34
 		}
35 35
 	}
36 36
 
37
+	var isFile bool
37 38
 	if len(lm.mounts) == 1 && (lm.mounts[0].Type == "bind" || lm.mounts[0].Type == "rbind") {
38
-		ro := false
39
-		for _, opt := range lm.mounts[0].Options {
40
-			if opt == "ro" {
41
-				ro = true
42
-				break
39
+		if !lm.forceRemount {
40
+			ro := false
41
+			for _, opt := range lm.mounts[0].Options {
42
+				if opt == "ro" {
43
+					ro = true
44
+					break
45
+				}
43 46
 			}
47
+			if !ro {
48
+				return lm.mounts[0].Source, nil
49
+			}
50
+		}
51
+		fi, err := os.Stat(lm.mounts[0].Source)
52
+		if err != nil {
53
+			return "", err
44 54
 		}
45
-		if !ro {
46
-			return lm.mounts[0].Source, nil
55
+		if !fi.IsDir() {
56
+			isFile = true
47 57
 		}
48 58
 	}
49 59
 
50
-	dir, err := os.MkdirTemp("", "buildkit-mount")
60
+	dest, err := os.MkdirTemp("", "buildkit-mount")
51 61
 	if err != nil {
52 62
 		return "", errors.Wrap(err, "failed to create temp dir")
53 63
 	}
54 64
 
55
-	if err := mount.All(lm.mounts, dir); err != nil {
56
-		os.RemoveAll(dir)
57
-		return "", errors.Wrapf(err, "failed to mount %s: %+v", dir, lm.mounts)
65
+	if isFile {
66
+		dest = filepath.Join(dest, "file")
67
+		if err := os.WriteFile(dest, []byte{}, 0644); err != nil {
68
+			os.RemoveAll(dest)
69
+			return "", errors.Wrap(err, "failed to create temp file")
70
+		}
71
+	}
72
+
73
+	if err := mount.All(lm.mounts, dest); err != nil {
74
+		os.RemoveAll(dest)
75
+		return "", errors.Wrapf(err, "failed to mount %s: %+v", dest, lm.mounts)
58 76
 	}
59
-	lm.target = dir
60
-	return dir, nil
77
+	lm.target = dest
78
+	return dest, nil
61 79
 }
62 80
 
63 81
 func (lm *localMounter) Unmount() error {
... ...
@@ -10,14 +10,11 @@ import (
10 10
 	"github.com/containerd/containerd/pkg/userns"
11 11
 	"github.com/containerd/containerd/snapshots"
12 12
 	"github.com/docker/docker/pkg/idtools"
13
+	"github.com/moby/buildkit/executor"
13 14
 	"github.com/pkg/errors"
14 15
 )
15 16
 
16
-type Mountable interface {
17
-	// ID() string
18
-	Mount() ([]mount.Mount, func() error, error)
19
-	IdentityMapping() *idtools.IdentityMapping
20
-}
17
+type Mountable = executor.MountableRef
21 18
 
22 19
 // Snapshotter defines interface that any snapshot implementation should satisfy
23 20
 type Snapshotter interface {
... ...
@@ -11,6 +11,8 @@ import (
11 11
 	"github.com/moby/buildkit/cache/remotecache"
12 12
 	"github.com/moby/buildkit/client"
13 13
 	"github.com/moby/buildkit/client/llb"
14
+	"github.com/moby/buildkit/executor"
15
+	resourcestypes "github.com/moby/buildkit/executor/resources/types"
14 16
 	"github.com/moby/buildkit/frontend"
15 17
 	gw "github.com/moby/buildkit/frontend/gateway/client"
16 18
 	"github.com/moby/buildkit/identity"
... ...
@@ -23,6 +25,7 @@ import (
23 23
 	"github.com/moby/buildkit/sourcepolicy"
24 24
 	spb "github.com/moby/buildkit/sourcepolicy/pb"
25 25
 	"github.com/moby/buildkit/util/bklog"
26
+	"github.com/moby/buildkit/util/entitlements"
26 27
 	"github.com/moby/buildkit/util/flightcontrol"
27 28
 	"github.com/moby/buildkit/util/progress"
28 29
 	"github.com/moby/buildkit/worker"
... ...
@@ -39,6 +42,10 @@ type llbBridge struct {
39 39
 	cms                       map[string]solver.CacheManager
40 40
 	cmsMu                     sync.Mutex
41 41
 	sm                        *session.Manager
42
+
43
+	executorOnce sync.Once
44
+	executorErr  error
45
+	executor     executor.Executor
42 46
 }
43 47
 
44 48
 func (b *llbBridge) Warn(ctx context.Context, dgst digest.Digest, msg string, opts frontend.WarnOpts) error {
... ...
@@ -79,6 +86,14 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp
79 79
 	}
80 80
 	var polEngine SourcePolicyEvaluator
81 81
 	if srcPol != nil || len(pol) > 0 {
82
+		for _, p := range pol {
83
+			if p == nil {
84
+				return nil, errors.Errorf("invalid nil policy")
85
+			}
86
+			if err := validateSourcePolicy(*p); err != nil {
87
+				return nil, err
88
+			}
89
+		}
82 90
 		if srcPol != nil {
83 91
 			pol = append([]*spb.Policy{srcPol}, pol...)
84 92
 		}
... ...
@@ -151,6 +166,52 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp
151 151
 	return res, nil
152 152
 }
153 153
 
154
+func (b *llbBridge) validateEntitlements(p executor.ProcessInfo) error {
155
+	ent, err := loadEntitlements(b.builder)
156
+	if err != nil {
157
+		return err
158
+	}
159
+	v := entitlements.Values{
160
+		NetworkHost:      p.Meta.NetMode == pb.NetMode_HOST,
161
+		SecurityInsecure: p.Meta.SecurityMode == pb.SecurityMode_INSECURE,
162
+	}
163
+	return ent.Check(v)
164
+}
165
+
166
+func (b *llbBridge) Run(ctx context.Context, id string, rootfs executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (resourcestypes.Recorder, error) {
167
+	if err := b.validateEntitlements(process); err != nil {
168
+		return nil, err
169
+	}
170
+
171
+	if err := b.loadExecutor(); err != nil {
172
+		return nil, err
173
+	}
174
+	return b.executor.Run(ctx, id, rootfs, mounts, process, started)
175
+}
176
+
177
+func (b *llbBridge) Exec(ctx context.Context, id string, process executor.ProcessInfo) error {
178
+	if err := b.validateEntitlements(process); err != nil {
179
+		return err
180
+	}
181
+
182
+	if err := b.loadExecutor(); err != nil {
183
+		return err
184
+	}
185
+	return b.executor.Exec(ctx, id, process)
186
+}
187
+
188
+func (b *llbBridge) loadExecutor() error {
189
+	b.executorOnce.Do(func() {
190
+		w, err := b.resolveWorker()
191
+		if err != nil {
192
+			b.executorErr = err
193
+			return
194
+		}
195
+		b.executor = w.Executor()
196
+	})
197
+	return b.executorErr
198
+}
199
+
154 200
 type resultProxy struct {
155 201
 	id         string
156 202
 	b          *provenanceBridge
... ...
@@ -165,7 +165,7 @@ func (b *provenanceBridge) Solve(ctx context.Context, req frontend.SolveRequest,
165 165
 			return nil, errors.Errorf("invalid frontend: %s", req.Frontend)
166 166
 		}
167 167
 		wb := &provenanceBridge{llbBridge: b.llbBridge, req: &req}
168
-		res, err = f.Solve(ctx, wb, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm)
168
+		res, err = f.Solve(ctx, wb, b.llbBridge, req.FrontendOpt, req.FrontendInputs, sid, b.llbBridge.sm)
169 169
 		if err != nil {
170 170
 			return nil, err
171 171
 		}
... ...
@@ -447,6 +447,9 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
447 447
 	j.SetValue(keyEntitlements, set)
448 448
 
449 449
 	if srcPol != nil {
450
+		if err := validateSourcePolicy(*srcPol); err != nil {
451
+			return nil, err
452
+		}
450 453
 		j.SetValue(keySourcePolicy, *srcPol)
451 454
 	}
452 455
 
... ...
@@ -455,7 +458,7 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
455 455
 	br := s.bridge(j)
456 456
 	var fwd gateway.LLBBridgeForwarder
457 457
 	if s.gatewayForwarder != nil && req.Definition == nil && req.Frontend == "" {
458
-		fwd = gateway.NewBridgeForwarder(ctx, br, s.workerController, req.FrontendInputs, sessionID, s.sm)
458
+		fwd = gateway.NewBridgeForwarder(ctx, br, br, s.workerController.Infos(), req.FrontendInputs, sessionID, s.sm)
459 459
 		defer fwd.Discard()
460 460
 		// Register build before calling s.recordBuildHistory, because
461 461
 		// s.recordBuildHistory can block for several seconds on
... ...
@@ -595,6 +598,23 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
595 595
 	}, nil
596 596
 }
597 597
 
598
+func validateSourcePolicy(pol spb.Policy) error {
599
+	for _, r := range pol.Rules {
600
+		if r == nil {
601
+			return errors.New("invalid nil rule in policy")
602
+		}
603
+		if r.Selector == nil {
604
+			return errors.New("invalid nil selector in policy")
605
+		}
606
+		for _, c := range r.Selector.Constraints {
607
+			if c == nil {
608
+				return errors.New("invalid nil constraint in policy")
609
+			}
610
+		}
611
+	}
612
+	return nil
613
+}
614
+
598 615
 func runCacheExporters(ctx context.Context, exporters []RemoteCacheExporter, j *solver.Job, cached *result.Result[solver.CachedResult], inp *result.Result[cache.ImmutableRef]) (map[string]string, error) {
599 616
 	eg, ctx := errgroup.WithContext(ctx)
600 617
 	g := session.NewGroup(j.SessionID)
... ...
@@ -991,6 +1011,9 @@ func loadSourcePolicy(b solver.Builder) (*spb.Policy, error) {
991 991
 			return errors.Errorf("invalid source policy %T", v)
992 992
 		}
993 993
 		for _, f := range x.Rules {
994
+			if f == nil {
995
+				return errors.Errorf("invalid nil policy rule")
996
+			}
994 997
 			r := *f
995 998
 			srcPol.Rules = append(srcPol.Rules, &r)
996 999
 		}
... ...
@@ -101,16 +101,12 @@ func ValidateEntitlements(ent entitlements.Set) LoadOpt {
101 101
 	return func(op *pb.Op, _ *pb.OpMetadata, opt *solver.VertexOptions) error {
102 102
 		switch op := op.Op.(type) {
103 103
 		case *pb.Op_Exec:
104
-			if op.Exec.Network == pb.NetMode_HOST {
105
-				if !ent.Allowed(entitlements.EntitlementNetworkHost) {
106
-					return errors.Errorf("%s is not allowed", entitlements.EntitlementNetworkHost)
107
-				}
104
+			v := entitlements.Values{
105
+				NetworkHost:      op.Exec.Network == pb.NetMode_HOST,
106
+				SecurityInsecure: op.Exec.Security == pb.SecurityMode_INSECURE,
108 107
 			}
109
-
110
-			if op.Exec.Security == pb.SecurityMode_INSECURE {
111
-				if !ent.Allowed(entitlements.EntitlementSecurityInsecure) {
112
-					return errors.Errorf("%s is not allowed", entitlements.EntitlementSecurityInsecure)
113
-				}
108
+			if err := ent.Check(v); err != nil {
109
+				return err
114 110
 			}
115 111
 		}
116 112
 		return nil
... ...
@@ -10,6 +10,9 @@ import (
10 10
 
11 11
 func match(ctx context.Context, src *selectorCache, ref string, attrs map[string]string) (bool, error) {
12 12
 	for _, c := range src.Constraints {
13
+		if c == nil {
14
+			return false, errors.Errorf("invalid nil constraint for %v", src)
15
+		}
13 16
 		switch c.Condition {
14 17
 		case spb.AttrMatch_EQUAL:
15 18
 			if attrs[c.Key] != c.Value {
... ...
@@ -58,3 +58,23 @@ func (s Set) Allowed(e Entitlement) bool {
58 58
 	_, ok := s[e]
59 59
 	return ok
60 60
 }
61
+
62
+func (s Set) Check(v Values) error {
63
+	if v.NetworkHost {
64
+		if !s.Allowed(EntitlementNetworkHost) {
65
+			return errors.Errorf("%s is not allowed", EntitlementNetworkHost)
66
+		}
67
+	}
68
+
69
+	if v.SecurityInsecure {
70
+		if !s.Allowed(EntitlementSecurityInsecure) {
71
+			return errors.Errorf("%s is not allowed", EntitlementSecurityInsecure)
72
+		}
73
+	}
74
+	return nil
75
+}
76
+
77
+type Values struct {
78
+	NetworkHost      bool
79
+	SecurityInsecure bool
80
+}
... ...
@@ -13,6 +13,9 @@ func Attributes(attrs []*commonpb.KeyValue) []attribute.KeyValue {
13 13
 
14 14
 	out := make([]attribute.KeyValue, 0, len(attrs))
15 15
 	for _, a := range attrs {
16
+		if a == nil {
17
+			continue
18
+		}
16 19
 		kv := attribute.KeyValue{
17 20
 			Key:   attribute.Key(a.Key),
18 21
 			Value: toValue(a.Value),
... ...
@@ -42,7 +45,9 @@ func toValue(v *commonpb.AnyValue) attribute.Value {
42 42
 func boolArray(kv []*commonpb.AnyValue) attribute.Value {
43 43
 	arr := make([]bool, len(kv))
44 44
 	for i, v := range kv {
45
-		arr[i] = v.GetBoolValue()
45
+		if v != nil {
46
+			arr[i] = v.GetBoolValue()
47
+		}
46 48
 	}
47 49
 	return attribute.BoolSliceValue(arr)
48 50
 }
... ...
@@ -50,7 +55,9 @@ func boolArray(kv []*commonpb.AnyValue) attribute.Value {
50 50
 func intArray(kv []*commonpb.AnyValue) attribute.Value {
51 51
 	arr := make([]int64, len(kv))
52 52
 	for i, v := range kv {
53
-		arr[i] = v.GetIntValue()
53
+		if v != nil {
54
+			arr[i] = v.GetIntValue()
55
+		}
54 56
 	}
55 57
 	return attribute.Int64SliceValue(arr)
56 58
 }
... ...
@@ -58,7 +65,9 @@ func intArray(kv []*commonpb.AnyValue) attribute.Value {
58 58
 func doubleArray(kv []*commonpb.AnyValue) attribute.Value {
59 59
 	arr := make([]float64, len(kv))
60 60
 	for i, v := range kv {
61
-		arr[i] = v.GetDoubleValue()
61
+		if v != nil {
62
+			arr[i] = v.GetDoubleValue()
63
+		}
62 64
 	}
63 65
 	return attribute.Float64SliceValue(arr)
64 66
 }
... ...
@@ -66,13 +75,15 @@ func doubleArray(kv []*commonpb.AnyValue) attribute.Value {
66 66
 func stringArray(kv []*commonpb.AnyValue) attribute.Value {
67 67
 	arr := make([]string, len(kv))
68 68
 	for i, v := range kv {
69
-		arr[i] = v.GetStringValue()
69
+		if v != nil {
70
+			arr[i] = v.GetStringValue()
71
+		}
70 72
 	}
71 73
 	return attribute.StringSliceValue(arr)
72 74
 }
73 75
 
74 76
 func arrayValues(kv []*commonpb.AnyValue) attribute.Value {
75
-	if len(kv) == 0 {
77
+	if len(kv) == 0 || kv[0] == nil {
76 78
 		return attribute.StringSliceValue([]string{})
77 79
 	}
78 80
 
... ...
@@ -32,14 +32,20 @@ func Spans(sdl []*tracepb.ResourceSpans) []tracesdk.ReadOnlySpan {
32 32
 		}
33 33
 
34 34
 		for _, sdi := range sd.ScopeSpans {
35
-			sda := make([]tracesdk.ReadOnlySpan, len(sdi.Spans))
36
-			for i, s := range sdi.Spans {
37
-				sda[i] = &readOnlySpan{
35
+			if sdi == nil {
36
+				continue
37
+			}
38
+			sda := make([]tracesdk.ReadOnlySpan, 0, len(sdi.Spans))
39
+			for _, s := range sdi.Spans {
40
+				if s == nil {
41
+					continue
42
+				}
43
+				sda = append(sda, &readOnlySpan{
38 44
 					pb:        s,
39 45
 					is:        sdi.Scope,
40 46
 					resource:  sd.Resource,
41 47
 					schemaURL: sd.SchemaUrl,
42
-				}
48
+				})
43 49
 			}
44 50
 			out = append(out, sda...)
45 51
 		}
... ...
@@ -170,6 +176,9 @@ var _ tracesdk.ReadOnlySpan = &readOnlySpan{}
170 170
 
171 171
 // status transform a OTLP span status into span code.
172 172
 func statusCode(st *tracepb.Status) codes.Code {
173
+	if st == nil {
174
+		return codes.Unset
175
+	}
173 176
 	switch st.Code {
174 177
 	case tracepb.Status_STATUS_CODE_ERROR:
175 178
 		return codes.Error
... ...
@@ -186,6 +195,9 @@ func links(links []*tracepb.Span_Link) []tracesdk.Link {
186 186
 
187 187
 	sl := make([]tracesdk.Link, 0, len(links))
188 188
 	for _, otLink := range links {
189
+		if otLink == nil {
190
+			continue
191
+		}
189 192
 		// This redefinition is necessary to prevent otLink.*ID[:] copies
190 193
 		// being reused -- in short we need a new otLink per iteration.
191 194
 		otLink := otLink
... ...
@@ -226,6 +238,9 @@ func spanEvents(es []*tracepb.Span_Event) []tracesdk.Event {
226 226
 		if messageEvents >= maxMessageEventsPerSpan {
227 227
 			break
228 228
 		}
229
+		if e == nil {
230
+			continue
231
+		}
229 232
 		messageEvents++
230 233
 		events = append(events,
231 234
 			tracesdk.Event{
... ...
@@ -43,6 +43,6 @@ type Worker interface {
43 43
 }
44 44
 
45 45
 type Infos interface {
46
-	GetDefault() (Worker, error)
46
+	DefaultCacheManager() (cache.Manager, error)
47 47
 	WorkerInfos() []client.WorkerInfo
48 48
 }
... ...
@@ -3,6 +3,7 @@ package worker
3 3
 import (
4 4
 	"github.com/containerd/containerd/filters"
5 5
 	"github.com/hashicorp/go-multierror"
6
+	"github.com/moby/buildkit/cache"
6 7
 	"github.com/moby/buildkit/client"
7 8
 	"github.com/pkg/errors"
8 9
 )
... ...
@@ -81,3 +82,25 @@ func (c *Controller) WorkerInfos() []client.WorkerInfo {
81 81
 	}
82 82
 	return out
83 83
 }
84
+
85
+func (c *Controller) Infos() Infos {
86
+	return &infosController{c: c}
87
+}
88
+
89
+type infosController struct {
90
+	c *Controller
91
+}
92
+
93
+var _ Infos = &infosController{}
94
+
95
+func (c *infosController) DefaultCacheManager() (cache.Manager, error) {
96
+	w, err := c.c.GetDefault()
97
+	if err != nil {
98
+		return nil, err
99
+	}
100
+	return w.CacheManager(), nil
101
+}
102
+
103
+func (c *infosController) WorkerInfos() []client.WorkerInfo {
104
+	return c.c.WorkerInfos()
105
+}
... ...
@@ -682,7 +682,7 @@ github.com/mitchellh/hashstructure/v2
682 682
 # github.com/mitchellh/reflectwalk v1.0.2
683 683
 ## explicit
684 684
 github.com/mitchellh/reflectwalk
685
-# github.com/moby/buildkit v0.12.5-0.20231208203051-3b6880d2a00f
685
+# github.com/moby/buildkit v0.12.5
686 686
 ## explicit; go 1.20
687 687
 github.com/moby/buildkit/api/services/control
688 688
 github.com/moby/buildkit/api/types