diff --git a/server/container_create.go b/server/container_create.go index 9e3f5670..1cbde263 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -45,7 +45,7 @@ const ( defaultSystemdParent = "system.slice" ) -func addOCIBindMounts(sb *sandbox.Sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) ([]oci.ContainerVolume, error) { +func addOCIBindMounts(mountLabel string, containerConfig *pb.ContainerConfig, specgen *generate.Generator) ([]oci.ContainerVolume, error) { volumes := []oci.ContainerVolume{} mounts := containerConfig.GetMounts() for _, mount := range mounts { @@ -73,7 +73,7 @@ func addOCIBindMounts(sb *sandbox.Sandbox, containerConfig *pb.ContainerConfig, if mount.SelinuxRelabel { // 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 != unix.ENOTSUP { + if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP { return nil, fmt.Errorf("relabel failed %s: %v", src, err) } } @@ -519,7 +519,18 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, specgen.HostSpecific = true specgen.ClearProcessRlimits() - containerVolumes, err := addOCIBindMounts(sb, containerConfig, &specgen) + mountLabel := sb.MountLabel() + processLabel := sb.ProcessLabel() + selinuxConfig := containerConfig.GetLinux().GetSecurityContext().GetSelinuxOptions() + if selinuxConfig != nil { + var err error + processLabel, mountLabel, err = getSELinuxLabels(selinuxConfig) + if err != nil { + return nil, err + } + } + + containerVolumes, err := addOCIBindMounts(mountLabel, containerConfig, &specgen) if err != nil { return nil, err } @@ -703,7 +714,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, } } } - specgen.SetProcessSelinuxLabel(sb.ProcessLabel()) + specgen.SetProcessSelinuxLabel(processLabel) } specgen.SetLinuxMountLabel(sb.MountLabel()) @@ -818,15 +829,18 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, options = []string{"ro"} } if sb.ResolvPath() != "" { - // TODO: selinux - // label.Relabel(sb.ResolvPath(), container.MountLabel, shared) + if err := label.Relabel(sb.ResolvPath(), mountLabel, true); err != nil && err != unix.ENOTSUP { + return nil, err + } // bind mount the pod resolver file specgen.AddBindMount(sb.ResolvPath(), "/etc/resolv.conf", options) } if sb.HostnamePath() != "" { - // TODO: selinux + if err := label.Relabel(sb.HostnamePath(), mountLabel, true); err != nil && err != unix.ENOTSUP { + return nil, err + } specgen.AddBindMount(sb.HostnamePath(), "/etc/hostname", options) } @@ -884,7 +898,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, containerName, containerID, metaname, attempt, - sb.MountLabel(), + mountLabel, nil) if err != nil { return nil, err @@ -907,7 +921,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, } // Add image volumes - if err := addImageVolumes(mountPoint, s, &containerInfo, &specgen, sb.MountLabel()); err != nil { + if err := addImageVolumes(mountPoint, s, &containerInfo, &specgen, mountLabel); err != nil { return nil, err } diff --git a/server/sandbox_run.go b/server/sandbox_run.go index d5e6ecc4..0444e6c0 100644 --- a/server/sandbox_run.go +++ b/server/sandbox_run.go @@ -203,8 +203,9 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest } return nil, err } - // TODO: selinux - // label.Relabel(sb.ResolvPath(), container.MountLabel, shared) + if err := label.Relabel(resolvPath, mountLabel, true); err != nil && err != unix.ENOTSUP { + return nil, err + } g.AddBindMount(resolvPath, "/etc/resolv.conf", []string{"ro"}) } @@ -248,7 +249,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest // Don't use SELinux separation with Host Pid or IPC Namespace, if !req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostPid && !req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostIpc { - processLabel, mountLabel, err = getSELinuxLabels(nil) + processLabel, mountLabel, err = getSELinuxLabels(req.GetConfig().GetLinux().GetSecurityContext().GetSelinuxOptions()) if err != nil { return nil, err } @@ -464,7 +465,9 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err := ioutil.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644); err != nil { return nil, err } - // TODO: selinux relabel + if err := label.Relabel(hostnamePath, mountLabel, true); err != nil && err != unix.ENOTSUP { + return nil, err + } g.AddBindMount(hostnamePath, "/etc/hostname", []string{"ro"}) g.AddAnnotation(annotations.HostnamePath, hostnamePath) sb.AddHostnamePath(hostnamePath) @@ -555,30 +558,22 @@ func (s *Server) setPodSandboxMountLabel(id, mountLabel string) error { } func getSELinuxLabels(selinuxOptions *pb.SELinuxOption) (processLabel string, mountLabel string, err error) { - processLabel = "" + labels := []string{} if selinuxOptions != nil { - user := selinuxOptions.User - if user == "" { - return "", "", fmt.Errorf("SELinuxOption.User is empty") + if selinuxOptions.User != "" { + labels = append(labels, "user:"+selinuxOptions.User) } - - role := selinuxOptions.Role - if role == "" { - return "", "", fmt.Errorf("SELinuxOption.Role is empty") + if selinuxOptions.Role != "" { + labels = append(labels, "role:"+selinuxOptions.Role) } - - t := selinuxOptions.Type - if t == "" { - return "", "", fmt.Errorf("SELinuxOption.Type is empty") + if selinuxOptions.Type != "" { + labels = append(labels, "type:"+selinuxOptions.Type) } - - level := selinuxOptions.Level - if level == "" { - return "", "", fmt.Errorf("SELinuxOption.Level is empty") + if selinuxOptions.Level != "" { + labels = append(labels, "level:"+selinuxOptions.Level) } - processLabel = fmt.Sprintf("%s:%s:%s:%s", user, role, t, level) } - return label.InitLabels(label.DupSecOpt(processLabel)) + return label.InitLabels(labels) } func setupShm(podSandboxRunDir, mountLabel string) (shmPath string, err error) { diff --git a/test/selinux.bats b/test/selinux.bats new file mode 100644 index 00000000..1617e554 --- /dev/null +++ b/test/selinux.bats @@ -0,0 +1,26 @@ +#!/usr/bin/env bats + +load helpers + +function teardown() { + cleanup_test +} + +@test "ctr termination reason Completed" { + start_crio + run crioctl pod run --config "$TESTDATA"/sandbox_config_selinux.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + run crioctl ctr start --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + + cleanup_ctrs + cleanup_pods + stop_crio +} diff --git a/test/testdata/container_config.json b/test/testdata/container_config.json index 28936dff..d8ef76a5 100644 --- a/test/testdata/container_config.json +++ b/test/testdata/container_config.json @@ -51,6 +51,12 @@ }, "security_context": { "readonly_rootfs": false, + "selinux_options": { + "user": "system_u", + "role": "system_r", + "type": "svirt_lxc_net_t", + "level": "s0:c4,c5" + }, "capabilities": { "add_capabilities": [ "setuid", @@ -58,12 +64,6 @@ ], "drop_capabilities": [ ] - }, - "selinux_options": { - "user": "system_u", - "role": "system_r", - "type": "container_t", - "level": "s0:c4,c5" } } } diff --git a/test/testdata/container_config_by_imageid.json b/test/testdata/container_config_by_imageid.json index 25b2b13a..d953efb3 100644 --- a/test/testdata/container_config_by_imageid.json +++ b/test/testdata/container_config_by_imageid.json @@ -62,7 +62,7 @@ "selinux_options": { "user": "system_u", "role": "system_r", - "type": "container_t", + "type": "svirt_lxc_net_t", "level": "s0:c4,c5" } } diff --git a/test/testdata/container_config_hostport.json b/test/testdata/container_config_hostport.json index ddc0014e..e5a0ca67 100644 --- a/test/testdata/container_config_hostport.json +++ b/test/testdata/container_config_hostport.json @@ -64,7 +64,7 @@ "selinux_options": { "user": "system_u", "role": "system_r", - "type": "container_t", + "type": "svirt_lxc_net_t", "level": "s0:c4,c5" } } diff --git a/test/testdata/container_config_logging.json b/test/testdata/container_config_logging.json index 92772818..8e8d0da4 100644 --- a/test/testdata/container_config_logging.json +++ b/test/testdata/container_config_logging.json @@ -64,7 +64,7 @@ "selinux_options": { "user": "system_u", "role": "system_r", - "type": "container_t", + "type": "svirt_lxc_net_t", "level": "s0:c4,c5" } } diff --git a/test/testdata/container_config_resolvconf.json b/test/testdata/container_config_resolvconf.json index ad22cf81..52b77e08 100644 --- a/test/testdata/container_config_resolvconf.json +++ b/test/testdata/container_config_resolvconf.json @@ -64,7 +64,7 @@ "selinux_options": { "user": "system_u", "role": "system_r", - "type": "container_t", + "type": "svirt_lxc_net_t", "level": "s0:c4,c5" } } diff --git a/test/testdata/container_config_resolvconf_ro.json b/test/testdata/container_config_resolvconf_ro.json index 8e866488..7e121c07 100644 --- a/test/testdata/container_config_resolvconf_ro.json +++ b/test/testdata/container_config_resolvconf_ro.json @@ -64,7 +64,7 @@ "selinux_options": { "user": "system_u", "role": "system_r", - "type": "container_t", + "type": "svirt_lxc_net_t", "level": "s0:c4,c5" } } diff --git a/test/testdata/container_config_seccomp.json b/test/testdata/container_config_seccomp.json index 9054a2c6..582132b0 100644 --- a/test/testdata/container_config_seccomp.json +++ b/test/testdata/container_config_seccomp.json @@ -65,7 +65,7 @@ "user": "system_u", "role": "system_r", "type": "svirt_lxc_net_t", - "level": "s0:c4-c5" + "level": "s0:c4,c5" } } } diff --git a/test/testdata/sandbox_config.json b/test/testdata/sandbox_config.json index 5f9e6871..57e211bd 100644 --- a/test/testdata/sandbox_config.json +++ b/test/testdata/sandbox_config.json @@ -39,6 +39,12 @@ "host_network": false, "host_pid": false, "host_ipc": false + }, + "selinux_options": { + "user": "system_u", + "role": "system_r", + "type": "svirt_lxc_net_t", + "level": "s0:c4,c5" } } } diff --git a/test/testdata/sandbox_config_seccomp.json b/test/testdata/sandbox_config_seccomp.json index eb272406..8e440b16 100644 --- a/test/testdata/sandbox_config_seccomp.json +++ b/test/testdata/sandbox_config_seccomp.json @@ -41,13 +41,13 @@ "host_network": false, "host_pid": false, "host_ipc": false + }, + "selinux_options": { + "user": "system_u", + "role": "system_r", + "type": "svirt_lxc_net_t", + "level": "s0:c4,c5" } - }, - "selinux_options": { - "user": "system_u", - "role": "system_r", - "type": "container_t", - "level": "s0:c1,c2" } } } diff --git a/test/testdata/sandbox_config_selinux.json b/test/testdata/sandbox_config_selinux.json new file mode 100644 index 00000000..916a10ec --- /dev/null +++ b/test/testdata/sandbox_config_selinux.json @@ -0,0 +1,48 @@ +{ + "metadata": { + "name": "podsandbox1", + "uid": "redhat-test-crio", + "namespace": "redhat.test.crio", + "attempt": 1 + }, + "hostname": "crioctl_host", + "log_directory": "", + "dns_config": { + "searches": [ + "8.8.8.8" + ] + }, + "port_mappings": [], + "resources": { + "cpu": { + "limits": 3, + "requests": 2 + }, + "memory": { + "limits": 50000000, + "requests": 2000000 + } + }, + "labels": { + "group": "test" + }, + "annotations": { + "owner": "hmeng", + "security.alpha.kubernetes.io/sysctls": "kernel.shm_rmid_forced=1,net.ipv4.ip_local_port_range=1024 65000", + "security.alpha.kubernetes.io/unsafe-sysctls": "kernel.msgmax=8192" , + "security.alpha.kubernetes.io/seccomp/pod": "unconfined" + }, + "linux": { + "cgroup_parent": "/Burstable/pod_123-456", + "security_context": { + "namespace_options": { + "host_network": false, + "host_pid": false, + "host_ipc": false + }, + "selinux_options": { + "level": "s0" + } + } + } +}