Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/cri-containerd/cri_containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"os"

"github.com/golang/glog"
"github.com/opencontainers/selinux/go-selinux"
"github.com/spf13/pflag"

"github.com/kubernetes-incubator/cri-containerd/cmd/cri-containerd/options"
Expand All @@ -37,6 +38,10 @@ func main() {
os.Exit(0)
}

if !o.EnableSelinux {
selinux.SetDisabled()
}

glog.V(2).Infof("Run cri-containerd grpc server on socket %q", o.SocketPath)
service, err := server.NewCRIContainerdService(
o.ContainerdEndpoint,
Expand Down
4 changes: 4 additions & 0 deletions cmd/cri-containerd/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type CRIContainerdOptions struct {
StreamServerPort string
// CgroupPath is the path for the cgroup that cri-containerd is placed in.
CgroupPath string
// EnableSelinux indicates to enable the selinux support
EnableSelinux bool
}

// NewCRIContainerdOptions returns a reference to CRIContainerdOptions
Expand Down Expand Up @@ -74,6 +76,8 @@ func (c *CRIContainerdOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&c.StreamServerPort, "stream-port",
"10010", "The port streaming server is listening on.")
fs.StringVar(&c.CgroupPath, "cgroup-path", "", "The cgroup that cri-containerd is part of. By default cri-containerd is not placed in a cgroup")
fs.BoolVar(&c.EnableSelinux, "selinux-enabled",
false, "Enable selinux support.")
}

// InitFlags must be called after adding all cli options flags are defined and
Expand Down
26 changes: 23 additions & 3 deletions pkg/server/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import (
"github.com/opencontainers/runc/libcontainer/devices"
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"golang.org/x/net/context"
"golang.org/x/sys/unix"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"

cio "github.com/kubernetes-incubator/cri-containerd/pkg/server/io"
Expand Down Expand Up @@ -234,9 +236,17 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
}

securityContext := config.GetLinux().GetSecurityContext()
selinuxOpt := securityContext.GetSelinuxOptions()
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
if err != nil {
return nil, fmt.Errorf("failed to init selinux options %+v: %v", securityContext.GetSelinuxOptions(), err)
}

// Add extra mounts first so that CRI specified mounts can override.
addOCIBindMounts(&g, append(extraMounts, config.GetMounts()...))
mounts := append(extraMounts, config.GetMounts()...)
if err := addOCIBindMounts(&g, mounts, mountLabel); err != nil {
return nil, fmt.Errorf("failed to set OCI bind mounts %+v: %v", mounts, err)
}

if securityContext.GetPrivileged() {
if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() {
Expand All @@ -259,6 +269,9 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3

}

g.SetProcessSelinuxLabel(processLabel)
g.SetLinuxMountLabel(mountLabel)

// TODO: Figure out whether we should set no new privilege for sandbox container by default
g.SetProcessNoNewPrivileges(securityContext.GetNoNewPrivs())

Expand Down Expand Up @@ -435,7 +448,7 @@ func setOCIDevicesPrivileged(g *generate.Generator) error {
// addOCIBindMounts adds bind mounts.
// TODO(random-liu): Figure out whether we need to change all CRI mounts to readonly when
// rootfs is readonly. (https://github.com/moby/moby/blob/master/daemon/oci_linux.go)
func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount) {
func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount, mountLabel string) error {
// Mount cgroup into the container as readonly, which inherits docker's behavior.
g.AddCgroupsMount("ro") // nolint: errcheck
for _, mount := range mounts {
Expand All @@ -447,9 +460,16 @@ func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount) {
} else {
options = append(options, "rw")
}
// TODO(random-liu): [P1] Apply selinux label

if mount.GetSelinuxRelabel() {
if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP {
return fmt.Errorf("relabel %q with %q failed: %v", src, mountLabel, err)
}
}
g.AddBindMount(src, dst, options)
}

return nil
}

func setOCIBindMountsPrivileged(g *generate.Generator) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/server/container_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ func TestPrivilegedBindMount(t *testing.T) {
t.Logf("TestCase %q", desc)
g := generate.New()
g.SetRootReadonly(test.readonlyRootFS)
addOCIBindMounts(&g, nil)
addOCIBindMounts(&g, nil, "")
if test.privileged {
setOCIBindMountsPrivileged(&g)
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/server/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
"github.com/opencontainers/image-spec/identity"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
"golang.org/x/net/context"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"

Expand Down Expand Up @@ -374,3 +376,16 @@ func getImageInfo(ctx context.Context, image containerd.Image, provider content.
config: ociimage.Config,
}, nil
}

func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) {
if selinuxOpt == nil {
return "", "", nil
}

labelOpts := fmt.Sprintf("%s:%s:%s:%s",
selinuxOpt.GetUser(),
selinuxOpt.GetRole(),
selinuxOpt.GetRole(),
selinuxOpt.GetType())
return label.InitLabels(selinux.DupSecOpt(labelOpts))
}
71 changes: 71 additions & 0 deletions pkg/server/helpers_selinux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// +build selinux

/*
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 server

import (
"testing"

"github.com/opencontainers/selinux/go-selinux"
"github.com/stretchr/testify/assert"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
)

func TestInitSelinuxOpts(t *testing.T) {
if !selinux.GetEnabled() {
return
}

for desc, test := range map[string]struct {
selinuxOpt *runtime.SELinuxOption
processLabel string
mountLabels []string
}{
"testNullValue": {
selinuxOpt: nil,
processLabel: "",
mountLabels: []string{"", ""},
},
"testEmptyString": {
selinuxOpt: &runtime.SELinuxOption{
User: "",
Role: "",
Type: "",
Level: "",
},
processLabel: ":::",
mountLabels: []string{":object_r:container_file_t:", ":object_r:svirt_sandbox_file_t:"},
},
"testUser": {
selinuxOpt: &runtime.SELinuxOption{
User: "user_u",
Role: "user_r",
Type: "user_t",
Level: "s0:c1,c2",
},
processLabel: "user_u:user_r:user_t:s0:c1,c2",
mountLabels: []string{"user_u:object_r:container_file_t:s0:c1,c2", "user_u:object_r:svirt_sandbox_file_t:s0:c1,c2"},
},
} {
t.Logf("TestCase %q", desc)
processLabel, mountLabel, err := initSelinuxOpts(test.selinuxOpt)
assert.NoError(t, err)
assert.Equal(t, test.processLabel, processLabel)
assert.Contains(t, test.mountLabels, mountLabel)
}
}
8 changes: 7 additions & 1 deletion pkg/server/sandbox_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,13 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r
g.RemoveLinuxNamespace(string(runtimespec.IPCNamespace)) // nolint: errcheck
}

// TODO(random-liu): [P1] Apply SeLinux options.
selinuxOpt := securityContext.GetSelinuxOptions()
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
if err != nil {
return nil, fmt.Errorf("failed to init selinux options %+v: %v", securityContext.GetSelinuxOptions(), err)
}
g.SetProcessSelinuxLabel(processLabel)
g.SetLinuxMountLabel(mountLabel)

supplementalGroups := securityContext.GetSupplementalGroups()
for _, group := range supplementalGroups {
Expand Down
1 change: 1 addition & 0 deletions vendor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ github.com/opencontainers/image-spec v1.0.0
github.com/opencontainers/runc e775f0fba3ea329b8b766451c892c41a3d49594d
github.com/opencontainers/runtime-spec v1.0.0
github.com/opencontainers/runtime-tools e29f3ca4eb806a582ee1a1864c7b0563bd64c19b
github.com/opencontainers/selinux 4a2974bf1ee960774ffd517717f1f45325af0206
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0
github.com/PuerkitoBio/purell v1.0.0
Expand Down
Loading