Skip to content

Commit 14fa4f2

Browse files
authored
Merge pull request moby#3203 from AkihiroSuda/make-selinux-labels-opt-in
Make SELinux labels opt-in (`--oci-worker-selinux=<BOOL>`)
2 parents 397d513 + bd57e5f commit 14fa4f2

File tree

13 files changed

+63
-22
lines changed

13 files changed

+63
-22
lines changed

cmd/buildkitd/config/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ type OCIConfig struct {
8282
// The profile should already be loaded (by a higher level system) before creating a worker.
8383
ApparmorProfile string `toml:"apparmor-profile"`
8484

85+
// SELinux enables applying SELinux labels.
86+
SELinux bool `toml:"selinux"`
87+
8588
// MaxParallelism is the maximum number of parallel build steps that can be run at the same time.
8689
MaxParallelism int `toml:"max-parallelism"`
8790
}
@@ -100,6 +103,9 @@ type ContainerdConfig struct {
100103
// The profile should already be loaded (by a higher level system) before creating a worker.
101104
ApparmorProfile string `toml:"apparmor-profile"`
102105

106+
// SELinux enables applying SELinux labels.
107+
SELinux bool `toml:"selinux"`
108+
103109
MaxParallelism int `toml:"max-parallelism"`
104110

105111
Rootless bool `toml:"rootless"`

cmd/buildkitd/main_containerd_worker.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ func init() {
104104
Name: "containerd-worker-apparmor-profile",
105105
Usage: "set the name of the apparmor profile applied to containers",
106106
},
107+
cli.BoolFlag{
108+
Name: "containerd-worker-selinux",
109+
Usage: "apply SELinux labels",
110+
},
107111
}
108112
n := "containerd-worker-rootless"
109113
u := "enable rootless mode"
@@ -225,6 +229,9 @@ func applyContainerdFlags(c *cli.Context, cfg *config.Config) error {
225229
if c.GlobalIsSet("containerd-worker-apparmor-profile") {
226230
cfg.Workers.Containerd.ApparmorProfile = c.GlobalString("containerd-worker-apparmor-profile")
227231
}
232+
if c.GlobalIsSet("containerd-worker-selinux") {
233+
cfg.Workers.Containerd.SELinux = c.GlobalBool("containerd-worker-selinux")
234+
}
228235

229236
return nil
230237
}
@@ -268,7 +275,7 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([
268275
if cfg.Snapshotter != "" {
269276
snapshotter = cfg.Snapshotter
270277
}
271-
opt, err := containerd.NewWorkerOpt(common.config.Root, cfg.Address, snapshotter, cfg.Namespace, cfg.Rootless, cfg.Labels, dns, nc, common.config.Workers.Containerd.ApparmorProfile, parallelismSem, common.traceSocket, ctd.WithTimeout(60*time.Second))
278+
opt, err := containerd.NewWorkerOpt(common.config.Root, cfg.Address, snapshotter, cfg.Namespace, cfg.Rootless, cfg.Labels, dns, nc, common.config.Workers.Containerd.ApparmorProfile, common.config.Workers.Containerd.SELinux, parallelismSem, common.traceSocket, ctd.WithTimeout(60*time.Second))
272279
if err != nil {
273280
return nil, err
274281
}

cmd/buildkitd/main_oci_worker.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ func init() {
115115
Name: "oci-worker-apparmor-profile",
116116
Usage: "set the name of the apparmor profile applied to containers",
117117
},
118+
cli.BoolFlag{
119+
Name: "oci-worker-selinux",
120+
Usage: "apply SELinux labels",
121+
},
118122
}
119123
n := "oci-worker-rootless"
120124
u := "enable rootless mode"
@@ -240,6 +244,10 @@ func applyOCIFlags(c *cli.Context, cfg *config.Config) error {
240244
if c.GlobalIsSet("oci-worker-apparmor-profile") {
241245
cfg.Workers.OCI.ApparmorProfile = c.GlobalString("oci-worker-apparmor-profile")
242246
}
247+
if c.GlobalIsSet("oci-worker-selinux") {
248+
cfg.Workers.OCI.SELinux = c.GlobalBool("oci-worker-selinux")
249+
}
250+
243251
return nil
244252
}
245253

@@ -299,7 +307,7 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker
299307
parallelismSem = semaphore.NewWeighted(int64(cfg.MaxParallelism))
300308
}
301309

302-
opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping, nc, dns, cfg.Binary, cfg.ApparmorProfile, parallelismSem, common.traceSocket, cfg.DefaultCgroupParent)
310+
opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping, nc, dns, cfg.Binary, cfg.ApparmorProfile, cfg.SELinux, parallelismSem, common.traceSocket, cfg.DefaultCgroupParent)
303311
if err != nil {
304312
return nil, err
305313
}

executor/containerdexecutor/executor.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,13 @@ type containerdExecutor struct {
4040
running map[string]chan error
4141
mu sync.Mutex
4242
apparmorProfile string
43+
selinux bool
4344
traceSocket string
4445
rootless bool
4546
}
4647

4748
// New creates a new executor backed by connection to containerd API
48-
func New(client *containerd.Client, root, cgroup string, networkProviders map[pb.NetMode]network.Provider, dnsConfig *oci.DNSConfig, apparmorProfile string, traceSocket string, rootless bool) executor.Executor {
49+
func New(client *containerd.Client, root, cgroup string, networkProviders map[pb.NetMode]network.Provider, dnsConfig *oci.DNSConfig, apparmorProfile string, selinux bool, traceSocket string, rootless bool) executor.Executor {
4950
// clean up old hosts/resolv.conf file. ignore errors
5051
os.RemoveAll(filepath.Join(root, "hosts"))
5152
os.RemoveAll(filepath.Join(root, "resolv.conf"))
@@ -58,6 +59,7 @@ func New(client *containerd.Client, root, cgroup string, networkProviders map[pb
5859
dnsConfig: dnsConfig,
5960
running: make(map[string]chan error),
6061
apparmorProfile: apparmorProfile,
62+
selinux: selinux,
6163
traceSocket: traceSocket,
6264
rootless: rootless,
6365
}
@@ -162,7 +164,7 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M
162164
}
163165

164166
processMode := oci.ProcessSandbox // FIXME(AkihiroSuda)
165-
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, processMode, nil, w.apparmorProfile, w.traceSocket, opts...)
167+
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, processMode, nil, w.apparmorProfile, w.selinux, w.traceSocket, opts...)
166168
if err != nil {
167169
return err
168170
}

executor/oci/spec.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (pm ProcessMode) String() string {
5050

5151
// GenerateSpec generates spec using containerd functionality.
5252
// opts are ignored for s.Process, s.Hostname, and s.Mounts .
53-
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, cgroupParent string, processMode ProcessMode, idmap *idtools.IdentityMapping, apparmorProfile string, tracingSocket string, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
53+
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, cgroupParent string, processMode ProcessMode, idmap *idtools.IdentityMapping, apparmorProfile string, selinuxB bool, tracingSocket string, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
5454
c := &containers.Container{
5555
ID: id,
5656
}
@@ -81,7 +81,7 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
8181
return nil, nil, err
8282
}
8383

84-
if securityOpts, err := generateSecurityOpts(meta.SecurityMode, apparmorProfile); err == nil {
84+
if securityOpts, err := generateSecurityOpts(meta.SecurityMode, apparmorProfile, selinuxB); err == nil {
8585
opts = append(opts, securityOpts...)
8686
} else {
8787
return nil, nil, err

executor/oci/spec_unix.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import (
1616
"github.com/moby/buildkit/solver/pb"
1717
"github.com/moby/buildkit/util/entitlements/security"
1818
specs "github.com/opencontainers/runtime-spec/specs-go"
19+
selinux "github.com/opencontainers/selinux/go-selinux"
1920
"github.com/opencontainers/selinux/go-selinux/label"
21+
"github.com/pkg/errors"
2022
)
2123

2224
func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
@@ -30,7 +32,10 @@ func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
3032
}
3133

3234
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
33-
func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string) (opts []oci.SpecOpts, _ error) {
35+
func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string, selinuxB bool) (opts []oci.SpecOpts, _ error) {
36+
if selinuxB && !selinux.GetEnabled() {
37+
return nil, errors.New("selinux is not available")
38+
}
3439
switch mode {
3540
case pb.SecurityMode_INSECURE:
3641
return []oci.SpecOpts{
@@ -39,7 +44,9 @@ func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string) (opts []
3944
oci.WithWriteableSysfs,
4045
func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
4146
var err error
42-
s.Process.SelinuxLabel, s.Linux.MountLabel, err = label.InitLabels([]string{"disable"})
47+
if selinuxB {
48+
s.Process.SelinuxLabel, s.Linux.MountLabel, err = label.InitLabels([]string{"disable"})
49+
}
4350
return err
4451
},
4552
}, nil
@@ -52,7 +59,9 @@ func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string) (opts []
5259
}
5360
opts = append(opts, func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
5461
var err error
55-
s.Process.SelinuxLabel, s.Linux.MountLabel, err = label.InitLabels(nil)
62+
if selinuxB {
63+
s.Process.SelinuxLabel, s.Linux.MountLabel, err = label.InitLabels(nil)
64+
}
5665
return err
5766
})
5867
return opts, nil

executor/oci/spec_windows.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
1515
}
1616

1717
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
18-
func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string) ([]oci.SpecOpts, error) {
18+
func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string, selinuxB bool) ([]oci.SpecOpts, error) {
1919
if mode == pb.SecurityMode_INSECURE {
2020
return nil, errors.New("no support for running in insecure mode on Windows")
2121
}

executor/runcexecutor/executor.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ type Opt struct {
4848
DNS *oci.DNSConfig
4949
OOMScoreAdj *int
5050
ApparmorProfile string
51+
SELinux bool
5152
TracingSocket string
5253
}
5354

@@ -67,6 +68,7 @@ type runcExecutor struct {
6768
running map[string]chan error
6869
mu sync.Mutex
6970
apparmorProfile string
71+
selinux bool
7072
tracingSocket string
7173
}
7274

@@ -131,6 +133,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
131133
oomScoreAdj: opt.OOMScoreAdj,
132134
running: make(map[string]chan error),
133135
apparmorProfile: opt.ApparmorProfile,
136+
selinux: opt.SELinux,
134137
tracingSocket: opt.TracingSocket,
135138
}
136139
return w, nil
@@ -251,7 +254,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount,
251254
}
252255
}
253256

254-
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, w.processMode, w.idmap, w.apparmorProfile, w.tracingSocket, opts...)
257+
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.cgroupParent, w.processMode, w.idmap, w.apparmorProfile, w.selinux, w.tracingSocket, opts...)
255258
if err != nil {
256259
return err
257260
}

worker/containerd/containerd.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"os"
66
"path/filepath"
7+
"strconv"
78
"strings"
89

910
"github.com/containerd/containerd"
@@ -26,16 +27,16 @@ import (
2627
)
2728

2829
// NewWorkerOpt creates a WorkerOpt.
29-
func NewWorkerOpt(root string, address, snapshotterName, ns string, rootless bool, labels map[string]string, dns *oci.DNSConfig, nopt netproviders.Opt, apparmorProfile string, parallelismSem *semaphore.Weighted, traceSocket string, opts ...containerd.ClientOpt) (base.WorkerOpt, error) {
30+
func NewWorkerOpt(root string, address, snapshotterName, ns string, rootless bool, labels map[string]string, dns *oci.DNSConfig, nopt netproviders.Opt, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket string, opts ...containerd.ClientOpt) (base.WorkerOpt, error) {
3031
opts = append(opts, containerd.WithDefaultNamespace(ns))
3132
client, err := containerd.New(address, opts...)
3233
if err != nil {
3334
return base.WorkerOpt{}, errors.Wrapf(err, "failed to connect client to %q . make sure containerd is running", address)
3435
}
35-
return newContainerd(root, client, snapshotterName, ns, rootless, labels, dns, nopt, apparmorProfile, parallelismSem, traceSocket)
36+
return newContainerd(root, client, snapshotterName, ns, rootless, labels, dns, nopt, apparmorProfile, selinux, parallelismSem, traceSocket)
3637
}
3738

38-
func newContainerd(root string, client *containerd.Client, snapshotterName, ns string, rootless bool, labels map[string]string, dns *oci.DNSConfig, nopt netproviders.Opt, apparmorProfile string, parallelismSem *semaphore.Weighted, traceSocket string) (base.WorkerOpt, error) {
39+
func newContainerd(root string, client *containerd.Client, snapshotterName, ns string, rootless bool, labels map[string]string, dns *oci.DNSConfig, nopt netproviders.Opt, apparmorProfile string, selinux bool, parallelismSem *semaphore.Weighted, traceSocket string) (base.WorkerOpt, error) {
3940
if strings.Contains(snapshotterName, "/") {
4041
return base.WorkerOpt{}, errors.Errorf("bad snapshotter name: %q", snapshotterName)
4142
}
@@ -67,10 +68,11 @@ func newContainerd(root string, client *containerd.Client, snapshotterName, ns s
6768
hostname = "unknown"
6869
}
6970
xlabels := map[string]string{
70-
wlabel.Executor: "containerd",
71-
wlabel.Snapshotter: snapshotterName,
72-
wlabel.Hostname: hostname,
73-
wlabel.Network: npResolvedMode,
71+
wlabel.Executor: "containerd",
72+
wlabel.Snapshotter: snapshotterName,
73+
wlabel.Hostname: hostname,
74+
wlabel.Network: npResolvedMode,
75+
wlabel.SELinuxEnabled: strconv.FormatBool(selinux),
7476
}
7577
if apparmorProfile != "" {
7678
xlabels[wlabel.ApparmorProfile] = apparmorProfile
@@ -135,7 +137,7 @@ func newContainerd(root string, client *containerd.Client, snapshotterName, ns s
135137
Labels: xlabels,
136138
MetadataStore: md,
137139
NetworkProviders: np,
138-
Executor: containerdexecutor.New(client, root, "", np, dns, apparmorProfile, traceSocket, rootless),
140+
Executor: containerdexecutor.New(client, root, "", np, dns, apparmorProfile, selinux, traceSocket, rootless),
139141
Snapshotter: snap,
140142
ContentStore: cs,
141143
Applier: winlayers.NewFileSystemApplierWithWindows(cs, df),

worker/containerd/containerd_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestContainerdWorkerIntegration(t *testing.T) {
3030
func newWorkerOpt(t *testing.T, addr string) base.WorkerOpt {
3131
tmpdir := t.TempDir()
3232
rootless := false
33-
workerOpt, err := NewWorkerOpt(tmpdir, addr, "overlayfs", "buildkit-test", rootless, nil, nil, netproviders.Opt{Mode: "host"}, "", nil, "")
33+
workerOpt, err := NewWorkerOpt(tmpdir, addr, "overlayfs", "buildkit-test", rootless, nil, nil, netproviders.Opt{Mode: "host"}, "", false, nil, "")
3434
require.NoError(t, err)
3535
return workerOpt
3636
}

0 commit comments

Comments
 (0)