sandbox, ctr: SELinux fixes

server: fix selinux labels for pod and containers

Signed-off-by: Antonio Murdaca <runcom@redhat.com>

sandbox: set selinux labels from request, not defaults

Signed-off-by: Antonio Murdaca <runcom@redhat.com>

container_create: use sandbox's selinux if container's nil

Signed-off-by: Antonio Murdaca <runcom@redhat.com>

sandbox: correctly init selinux labels

First, we weren't correctly initializing selinux labels. If any of
(level, user, role, type) was missing from kube selinux options, we
were erroring out. This is wrong as kube sends just `level=s0`
sometimes and docker itself allows `--security-opt label=level:s0`.
This patch directly initializes selinux labels, correctly, and adds a
test to verify it.

Signed-off-by: Antonio Murdaca <runcom@redhat.com>

test: testdata: use container_runtime_t selinux type

RHEL SELinux policy doesn't have `container_t` type but we're using it
in our fixtures. That means Fedora integration tests pass because
`container_t` is in Fedora's container policy but RHEL is broken.
Fix it by using `container_runtime_t` which is aliased in Fedora policy
to `container_t`.

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-09-13 21:06:54 +02:00
parent ec42a40936
commit a11b8cd8ec
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
13 changed files with 138 additions and 49 deletions

View file

@ -45,7 +45,7 @@ const (
defaultSystemdParent = "system.slice" 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{} volumes := []oci.ContainerVolume{}
mounts := containerConfig.GetMounts() mounts := containerConfig.GetMounts()
for _, mount := range mounts { for _, mount := range mounts {
@ -73,7 +73,7 @@ func addOCIBindMounts(sb *sandbox.Sandbox, containerConfig *pb.ContainerConfig,
if mount.SelinuxRelabel { if mount.SelinuxRelabel {
// Need a way in kubernetes to determine if the volume is shared or private // 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) 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.HostSpecific = true
specgen.ClearProcessRlimits() 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 { if err != nil {
return nil, err 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()) specgen.SetLinuxMountLabel(sb.MountLabel())
@ -818,15 +829,18 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
options = []string{"ro"} options = []string{"ro"}
} }
if sb.ResolvPath() != "" { if sb.ResolvPath() != "" {
// TODO: selinux if err := label.Relabel(sb.ResolvPath(), mountLabel, true); err != nil && err != unix.ENOTSUP {
// label.Relabel(sb.ResolvPath(), container.MountLabel, shared) return nil, err
}
// bind mount the pod resolver file // bind mount the pod resolver file
specgen.AddBindMount(sb.ResolvPath(), "/etc/resolv.conf", options) specgen.AddBindMount(sb.ResolvPath(), "/etc/resolv.conf", options)
} }
if sb.HostnamePath() != "" { 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) specgen.AddBindMount(sb.HostnamePath(), "/etc/hostname", options)
} }
@ -884,7 +898,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
containerName, containerID, containerName, containerID,
metaname, metaname,
attempt, attempt,
sb.MountLabel(), mountLabel,
nil) nil)
if err != nil { if err != nil {
return nil, err return nil, err
@ -907,7 +921,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
} }
// Add image volumes // 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 return nil, err
} }

View file

@ -203,8 +203,9 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
} }
return nil, err return nil, err
} }
// TODO: selinux if err := label.Relabel(resolvPath, mountLabel, true); err != nil && err != unix.ENOTSUP {
// label.Relabel(sb.ResolvPath(), container.MountLabel, shared) return nil, err
}
g.AddBindMount(resolvPath, "/etc/resolv.conf", []string{"ro"}) 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, // Don't use SELinux separation with Host Pid or IPC Namespace,
if !req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostPid && !req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostIpc { 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 { if err != nil {
return nil, err 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 { if err := ioutil.WriteFile(hostnamePath, []byte(hostname+"\n"), 0644); err != nil {
return nil, err 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.AddBindMount(hostnamePath, "/etc/hostname", []string{"ro"})
g.AddAnnotation(annotations.HostnamePath, hostnamePath) g.AddAnnotation(annotations.HostnamePath, hostnamePath)
sb.AddHostnamePath(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) { func getSELinuxLabels(selinuxOptions *pb.SELinuxOption) (processLabel string, mountLabel string, err error) {
processLabel = "" labels := []string{}
if selinuxOptions != nil { if selinuxOptions != nil {
user := selinuxOptions.User if selinuxOptions.User != "" {
if user == "" { labels = append(labels, "user:"+selinuxOptions.User)
return "", "", fmt.Errorf("SELinuxOption.User is empty")
} }
if selinuxOptions.Role != "" {
role := selinuxOptions.Role labels = append(labels, "role:"+selinuxOptions.Role)
if role == "" {
return "", "", fmt.Errorf("SELinuxOption.Role is empty")
} }
if selinuxOptions.Type != "" {
t := selinuxOptions.Type labels = append(labels, "type:"+selinuxOptions.Type)
if t == "" {
return "", "", fmt.Errorf("SELinuxOption.Type is empty")
} }
if selinuxOptions.Level != "" {
level := selinuxOptions.Level labels = append(labels, "level:"+selinuxOptions.Level)
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)) return label.InitLabels(labels)
} }
func setupShm(podSandboxRunDir, mountLabel string) (shmPath string, err error) { func setupShm(podSandboxRunDir, mountLabel string) (shmPath string, err error) {

26
test/selinux.bats Normal file
View file

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

View file

@ -51,6 +51,12 @@
}, },
"security_context": { "security_context": {
"readonly_rootfs": false, "readonly_rootfs": false,
"selinux_options": {
"user": "system_u",
"role": "system_r",
"type": "svirt_lxc_net_t",
"level": "s0:c4,c5"
},
"capabilities": { "capabilities": {
"add_capabilities": [ "add_capabilities": [
"setuid", "setuid",
@ -58,12 +64,6 @@
], ],
"drop_capabilities": [ "drop_capabilities": [
] ]
},
"selinux_options": {
"user": "system_u",
"role": "system_r",
"type": "container_t",
"level": "s0:c4,c5"
} }
} }
} }

View file

@ -62,7 +62,7 @@
"selinux_options": { "selinux_options": {
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "container_t", "type": "svirt_lxc_net_t",
"level": "s0:c4,c5" "level": "s0:c4,c5"
} }
} }

View file

@ -64,7 +64,7 @@
"selinux_options": { "selinux_options": {
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "container_t", "type": "svirt_lxc_net_t",
"level": "s0:c4,c5" "level": "s0:c4,c5"
} }
} }

View file

@ -64,7 +64,7 @@
"selinux_options": { "selinux_options": {
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "container_t", "type": "svirt_lxc_net_t",
"level": "s0:c4,c5" "level": "s0:c4,c5"
} }
} }

View file

@ -64,7 +64,7 @@
"selinux_options": { "selinux_options": {
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "container_t", "type": "svirt_lxc_net_t",
"level": "s0:c4,c5" "level": "s0:c4,c5"
} }
} }

View file

@ -64,7 +64,7 @@
"selinux_options": { "selinux_options": {
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "container_t", "type": "svirt_lxc_net_t",
"level": "s0:c4,c5" "level": "s0:c4,c5"
} }
} }

View file

@ -65,7 +65,7 @@
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "svirt_lxc_net_t", "type": "svirt_lxc_net_t",
"level": "s0:c4-c5" "level": "s0:c4,c5"
} }
} }
} }

View file

@ -39,6 +39,12 @@
"host_network": false, "host_network": false,
"host_pid": false, "host_pid": false,
"host_ipc": false "host_ipc": false
},
"selinux_options": {
"user": "system_u",
"role": "system_r",
"type": "svirt_lxc_net_t",
"level": "s0:c4,c5"
} }
} }
} }

View file

@ -41,13 +41,13 @@
"host_network": false, "host_network": false,
"host_pid": false, "host_pid": false,
"host_ipc": false "host_ipc": false
}
}, },
"selinux_options": { "selinux_options": {
"user": "system_u", "user": "system_u",
"role": "system_r", "role": "system_r",
"type": "container_t", "type": "svirt_lxc_net_t",
"level": "s0:c1,c2" "level": "s0:c4,c5"
}
} }
} }
} }

View file

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