From fff03b7135ad936c39d6d885441bda285f33c553 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Wed, 3 Dec 2025 10:30:41 +0530 Subject: [PATCH] tests: selinux-label - convert to python Signed-off-by: Susant Sahani --- tests/Makefile.am | 4 +- tests/relabel/test-relabel.pl | 141 ---------------------------------- tests/relabel/test-relabel.py | 131 +++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 143 deletions(-) delete mode 100755 tests/relabel/test-relabel.pl create mode 100755 tests/relabel/test-relabel.py diff --git a/tests/Makefile.am b/tests/Makefile.am index 3119a8a21..5b87f9927 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -734,8 +734,8 @@ regressions_test_big_heap_LDADD = \ SLOW_TESTS += regressions/rhbz909624.sh EXTRA_DIST += regressions/rhbz909624.sh -TESTS += relabel/test-relabel.pl -EXTRA_DIST += relabel/test-relabel.pl +TESTS += relabel/test-relabel.py +EXTRA_DIST += relabel/test-relabel.py # Test relative paths to backing files. Mainly this is a test that we # don't break this. diff --git a/tests/relabel/test-relabel.pl b/tests/relabel/test-relabel.pl deleted file mode 100755 index 4d4f6c7ba..000000000 --- a/tests/relabel/test-relabel.pl +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env perl -# Copyright (C) 2016 Red Hat Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -use strict; -use warnings; - -use Sys::Guestfs; - -my $prog = $0; -$prog =~ s{.*/}{}; - -# Because we parse error message strings below. -$ENV{LANG} = "C"; - -if ($ENV{"SKIP_TEST_RELABEL_PL"}) { - print "$prog: test skipped because environment variable is set.\n"; - exit 77 -} - -# SELinux labelling won't work (and can be skipped) if SELinux isn't -# installed on the host. -if (! -f "/etc/selinux/config" || ! -x "/usr/sbin/load_policy") { - print "$prog: test skipped because SELinux is not available.\n"; - exit 77 -} - -# Create a filesystem. -my $g = Sys::Guestfs->new (); - -$g->add_drive_scratch (256*1024*1024); -$g->launch (); - -# If Linux extended attrs aren't available then we cannot test this. -unless ($g->feature_available (["linuxxattrs"])) { - print "$prog: test skipped because 'linuxxattrs' feature not available.\n"; - $g->close (); - exit 77 -} - -# If SELinux relabelling is not available then we cannot test this. -unless ($g->feature_available (["selinuxrelabel"])) { - print "$prog: test skipped because 'selinuxrelabel' feature not available.\n"; - $g->close (); - exit 77 -} - -$g->part_disk ("/dev/sda", "mbr"); -$g->mkfs ("ext4", "/dev/sda1"); - -$g->mount_options ("user_xattr", "/dev/sda1", "/"); - -# Create some files and directories that we want to have relabelled. -$g->mkdir ("/bin"); -$g->touch ("/bin/ls"); -$g->mkdir ("/etc"); -$g->mkdir ("/tmp"); -$g->touch ("/tmp/test"); -$g->mkdir ("/var"); -$g->mkdir ("/var/log"); -$g->touch ("/var/log/messages"); - -# Create a spec file. -# This doesn't test the optional file_type field. XXX -# See also file_contexts(5). -$g->write ("/etc/file_contexts", <<'EOF'); -/.* system_u:object_r:default_t:s0 -/bin/.* system_u:object_r:bin_t:s0 -/etc/.* system_u:object_r:etc_t:s0 -/etc/file_contexts <> -/tmp/.* <> -/var/.* system_u:object_r:var_t:s0 -/var/log/.* system_u:object_r:var_log_t:s0 -EOF - -# Do the relabel. -$g->setfiles ("/etc/file_contexts", ["/"], force => 1); - -# Check the labels were set correctly. -my $errors = 0; - -sub check_label -{ - my $file = shift; - my $expected_label = shift; - - my $actual_label = $g->lgetxattr ($file, "security.selinux"); - # The label returned from lgetxattr has \0 appended. - if ("$expected_label\0" ne $actual_label) { - print STDERR "$prog: expected label on file $file: expected=$expected_label actual=$actual_label\n"; - $errors++; - } -} - -sub check_label_none -{ - my $file = shift; - my $r; - - eval { - $r = $g->lgetxattr ($file, "security.selinux"); - }; - if (defined $r) { - print STDERR "$prog: expecting no label on file $file, but got $r\n"; - $errors++; - } elsif ($@) { - if ($@ !~ /No data available/) { - print STDERR "$prog: expecting an error reading label from file $file, but got $@\n"; - $errors++; - } - } -} - -check_label ("/bin", "system_u:object_r:default_t:s0"); -check_label ("/bin/ls", "system_u:object_r:bin_t:s0"); -check_label ("/etc", "system_u:object_r:default_t:s0"); -check_label_none ("/etc/file_contexts"); -check_label ("/tmp", "system_u:object_r:default_t:s0"); -check_label_none ("/tmp/test"); -check_label ("/var", "system_u:object_r:default_t:s0"); -check_label ("/var/log", "system_u:object_r:var_t:s0"); -check_label ("/var/log/messages", "system_u:object_r:var_log_t:s0"); - -# Finish up. -$g->shutdown (); -$g->close (); - -exit ($errors == 0 ? 0 : 1); diff --git a/tests/relabel/test-relabel.py b/tests/relabel/test-relabel.py new file mode 100755 index 000000000..c2c4c5e41 --- /dev/null +++ b/tests/relabel/test-relabel.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# Copyright (C) 2025 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import sys +import guestfs + +prog = os.path.basename(sys.argv[0]) +# Because we parse error message strings below. +os.environ["LANG"] = "C" + +if os.environ.get("SKIP_TEST_RELABEL_PY"): + print(f"{prog}: test skipped because environment variable is set.") + sys.exit(77) + +# SELinux labelling won't work (and can be skipped) if SELinux isn't +# installed on the host. +if not os.path.isfile("/etc/selinux/config") or not os.access("/usr/sbin/load_policy", os.X_OK): + print(f"{prog}: test skipped because SELinux is not available.") + sys.exit(77) + +# Create a filesystem. +g = guestfs.GuestFS(python_return_dict=True) +g.add_drive_scratch(256 * 1024 * 1024) +g.launch() + +# If Linux extended attrs aren't available then we cannot test this. +if not g.feature_available(["linuxxattrs"]): + print(f"{prog}: test skipped because 'linuxxattrs' feature not available.") + g.close() + sys.exit(77) + +# If SELinux relabelling is not available then we cannot test this. +if not g.feature_available(["selinuxrelabel"]): + print(f"{prog}: test skipped because 'selinuxrelabel' feature not available.") + g.close() + sys.exit(77) + +g.part_disk("/dev/sda", "mbr") +g.mkfs("ext4", "/dev/sda1") +g.mount_options("user_xattr", "/dev/sda1", "/") + +# Create some files and directories that we want to have relabelled. +g.mkdir("/bin") +g.touch("/bin/ls") +g.mkdir("/etc") +g.mkdir("/tmp") +g.touch("/tmp/test") +g.mkdir("/var") +g.mkdir("/var/log") +g.touch("/var/log/messages") + +# Create a spec file. +# This doesn't test the optional file_type field. XXX +# See also file_contexts(5). +g.write("/etc/file_contexts", """/.* system_u:object_r:default_t:s0 +/bin/.* system_u:object_r:bin_t:s0 +/etc/.* system_u:object_r:etc_t:s0 +/etc/file_contexts <> +/tmp/.* <> +/var/.* system_u:object_r:var_t:s0 +/var/log/.* system_u:object_r:var_log_t:s0 +""") + +# Do the relabel. +g.selinux_relabel("/etc/file_contexts", "/", force=True) + +# Check the labels were set correctly. +errors = 0 + +def check_label(file, expected_label): + global errors + actual_label = g.lgetxattr(file, "security.selinux") + # The label returned from lgetxattr has \0 appended. + if (expected_label + "\0").encode() != actual_label: + print( + f"{prog}: expected label on file {file}: " + f"expected={expected_label} actual={actual_label.decode(errors='ignore')}", + file=sys.stderr, + ) + errors += 1 + +def check_label_none(file): + global errors + try: + r = g.lgetxattr(file, "security.selinux") + if r: + print( + f"{prog}: expecting no label on file {file}, " + f"but got {r.decode(errors='ignore')}", + file=sys.stderr, + ) + errors += 1 + except RuntimeError as e: + if "No data available" not in str(e): + print( + f"{prog}: expecting an error reading label from file {file}, " + f"but got {e}", + file=sys.stderr, + ) + errors += 1 + +check_label("/bin", "system_u:object_r:default_t:s0") +check_label("/bin/ls", "system_u:object_r:bin_t:s0") +check_label("/etc", "system_u:object_r:default_t:s0") +check_label_none("/etc/file_contexts") +check_label("/tmp", "system_u:object_r:default_t:s0") +check_label_none("/tmp/test") +check_label("/var", "system_u:object_r:default_t:s0") +check_label("/var/log", "system_u:object_r:var_t:s0") +check_label("/var/log/messages", "system_u:object_r:var_log_t:s0") + +# Finish up. +g.shutdown() +g.close() + +sys.exit(0 if errors == 0 else 1)