From c0a2d152d99dd9344f73bd70bb4ac92c11c9e07b Mon Sep 17 00:00:00 2001 From: Mike Brown Date: Wed, 6 Sep 2017 08:09:27 -0500 Subject: [PATCH] adds seccomp support Signed-off-by: Mike Brown --- pkg/server/container_create.go | 43 +++++++++++++++++++++++++++++++--- pkg/server/sandbox_run.go | 30 ++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index 4cecbf469..4bfa01b86 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/contrib/apparmor" + "github.com/containerd/containerd/contrib/seccomp" "github.com/containerd/containerd/typeurl" "github.com/docker/docker/pkg/mount" "github.com/golang/glog" @@ -48,10 +49,20 @@ import ( const ( // profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName. profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747 - // runtimeDefault indicates that we should use or create a runtime default apparmor profile. + // runtimeDefault indicates that we should use or create a runtime default profile. runtimeDefault = "runtime/default" + // runtimeDefault indicates that we should use or create a docker default profile. + dockerDefault = "docker/default" // appArmorDefaultProfileName is name to use when creating a default apparmor profile. appArmorDefaultProfileName = "cri-containerd.apparmor.d" + // unconfinedProfile is a string indicating one should run a pod/containerd without a security profile + unconfinedProfile = "unconfined" + // seccompDefaultPodProfile is the default seccomp profile for pods. + seccompDefaultSandboxProfile = unconfinedProfile + // seccompDefaultContainerProfile is the default seccomp profile for containers. + seccompDefaultContainerProfile = dockerDefault + // seccompEnabled is a flag for globally enabling/disabling seccomp profiles for containers. + seccompEnabled = true // TODO (mikebrow): make these seccomp defaults configurable ) func init() { @@ -211,6 +222,33 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C specOpts = append(specOpts, apparmor.WithProfile(strings.TrimPrefix(appArmorProf, profileNamePrefix))) } } + + // Set seccomp profile + seccompProf := config.GetLinux().GetSecurityContext().GetSeccompProfilePath() + if seccompProf == runtimeDefault || seccompProf == dockerDefault { + // use correct default profile (Eg. if not configured otherwise, the default is docker/default for containers) + seccompProf = seccompDefaultContainerProfile + } + // Unset the seccomp profile, if seccomp is not enabled, unconfined, unset, or the security context is privileged + if !seccompEnabled || + seccompProf == unconfinedProfile || + seccompProf == "" || + config.GetLinux().GetSecurityContext().GetPrivileged() { + spec.Linux.Seccomp = nil + } else { + switch seccompProf { + case dockerDefault: + // Note: WithDefaultProfile specOpts must be added after capabilities + specOpts = append(specOpts, seccomp.WithDefaultProfile()) + default: + // Require and Trim default profile name prefix + if !strings.HasPrefix(seccompProf, profileNamePrefix) { + return nil, fmt.Errorf("invalid seccomp profile %q", seccompProf) + } + specOpts = append(specOpts, seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix))) + } + } + opts = append(opts, containerd.WithSpec(spec, specOpts...), containerd.WithRuntime(defaultRuntime, nil), @@ -312,7 +350,7 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3 if err := setOCIPrivileged(&g, config); err != nil { return nil, err } - } else { + } else { // not privileged if err := c.addOCIDevices(&g, config.GetDevices()); err != nil { return nil, fmt.Errorf("failed to set devices mapping %+v: %v", config.GetDevices(), err) } @@ -321,7 +359,6 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3 return nil, fmt.Errorf("failed to set capabilities %+v: %v", securityContext.GetCapabilities(), err) } - // TODO(random-liu): [P2] Add seccomp not privileged only. } g.SetProcessSelinuxLabel(processLabel) diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index 7074d995a..575e1dfed 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/containerd/contrib/seccomp" "github.com/containerd/containerd/typeurl" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/golang/glog" @@ -127,6 +128,33 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run if uid := config.GetLinux().GetSecurityContext().GetRunAsUser(); uid != nil { specOpts = append(specOpts, containerd.WithUserID(uint32(uid.GetValue()))) } + + // Set seccomp profile + seccompProf := config.GetLinux().GetSecurityContext().GetSeccompProfilePath() + if seccompProf == runtimeDefault || seccompProf == dockerDefault { + // use correct default profile (Eg. if not configured otherwise, the default is unconfined for pods) + seccompProf = seccompDefaultSandboxProfile + } + // Unset the seccomp profile, if seccomp is not enabled, unconfined, unset, or the security context is privileged + if !seccompEnabled || + seccompProf == unconfinedProfile || + seccompProf == "" || + config.GetLinux().GetSecurityContext().GetPrivileged() { + spec.Linux.Seccomp = nil + } else { + switch seccompProf { + case dockerDefault: + // Note: WithDefaultProfile specOpts must be added after capabilities + specOpts = append(specOpts, seccomp.WithDefaultProfile()) + default: + // Require and Trim default profile name prefix + if !strings.HasPrefix(seccompProf, profileNamePrefix) { + return nil, fmt.Errorf("invalid seccomp profile %q", seccompProf) + } + specOpts = append(specOpts, seccomp.WithProfile(strings.TrimPrefix(seccompProf, profileNamePrefix))) + } + } + opts := []containerd.NewContainerOpts{ containerd.WithSnapshotter(c.config.ContainerdSnapshotter), containerd.WithNewSnapshot(id, image.Image), @@ -288,8 +316,6 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r g.AddLinuxSysctl(key, value) } - // TODO(random-liu): [P2] Set seccomp - // Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))