]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: make TEST-06-SELINUX work with the refpolicy and beef it up a bit 30023/head
authorFrantisek Sumsal <frantisek@sumsal.cz>
Tue, 14 Nov 2023 11:53:51 +0000 (12:53 +0100)
committerFrantisek Sumsal <frantisek@sumsal.cz>
Tue, 14 Nov 2023 17:54:16 +0000 (18:54 +0100)
Currently the test works only with policy shipped by Fedora, which makes
it pretty much useless in most of our CIs. Let's drop the custom module
and make the test more generic, so it works with the refpolicy as well,
which should allow us to run it on Arch and probably even in Ubuntu CI.

test/TEST-06-SELINUX/systemd_test.fc [deleted file]
test/TEST-06-SELINUX/systemd_test.if [deleted file]
test/TEST-06-SELINUX/systemd_test.te [deleted file]
test/TEST-06-SELINUX/test.sh
test/test-functions
test/units/testsuite-06.sh

diff --git a/test/TEST-06-SELINUX/systemd_test.fc b/test/TEST-06-SELINUX/systemd_test.fc
deleted file mode 100644 (file)
index 2aa442c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-/usr/lib/systemd/tests/testdata/testsuite-06\.units(/.*)?   system_u:object_r:systemd_unit_file_t:s0
diff --git a/test/TEST-06-SELINUX/systemd_test.if b/test/TEST-06-SELINUX/systemd_test.if
deleted file mode 100644 (file)
index 1e74e1d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-template(`systemd_test_base_template', `
-       gen_require(`
-               attribute systemd_test_domain_type;
-       ')
-
-       type $1_t, systemd_test_domain_type;
-       domain_type($1_t)
-')
diff --git a/test/TEST-06-SELINUX/systemd_test.te b/test/TEST-06-SELINUX/systemd_test.te
deleted file mode 100644 (file)
index 43dbf3e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-policy_module(systemd_test, 0.0.1)
-
-# declarations
-attribute systemd_test_domain_type;
-
-systemd_test_base_template(systemd_test)
-systemd_test_base_template(systemd_test_status)
-systemd_test_base_template(systemd_test_start)
-systemd_test_base_template(systemd_test_stop)
-systemd_test_base_template(systemd_test_reload)
-
-# systemd_test_domain_type
-
-require {
-       role system_r;
-       role unconfined_r;
-       type bin_t;
-       type initrc_t;
-       type systemd_systemctl_exec_t;
-       type unconfined_service_t;
-}
-
-role system_r types systemd_test_domain_type;
-role unconfined_r types systemd_test_domain_type;
-
-allow systemd_test_domain_type bin_t: file entrypoint;
-allow systemd_test_domain_type systemd_systemctl_exec_t: file entrypoint;
-allow initrc_t systemd_test_domain_type: process transition;
-allow unconfined_service_t systemd_test_domain_type: process transition;
-corecmd_exec_bin(systemd_test_domain_type)
-init_signal_script(systemd_test_domain_type)
-init_sigchld_script(systemd_test_domain_type)
-systemd_exec_systemctl(systemd_test_domain_type)
-userdom_use_user_ttys(systemd_test_domain_type)
-userdom_use_user_ptys(systemd_test_domain_type)
-
-optional_policy(`
-       dbus_system_bus_client(systemd_test_domain_type)
-       init_dbus_chat(systemd_test_domain_type)
-')
-
-# systemd_test_*_t
-require {
-       type systemd_unit_file_t;
-}
-
-allow systemd_test_status_t systemd_unit_file_t: service { status };
-allow systemd_test_start_t systemd_unit_file_t: service { start };
-allow systemd_test_stop_t systemd_unit_file_t: service { stop };
-allow systemd_test_reload_t systemd_unit_file_t: service { reload };
index c7eaae8ab4aa0d25da3e1eb98f8908f20f0543ce..384101577fd3eb0e37fdf9c85997087abe310b05 100755 (executable)
@@ -6,60 +6,38 @@ TEST_DESCRIPTION="SELinux tests"
 IMAGE_NAME="selinux"
 TEST_NO_NSPAWN=1
 
-# Requirements:
-# A selinux policy is installed. Preferably selinux-policy-targeted, but it could work with others
-# selinux-policy-devel
+if [[ -e /etc/selinux/config ]]; then
+    SEPOLICY="$(awk -F= '/^SELINUXTYPE=/ {print $2; exit}' /etc/selinux/config)"
 
-# Check if
-# - selinux-policy-devel is installed and
-# - some selinux policy is installed. To keep this generic just check for the
-#   existence of a directory below /etc/selinux/, indicating a SELinux policy is
-#   installed
-# otherwise bail out early instead of failing
-test -f /usr/share/selinux/devel/include/system/systemd.if && find /etc/selinux -mindepth 1 -maxdepth 1 -not -empty -type d | grep -q . || exit 0
+    # C8S doesn't set SELINUXTYPE in /etc/selinux/config, so default to 'targeted'
+    if [[ -z "$SEPOLICY" ]]; then
+        echo "Failed to parse SELinux policy from /etc/selinux/config, falling back to 'targeted'"
+        SEPOLICY="targeted"
+    fi
+
+    if [[ ! -d "/etc/selinux/$SEPOLICY" ]]; then
+        echo "Missing policy directory /etc/selinux/$SEPOLICY, skipping the test"
+        exit 0
+    fi
+
+    echo "Using SELinux policy '$SEPOLICY'"
+else
+    echo "/etc/selinux/config is missing, skipping the test"
+    exit 0
+fi
 
 # shellcheck source=test/test-functions
 . "${TEST_BASE_DIR:?}/test-functions"
 
 SETUP_SELINUX=yes
-KERNEL_APPEND="${KERNEL_APPEND:=} selinux=1 security=selinux enforcing=0"
+KERNEL_APPEND="${KERNEL_APPEND:-} selinux=1 enforcing=0 lsm=selinux"
 
 test_append_files() {
     local workspace="${1:?}"
-    local policy_headers_dir=/usr/share/selinux/devel
-    local modules_dir=/var/lib/selinux
 
     setup_selinux
-    # Make sure we never expand this to "/..."
-    rm -rf "${workspace:?}/$modules_dir"
-
-    if ! cp -ar "$modules_dir" "$workspace/$modules_dir"; then
-        dfatal "Failed to copy $modules_dir"
-        exit 1
-    fi
-
-    rm -rf "${workspace:?}/$policy_headers_dir"
-    inst_dir /usr/share/selinux
-
-    if ! cp -ar "$policy_headers_dir" "$workspace/$policy_headers_dir"; then
-        dfatal "Failed to copy $policy_headers_dir"
-        exit 1
-    fi
-
-    mkdir "$workspace/systemd-test-module"
-    cp -v systemd_test.* "$workspace/systemd-test-module/"
-    image_install checkmodule load_policy m4 make sefcontext_compile semodule semodule_package runcon
-    image_install -o sesearch
-    image_install -o /usr/libexec/selinux/hll/pp # Fedora/RHEL/...
-    image_install -o /usr/lib/selinux/hll/pp     # Debian/Ubuntu/...
-
     # Config file has (unfortunately) always precedence, so let's switch it there as well
     sed -i '/^SELINUX=disabled$/s/disabled/permissive/' "$workspace/etc/selinux/config"
-
-    if ! chroot "$workspace" make -C /systemd-test-module -f /usr/share/selinux/devel/Makefile clean load systemd_test.pp QUIET=n; then
-        dfatal "Failed to build the systemd test module"
-        exit 1
-    fi
 }
 
 do_test "$@"
index 3cb08fb47a9b5db7ee782447b376a9a8c770a8ad..7375d3465c7aab95ac3bd458fe94a9990fa7bb9a 100644 (file)
@@ -924,16 +924,13 @@ setup_selinux() {
         return 0
     fi
 
-    local conf_dir=/etc/selinux
-    local fixfiles_tools=(awk bash cat chcon expr egrep find grep head secon setfiles rm sort uname uniq)
-
-    # Make sure the following statement can't expand to "/" to prevent
-    # a potential where-are-my-backups situation
-    rm -rf "${initdir:?}/$conf_dir"
-    if ! cp -ar "$conf_dir" "$initdir/$conf_dir"; then
-        dfatal "Failed to copy $conf_dir"
-        exit 1
-    fi
+    for dir in /etc/selinux /usr/share/selinux; do
+        rm -rf "${initdir:?}/$dir"
+        if ! cp -ar "$dir" "$initdir/$dir"; then
+            dfatal "Failed to copy $dir"
+            exit 1
+        fi
+    done
 
     # We use a custom autorelabel service instead of the SELinux provided set
     # of units & a generator, since the generator overrides the default target
@@ -944,13 +941,13 @@ setup_selinux() {
     # and does the relabeling unconditionally which always ends with a reboot, so
     # we end up in a reboot loop (and it also spews quite a lot of errors as it
     # wants /etc/fstab and dracut-initramfs-restore).
-
     touch "$initdir/.autorelabel"
     mkdir -p "$initdir/usr/lib/systemd/tests/testdata/units/basic.target.wants"
     ln -sf ../autorelabel.service "$initdir/usr/lib/systemd/tests/testdata/units/basic.target.wants/"
 
-    image_install "${fixfiles_tools[@]}"
-    image_install fixfiles sestatus
+    # Tools requires by fixfiles
+    image_install awk bash cat chcon expr egrep find grep head secon setfiles rm sort uname uniq
+    image_install fixfiles getenforce load_policy selinuxenabled sestatus
 }
 
 install_valgrind() {
index 73ae485041801c16487587322b7a70ad20cebf02..7fc3c379e57c749b96cef81eaccdf318381d37ae 100755 (executable)
@@ -3,8 +3,41 @@
 set -eux
 set -o pipefail
 
-runcon -t systemd_test_start_t systemctl start hola
-runcon -t systemd_test_reload_t systemctl reload hola
-runcon -t systemd_test_stop_t systemctl stop hola
+# Note: ATTOW the following checks should work with both Fedora and upstream reference policy
+#       (with or without MCS/MLS)
+
+sestatus
+
+# We should end up in permissive mode
+[[ "$(getenforce)" == "Permissive" ]]
+
+# Check PID 1's context
+PID1_CONTEXT="$(ps -h -o label 1)"
+[[ "$PID1_CONTEXT" =~ ^system_u:system_r:init_t(:s0)?$ ]]
+# The same label should be attached to all PID 1's journal messages
+journalctl -q -b -p info -n 5 --grep . _SELINUX_CONTEXT="$PID1_CONTEXT"
+
+# Check context on a couple of arbitrarily-selected files/directories
+[[ "$(stat --printf %C /run/systemd/journal/)" =~ ^system_u:object_r:(syslogd_runtime_t|syslogd_var_run_t)(:s0)?$ ]]
+[[ "$(stat --printf %C /run/systemd/notify)" =~ ^system_u:object_r:(init_runtime_t|init_var_run_t)(:s0)?$ ]]
+[[ "$(stat --printf %C /run/systemd/sessions/)" =~ ^system_u:object_r:(systemd_sessions_runtime_t|systemd_logind_sessions_t)(:s0)?$ ]]
+
+# Check if our SELinux-related functionality works
+#
+# Since the SELinux policies vary wildly, use a context from some existing file
+# as our test context
+CONTEXT="$(stat -c %C /proc/sys/kernel/core_pattern)"
+
+[[ "$(systemd-run --wait --pipe -p SELinuxContext="$CONTEXT" cat /proc/self/attr/current | tr -d '\0')" == "$CONTEXT" ]]
+(! systemd-run --wait --pipe -p SELinuxContext="foo:bar:baz" cat /proc/self/attr/current)
+(! systemd-run --wait --pipe -p ConditionSecurity='selinux' false)
+systemd-run --wait --pipe -p ConditionSecurity='!selinux' false
+
+NSPAWN_ARGS=(systemd-nspawn -q --volatile=yes --directory=/ --bind-ro=/etc --inaccessible=/etc/machine-id)
+[[ "$("${NSPAWN_ARGS[@]}" cat /proc/self/attr/current | tr -d '\0')" != "$CONTEXT" ]]
+[[ "$("${NSPAWN_ARGS[@]}" --selinux-context="$CONTEXT" cat /proc/self/attr/current | tr -d '\0')" == "$CONTEXT" ]]
+[[ "$("${NSPAWN_ARGS[@]}" stat --printf %C /run)" != "$CONTEXT" ]]
+[[ "$("${NSPAWN_ARGS[@]}" --selinux-apifs-context="$CONTEXT" stat --printf %C /run)" == "$CONTEXT" ]]
+[[ "$("${NSPAWN_ARGS[@]}" --selinux-apifs-context="$CONTEXT" --tmpfs=/tmp stat --printf %C /tmp)" == "$CONTEXT" ]]
 
 touch /testok