From d715d009061edf5ed0da5aa81fe7b6d2a6b3c10c Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Wed, 26 Aug 2020 19:18:06 -0400 Subject: [PATCH] Handle KVM based runtimes with selinux Signed-off-by: Michael Crosby --- pkg/server/container_create.go | 6 +++ pkg/server/helpers_unix.go | 34 ++++++++++++++++ pkg/server/helpers_windows.go | 6 +++ pkg/server/sandbox_run.go | 5 +++ pkg/seutil/seutil.go | 71 ++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+) create mode 100644 pkg/seutil/seutil.go diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index 12c068518..01eac7bc8 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -161,6 +161,12 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta } meta.ProcessLabel = spec.Process.SelinuxLabel + + // handle any KVM based runtime + if err := modifyProcessLabel(ociRuntime.Type, spec); err != nil { + return nil, err + } + 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 diff --git a/pkg/server/helpers_unix.go b/pkg/server/helpers_unix.go index b96af1c5a..0c3a6652d 100644 --- a/pkg/server/helpers_unix.go +++ b/pkg/server/helpers_unix.go @@ -33,7 +33,9 @@ import ( "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" "github.com/containerd/cri/pkg/seccomp" + "github.com/containerd/cri/pkg/seutil" runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor" + "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "golang.org/x/sys/unix" @@ -256,3 +258,35 @@ func ensureRemoveAll(ctx context.Context, dir string) error { time.Sleep(100 * time.Millisecond) } } + +var vmbasedRuntimes = []string{ + "io.containerd.kata", +} + +func isVMBasedRuntime(runtimeType string) bool { + for _, rt := range vmbasedRuntimes { + if strings.Contains(runtimeType, rt) { + return true + } + } + return false +} + +func modifyProcessLabel(runtimeType string, spec *specs.Spec) error { + if !isVMBasedRuntime(runtimeType) { + return nil + } + l, err := getKVMLabel(spec.Process.SelinuxLabel) + if err != nil { + return errors.Wrap(err, "failed to get selinux kvm label") + } + spec.Process.SelinuxLabel = l + return nil +} + +func getKVMLabel(l string) (string, error) { + if !seutil.HasType("container_kvm_t") { + return "", nil + } + return seutil.ChangeToKVM(l) +} diff --git a/pkg/server/helpers_windows.go b/pkg/server/helpers_windows.go index df5aa6d59..5ce7104da 100644 --- a/pkg/server/helpers_windows.go +++ b/pkg/server/helpers_windows.go @@ -24,6 +24,8 @@ import ( "path/filepath" "syscall" "time" + + "github.com/opencontainers/runtime-spec/specs-go" ) // openLogFile opens/creates a container log file. @@ -217,3 +219,7 @@ func ensureRemoveAll(_ context.Context, dir string) error { time.Sleep(100 * time.Millisecond) } } + +func modifyProcessLabel(runtimeType string, spec *specs.Spec) error { + return nil +} diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index e4b46e26b..e0b207d7a 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -167,6 +167,11 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox } }() + // handle any KVM based runtime + if err := modifyProcessLabel(ociRuntime.Type, spec); err != nil { + return nil, err + } + if config.GetLinux().GetSecurityContext().GetPrivileged() { // If privileged don't set selinux label, but we still record the MCS label so that // the unused label can be freed later. diff --git a/pkg/seutil/seutil.go b/pkg/seutil/seutil.go new file mode 100644 index 000000000..f453a7775 --- /dev/null +++ b/pkg/seutil/seutil.go @@ -0,0 +1,71 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package seutil + +import ( + "bufio" + "os" + + "github.com/opencontainers/selinux/go-selinux" +) + +var seTypes map[string]struct{} + +const typePath = "/etc/selinux/targeted/contexts/customizable_types" + +func init() { + seTypes = make(map[string]struct{}) + if !selinux.GetEnabled() { + return + } + f, err := os.Open(typePath) + if err != nil { + return + } + defer f.Close() + s := bufio.NewScanner(f) + for s.Scan() { + seTypes[s.Text()] = struct{}{} + } +} + +// HasType returns true if the underlying system has the +// provided selinux type enabled. +func HasType(name string) bool { + _, ok := seTypes[name] + return ok +} + +// ChangeToKVM process label +func ChangeToKVM(l string) (string, error) { + if l == "" || !selinux.GetEnabled() { + return "", nil + } + proc, _ := selinux.KVMContainerLabels() + selinux.ReleaseLabel(proc) + + current, err := selinux.NewContext(l) + if err != nil { + return "", err + } + next, err := selinux.NewContext(proc) + if err != nil { + return "", err + } + current["type"] = next["type"] + return current.Get(), nil +}