Add support for confined users

The original SELinux support in Docker and Podman does not follow the
default SELinux rules for how label transitions are supposed to be
handled. Containers always switch their user and role to
system_u:system_r, rather then maintain the collers user and role.
For example
unconfined_u:unconfined_r:container_t:s0:c1,c2

Advanced SELinux administrators want to confine users but still allow
them to create containers from their role, but not allow them to launch
a privileged container like spc_t.

This means if a user running as
container_user_u:container_user_r:container_user_t:s0

Ran a container they would get

container_user_u:container_user_r:container_t:s0:c1,c2

If they run a privileged container they would run it with:

container_user_u:container_user_r:container_user_t:s0

If they want to force the label they would get an error

podman run --security-opt label=type:spc_t ...

Should fail. Because the container_user_r can not run with the spc_t.

SELinux rules would also prevent the user from forcing system_u user and
the sytem_r role.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Signed-off-by: Chris Evich <cevich@redhat.com>
This commit is contained in:
Daniel J Walsh
2023-05-04 13:41:09 -04:00
committed by Chris Evich
parent 78b850c48b
commit 5b7dce8a3d
2 changed files with 73 additions and 2 deletions

View File

@ -21,6 +21,7 @@ import (
"github.com/containers/podman/v4/pkg/util"
"github.com/docker/go-units"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
)
const (
@ -301,12 +302,38 @@ func GenRlimits(ulimits []string) ([]specs.POSIXRlimit, error) {
return rlimits, nil
}
func currentLabelOpts() ([]string, error) {
label, err := selinux.CurrentLabel()
if err != nil {
return nil, err
}
if label == "" {
return nil, nil
}
con, err := selinux.NewContext(label)
if err != nil {
return nil, err
}
return []string{
fmt.Sprintf("label=user:%s", con["user"]),
fmt.Sprintf("label=role:%s", con["role"]),
}, nil
}
func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions, args []string) error {
rtc, err := config.Default()
if err != nil {
return err
}
if rtc.Containers.EnableLabeledUsers {
defSecurityOpts, err := currentLabelOpts()
if err != nil {
return err
}
c.SecurityOpt = append(defSecurityOpts, c.SecurityOpt...)
}
// validate flags as needed
if err := validate(c); err != nil {
return err

View File

@ -19,9 +19,22 @@ function check_label() {
# warning line about dup devices. Ignore it.
remove_same_dev_warning
local context="$output"
run id -Z
user=$(secon -u $output)
role=$(secon -r $output)
is "$context" ".*_u:system_r:.*" "SELinux role should always be system_r"
case "$args" in
# Containers that run automatically without SELinux transitions, run
# with the current role.
*--privileged*| *--pid=host* | *--ipc=host* | *"--security-opt label=disable"*)
is "$context" "$user:$role:.*" "Non SELinux separated containers role should always be the current user and role"
;;
# Containers that are confined or force the spc_t type default
# to running with the system_r role.
*)
is "$context" ".*_u:system_r:.*" "SELinux separated containers role should always be system_r"
;;
esac
# e.g. system_u:system_r:container_t:s0:c45,c745 -> "container_t"
type=$(cut -d: -f3 <<<"$context")
is "$type" "$1" "SELinux type"
@ -46,9 +59,18 @@ function check_label() {
# FIXME #19376 - container-selinux broken -- bats test_tags=distro-integration
@test "podman selinux: privileged container" {
check_label "--privileged" "spc_t"
}
@test "podman selinux: privileged --userns=host container" {
check_label "--privileged --userns=host" "spc_t"
}
# bats test_tags=distro-integration
@test "podman selinux: --ipc=host container" {
check_label "--ipc=host" "spc_t"
}
# bats test_tags=distro-integration
@test "podman selinux: init container" {
check_label "--systemd=always" "container_init_t"
@ -311,4 +333,26 @@ function check_label() {
assert "$output" =~ "${SELINUXMNT}" "Mount SELinux file system readwrite"
}
@test "podman EnableLabeledUsers" {
skip_if_no_selinux
overrideConf=$PODMAN_TMPDIR/containers.conf
cat >$overrideConf <<EOF
[Containers]
label_users=true
EOF
run id -Z
user=$(secon -u $output)
role=$(secon -r $output)
CONTAINERS_CONF_OVERRIDE=$overrideConf run_podman run $IMAGE cat /proc/self/attr/current
level=$(secon -l $output)
id -Z
is "$output" "$user:$role:container_t:$level" "Confined label Correctly"
CONTAINERS_CONF_OVERRIDE=$overrideConf run_podman run --rm --name label --security-opt label=role:system_r $IMAGE cat /proc/self/attr/current
level=$(secon -l $output)
is "$output" "$user:system_r:container_t:$level" "Confined with role override label Correctly"
}
# vim: filetype=sh