* [RFC PATCH 1/1] selinux-testsuite: Test all mount option context types
2020-02-04 14:37 [RFC PATCH 0/1] selinux-testsuite: Test all mount option context types Richard Haines
@ 2020-02-04 14:37 ` Richard Haines
2020-02-04 18:22 ` [RFC PATCH 0/1] " Stephen Smalley
1 sibling, 0 replies; 3+ messages in thread
From: Richard Haines @ 2020-02-04 14:37 UTC (permalink / raw)
To: selinux; +Cc: Richard Haines
Test supported filesystems for mount options: context, defcontext,
rootcontext and fscontext. The tests use fsconfig(2) and therefore does
not actually mount the filesystem to a target.
All /sbin/mkfs.* entries are read and if supported, tested with each option.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
policy/test_filesystem.te | 12 +++
tests/Makefile | 2 +-
tests/filesystem/Filesystem.pm | 19 +++-
tests/fs_contexts/.gitignore | 1 +
tests/fs_contexts/Makefile | 13 +++
tests/fs_contexts/fsconfig.c | 72 ++++++++++++++++
tests/fs_contexts/test | 153 +++++++++++++++++++++++++++++++++
7 files changed, 268 insertions(+), 4 deletions(-)
create mode 100644 tests/fs_contexts/.gitignore
create mode 100644 tests/fs_contexts/Makefile
create mode 100644 tests/fs_contexts/fsconfig.c
create mode 100755 tests/fs_contexts/test
diff --git a/policy/test_filesystem.te b/policy/test_filesystem.te
index 4ff493a..220f79e 100644
--- a/policy/test_filesystem.te
+++ b/policy/test_filesystem.te
@@ -6,6 +6,9 @@
attribute filesystemdomain;
kernel_setsched(filesystemdomain)
+# For module filesystems
+kernel_request_load_module(filesystemdomain)
+
#################### Create test file contexts ######################
type test_filesystem_filecon_t;
files_type(test_filesystem_filecon_t)
@@ -58,6 +61,15 @@ type_transition test_filesystem_t test_filesystem_file_t:file test_filesystem_fi
allow test_filesystem_t test_filesystem_filetranscon_t:file { create getattr open write relabelfrom };
dontaudit unconfined_t test_filesystem_filetranscon_t:file { getattr read };
+#
+# For fs_contexts tests
+#
+allow test_filesystem_t test_filesystem_file_t:filesystem { mount relabelfrom relabelto };
+allow test_filesystem_t unlabeled_t:filesystem { relabelfrom };
+# For fs_context test rootcontext= minix
+allow test_filesystem_file_t unlabeled_t:filesystem { associate };
+allow test_filesystem_t unlabeled_t:filesystem { mount };
+
#################### Deny filesystem { relabelfrom } ######################
# hooks.c may_context_mount_sb_relabel() FILESYSTEM__RELABELFROM
type test_filesystem_sb_relabel_no_relabelfrom_t;
diff --git a/tests/Makefile b/tests/Makefile
index 46a1641..87708fb 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -100,7 +100,7 @@ endif
ifeq ($(shell grep -q filesystem $(POLDEV)/include/support/all_perms.spt && echo true),true)
ifneq ($(shell ./kvercmp $$(uname -r) 5.2),-1)
-SUBDIRS += fs_filesystem
+SUBDIRS += fs_filesystem fs_contexts
endif
endif
diff --git a/tests/filesystem/Filesystem.pm b/tests/filesystem/Filesystem.pm
index 3d4194d..680bf0b 100644
--- a/tests/filesystem/Filesystem.pm
+++ b/tests/filesystem/Filesystem.pm
@@ -111,17 +111,30 @@ sub attach_dev {
sub make_fs {
my ( $mk_type, $mk_dev, $mk_dir ) = @_;
+
+ if ( $mk_type eq "btrfs" or $mk_type eq "reiserfs" ) {
+ $count = "count=27904";
+ }
+ else {
+ $count = "count=4096";
+ }
+
print "Create $mk_dir/fstest with dd\n";
- $result = system(
- "dd if=/dev/zero of=$mk_dir/fstest bs=1024 count=10240 2>/dev/null");
+ $result =
+ system("dd if=/dev/zero of=$mk_dir/fstest bs=4096 $count 2>/dev/null");
if ( $result != 0 ) {
print "dd failed to create $mk_dir/fstest\n";
}
attach_dev( $mk_dev, $mk_dir );
+ $opt = " ";
+ if ( $mk_type eq "reiserfs" ) {
+ $opt = "-q"; # Otherwise asks to proceed
+ }
+
print "Make $mk_type filesystem on $mk_dev\n";
- $result = system("mkfs.$mk_type -I 256 $mk_dev >& /dev/null");
+ $result = system("mkfs.$mk_type $opt $mk_dev >& /dev/null");
if ( $result != 0 ) {
system("losetup -d $mk_dev 2>/dev/null");
print "mkfs.$mk_type failed to create filesystem on $mk_dev\n";
diff --git a/tests/fs_contexts/.gitignore b/tests/fs_contexts/.gitignore
new file mode 100644
index 0000000..c870437
--- /dev/null
+++ b/tests/fs_contexts/.gitignore
@@ -0,0 +1 @@
+fsconfig
diff --git a/tests/fs_contexts/Makefile b/tests/fs_contexts/Makefile
new file mode 100644
index 0000000..012c4fa
--- /dev/null
+++ b/tests/fs_contexts/Makefile
@@ -0,0 +1,13 @@
+TARGETS = fsconfig
+USE_FS = ../fs_filesystem
+DEPS = $(USE_FS)/fs_common.c $(USE_FS)/fs_common.h
+LDLIBS += -lselinux
+
+all: $(TARGETS)
+ @set -e; for i in $(USE_FS); do $(MAKE) -C $$i all ; done
+
+clean:
+ rm -f $(TARGETS)
+ @set -e; for i in $(USE_FS); do $(MAKE) -C $$i clean ; done
+
+$(TARGETS): $(DEPS)
diff --git a/tests/fs_contexts/fsconfig.c b/tests/fs_contexts/fsconfig.c
new file mode 100644
index 0000000..e4cd8d8
--- /dev/null
+++ b/tests/fs_contexts/fsconfig.c
@@ -0,0 +1,72 @@
+#include "../fs_filesystem/fs_common.h"
+
+static void print_usage(char *progname)
+{
+ fprintf(stderr,
+ "usage: %s -s src -f fs_type -o options [-v]\n"
+ "Where:\n\t"
+ "-s Source path\n\t"
+ "-f Filesystem type\n\t"
+ "-o Options list (comma separated list)\n\t"
+ "-v Print information.\n", progname);
+ exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+ int opt, result, fsfd;
+ char *context, *src = NULL, *opts1, *fs_type = NULL, *opts = NULL;
+ bool verbose = false;
+
+ while ((opt = getopt(argc, argv, "s:f:o:v")) != -1) {
+ switch (opt) {
+ case 's':
+ src = optarg;
+ break;
+ case 'f':
+ fs_type = optarg;
+ break;
+ case 'o':
+ opts = optarg;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ print_usage(argv[0]);
+ }
+ }
+
+ if (!src || !fs_type || !opts)
+ print_usage(argv[0]);
+
+ if (verbose) {
+ result = getcon(&context);
+ if (result < 0) {
+ fprintf(stderr, "Failed to obtain process context\n");
+ return -1;
+ }
+ printf("Process context:\n\t%s\n", context);
+ free(context);
+ }
+
+ fsfd = fsopen(fs_type, 0);
+ if (fsfd < 0) {
+ fprintf(stderr, "Failed fsopen(2): %s\n", strerror(errno));
+ return -1;
+ }
+
+ opts1 = strdup(opts);
+
+ /* fsconfig_opts() will return 0 or errno from fsconfig(2) */
+ result = fsconfig_opts(fsfd, src, NULL, opts, verbose);
+ if (result) {
+ fprintf(stderr, "Failed config_opts\n");
+ return result;
+ }
+ if (verbose)
+ printf("Successfully added options: %s\n", opts1);
+
+ close(fsfd);
+ return 0;
+}
diff --git a/tests/fs_contexts/test b/tests/fs_contexts/test
new file mode 100755
index 0000000..8437dcb
--- /dev/null
+++ b/tests/fs_contexts/test
@@ -0,0 +1,153 @@
+#!/usr/bin/perl
+use Test::More;
+
+my @mkfs_list;
+my @fs_type_list;
+
+BEGIN {
+ $basedir = $0;
+ $basedir =~ s|(.*)/[^/]*|$1|;
+
+ # Load common subroutines.
+ use File::Basename qw(dirname);
+ use Cwd qw(abs_path);
+ use lib dirname( abs_path $0) . '/../filesystem';
+ use Filesystem
+ qw(udisks2_stop udisks2_restart get_loop_dev make_fs mk_mntpoint_1 cleanup1 reaper);
+
+ # Options: -v = Verbose, -e enable udisks(8) daemon
+ $v = " ";
+
+ # MUST stop udisksd(8) as it interferes with creating/deleting
+ # filesystems during these tests
+ $disable_udisks = 1;
+ $udisks2_status = 0;
+ foreach $arg (@ARGV) {
+ if ( $arg eq "-v" ) {
+ $v = $arg;
+ }
+ elsif ( $arg eq "-e" ) {
+ $disable_udisks = 0;
+ }
+ }
+
+ my @mkfs_list = map { chomp; $_ } `find /sbin/mkfs.* -printf "%f\n"`;
+ $i = 0;
+ foreach my $fstype (@mkfs_list) {
+ @split_fn = split( /\./, $fstype );
+ if ( $split_fn[1] eq "cramfs" ) {
+ print "$split_fn[1] - unsupported\n";
+ next;
+ }
+ elsif ($split_fn[1] eq "btrfs"
+ or $split_fn[1] eq "ext2"
+ or $split_fn[1] eq "ext3"
+ or $split_fn[1] eq "ext4"
+ or $split_fn[1] eq "fat"
+ or $split_fn[1] eq "hfsplus"
+ or $split_fn[1] eq "minix"
+ or $split_fn[1] eq "msdos"
+ or $split_fn[1] eq "ntfs"
+ or $split_fn[1] eq "reiserfs"
+ or $split_fn[1] eq "vfat"
+ or $split_fn[1] eq "xfs" )
+ {
+ $fs_type_list[$i] = $split_fn[1];
+ print "$split_fn[1] - supported\n";
+ $i++;
+ }
+ }
+
+ plan tests => ( $i * 4 );
+}
+
+# Keep a list of devices used for removal at end of test.
+$device_count = 0;
+my @device_list;
+
+if ($disable_udisks) {
+ $udisks2_status = udisks2_stop();
+}
+
+$context_opt = "context=system_u:object_r:test_filesystem_file_t:s0";
+$rootcontext_opt = "rootcontext=system_u:object_r:test_filesystem_file_t:s0";
+$defcontext_opt = "defcontext=system_u:object_r:test_filesystem_file_t:s0";
+$fscontext_opt = "fscontext=system_u:object_r:test_filesystem_file_t:s0";
+
+foreach my $fs_type (@fs_type_list) {
+ mk_mntpoint_1("$basedir/mntpoint");
+ ( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+ make_fs( $fs_type, $dev, $basedir );
+
+ if ( $fs_type eq "ntfs" ) {
+ $fs_type = "fuseblk";
+ }
+ if ( $fs_type eq "fat" ) {
+ $fs_type = "vfat";
+ }
+
+ # Test context
+ print "Testing context= for $fs_type\n";
+ $result = system(
+"runcon -t test_filesystem_t $basedir/fsconfig $v -f $fs_type -s $dev -o $context_opt 2>&1"
+ );
+ if ( $fs_type eq "fuseblk" ) { # This is expected to fail
+ ok(1);
+ }
+ else {
+ ok( $result eq 0 );
+ }
+
+ # Test defcontext
+ print "Testing defcontext= for $fs_type\n";
+ $result = system(
+"runcon -t test_filesystem_t $basedir/fsconfig $v -f $fs_type -s $dev -o $defcontext_opt 2>&1"
+ );
+ if ( $fs_type eq "vfat"
+ or $fs_type eq "hfsplus"
+ or $fs_type eq "minix"
+ or $fs_type eq "msdos"
+ or $fs_type eq "fuseblk"
+ or $fs_type eq "reiserfs" )
+ { # These are expected to fail
+ ok(1);
+ }
+ else {
+ ok( $result eq 0 );
+ }
+
+ # Test rootcontext
+ print "Testing rootcontext= for $fs_type\n";
+ $result = system(
+"runcon -t test_filesystem_t $basedir/fsconfig $v -f $fs_type -s $dev -o $rootcontext_opt 2>&1"
+ );
+ if ( $fs_type eq "fuseblk" ) { # This is expected to fail
+ ok(1);
+ }
+ else {
+ ok( $result eq 0 );
+ }
+
+ # Test fscontext
+ print "Testing fscontext= for $fs_type\n";
+ $result = system(
+"runcon -t test_filesystem_t $basedir/fsconfig $v -f $fs_type -s $dev -o $fscontext_opt 2>&1"
+ );
+ if ( $fs_type eq "fuseblk" ) { # This is expected to fail
+ ok(1);
+ }
+ else {
+ ok( $result eq 0 );
+ }
+
+ cleanup1( $basedir, $dev );
+}
+
+cleanup1( $basedir, $dev );
+reaper( \@device_list, $basedir, $v );
+
+if ($disable_udisks) {
+ udisks2_restart($udisks2_status);
+}
+
+exit;
--
2.24.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [RFC PATCH 0/1] selinux-testsuite: Test all mount option context types
2020-02-04 14:37 [RFC PATCH 0/1] selinux-testsuite: Test all mount option context types Richard Haines
2020-02-04 14:37 ` [RFC PATCH 1/1] " Richard Haines
@ 2020-02-04 18:22 ` Stephen Smalley
1 sibling, 0 replies; 3+ messages in thread
From: Stephen Smalley @ 2020-02-04 18:22 UTC (permalink / raw)
To: Richard Haines, selinux
On 2/4/20 9:37 AM, Richard Haines wrote:
> Not sure how useful these tests are but using them as a starter for running
> tests on all supported filesystems (that I could find).
>
> These test all the *context= mount options by reading /sbin/mkfs.* entries.
> I've failed/passed tests based on what I have seen, however some could be
> wrong.
A few preliminary comments:
- The existence of /sbin/mkfs.foo does not guarantee that the kernel
config enables the foo filesystem,
- I'm not sure that we really want to test all of these filesystem types
all the time; my earlier comments were more directed at enabling us to
apply as many of the existing filesystem + fs_filesystem tests as
possible to whatever filesystem type is in use as the native/host
filesystem type in which selinux-testsuite lives as is the case for all
other tests, so that distributions with different defaults will get
their own defaults tested automatically (e.g. ext4 vs xfs vs btrfs) when
run on their distribution and labeled NFS will be fully exercised when
running nfs.sh,
- Only exercising fsconfig(2) without actually mounting won't tell us if
the context is actually being applied as expected, unlike the existing
filesystem tests,
- Fail/pass shouldn't be based on what we happen to see when we run the
test but on what is known to be the actual correct behavior. Offhand,
the only cases expected to fail if allowed by policy would be use of any
of the context mount options in a non-init user namespace (except for
tmpfs/ramfs/devpts) or use of defcontext= with a filesystem type that
isn't fs_use_xattr in policy or using native labeling (labeled NFS).
>
> Notes:
> 1) As I use fsconfig(2), the btrfs tests will always fail as there is a
> bug somewhere in the kernel (being investigated).
> 2) I have had to disable udisks as that interferes with the tests. You can
> keep it enabled by ./test -e.
> I think there is really a problem with udisks getting in the way as I
> rapidly fsopen(fd), fsconfig(2) close(fd) for each test (on my system
> this equals 48 times).
>
> Richard Haines (1):
> selinux-testsuite: Test all mount option context types
>
> policy/test_filesystem.te | 12 +++
> tests/Makefile | 2 +-
> tests/filesystem/Filesystem.pm | 19 +++-
> tests/fs_contexts/.gitignore | 1 +
> tests/fs_contexts/Makefile | 13 +++
> tests/fs_contexts/fsconfig.c | 72 ++++++++++++++++
> tests/fs_contexts/test | 153 +++++++++++++++++++++++++++++++++
> 7 files changed, 268 insertions(+), 4 deletions(-)
> create mode 100644 tests/fs_contexts/.gitignore
> create mode 100644 tests/fs_contexts/Makefile
> create mode 100644 tests/fs_contexts/fsconfig.c
> create mode 100755 tests/fs_contexts/test
^ permalink raw reply [flat|nested] 3+ messages in thread