From 5b7dce8a3d440f8b137df8f91fba2676a7dcba37 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 4 May 2023 13:41:09 -0400 Subject: [PATCH] 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 Signed-off-by: Chris Evich --- pkg/specgenutil/specgen.go | 27 ++++++++++++++++++++ test/system/410-selinux.bats | 48 ++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 9167f80321..3f6475a7e4 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -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 diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats index 4b60f0c0cf..a8b0fbc604 100644 --- a/test/system/410-selinux.bats +++ b/test/system/410-selinux.bats @@ -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 <