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:
parent
ec42a40936
commit
a11b8cd8ec
13 changed files with 138 additions and 49 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
26
test/selinux.bats
Normal 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
|
||||||
|
}
|
12
test/testdata/container_config.json
vendored
12
test/testdata/container_config.json
vendored
|
@ -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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
test/testdata/container_config_hostport.json
vendored
2
test/testdata/container_config_hostport.json
vendored
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
test/testdata/container_config_logging.json
vendored
2
test/testdata/container_config_logging.json
vendored
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
test/testdata/container_config_seccomp.json
vendored
2
test/testdata/container_config_seccomp.json
vendored
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
test/testdata/sandbox_config.json
vendored
6
test/testdata/sandbox_config.json
vendored
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
test/testdata/sandbox_config_seccomp.json
vendored
6
test/testdata/sandbox_config_seccomp.json
vendored
|
@ -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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
48
test/testdata/sandbox_config_selinux.json
vendored
Normal file
48
test/testdata/sandbox_config_selinux.json
vendored
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue