From 81ee155b9d385f73efa8540faea5725701d1ec5d Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 14 Jun 2012 12:38:01 +0100 Subject: tests: Add tests for extended attrs and SELinux, direct and via FUSE. Note that the SELinux + FUSE test is disabled because of: https://bugzilla.redhat.com/show_bug.cgi?id=811217 https://bugzilla.redhat.com/show_bug.cgi?id=812798#c42 --- tests/selinux/Makefile.am | 44 +++++ tests/selinux/run-test.pl | 336 +++++++++++++++++++++++++++++++++++ tests/selinux/test-selinux-direct.sh | 21 +++ tests/selinux/test-selinux-fuse.sh | 21 +++ tests/selinux/test-xattrs-direct.sh | 21 +++ tests/selinux/test-xattrs-fuse.sh | 21 +++ 6 files changed, 464 insertions(+) create mode 100644 tests/selinux/Makefile.am create mode 100755 tests/selinux/run-test.pl create mode 100755 tests/selinux/test-selinux-direct.sh create mode 100755 tests/selinux/test-selinux-fuse.sh create mode 100755 tests/selinux/test-xattrs-direct.sh create mode 100755 tests/selinux/test-xattrs-fuse.sh (limited to 'tests/selinux') diff --git a/tests/selinux/Makefile.am b/tests/selinux/Makefile.am new file mode 100644 index 00000000..29ee7fdc --- /dev/null +++ b/tests/selinux/Makefile.am @@ -0,0 +1,44 @@ +# libguestfs +# Copyright (C) 2012 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. + +# Test extended attributes and SELinux labelling, both using the API +# directly, and over FUSE. + +include $(top_srcdir)/subdir-rules.mk + +TESTS = \ + test-xattrs-direct.sh \ + test-selinux-direct.sh + +if HAVE_FUSE +TESTS += \ + test-xattrs-fuse.sh \ + test-selinux-fuse.sh +endif + +random_val := $(shell awk 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null) + +TESTS_ENVIRONMENT = \ + MALLOC_PERTURB_=$(random_val) \ + $(top_builddir)/run + +EXTRA_DIST = \ + run-test.pl \ + test-xattrs-direct.sh \ + test-xattrs-fuse.sh \ + test-selinux-direct.sh \ + test-selinux-fuse.sh diff --git a/tests/selinux/run-test.pl b/tests/selinux/run-test.pl new file mode 100755 index 00000000..4a0ccee4 --- /dev/null +++ b/tests/selinux/run-test.pl @@ -0,0 +1,336 @@ +#!/usr/bin/perl +# Copyright (C) 2012 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; +use Sys::Guestfs::Lib qw(feature_available); + +# These are two SELinux labels that we assume everyone is allowed to +# set under any policy. +my $label1 = "unconfined_u:object_r:user_tmp_t:s0"; +my $label2 = "unconfined_u:object_r:user_home_t:s0"; + +my $prog = $0; +$prog =~ s{.*/}{}; + +my $errors = 0; + +if (@ARGV == 3 && $ARGV[0] eq "--test") { + run_fuse_tests ($ARGV[1], $ARGV[2]); +} + +if (@ARGV != 2) { + print STDERR "$0: incorrect number of parameters for test\n"; + exit 1 +} + +my $test_type = $ARGV[0]; +die unless $test_type eq "xattrs" || $test_type eq "selinux"; +my $test_via = $ARGV[1]; +die unless $test_via eq "direct" || $test_via eq "fuse"; + +# SELinux labelling won't work (and can be skipped) if SELinux isn't +# installed or isn't enabled on the host. +if ($test_type eq "selinux") { + $_ = qx{getenforce 2>&1 ||:}; + chomp; + if ($_ ne "Enforcing" && $_ ne "Permissive") { + print "$prog $test_type $test_via: test skipped because SELinux is not enabled.\n"; + exit + } +} + +# Skip FUSE test if the kernel module is not available. +if ($test_via eq "fuse") { + unless (-w "/dev/fuse") { + print "$prog $test_type $test_via: test skipped because there is no /dev/fuse.\n"; + exit + } +} + +# For FUSE xattr test, setfattr program is required. +if ($test_type eq "xattrs" && $test_via eq "fuse") { + if (system ("setfattr --help >/dev/null 2>&1") != 0) { + print "$prog $test_type $test_via: test skipped because 'setfattr' is not installed.\n"; + exit + } +} + +# For SELinux on FUSE test, chcon program is required. +if ($test_type eq "selinux" && $test_via eq "fuse") { + if (system ("chcon --help >/dev/null 2>&1") != 0) { + print "$prog $test_type $test_via: test skipped because 'chcon' is not installed.\n"; + exit + } +} + +# SELinux on FUSE test won't work until SELinux (or FUSE) is fixed. +# See: +# https://bugzilla.redhat.com/show_bug.cgi?id=811217 +# https://bugzilla.redhat.com/show_bug.cgi?id=812798#c42 +if ($test_type eq "selinux" && $test_via eq "fuse") { + print "$prog $test_type $test_via: test skipped because SELinux and FUSE\n"; + print "don't work well together:\n"; + print "https://bugzilla.redhat.com/show_bug.cgi?id=811217\n"; + print "https://bugzilla.redhat.com/show_bug.cgi?id=812798#c42\n"; + exit; +} + +# Create a filesystem that could support xattrs and SELinux labels. +my $g = Sys::Guestfs->new (); + +#$g->set_selinux (1) if $test_type eq "selinux"; + +my $testimg = "test.img"; +open FILE, ">$testimg" or die "$testimg: $!"; +truncate FILE, 256*1024*1024 or die "$testimg: truncate: $!"; +close FILE or die "$testimg: $!"; + +$g->add_drive_opts ($testimg, format => "raw"); +$g->launch (); + +unless (feature_available ($g, "linuxxattrs")) { + print "$prog $test_type $test_via: test skipped because 'linuxxattrs' feature not available.\n"; + $g->close (); + unlink $testimg; + exit 0 +} + +$g->part_disk ("/dev/sda", "mbr"); +$g->mkfs ("ext4", "/dev/sda1"); + +$g->mount_options ("user_xattr", "/dev/sda1", "/"); + +# Run the test. +if ($test_via eq "direct") { + if ($test_type eq "xattrs") { + xattrs_direct (); + } elsif ($test_type eq "selinux") { + selinux_direct (); + } else { + die "unknown test type: $test_type"; + } +} else { + # Make a local mountpoint and mount it. + mkdir "mp" or die "mkdir: mp: $!"; + $g->mount_local ("mp"); + + # Run the test in another process. + my $pid = fork (); + die "fork: $!" unless defined $pid; + if ($pid == 0) { + exec ("./run-test.pl", "--test", "mp", $test_type); + die "run-test.pl: exec failed: $!\n"; + } + + $g->mount_local_run (); + + waitpid ($pid, 0); + $errors++ if $?; + + rmdir "mp" or die "rmdir: mp: $!"; +} + +# Finish up. +$g->close (); +unlink $testimg or die "$testimg: $!"; + +exit ($errors == 0 ? 0 : 1); + +# Run the FUSE tests in a subprocess. +sub run_fuse_tests +{ + my $mpdir = shift; + my $test_type = shift; # "xattrs" or "selinux" + + if ($test_type eq "xattrs") { + xattrs_fuse ($mpdir); + } elsif ($test_type eq "selinux") { + selinux_fuse ($mpdir); + } else { + die "unknown test type: $test_type"; + } + + # Unmount the test directory. + unmount ($mpdir); + + exit ($errors == 0 ? 0 : 1); +} + +# Unmount the FUSE directory. We may need to retry this a few times. +sub unmount +{ + my $mpdir = shift; + my $retries = 5; + + while ($retries > 0) { + if (system ("fusermount", "-u", $mpdir) == 0) { + last; + } + sleep 1; + $retries--; + } + + if ($retries == 0) { + die "failed to unmount FUSE directory\n"; + } +} + +# Test extended attributes, using the libguestfs API directly. +sub xattrs_direct +{ + $g->touch ("/test"); + $g->setxattr ("user.test", "test content", 12, "/test"); + my $attrval = $g->getxattr ("/test", "user.test"); + if ($attrval ne "test content") { + print STDERR "$prog: failed to set or get xattr using API.\n"; + $errors++; + } + my @xattrs = $g->getxattrs ("/test"); + my $found = 0; + foreach (@xattrs) { + if ($_->{attrname} eq "user.test" && $_->{attrval} eq "test content") { + $found++; + } + } + if ($found != 1) { + print STDERR "$prog: user.test xattr not returned by getxattrs.\n"; + $errors++; + } + $g->removexattr ("user.test", "/test"); + @xattrs = $g->getxattrs ("/test"); + $found = 0; + foreach (@xattrs) { + if ($_->{attrname} eq "user.test") { + $found++; + } + } + if ($found != 0) { + print STDERR "$prog: user.test xattr not removed by removexattr.\n"; + $errors++; + } +} + +# Test extended attributes, over FUSE. +sub xattrs_fuse +{ + my $mpdir = shift; + + open FILE, "> $mpdir/test" or die "$mpdir/test: $!"; + print FILE "test\n"; + close FILE; + + system ("setfattr", "-n", "user.test", "-v", "test content", "$mpdir/test") + == 0 or die "setfattr: $!"; + my @xattrs = qx{ getfattr -m '.*' -d $mpdir/test }; + my $found = 0; + foreach (@xattrs) { + if (m/^user.test="test content"$/) { + $found++; + } + } + if ($found != 1) { + print STDERR "$prog: user.test xattr not returned by getfattr.\n"; + $errors++; + } + + system ("setfattr", "-x", "user.test", "$mpdir/test") + == 0 or die "setfattr: $!"; + @xattrs = qx{ getfattr -m '.*' -d $mpdir/test }; + $found = 0; + foreach (@xattrs) { + if (m/^user.test=$/) { + $found++; + } + } + if ($found != 0) { + print STDERR "$prog: user.test xattr not removed by setfattr -x.\n"; + $errors++; + } +} + +# Test SELinux labels, using the libguestfs API directly. +sub selinux_direct +{ + $g->touch ("/test"); + + $g->setxattr ("security.selinux", $label1, length $label1, "/test"); + my $attrval = $g->getxattr ("/test", "security.selinux"); + if ($attrval ne $label1) { + print STDERR "$prog: failed to set or get selinux label '$label1' using API.\n"; + $errors++; + } + + $g->setxattr ("security.selinux", $label2, length $label2, "/test"); + $attrval = $g->getxattr ("/test", "security.selinux"); + if ($attrval ne $label2) { + print STDERR "$prog: failed to set or get selinux label '$label2' using API.\n"; + $errors++; + } + + my @xattrs = $g->getxattrs ("/test"); + my $found = 0; + foreach (@xattrs) { + if ($_->{attrname} eq "security.selinux" && $_->{attrval} eq $label2) { + $found++; + } + } + if ($found != 1) { + print STDERR "$prog: security.selinux xattr not returned by getxattrs.\n"; + $errors++; + } + $g->removexattr ("security.selinux", "/test"); + @xattrs = $g->getxattrs ("/test"); + $found = 0; + foreach (@xattrs) { + if ($_->{attrname} eq "security.selinux") { + $found++; + } + } + if ($found != 0) { + print STDERR "$prog: security.selinux xattr not removed by removexattr.\n"; + $errors++; + } +} + +# Test SELinux labels, over FUSE. +sub selinux_fuse +{ + my $mpdir = shift; + + open FILE, "> $mpdir/test" or die "$mpdir/test: $!"; + print FILE "test\n"; + close FILE; + + system ("chcon", $label1, "$mpdir/test") == 0 or die "chcon: $!"; + $_ = qx{ ls -Z $mpdir/test | awk '{print $4}' }; + chomp; + if ($_ ne $label1) { + print STDERR "$prog: failed to set of get selinux label '$label1' using FUSE.\n"; + $errors++; + } + + system ("chcon", $label2, "$mpdir/test") == 0 or die "chcon: $!"; + $_ = qx{ ls -Z $mpdir/test | awk '{print $4}' }; + chomp; + if ($_ ne $label2) { + print STDERR "$prog: failed to set of get selinux label '$label2' using FUSE.\n"; + $errors++; + } +} diff --git a/tests/selinux/test-selinux-direct.sh b/tests/selinux/test-selinux-direct.sh new file mode 100755 index 00000000..caf39f20 --- /dev/null +++ b/tests/selinux/test-selinux-direct.sh @@ -0,0 +1,21 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2012 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. + +rm -rf test.img mp + +exec ./run-test.pl selinux direct diff --git a/tests/selinux/test-selinux-fuse.sh b/tests/selinux/test-selinux-fuse.sh new file mode 100755 index 00000000..ab7b0ede --- /dev/null +++ b/tests/selinux/test-selinux-fuse.sh @@ -0,0 +1,21 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2012 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. + +rm -rf test.img mp + +exec ./run-test.pl selinux fuse diff --git a/tests/selinux/test-xattrs-direct.sh b/tests/selinux/test-xattrs-direct.sh new file mode 100755 index 00000000..354a496a --- /dev/null +++ b/tests/selinux/test-xattrs-direct.sh @@ -0,0 +1,21 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2012 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. + +rm -rf test.img mp + +exec ./run-test.pl xattrs direct diff --git a/tests/selinux/test-xattrs-fuse.sh b/tests/selinux/test-xattrs-fuse.sh new file mode 100755 index 00000000..87652612 --- /dev/null +++ b/tests/selinux/test-xattrs-fuse.sh @@ -0,0 +1,21 @@ +#!/bin/bash - +# libguestfs +# Copyright (C) 2012 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. + +rm -rf test.img mp + +exec ./run-test.pl xattrs fuse -- cgit