Handle KVM based runtimes with selinux

Signed-off-by: Michael Crosby <michael@thepasture.io>
This commit is contained in:
Michael Crosby 2020-08-26 19:18:06 -04:00
parent 56a89cda34
commit d715d00906
5 changed files with 122 additions and 0 deletions

View File

@ -161,6 +161,12 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
} }
meta.ProcessLabel = spec.Process.SelinuxLabel 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 config.GetLinux().GetSecurityContext().GetPrivileged() {
// If privileged don't set the SELinux label but still record it on the container so // If privileged don't set the SELinux label but still record it on the container so
// the unused MCS label can be release later // the unused MCS label can be release later

View File

@ -33,7 +33,9 @@ import (
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/cri/pkg/seccomp" "github.com/containerd/cri/pkg/seccomp"
"github.com/containerd/cri/pkg/seutil"
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor" runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label" "github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
@ -256,3 +258,35 @@ func ensureRemoveAll(ctx context.Context, dir string) error {
time.Sleep(100 * time.Millisecond) 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)
}

View File

@ -24,6 +24,8 @@ import (
"path/filepath" "path/filepath"
"syscall" "syscall"
"time" "time"
"github.com/opencontainers/runtime-spec/specs-go"
) )
// openLogFile opens/creates a container log file. // openLogFile opens/creates a container log file.
@ -217,3 +219,7 @@ func ensureRemoveAll(_ context.Context, dir string) error {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
} }
func modifyProcessLabel(runtimeType string, spec *specs.Spec) error {
return nil
}

View File

@ -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 config.GetLinux().GetSecurityContext().GetPrivileged() {
// If privileged don't set selinux label, but we still record the MCS label so that // If privileged don't set selinux label, but we still record the MCS label so that
// the unused label can be freed later. // the unused label can be freed later.

71
pkg/seutil/seutil.go Normal file
View File

@ -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
}