From 4d32fe99590dcc6e476aa8761f7f01cce94fe71b Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Mon, 24 Feb 2020 13:13:59 -0700 Subject: [PATCH 1/2] Support SELinux --- Dockerfile.dapper | 5 ++++- pkg/agent/containerd/containerd.go | 7 +++++++ pkg/agent/containerd/selinux.go | 27 +++++++++++++++++++++++++++ pkg/agent/templates/templates.go | 2 ++ scripts/build | 8 +++++++- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 pkg/agent/containerd/selinux.go diff --git a/Dockerfile.dapper b/Dockerfile.dapper index ae5d822705..ed23921724 100644 --- a/Dockerfile.dapper +++ b/Dockerfile.dapper @@ -3,7 +3,7 @@ FROM golang:1.13.8-alpine3.10 RUN apk -U --no-cache add bash git gcc musl-dev docker vim less file curl wget ca-certificates jq linux-headers zlib-dev tar zip squashfs-tools npm coreutils \ python2 python3 py3-pip python3-dev openssl-dev libffi-dev libseccomp libseccomp-dev make libuv-static RUN pip3 install 'tox==3.6.0' -RUN apk -U --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/main/ add sqlite-dev sqlite-static +RUN apk -U --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/main/ add sqlite-dev sqlite-static libselinux libselinux-dev RUN mkdir -p /go/src/golang.org/x && \ cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \ git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \ @@ -17,6 +17,9 @@ RUN if [ "${ARCH}" == "amd64" ]; then \ curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0; \ fi +ARG SELINUX=true +ENV SELINUX $SELINUX + ARG DQLITE=true ENV DQLITE $DQLITE COPY --from=rancher/dqlite-build:v1.3.1-r1 /dist/artifacts /usr/src/ diff --git a/pkg/agent/containerd/containerd.go b/pkg/agent/containerd/containerd.go index 9c71e88f0a..ceb58ac39a 100644 --- a/pkg/agent/containerd/containerd.go +++ b/pkg/agent/containerd/containerd.go @@ -15,6 +15,7 @@ import ( "github.com/containerd/containerd/namespaces" "github.com/natefinch/lumberjack" "github.com/opencontainers/runc/libcontainer/system" + "github.com/pkg/errors" "github.com/rancher/k3s/pkg/agent/templates" util2 "github.com/rancher/k3s/pkg/agent/util" "github.com/rancher/k3s/pkg/daemons/config" @@ -170,6 +171,12 @@ func setupContainerdConfig(ctx context.Context, cfg *config.Node) error { PrivateRegistryConfig: privRegistries, } + selinux, err := selinuxEnabled() + if err != nil { + return errors.Wrap(err, "failed to detect selinux") + } + containerdConfig.SELinuxEnabled = selinux + containerdTemplateBytes, err := ioutil.ReadFile(cfg.Containerd.Template) if err == nil { logrus.Infof("Using containerd template at %s", cfg.Containerd.Template) diff --git a/pkg/agent/containerd/selinux.go b/pkg/agent/containerd/selinux.go new file mode 100644 index 0000000000..2ad2eeb9a8 --- /dev/null +++ b/pkg/agent/containerd/selinux.go @@ -0,0 +1,27 @@ +package containerd + +import ( + "github.com/opencontainers/selinux/go-selinux" +) + +const ( + SELinuxContextType = "container_runtime_t" +) + +func selinuxEnabled() (bool, error) { + if !selinux.GetEnabled() { + return false, nil + } + + label, err := selinux.CurrentLabel() + if err != nil { + return false, err + } + + ctx, err := selinux.NewContext(label) + if err != nil { + return false, err + } + + return ctx["type"] == SELinuxContextType, nil +} diff --git a/pkg/agent/templates/templates.go b/pkg/agent/templates/templates.go index a1d8940535..c340eea7ef 100644 --- a/pkg/agent/templates/templates.go +++ b/pkg/agent/templates/templates.go @@ -10,6 +10,7 @@ import ( type ContainerdConfig struct { NodeConfig *config.Node IsRunningInUserNS bool + SELinuxEnabled bool PrivateRegistryConfig *Registry } @@ -20,6 +21,7 @@ const ContainerdConfigTemplate = ` [plugins.cri] stream_server_address = "127.0.0.1" stream_server_port = "10010" + enable_selinux = {{ .SELinuxEnabled }} {{- if .IsRunningInUserNS }} disable_cgroup = true diff --git a/scripts/build b/scripts/build index 72d3c07ece..0c6d7305dd 100755 --- a/scripts/build +++ b/scripts/build @@ -46,6 +46,12 @@ STATIC_SQLITE=" -extldflags '-static -lm -ldl -lz -lpthread $DQLITE_STATIC_SQLITE' " TAGS="ctrd apparmor seccomp no_btrfs netcgo osusergo providerless $DQLITE_TAGS" +RUNC_TAGS="apparmor seccomp" + +if [ "$SELINUX" = "true" ]; then + TAGS="$TAGS selinux" + RUNC_TAGS="$RUNC_TAGS selinux" +fi if [ "$STATIC_BUILD" != "true" ]; then STATIC=" @@ -109,7 +115,7 @@ ln -s containerd ./bin/ctr # echo Building containerd # CGO_ENABLED=0 go build -tags "$TAGS" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/containerd ./cmd/containerd/ echo Building runc -make EXTRA_LDFLAGS="-w -s" BUILDTAGS="apparmor seccomp" -C ./vendor/github.com/opencontainers/runc static +make EXTRA_LDFLAGS="-w -s" BUILDTAGS="$RUNC_TAGS" -C ./vendor/github.com/opencontainers/runc static cp -f ./vendor/github.com/opencontainers/runc/runc ./bin/runc echo Building containerd-shim From 124def22ed66b618afccceb8df365cff627bd910 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Mon, 24 Feb 2020 13:16:56 -0700 Subject: [PATCH 2/2] Update vendor --- go.mod | 6 +- go.sum | 8 +- .../containerd/containerd/container.go | 11 +++ .../cri/pkg/server/container_create.go | 35 +++++++- .../containerd/cri/pkg/server/helpers.go | 60 +++++++------ .../containerd/cri/pkg/server/sandbox_run.go | 23 ++++- .../containerd/cri/pkg/server/service.go | 6 +- .../cri/pkg/store/container/container.go | 9 +- .../cri/pkg/store/container/metadata.go | 2 + .../containerd/cri/pkg/store/label/label.go | 90 +++++++++++++++++++ .../cri/pkg/store/sandbox/metadata.go | 2 + .../cri/pkg/store/sandbox/sandbox.go | 9 +- vendor/modules.txt | 5 +- 13 files changed, 221 insertions(+), 45 deletions(-) create mode 100644 vendor/github.com/containerd/cri/pkg/store/label/label.go diff --git a/go.mod b/go.mod index 8de0a27e18..1226a61368 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ replace ( github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83 github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 - github.com/containerd/containerd => github.com/rancher/containerd v1.3.3-k3s1 + github.com/containerd/containerd => github.com/rancher/containerd v1.3.3-k3s2 github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02 - github.com/containerd/cri => github.com/rancher/cri v1.3.0-k3s.3 + github.com/containerd/cri => github.com/rancher/cri v1.3.0-k3s.4 github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c github.com/containerd/go-runc => github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda github.com/containerd/typeurl => github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd @@ -94,6 +94,7 @@ require ( github.com/mattn/go-sqlite3 v1.13.0 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/opencontainers/runc v1.0.0-rc9 + github.com/opencontainers/selinux v1.3.1-0.20190929122143-5215b1806f52 github.com/pkg/errors v0.8.1 github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 // indirect github.com/rancher/dynamiclistener v0.2.0 @@ -122,6 +123,5 @@ require ( k8s.io/component-base v0.0.0 k8s.io/cri-api v0.0.0 k8s.io/klog v1.0.0 - k8s.io/kubelet v0.0.0 k8s.io/kubernetes v1.16.0 ) diff --git a/go.sum b/go.sum index 90ad9eebb9..edeb27d802 100644 --- a/go.sum +++ b/go.sum @@ -708,10 +708,10 @@ github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1: github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 h1:83l9gPhYtgxODlZKU0Odq4pQuDcMZEVgAh364+PV3OU= github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8/go.mod h1:4XHkfaUj+URzGO9sohoAgt2V9Y8nIW7fugpu0E6gShk= -github.com/rancher/containerd v1.3.3-k3s1 h1:j8NGZdXKsZd2ne0XQg6OBfMJ/NkY/Qri6QhscGrJp2M= -github.com/rancher/containerd v1.3.3-k3s1/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM= -github.com/rancher/cri v1.3.0-k3s.3 h1:j/Sq2LMyg6gBn2MS1j5dEudpdL+UYVH7ubbewUCXkS0= -github.com/rancher/cri v1.3.0-k3s.3/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY= +github.com/rancher/containerd v1.3.3-k3s2 h1:RZr+TqFt7+YsrSYkyytlhW4HmneWeFNM7IymNOoGW6A= +github.com/rancher/containerd v1.3.3-k3s2/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM= +github.com/rancher/cri v1.3.0-k3s.4 h1:BXER8109dxgNw4qq8HHOCJ+3sHO+9AA1cwZTOLlqoTo= +github.com/rancher/cri v1.3.0-k3s.4/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY= github.com/rancher/cri-tools v1.17.0-k3s1 h1:jfu97FowbraTDc7b6fxWtO+dq+DU2oW+ABBQSEFiRb0= github.com/rancher/cri-tools v1.17.0-k3s1/go.mod h1:bRTZttsvk+nCG8tSFs8D6UUx8CkMXR5TAsRLS0fXAqI= github.com/rancher/dynamiclistener v0.2.0 h1:KucYwJXVVGhZ/NndfMCeQoCafT/VN7kvqSGgmlX8Lxk= diff --git a/vendor/github.com/containerd/containerd/container.go b/vendor/github.com/containerd/containerd/container.go index fd880d0e0a..187934eadd 100644 --- a/vendor/github.com/containerd/containerd/container.go +++ b/vendor/github.com/containerd/containerd/container.go @@ -36,6 +36,7 @@ import ( prototypes "github.com/gogo/protobuf/types" ver "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" ) @@ -242,7 +243,17 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N if err != nil { return nil, err } + spec, err := c.Spec(ctx) + if err != nil { + return nil, err + } for _, m := range mounts { + if spec.Linux != nil && spec.Linux.MountLabel != "" { + context := label.FormatMountLabel("", spec.Linux.MountLabel) + if context != "" { + m.Options = append(m.Options, context) + } + } request.Rootfs = append(request.Rootfs, &types.Mount{ Type: m.Type, Source: m.Source, diff --git a/vendor/github.com/containerd/cri/pkg/server/container_create.go b/vendor/github.com/containerd/cri/pkg/server/container_create.go index d35fff30cb..cf6a6acd6a 100644 --- a/vendor/github.com/containerd/cri/pkg/server/container_create.go +++ b/vendor/github.com/containerd/cri/pkg/server/container_create.go @@ -39,6 +39,7 @@ import ( "github.com/davecgh/go-spew/spew" imagespec "github.com/opencontainers/image-spec/specs-go/v1" runtimespec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "golang.org/x/net/context" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -173,6 +174,18 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta return nil, errors.Wrapf(err, "failed to generate container %q spec", id) } + meta.ProcessLabel = spec.Process.SelinuxLabel + if config.GetLinux().GetSecurityContext().GetPrivileged() { + // If privileged don't set the SELinux label but still record it on the container so + // the unused MCS label can be release later + spec.Process.SelinuxLabel = "" + } + defer func() { + if retErr != nil { + _ = label.ReleaseLabel(spec.Process.SelinuxLabel) + } + }() + log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec)) // Set snapshotter before any other options. @@ -324,7 +337,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig, sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount, - ociRuntime config.Runtime) (*runtimespec.Spec, error) { + ociRuntime config.Runtime) (retSpec *runtimespec.Spec, retErr error) { specOpts := []oci.SpecOpts{ customopts.WithoutRunMount, @@ -366,11 +379,27 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP specOpts = append(specOpts, oci.WithEnv(env)) securityContext := config.GetLinux().GetSecurityContext() - selinuxOpt := securityContext.GetSelinuxOptions() - processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt) + labelOptions := toLabel(securityContext.GetSelinuxOptions()) + if len(labelOptions) == 0 { + // Use pod level SELinux config + if sandbox, err := c.sandboxStore.Get(sandboxID); err == nil { + labelOptions, err = label.DupSecOpt(sandbox.ProcessLabel) + if err != nil { + return nil, err + } + } + } + + processLabel, mountLabel, err := label.InitLabels(labelOptions) if err != nil { return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions()) } + defer func() { + if retErr != nil { + _ = label.ReleaseLabel(processLabel) + } + }() + specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel)) if !c.config.DisableProcMount { diff --git a/vendor/github.com/containerd/cri/pkg/server/helpers.go b/vendor/github.com/containerd/cri/pkg/server/helpers.go index 1d15657047..4ec03ca33c 100644 --- a/vendor/github.com/containerd/cri/pkg/server/helpers.go +++ b/vendor/github.com/containerd/cri/pkg/server/helpers.go @@ -298,47 +298,55 @@ func (c *criService) ensureImageExists(ctx context.Context, ref string, config * return &newImage, nil } -func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) { - if selinuxOpt == nil { - return "", "", nil +func toLabel(selinuxOptions *runtime.SELinuxOption) (labels []string) { + if selinuxOptions == nil { + return nil } - // Should ignored selinuxOpts if they are incomplete. - if selinuxOpt.GetUser() == "" || - selinuxOpt.GetRole() == "" || - selinuxOpt.GetType() == "" { - return "", "", nil + if selinuxOptions.User != "" { + labels = append(labels, "user:"+selinuxOptions.User) + } + if selinuxOptions.Role != "" { + labels = append(labels, "role:"+selinuxOptions.Role) + } + if selinuxOptions.Type != "" { + labels = append(labels, "type:"+selinuxOptions.Type) + } + if selinuxOptions.Level != "" { + labels = append(labels, "level:"+selinuxOptions.Level) } - // make sure the format of "level" is correct. - ok, err := checkSelinuxLevel(selinuxOpt.GetLevel()) - if err != nil || !ok { - return "", "", err - } + return +} - labelOpts := fmt.Sprintf("%s:%s:%s:%s", - selinuxOpt.GetUser(), - selinuxOpt.GetRole(), - selinuxOpt.GetType(), - selinuxOpt.GetLevel()) +func initLabelsFromOpt(selinuxOpts *runtime.SELinuxOption) (string, string, error) { + return initLabels(toLabel(selinuxOpts)) +} - options, err := label.DupSecOpt(labelOpts) - if err != nil { - return "", "", err +func initLabels(options []string) (string, string, error) { + for _, opt := range options { + if strings.HasPrefix(opt, "level:") { + if err := checkSelinuxLevel(strings.TrimPrefix(opt, "level:")); err != nil { + return "", "", err + } + } } return label.InitLabels(options) } -func checkSelinuxLevel(level string) (bool, error) { +func checkSelinuxLevel(level string) error { if len(level) == 0 { - return true, nil + return nil } matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}((.c\d{1,4})?,c\d{1,4})*(.c\d{1,4})?(,c\d{1,4}(.c\d{1,4})?)*)?$`, level) - if err != nil || !matched { - return false, errors.Wrapf(err, "the format of 'level' %q is not correct", level) + if err != nil { + return errors.Wrapf(err, "the format of 'level' %q is not correct", level) } - return true, nil + if !matched { + return fmt.Errorf("the format of 'level' %q is not correct", level) + } + return nil } // isInCRIMounts checks whether a destination is in CRI mount list. diff --git a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go index 9d64819afa..24cdf5f03a 100644 --- a/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go +++ b/vendor/github.com/containerd/cri/pkg/server/sandbox_run.go @@ -34,6 +34,7 @@ import ( "github.com/davecgh/go-spew/spew" imagespec "github.com/opencontainers/image-spec/specs-go/v1" runtimespec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/net/context" @@ -158,6 +159,18 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox return nil, errors.Wrap(err, "failed to generate sandbox container spec") } log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec)) + sandbox.ProcessLabel = spec.Process.SelinuxLabel + defer func() { + if retErr != nil { + _ = label.ReleaseLabel(sandbox.ProcessLabel) + } + }() + + if securityContext.GetPrivileged() { + // If privileged don't set selinux label, but we still record the MCS label so that + // the unused label can be freed later. + spec.Process.SelinuxLabel = "" + } var specOpts []oci.SpecOpts userstr, err := generateUserString( @@ -328,7 +341,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox } func (c *criService) generateSandboxContainerSpec(id string, config *runtime.PodSandboxConfig, - imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) { + imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (retSpec *runtimespec.Spec, retErr error) { // Creates a spec Generator with the default spec. // TODO(random-liu): [P1] Compare the default settings with docker and containerd default. specOpts := []oci.SpecOpts{ @@ -403,11 +416,15 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod }, })) - selinuxOpt := securityContext.GetSelinuxOptions() - processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt) + processLabel, mountLabel, err := initLabelsFromOpt(securityContext.GetSelinuxOptions()) if err != nil { return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions()) } + defer func() { + if retErr != nil && processLabel != "" { + _ = label.ReleaseLabel(processLabel) + } + }() supplementalGroups := securityContext.GetSupplementalGroups() specOpts = append(specOpts, diff --git a/vendor/github.com/containerd/cri/pkg/server/service.go b/vendor/github.com/containerd/cri/pkg/server/service.go index 87b2b3ea21..5b4d826a08 100644 --- a/vendor/github.com/containerd/cri/pkg/server/service.go +++ b/vendor/github.com/containerd/cri/pkg/server/service.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/plugin" + "github.com/containerd/cri/pkg/store/label" cni "github.com/containerd/go-cni" runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor" runcseccomp "github.com/opencontainers/runc/libcontainer/seccomp" @@ -104,14 +105,15 @@ type criService struct { // NewCRIService returns a new instance of CRIService func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIService, error) { var err error + labels := label.NewStore() c := &criService{ config: config, client: client, apparmorEnabled: runcapparmor.IsEnabled() && !config.DisableApparmor, seccompEnabled: runcseccomp.IsEnabled(), os: osinterface.RealOS{}, - sandboxStore: sandboxstore.NewStore(), - containerStore: containerstore.NewStore(), + sandboxStore: sandboxstore.NewStore(labels), + containerStore: containerstore.NewStore(labels), imageStore: imagestore.NewStore(client), snapshotStore: snapshotstore.NewStore(), sandboxNameIndex: registrar.NewRegistrar(), diff --git a/vendor/github.com/containerd/cri/pkg/store/container/container.go b/vendor/github.com/containerd/cri/pkg/store/container/container.go index 444eb33b21..544678f893 100644 --- a/vendor/github.com/containerd/cri/pkg/store/container/container.go +++ b/vendor/github.com/containerd/cri/pkg/store/container/container.go @@ -20,6 +20,7 @@ import ( "sync" "github.com/containerd/containerd" + "github.com/containerd/cri/pkg/store/label" "github.com/docker/docker/pkg/truncindex" runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2" @@ -101,13 +102,15 @@ type Store struct { lock sync.RWMutex containers map[string]Container idIndex *truncindex.TruncIndex + labels *label.Store } // NewStore creates a container store. -func NewStore() *Store { +func NewStore(labels *label.Store) *Store { return &Store{ containers: make(map[string]Container), idIndex: truncindex.NewTruncIndex([]string{}), + labels: labels, } } @@ -119,6 +122,9 @@ func (s *Store) Add(c Container) error { if _, ok := s.containers[c.ID]; ok { return store.ErrAlreadyExist } + if err := s.labels.Reserve(c.ProcessLabel); err != nil { + return err + } if err := s.idIndex.Add(c.ID); err != nil { return err } @@ -165,6 +171,7 @@ func (s *Store) Delete(id string) { // So we need to return if there are error. return } + s.labels.Release(s.containers[id].ProcessLabel) s.idIndex.Delete(id) // nolint: errcheck delete(s.containers, id) } diff --git a/vendor/github.com/containerd/cri/pkg/store/container/metadata.go b/vendor/github.com/containerd/cri/pkg/store/container/metadata.go index 73d64a8f57..d0747e43ee 100644 --- a/vendor/github.com/containerd/cri/pkg/store/container/metadata.go +++ b/vendor/github.com/containerd/cri/pkg/store/container/metadata.go @@ -61,6 +61,8 @@ type Metadata struct { // StopSignal is the system call signal that will be sent to the container to exit. // TODO(random-liu): Add integration test for stop signal. StopSignal string + // ProcessLabel is the SELinux process label for the container + ProcessLabel string } // MarshalJSON encodes Metadata into bytes in json format. diff --git a/vendor/github.com/containerd/cri/pkg/store/label/label.go b/vendor/github.com/containerd/cri/pkg/store/label/label.go new file mode 100644 index 0000000000..7689cf5c18 --- /dev/null +++ b/vendor/github.com/containerd/cri/pkg/store/label/label.go @@ -0,0 +1,90 @@ +/* +Copyright 2017 The Kubernetes 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 label + +import ( + "sync" + + "github.com/opencontainers/selinux/go-selinux" +) + +type Store struct { + sync.Mutex + levels map[string]int + Releaser func(string) + Reserver func(string) +} + +func NewStore() *Store { + return &Store{ + levels: map[string]int{}, + Releaser: selinux.ReleaseLabel, + Reserver: selinux.ReserveLabel, + } +} + +func (s *Store) Reserve(label string) error { + s.Lock() + defer s.Unlock() + + context, err := selinux.NewContext(label) + if err != nil { + return err + } + + level := context["level"] + // no reason to count empty + if level == "" { + return nil + } + + if _, ok := s.levels[level]; !ok { + s.Reserver(label) + } + + s.levels[level]++ + return nil +} + +func (s *Store) Release(label string) { + s.Lock() + defer s.Unlock() + + context, err := selinux.NewContext(label) + if err != nil { + return + } + + level := context["level"] + if level == "" { + return + } + + count, ok := s.levels[level] + if !ok { + return + } + switch { + case count == 1: + s.Releaser(label) + delete(s.levels, level) + case count < 1: + delete(s.levels, level) + case count > 1: + s.levels[level] = count - 1 + } +} diff --git a/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go b/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go index 68f5fd881d..3d15d4658d 100644 --- a/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go +++ b/vendor/github.com/containerd/cri/pkg/store/sandbox/metadata.go @@ -61,6 +61,8 @@ type Metadata struct { RuntimeHandler string // CNIresult resulting configuration for attached network namespace interfaces CNIResult *cni.CNIResult + // ProcessLabel is the SELinux process label for the container + ProcessLabel string } // MarshalJSON encodes Metadata into bytes in json format. diff --git a/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go b/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go index 2fc01c5b35..03a71cbc36 100644 --- a/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go +++ b/vendor/github.com/containerd/cri/pkg/store/sandbox/sandbox.go @@ -20,6 +20,7 @@ import ( "sync" "github.com/containerd/containerd" + "github.com/containerd/cri/pkg/store/label" "github.com/docker/docker/pkg/truncindex" "github.com/containerd/cri/pkg/netns" @@ -62,13 +63,15 @@ type Store struct { lock sync.RWMutex sandboxes map[string]Sandbox idIndex *truncindex.TruncIndex + labels *label.Store } // NewStore creates a sandbox store. -func NewStore() *Store { +func NewStore(labels *label.Store) *Store { return &Store{ sandboxes: make(map[string]Sandbox), idIndex: truncindex.NewTruncIndex([]string{}), + labels: labels, } } @@ -79,6 +82,9 @@ func (s *Store) Add(sb Sandbox) error { if _, ok := s.sandboxes[sb.ID]; ok { return store.ErrAlreadyExist } + if err := s.labels.Reserve(sb.ProcessLabel); err != nil { + return err + } if err := s.idIndex.Add(sb.ID); err != nil { return err } @@ -125,6 +131,7 @@ func (s *Store) Delete(id string) { // So we need to return if there are error. return } + s.labels.Release(s.sandboxes[id].ProcessLabel) s.idIndex.Delete(id) // nolint: errcheck delete(s.sandboxes, id) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 816fc79156..b278ab60c7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -151,7 +151,7 @@ github.com/container-storage-interface/spec/lib/go/csi github.com/containerd/cgroups # github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 github.com/containerd/console -# github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69 => github.com/rancher/containerd v1.3.3-k3s1 +# github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69 => github.com/rancher/containerd v1.3.3-k3s2 github.com/containerd/containerd github.com/containerd/containerd/api/events github.com/containerd/containerd/api/services/containers/v1 @@ -288,7 +288,7 @@ github.com/containerd/continuity/pathdriver github.com/containerd/continuity/proto github.com/containerd/continuity/syscallx github.com/containerd/continuity/sysx -# github.com/containerd/cri v0.0.0-00010101000000-000000000000 => github.com/rancher/cri v1.3.0-k3s.3 +# github.com/containerd/cri v0.0.0-00010101000000-000000000000 => github.com/rancher/cri v1.3.0-k3s.4 github.com/containerd/cri github.com/containerd/cri/pkg/annotations github.com/containerd/cri/pkg/api/runtimeoptions/v1 @@ -306,6 +306,7 @@ github.com/containerd/cri/pkg/server/io github.com/containerd/cri/pkg/store github.com/containerd/cri/pkg/store/container github.com/containerd/cri/pkg/store/image +github.com/containerd/cri/pkg/store/label github.com/containerd/cri/pkg/store/sandbox github.com/containerd/cri/pkg/store/snapshot github.com/containerd/cri/pkg/util