From be77b841fa605d5cbaf1dd7bc83eb198a236aa69 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Wed, 5 Oct 2016 09:29:30 -0400 Subject: [PATCH] Add SELinux support to OCID Signed-off-by: Dan Walsh --- Makefile | 3 ++- cmd/server/main.go | 8 ++++++ server/container.go | 36 ++++++++------------------ server/sandbox.go | 62 ++++++++++++++++++++++++++++++++++++--------- server/server.go | 19 ++++++++++---- 5 files changed, 84 insertions(+), 44 deletions(-) diff --git a/Makefile b/Makefile index 9a0bf31b..832aba4d 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ PREFIX ?= ${DESTDIR}/usr INSTALLDIR=${PREFIX}/bin GO_MD2MAN ?= $(shell which go-md2man) export GOPATH := ${CURDIR}/vendor +BUILDTAGS := selinux default: help @@ -38,7 +39,7 @@ pause: make -C $@ ocid: ${OCID_LINK} - go build -o ocid ./cmd/server/ + go build --tags "$(BUILDTAGS)" -o ocid ./cmd/server/ ocic: ${OCID_LINK} go build -o ocic ./cmd/client/ diff --git a/cmd/server/main.go b/cmd/server/main.go index d1f28aa1..5fcc0bb1 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -8,6 +8,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/kubernetes-incubator/cri-o/server" + "github.com/opencontainers/runc/libcontainer/selinux" "github.com/urfave/cli" "google.golang.org/grpc" "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" @@ -65,6 +66,10 @@ func main() { Name: "debug", Usage: "enable debug output for logging", }, + cli.BoolFlag{ + Name: "selinux-enabled", + Usage: "enable selinux support", + }, cli.StringFlag{ Name: "log", Value: "", @@ -81,6 +86,9 @@ func main() { if c.GlobalBool("debug") { logrus.SetLevel(logrus.DebugLevel) } + if !c.GlobalBool("selinux-enabled") { + selinux.SetDisabled() + } if path := c.GlobalString("log"); path != "" { f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0666) if err != nil { diff --git a/server/container.go b/server/container.go index de188654..f0d0973e 100644 --- a/server/container.go +++ b/server/container.go @@ -5,11 +5,13 @@ import ( "fmt" "os" "path/filepath" + "syscall" "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/stringid" "github.com/kubernetes-incubator/cri-o/oci" "github.com/kubernetes-incubator/cri-o/utils" + "github.com/opencontainers/runc/libcontainer/label" "github.com/opencontainers/runtime-tools/generate" "golang.org/x/net/context" pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" @@ -161,8 +163,12 @@ func (s *Server) createSandboxContainer(containerID string, containerName string options = "ro" } - //TODO(hmeng): how to use this info? Do we need to handle relabel a FS with Selinux? - //selinuxRelabel := mount.GetSelinuxRelabel() + if mount.GetSelinuxRelabel() { + // Need a way in kubernetes to determine if the volume is shared or private + if err := label.Relabel(src, sb.mountLabel, true); err != nil && err != syscall.ENOTSUP { + return nil, fmt.Errorf("relabel failed %s: %v", src, err) + } + } specgen.AddBindMount(src, dest, options) @@ -240,30 +246,8 @@ func (s *Server) createSandboxContainer(containerID string, containerName string } } - selinuxOptions := linux.GetSelinuxOptions() - if selinuxOptions != nil { - user := selinuxOptions.GetUser() - if user == "" { - return nil, fmt.Errorf("SELinuxOption.User is empty") - } - - role := selinuxOptions.GetRole() - if role == "" { - return nil, fmt.Errorf("SELinuxOption.Role is empty") - } - - t := selinuxOptions.GetType() - if t == "" { - return nil, fmt.Errorf("SELinuxOption.Type is empty") - } - - level := selinuxOptions.GetLevel() - if level == "" { - return nil, fmt.Errorf("SELinuxOption.Level is empty") - } - - specgen.SetProcessSelinuxLabel(fmt.Sprintf("%s:%s:%s:%s", user, role, t, level)) - } + specgen.SetProcessSelinuxLabel(sb.processLabel) + specgen.SetLinuxMountLabel(sb.mountLabel) user := linux.GetUser() if user != nil { diff --git a/server/sandbox.go b/server/sandbox.go index 579db4ef..fcaa411d 100644 --- a/server/sandbox.go +++ b/server/sandbox.go @@ -10,18 +10,21 @@ import ( "github.com/docker/docker/pkg/stringid" "github.com/kubernetes-incubator/cri-o/oci" "github.com/kubernetes-incubator/cri-o/utils" + "github.com/opencontainers/runc/libcontainer/label" "github.com/opencontainers/runtime-tools/generate" "golang.org/x/net/context" pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" ) type sandbox struct { - id string - name string - logDir string - labels map[string]string - annotations map[string]string - containers oci.Store + id string + name string + logDir string + labels map[string]string + annotations map[string]string + containers oci.Store + processLabel string + mountLabel string } const ( @@ -58,6 +61,7 @@ func (s *Server) generatePodIDandName(name string, namespace string, attempt uin // RunPodSandbox creates and runs a pod-level sandbox. func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest) (*pb.RunPodSandboxResponse, error) { + var processLabel, mountLabel string // process req.Name name := req.GetConfig().GetMetadata().GetName() if name == "" { @@ -140,6 +144,11 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest return nil, err } + processLabel, mountLabel, err = getSELinuxLabels(nil) + if err != nil { + return nil, err + } + containerID, containerName, err := s.generateContainerIDandName(name, "infra", 0) g.AddAnnotation("ocid/labels", string(labelsJSON)) g.AddAnnotation("ocid/annotations", string(annotationsJSON)) @@ -148,12 +157,14 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest g.AddAnnotation("ocid/container_name", containerName) g.AddAnnotation("ocid/container_id", containerID) s.addSandbox(&sandbox{ - id: id, - name: name, - logDir: logDir, - labels: labels, - annotations: annotations, - containers: oci.NewMemoryStore(), + id: id, + name: name, + logDir: logDir, + labels: labels, + annotations: annotations, + containers: oci.NewMemoryStore(), + processLabel: processLabel, + mountLabel: mountLabel, }) for k, v := range annotations { @@ -442,3 +453,30 @@ func (s *Server) ListPodSandbox(context.Context, *pb.ListPodSandboxRequest) (*pb Items: pods, }, nil } + +func getSELinuxLabels(selinuxOptions *pb.SELinuxOption) (processLabel string, mountLabel string, err error) { + processLabel = "" + if selinuxOptions != nil { + user := selinuxOptions.GetUser() + if user == "" { + return "", "", fmt.Errorf("SELinuxOption.User is empty") + } + + role := selinuxOptions.GetRole() + if role == "" { + return "", "", fmt.Errorf("SELinuxOption.Role is empty") + } + + t := selinuxOptions.GetType() + if t == "" { + return "", "", fmt.Errorf("SELinuxOption.Type is empty") + } + + level := selinuxOptions.GetLevel() + if level == "" { + return "", "", fmt.Errorf("SELinuxOption.Level is empty") + } + processLabel = fmt.Sprintf("%s:%s:%s:%s", user, role, t, level) + } + return label.InitLabels(label.DupSecOpt(processLabel)) +} diff --git a/server/server.go b/server/server.go index 4be9a23b..6cf9b6f6 100644 --- a/server/server.go +++ b/server/server.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/pkg/truncindex" "github.com/kubernetes-incubator/cri-o/oci" "github.com/kubernetes-incubator/cri-o/utils" + "github.com/opencontainers/runc/libcontainer/label" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/rajatchopra/ocicni" ) @@ -55,14 +56,22 @@ func (s *Server) loadSandbox(id string) error { if err != nil { return err } + + processLabel, mountLabel, err := label.InitLabels(label.DupSecOpt(m.Process.SelinuxLabel)) + if err != nil { + return err + } s.addSandbox(&sandbox{ - id: id, - name: name, - logDir: m.Annotations["ocid/log_path"], - labels: labels, - containers: oci.NewMemoryStore(), + id: id, + name: name, + logDir: m.Annotations["ocid/log_path"], + labels: labels, + containers: oci.NewMemoryStore(), + processLabel: processLabel, + mountLabel: mountLabel, }) sandboxPath := filepath.Join(s.sandboxDir, id) + scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], m.Annotations["ocid/container_name"], sandboxPath, sandboxPath, labels, id, false) if err != nil { return err