Skip to content

Commit

Permalink
Add support for confined users
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rhatdan committed Jul 24, 2023
1 parent c8ccd3a commit a81bf57
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 3 deletions.
27 changes: 27 additions & 0 deletions pkg/specgenutil/specgen.go
Expand Up @@ -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 (
Expand Down Expand Up @@ -263,12 +264,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
Expand Down
49 changes: 46 additions & 3 deletions test/system/410-selinux.bats
Expand Up @@ -19,9 +19,22 @@ function check_label() {
# warning line about dup devices. Ignore it.
remove_same_dev_warning
local context="$output"

is "$context" ".*_u:system_r:.*" "SELinux role should always be system_r"

run id -Z
user=$(secon -u $output)
role=$(secon -r $output)

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"
Expand All @@ -43,9 +56,17 @@ function check_label() {
}

@test "podman selinux: privileged container" {
check_label "--privileged" "spc_t"
}

@test "podman selinux: privileged --userns=host container" {
check_label "--privileged --userns=host" "spc_t"
}

@test "podman selinux: --ipc=host container" {
check_label "--ipc=host" "spc_t"
}

@test "podman selinux: init container" {
check_label "--systemd=always" "container_init_t"
}
Expand Down Expand Up @@ -302,4 +323,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

0 comments on commit a81bf57

Please sign in to comment.