selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests
@ 2020-01-27  9:32 Richard Haines
  2020-01-27  9:32 ` [PATCH V2 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Richard Haines @ 2020-01-27  9:32 UTC (permalink / raw)
  To: selinux; +Cc: Richard Haines

These patches update the current tests/filesystem to share code (patch 1)
with the fs*(2) API filesystem tests (patch 2).

V2 Changes:
1) If kernel patch [1] installed move_mount test for denying FILE__MOUNTON
   should pass. If not installed, display 'Failed as kernel 5.x without
   "selinux: fix regression introduced by move_mount(2) syscall" patch'
   (as there is a regression that should be fixed).
   Note: Kernels 5.2 - 5.5 will fail unless [1] backported. 5.6 is expected
   to have [1].
2) Move policy changes to patch 2.

[1] https://lore.kernel.org/selinux/20200117202407.12344-1-sds@tycho.nsa.gov

Richard Haines (2):
  selinux-testsuite: Prepare for adding fs*(2) API tests
  selinux-testsuite: Add fs*(2) API filesystem tests

 policy/test_filesystem.te        |  18 +-
 tests/Makefile                   |   6 +
 tests/filesystem/Filesystem.pm   | 166 ++++++
 tests/filesystem/test            | 219 ++------
 tests/fs_filesystem/.gitignore   |   3 +
 tests/fs_filesystem/Makefile     |  16 +
 tests/fs_filesystem/fs_common.c  | 110 ++++
 tests/fs_filesystem/fs_common.h  |  30 ++
 tests/fs_filesystem/fsmount.c    |  89 ++++
 tests/fs_filesystem/fspick.c     |  68 +++
 tests/fs_filesystem/move_mount.c |  76 +++
 tests/fs_filesystem/test         | 835 +++++++++++++++++++++++++++++++
 tools/check-syntax               |   2 +-
 13 files changed, 1455 insertions(+), 183 deletions(-)
 create mode 100644 tests/filesystem/Filesystem.pm
 create mode 100644 tests/fs_filesystem/.gitignore
 create mode 100644 tests/fs_filesystem/Makefile
 create mode 100644 tests/fs_filesystem/fs_common.c
 create mode 100644 tests/fs_filesystem/fs_common.h
 create mode 100644 tests/fs_filesystem/fsmount.c
 create mode 100644 tests/fs_filesystem/fspick.c
 create mode 100644 tests/fs_filesystem/move_mount.c
 create mode 100755 tests/fs_filesystem/test

-- 
2.24.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH V2 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests
  2020-01-27  9:32 [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
@ 2020-01-27  9:32 ` Richard Haines
  2020-01-27  9:32 ` [PATCH V2 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
  2020-01-27 17:46 ` [PATCH V2 0/2] " Stephen Smalley
  2 siblings, 0 replies; 7+ messages in thread
From: Richard Haines @ 2020-01-27  9:32 UTC (permalink / raw)
  To: selinux; +Cc: Richard Haines

Update the current tests/filesystem to share code and perl subroutines.
Also update tools/check-syntax to handle *.pm files.

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
 tests/filesystem/Filesystem.pm | 166 +++++++++++++++++++++++++
 tests/filesystem/test          | 219 ++++++---------------------------
 tools/check-syntax             |   2 +-
 3 files changed, 206 insertions(+), 181 deletions(-)
 create mode 100644 tests/filesystem/Filesystem.pm

diff --git a/tests/filesystem/Filesystem.pm b/tests/filesystem/Filesystem.pm
new file mode 100644
index 0000000..3d4194d
--- /dev/null
+++ b/tests/filesystem/Filesystem.pm
@@ -0,0 +1,166 @@
+package Filesystem;
+use Exporter qw(import);
+our @EXPORT_OK =
+  qw(check_config udisks2_stop udisks2_restart get_loop_dev attach_dev make_fs mk_mntpoint_1 mk_mntpoint_2 cleanup cleanup1 reaper);
+
+sub check_config {
+    my ( $base, $fanotify_fs ) = @_;
+
+    $tst_count = 0;
+
+    # From kernel 5.5 support for fanotify(7) with filesystem { watch }
+    $kvercur = `uname -r`;
+    chomp($kvercur);
+    $kverminstream = "5.5";
+    $watch         = 0;
+
+    $result = `$base/../kvercmp $kvercur $kverminstream`;
+    if ( $result > 0 && -e $fanotify_fs ) {
+        $watch = 1;
+        $tst_count += 4;
+    }
+
+    $name_trans        = 0;
+    $pol_vers          = `checkpolicy -V | cut -f 1 -d ' '`;
+    $mod_pol_vers      = `checkmodule -V | cut -f 2 -d '-'`;
+    $max_kernel_policy = `cat /sys/fs/selinux/policyvers`;
+
+    if ( $mod_pol_vers >= 11 and $pol_vers >= 25 and $max_kernel_policy >= 25 )
+    {
+        $name_trans = 1;
+        $tst_count += 2;
+    }
+    return ( $tst_count, $watch, $name_trans );
+}
+
+# Optionally stop the udisks(8) daemon, then restart on exit.
+sub udisks2_stop {
+    $status = 0;
+
+    if ( -e "/usr/bin/systemctl" ) {
+        $u_status_cmd = "/usr/bin/systemctl status udisks2 >& /dev/null";
+        $u_stop_cmd   = "/usr/bin/systemctl stop udisks2 >& /dev/null";
+    }
+    elsif ( -e "/usr/sbin/service" ) {
+        $u_status_cmd = "/usr/sbin/service udisks2 status >& /dev/null";
+        $u_stop_cmd   = "/usr/sbin/service udisks2 stop >& /dev/null";
+    }
+
+    if ($u_status_cmd) {
+        $result = system("$u_status_cmd");
+        $status = $result >> 8;
+        if ( $status eq 0 ) {
+            print "Stopping udisks2 service for these tests.\n";
+            system("$u_stop_cmd");
+            $status = 3;
+        }
+        else {
+            $status = 4;
+        }
+    }
+    return $status;
+}
+
+sub udisks2_restart {
+    my ($status) = @_;
+
+    if ( $status eq 3 ) {
+        print "Restarting udisks2 service.\n";
+        if ( -e "/usr/bin/systemctl" ) {
+            system("/usr/bin/systemctl start udisks2 >& /dev/null");
+        }
+        elsif ( -e "/usr/sbin/service" ) {
+            system("/usr/sbin/service udisks2 start >& /dev/null");
+        }
+    }
+}
+
+sub get_loop_dev {
+    my ( $dev_list, $dev_count ) = @_;
+
+    system("udevadm settle");
+    print "Finding free /dev/loop entry\n";
+    $new_dev = `losetup -f 2>/dev/null`;
+    chomp($new_dev);
+    if ( $new_dev eq "" ) {
+        print "losetup failed to obtain /dev/loop entry\n";
+    }
+
+    # Keep list of devices for cleanup later
+    if ( $dev_count eq 0 ) {
+        $dev_list[$dev_count] = $new_dev;
+        $dev_count += 1;
+    }
+    elsif ( $new_dev ne $dev_list[ $dev_count - 1 ] ) {
+        $dev_list[$dev_count] = $new_dev;
+        $dev_count += 1;
+    }
+    return ( $new_dev, $dev_count );
+}
+
+sub attach_dev {
+    my ( $att_dev, $base ) = @_;
+    system("udevadm settle");
+    print "Attaching $base/fstest to $att_dev\n";
+    $result = system("losetup $att_dev $base/fstest 2>/dev/null");
+    if ( $result != 0 ) {
+        print "Failed to attach $base/fstest to $att_dev\n";
+    }
+    system("udevadm settle");
+}
+
+sub make_fs {
+    my ( $mk_type, $mk_dev, $mk_dir ) = @_;
+    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");
+    if ( $result != 0 ) {
+        print "dd failed to create $mk_dir/fstest\n";
+    }
+
+    attach_dev( $mk_dev, $mk_dir );
+
+    print "Make $mk_type filesystem on $mk_dev\n";
+    $result = system("mkfs.$mk_type -I 256 $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";
+    }
+}
+
+sub mk_mntpoint_1 {
+    my ($path) = @_;
+    system("rm -rf $path/mp1 2>/dev/null");
+    system("mkdir -p $path/mp1 2>/dev/null");
+}
+
+sub mk_mntpoint_2 {
+    my ($path) = @_;
+    system("rm -rf $path/mp2 2>/dev/null");
+    system("mkdir -p $path/mp2 2>/dev/null");
+}
+
+sub cleanup {
+    my ($base) = @_;
+    system("rm -rf $base/fstest 2>/dev/null");
+    system("rm -rf $base/mntpoint 2>/dev/null");
+}
+
+sub cleanup1 {
+    my ( $base, $d ) = @_;
+    system("udevadm settle");
+    system("losetup -d $d 2>/dev/null");
+    system("udevadm settle");
+    system("rm -rf $base/fstest 2>/dev/null");
+    system("rm -rf $base/mntpoint 2>/dev/null");
+}
+
+# Cleanup any attached /dev/loop entries
+sub reaper {
+    my ( $dev_list, $base, $v ) = @_;
+
+    foreach my $n (@dev_list) {
+        system("udevadm settle");
+        system("$base/grim_reaper -t $n $v 2>/dev/null");
+    }
+}
diff --git a/tests/filesystem/test b/tests/filesystem/test
index 1d90fdf..5bdd124 100755
--- a/tests/filesystem/test
+++ b/tests/filesystem/test
@@ -5,6 +5,13 @@ 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);
+    use Filesystem
+      qw(check_config udisks2_stop udisks2_restart get_loop_dev attach_dev make_fs mk_mntpoint_1 mk_mntpoint_2 cleanup cleanup1 reaper);
+
     $test_count = 68;
 
     # Options: -v = Verbose, -d disable udisks(8) daemon
@@ -20,29 +27,11 @@ BEGIN {
         }
     }
 
-    # From kernel 5.5 support for fanotify(7) with filesystem { watch }
-    $kvercur = `uname -r`;
-    chomp($kvercur);
-    $kverminstream = "5.5";
-
-    $result = `$basedir/../kvercmp $kvercur $kverminstream`;
-    if ( $result > 0 && -e "$basedir/fanotify_fs" ) {
-        $test_watch = 1;
-        $test_count += 4;
-    }
-
-    $test_name_trans   = 0;
-    $pol_vers          = `checkpolicy -V | cut -f 1 -d ' '`;
-    $mod_pol_vers      = `checkmodule -V | cut -f 2 -d '-'`;
-    $max_kernel_policy = `cat /sys/fs/selinux/policyvers`;
+    # Check if watch and/or named type_transition rules configured
+    ( $addit, $test_watch, $test_name_trans ) =
+      check_config( $basedir, "$basedir/fanotify_fs" );
 
-    if ( $mod_pol_vers >= 11 and $pol_vers >= 25 and $max_kernel_policy >= 25 )
-    {
-        $test_name_trans = 1;
-        $test_count += 2;
-    }
-
-    plan tests => $test_count;
+    plan tests => ( $test_count += $addit );
 }
 
 # mount(2) MS_BIND | MS_PRIVATE requires an absolute path to a private mount
@@ -60,139 +49,9 @@ else {
 # Set initial filesystem type
 $fs_type = "ext4";
 
-# For list of devices used
+# Keep a list of devices used for removal at end of test.
 $device_count = 0;
-
-# Optionally stop the udisks(8) daemon, then restart on exit.
-sub udisks2_stop {
-    $status = 0;
-
-    if ( -e "/usr/bin/systemctl" ) {
-        $u_status_cmd = "/usr/bin/systemctl status udisks2 >& /dev/null";
-        $u_stop_cmd   = "/usr/bin/systemctl stop udisks2 >& /dev/null";
-    }
-    elsif ( -e "/usr/sbin/service" ) {
-        $u_status_cmd = "/usr/sbin/service udisks2 status >& /dev/null";
-        $u_stop_cmd   = "/usr/sbin/service udisks2 stop >& /dev/null";
-    }
-
-    if ($u_status_cmd) {
-        $result = system("$u_status_cmd");
-        $status = $result >> 8;
-        if ( $status eq 0 ) {
-            print "Stopping udisks2 service for these tests.\n";
-            system("$u_stop_cmd");
-            $status = 3;
-        }
-        else {
-            $status = 4;
-        }
-    }
-    return $status;
-}
-
-sub udisks2_restart {
-    my ($status) = @_;
-
-    if ( $status eq 3 ) {
-        print "Restarting udisks2 service.\n";
-        if ( -e "/usr/bin/systemctl" ) {
-            system("/usr/bin/systemctl start udisks2 >& /dev/null");
-        }
-        elsif ( -e "/usr/sbin/service" ) {
-            system("/usr/sbin/service udisks2 start >& /dev/null");
-        }
-    }
-}
-
-sub get_loop_dev {
-    system("udevadm settle");
-    print "Finding free /dev/loop entry\n";
-    $get_dev = `losetup -f 2>/dev/null`;
-    chomp($get_dev);
-    if ( $get_dev eq "" ) {
-        print "losetup failed to obtain /dev/loop entry\n";
-    }
-
-    # Keep list of devices for cleanup later
-    if ( $device_count eq 0 ) {
-        $device_list[$device_count] = $get_dev;
-        $device_count += 1;
-    }
-    elsif ( $get_dev ne $device_list[ $device_count - 1 ] ) {
-        $device_list[$device_count] = $get_dev;
-        $device_count += 1;
-    }
-    return $get_dev;
-}
-
-sub attach_dev {
-    my ( $att_dev, $base ) = @_;
-    system("udevadm settle");
-    print "Attaching $base/fstest to $att_dev\n";
-    $result = system("losetup $att_dev $base/fstest 2>/dev/null");
-    if ( $result != 0 ) {
-        print "Failed to attach $base/fstest to $att_dev\n";
-    }
-    system("udevadm settle");
-}
-
-sub make_fs {
-    my ( $mk_type, $mk_dev, $mk_dir ) = @_;
-    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");
-    if ( $result != 0 ) {
-        print "dd failed to create $mk_dir/fstest\n";
-    }
-
-    attach_dev( $mk_dev, $mk_dir );
-
-    print "Make $mk_type filesystem on $mk_dev\n";
-    $result = system("mkfs.$mk_type -I 256 $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";
-    }
-}
-
-sub mk_mntpoint_1 {
-    my ($path) = @_;
-    system("rm -rf $path/mp1 2>/dev/null");
-    system("mkdir -p $path/mp1 2>/dev/null");
-}
-
-sub mk_mntpoint_2 {
-    my ($path) = @_;
-    system("rm -rf $path/mp2 2>/dev/null");
-    system("mkdir -p $path/mp2 2>/dev/null");
-}
-
-sub cleanup {
-    my ($base) = @_;
-    system("rm -rf $base/fstest 2>/dev/null");
-    system("rm -rf $base/mntpoint 2>/dev/null");
-}
-
-sub cleanup1 {
-    my ( $base, $d ) = @_;
-    system("udevadm settle");
-    system("losetup -d $d 2>/dev/null");
-    system("udevadm settle");
-    system("rm -rf $base/fstest 2>/dev/null");
-    system("rm -rf $base/mntpoint 2>/dev/null");
-}
-
-# Cleanup any attached /dev/loop entries
-sub reaper {
-    my ( $base, $v ) = @_;
-
-    foreach my $n (@device_list) {
-        system("$base/grim_reaper -t $n $v 2>/dev/null");
-    }
-}
-
-# End subroutines
+my @device_list;
 
 if ($disable_udisks) {
     $udisks2_status = udisks2_stop();
@@ -216,7 +75,7 @@ system("rm -rf $basedir/mntpoint 2>/dev/null");
 
 ############### Test Basic Mount/Unmount ##########################
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $mount_opts1 =
 "quota,usrquota,grpquota,defcontext=system_u:object_r:test_filesystem_file_t:s0";
@@ -306,7 +165,7 @@ cleanup1( $basedir, $dev );
 
 ############### Test Move Mount ##########################
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $mount_opts2 =
 "quota,usrquota,grpquota,rootcontext=system_u:object_r:test_filesystem_file_t:s0";
@@ -353,7 +212,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { relabelfrom } ##########################
 # hooks.c may_context_mount_sb_relabel() FILESYSTEM__RELABELFROM
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_relabelfrom =
   "defcontext=system_u:object_r:test_filesystem_sb_relabel_no_relabelfrom_t:s0";
@@ -371,7 +230,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { relabelto } ##########################
 # hooks.c may_context_mount_sb_relabel() FILESYSTEM__RELABELTO
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_relabelto =
   "fscontext=system_u:object_r:test_filesystem_sb_relabel_no_relabelto_t:s0";
@@ -389,7 +248,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { relabelfrom } ##########################
 # hooks.c may_context_mount_inode_relabel() FILESYSTEM__RELABELFROM
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_relabelfrom =
   "rootcontext=system_u:object_r:test_filesystem_no_inode_no_relabelfrom_t:s0";
@@ -407,7 +266,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { associate } ##########################
 # hooks.c may_context_mount_inode_relabel() FILESYSTEM__ASSOCIATE
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 
 # This defcontext will trigger denial.
@@ -427,7 +286,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { associate } ##########################
 # hooks.c may_create() FILESYSTEM__ASSOCIATE
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 
 # Use this fscontext= to get sensible audit log entry of:
@@ -462,7 +321,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { quotamod } ##########################
 # hooks.c selinux_quotactl() FILESYSTEM__QUOTAMOD
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_quotamod =
 "quota,usrquota,grpquota,fscontext=system_u:object_r:test_filesystem_no_quotamod_t:s0";
@@ -475,7 +334,7 @@ $result = system(
 ok( $result eq 0 );
 
 # No need to run quotacheck(8) as never gets far enough to read quota file
-print "Toggle User & Group quotas on/off\n";    # Must have full path
+print "Toggle User & Group quotas on/off\n";
 $result = system(
 "runcon -t test_filesystem_no_quotamod_t $basedir/quotas_test -s $dev -t $private_path/mp1/aquota.user $v 2>&1"
 );
@@ -493,7 +352,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { quotaget } ##########################
 # hooks.c selinux_quotactl() FILESYSTEM__QUOTAGET
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_quotaget =
 "quota,usrquota,grpquota,context=system_u:object_r:test_filesystem_no_quotaget_t:s0";
@@ -509,7 +368,7 @@ print "Running quotacheck(8) to init user/group quota files\n";
 $result = system("runcon `id -Z` quotacheck -ugF vfsv0 $private_path/mp1");
 ok( $result eq 0 );
 
-print "Toggle User & Group quotas on/off\n";    # Must have full path
+print "Toggle User & Group quotas on/off\n";
 $result = system(
 "runcon -t test_filesystem_no_quotaget_t $basedir/quotas_test -s $dev -t $private_path/mp1/aquota.user $v 2>&1"
 );
@@ -527,7 +386,7 @@ cleanup1( $basedir, $dev );
 ############### Deny file { quotaon } ##########################
 # hooks.c selinux_quota_on() FILE__QUOTAON
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_quotaon =
   "quota,usrquota,grpquota,context=system_u:object_r:test_file_no_quotaon_t:s0";
@@ -543,7 +402,7 @@ print "Running quotacheck(8) to init user/group quota files\n";
 $result = system("runcon `id -Z` quotacheck -ugF vfsv0 $private_path/mp1");
 ok( $result eq 0 );
 
-print "Toggle User quotas on/off\n";    # Must have full path
+print "Toggle User quotas on/off\n";
 $result = system(
 "runcon -t test_file_no_quotaon_t $basedir/quotas_test -s $dev -t $private_path/mp1/aquota.user $v 2>&1"
 );
@@ -561,7 +420,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { mount } ##########################
 # hooks.c selinux_sb_kern_mount() FILESYSTEM__MOUNT
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_mount = "rootcontext=system_u:object_r:test_filesystem_no_mount_t:s0";
 
@@ -578,7 +437,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { getattr } ##########################
 # hooks.c selinux_sb_statfs() FILESYSTEM__GETATTR
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_getattr =
   "rootcontext=system_u:object_r:test_filesystem_no_getattr_t:s0";
@@ -607,7 +466,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { remount } ##########################
 # hooks.c selinux_mount() FILESYSTEM__REMOUNT
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_remount =
   "rootcontext=system_u:object_r:test_filesystem_no_remount_t:s0";
@@ -637,7 +496,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { unmount } ##########################
 # hooks.c selinux_umount() FILESYSTEM__UNMOUNT
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_unmount =
   "rootcontext=system_u:object_r:test_filesystem_no_unmount_t:s0";
@@ -668,7 +527,7 @@ cleanup1( $basedir, $dev );
 ############### Deny filesystem { associate }  ##########################
 # hooks.c selinux_inode_setxattr() FILESYSTEM__ASSOCIATE
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $opts_no_associate_xattr =
 "defcontext=system_u:object_r:test_filesystem_inode_setxattr_no_associate_t:s0,fscontext=system_u:object_r:test_filesystem_inode_setxattr_no_associate_t:s0";
@@ -701,7 +560,7 @@ cleanup1( $basedir, $dev );
 # hooks.c selinux_path_notify() FILESYSTEM__WATCH
 if ($test_watch) {
     mk_mntpoint_1($private_path);
-    $dev = get_loop_dev();
+    ( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
     make_fs( $fs_type, $dev, $basedir );
     $opts_no_watch = "context=system_u:object_r:test_filesystem_no_watch_t:s0";
 
@@ -738,7 +597,7 @@ if ($test_watch) {
 #               files within the mount fails with errno EOPNOTSUPP.
 ##########################################################################
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 
 # Mount with xttrs to create a file with specific context.
@@ -769,7 +628,7 @@ ok( $result eq 0 );
 
 # Need to free the loop device, then get new one and attach
 system("losetup -d $dev 2>/dev/null");
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 attach_dev( $dev, $basedir );
 
 # Mount again with no xttr support
@@ -816,7 +675,7 @@ cleanup1( $basedir, $dev );
 #               the mount operation.
 ##########################################################################
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $root_opts = "rootcontext=system_u:object_r:test_filesystem_context_file_t:s0";
 
@@ -863,7 +722,7 @@ cleanup1( $basedir, $dev );
 #               where defcontext differs from the policy default.
 ##########################################################################
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 make_fs( $fs_type, $dev, $basedir );
 $test_opts = "context=system_u:object_r:test_filesystem_context_file_t:s0";
 
@@ -891,7 +750,7 @@ ok( $result eq 0 );
 
 # Need to free the loop device, then get new dev one and attach
 system("losetup -d $dev 2>/dev/null");
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 attach_dev( $dev, $basedir );
 
 # Mount again with defcontext=
@@ -930,7 +789,7 @@ cleanup1( $basedir, $dev );
 ##########################################################################
 $fs_type = "tmpfs";
 mk_mntpoint_1($private_path);
-$dev = get_loop_dev();
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
 $fscontext_opts =
 "fscontext=system_u:object_r:test_filesystem_fscontext_fs_t:s0,size=10M,mode=0770";
 
@@ -959,7 +818,7 @@ ok( $result eq 0 );
 print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
 cleanup1( $basedir, $dev );
 
-reaper( $basedir, $v );
+reaper( \@device_list, $basedir, $v );
 
 if ($disable_udisks) {
     udisks2_restart($udisks2_status);
diff --git a/tools/check-syntax b/tools/check-syntax
index 7f9768d..0ca79e2 100755
--- a/tools/check-syntax
+++ b/tools/check-syntax
@@ -13,7 +13,7 @@
 CHK_C_LIST="$(find tests/ -name "*.c") $(find tests/ -name "*.h")"
 CHK_C_EXCLUDE=""
 
-CHK_PERL_LIST="$(find tests/ -name "*.pl") $(find tests/ -name "test")"
+CHK_PERL_LIST="$(find tests/ -name "*.pl") $(find tests/ -name "test") $(find tests/ -name "*.pm")"
 CHK_PERL_EXCLUDE=""
 
 ####
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH V2 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-27  9:32 [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
  2020-01-27  9:32 ` [PATCH V2 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
@ 2020-01-27  9:32 ` Richard Haines
  2020-01-29 18:21   ` Stephen Smalley
  2020-01-27 17:46 ` [PATCH V2 0/2] " Stephen Smalley
  2 siblings, 1 reply; 7+ messages in thread
From: Richard Haines @ 2020-01-27  9:32 UTC (permalink / raw)
  To: selinux; +Cc: Richard Haines

Test filesystem permissions using the fsopen(2), fsconfig(2), fsmount(2),
fspick(2) and fsmount(2) api's introduced in kernel 5.2.

Also tests move_mount(2) using open_tree(2).

These tests use common code from tests/filesystem.

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
---
 policy/test_filesystem.te        |  18 +-
 tests/Makefile                   |   6 +
 tests/fs_filesystem/.gitignore   |   3 +
 tests/fs_filesystem/Makefile     |  16 +
 tests/fs_filesystem/fs_common.c  | 110 ++++
 tests/fs_filesystem/fs_common.h  |  30 ++
 tests/fs_filesystem/fsmount.c    |  89 ++++
 tests/fs_filesystem/fspick.c     |  68 +++
 tests/fs_filesystem/move_mount.c |  76 +++
 tests/fs_filesystem/test         | 835 +++++++++++++++++++++++++++++++
 10 files changed, 1249 insertions(+), 2 deletions(-)
 create mode 100644 tests/fs_filesystem/.gitignore
 create mode 100644 tests/fs_filesystem/Makefile
 create mode 100644 tests/fs_filesystem/fs_common.c
 create mode 100644 tests/fs_filesystem/fs_common.h
 create mode 100644 tests/fs_filesystem/fsmount.c
 create mode 100644 tests/fs_filesystem/fspick.c
 create mode 100644 tests/fs_filesystem/move_mount.c
 create mode 100755 tests/fs_filesystem/test

diff --git a/policy/test_filesystem.te b/policy/test_filesystem.te
index a029a1b..9cf8903 100644
--- a/policy/test_filesystem.te
+++ b/policy/test_filesystem.te
@@ -233,6 +233,22 @@ fs_relabelfrom_all_fs(test_filesystem_no_remount_t)
 fs_associate(test_filesystem_no_remount_t)
 allow test_filesystem_no_remount_t test_file_t:dir { mounton write remove_name rmdir };
 
+#################### Deny file { mounton } ######################
+# hooks.c selinux_move_mount() FILE__MOUNTON
+type test_move_mount_no_mounton_t;
+domain_type(test_move_mount_no_mounton_t)
+unconfined_runs_test(test_move_mount_no_mounton_t)
+typeattribute test_move_mount_no_mounton_t testdomain;
+typeattribute test_move_mount_no_mounton_t filesystemdomain;
+
+allow test_move_mount_no_mounton_t self:capability { sys_admin };
+fs_mount_all_fs(test_move_mount_no_mounton_t)
+fs_unmount_all_fs(test_move_mount_no_mounton_t)
+fs_relabelfrom_all_fs(test_move_mount_no_mounton_t)
+fs_associate(test_move_mount_no_mounton_t)
+allow test_move_mount_no_mounton_t test_file_t:dir { mounton write remove_name rmdir };
+# neverallow test_move_mount_no_mounton_t self:dir { mounton };
+
 #################### Deny filesystem { unmount } ######################
 # hooks.c selinux_umount() FILESYSTEM__UNMOUNT
 type test_filesystem_no_unmount_t;
@@ -273,8 +289,6 @@ dontaudit unconfined_t test_filesystem_filecon_t:file { getattr read };
 allow test_filesystem_inode_setxattr_no_associate_t unconfined_t:dir { add_name write };
 allow test_filesystem_inode_setxattr_no_associate_t unconfined_t:file { create relabelfrom relabelto };
 
-#allow test_filesystem_inode_setxattr_no_associate_t unconfined_t:file { open read getattr write };
-
 #################### Deny filesystem { watch } ######################
 # hooks.c selinux_path_notify() FILESYSTEM__WATCH
 type test_filesystem_no_watch_t;
diff --git a/tests/Makefile b/tests/Makefile
index a1478f1..46a1641 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -98,6 +98,12 @@ export CFLAGS += -DHAVE_FS_WATCH_PERM
 endif
 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
+endif
+endif
+
 ifeq ($(DISTRO),RHEL4)
     SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS))
 endif
diff --git a/tests/fs_filesystem/.gitignore b/tests/fs_filesystem/.gitignore
new file mode 100644
index 0000000..449f625
--- /dev/null
+++ b/tests/fs_filesystem/.gitignore
@@ -0,0 +1,3 @@
+fsmount
+fspick
+move_mount
diff --git a/tests/fs_filesystem/Makefile b/tests/fs_filesystem/Makefile
new file mode 100644
index 0000000..f7ae89d
--- /dev/null
+++ b/tests/fs_filesystem/Makefile
@@ -0,0 +1,16 @@
+TARGETS = fsmount fspick move_mount
+
+DEPS = fs_common.c fs_common.h
+
+LDLIBS += -lselinux
+
+USE_FS = ../filesystem
+
+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_filesystem/fs_common.c b/tests/fs_filesystem/fs_common.c
new file mode 100644
index 0000000..79200ac
--- /dev/null
+++ b/tests/fs_filesystem/fs_common.c
@@ -0,0 +1,110 @@
+#include "fs_common.h"
+
+int fsopen(const char *fs_name, unsigned int flags)
+{
+	return syscall(__NR_fsopen, fs_name, flags);
+}
+
+int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
+{
+	return syscall(__NR_fsmount, fsfd, flags, ms_flags);
+}
+
+int fsconfig(int fsfd, unsigned int cmd, const char *key,
+	     const void *val, int aux)
+{
+	return syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
+}
+
+int fspick(int dirfd, const char *pathname, unsigned int flags)
+{
+	return syscall(__NR_fspick, dirfd, pathname, flags);
+}
+
+int move_mount(int from_dfd, const char *from_pathname, int to_dfd,
+	       const char *to_pathname, unsigned int flags)
+{
+	return syscall(__NR_move_mount, from_dfd, from_pathname,
+		       to_dfd, to_pathname, flags);
+}
+
+int open_tree(int dirfd, const char *pathname, unsigned int flags)
+{
+	return syscall(__NR_open_tree, dirfd, pathname, flags);
+}
+
+int fsconfig_opts(int fd, char *src, char *tgt, char *opts, bool verbose)
+{
+	int result, i, save_errno, start_count, max_entries = 0;
+	int cmd[MAX_OPS];
+	char *key[MAX_OPS], *value[MAX_OPS];
+	char *src_str = "source";
+
+	/* If src then fsmount(2), else its going to be fspick(2) */
+	if (src) {
+		cmd[0] = FSCONFIG_SET_STRING;
+		key[0] = src_str;
+		value[0] = src;
+		start_count = 1;
+	} else {
+		start_count = 0;
+	}
+
+	for (i = start_count; i < MAX_OPS; i++) {
+		value[i] = strsep(&opts, ",");
+		if (!value[i]) {
+			max_entries = i + 1;
+			break;
+		}
+		cmd[i] = FSCONFIG_SET_STRING;
+	}
+
+	for (i = start_count; value[i] != NULL; i++) {
+		key[i] = strsep(&value[i], "=");
+		if (!value[i])
+			cmd[i] = FSCONFIG_SET_FLAG;
+	}
+
+	if (src) {
+		cmd[i] = FSCONFIG_CMD_CREATE;
+		key[i] = NULL;
+		value[i] = NULL;
+	} else {
+		cmd[i] = FSCONFIG_CMD_RECONFIGURE;
+		key[i] = NULL;
+		value[i] = NULL;
+	}
+
+	for (i = 0; i != max_entries; i++) {
+		if (verbose) {
+			switch (cmd[i]) {
+			case FSCONFIG_CMD_CREATE:
+				printf("fsconfig(FSCONFIG_CMD_CREATE, %s, %s, 0)\n",
+				       key[i], value[i]);
+				break;
+			case FSCONFIG_CMD_RECONFIGURE:
+				printf("fsconfig(FSCONFIG_CMD_RECONFIGURE, %s, %s, 0)\n",
+				       key[i], value[i]);
+				break;
+			case FSCONFIG_SET_FLAG:
+				printf("fsconfig(FSCONFIG_SET_FLAG, %s, %s, 0)\n",
+				       key[i], value[i]);
+				break;
+			case FSCONFIG_SET_STRING:
+				printf("fsconfig(FSCONFIG_SET_STRING, %s, %s, 0)\n",
+				       key[i], value[i]);
+				break;
+			}
+		}
+
+		result = fsconfig(fd, cmd[i], key[i], value[i], 0);
+		save_errno = errno;
+		if (result < 0) {
+			fprintf(stderr, "Failed fsconfig(2): %s\n",
+				strerror(save_errno));
+			return save_errno;
+		}
+	}
+
+	return 0;
+}
diff --git a/tests/fs_filesystem/fs_common.h b/tests/fs_filesystem/fs_common.h
new file mode 100644
index 0000000..e2fd08f
--- /dev/null
+++ b/tests/fs_filesystem/fs_common.h
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <sys/prctl.h>
+#include <linux/mount.h>
+#include <linux/unistd.h>
+#include <selinux/selinux.h>
+
+#ifndef AT_EMPTY_PATH
+#define AT_EMPTY_PATH		0x1000
+#endif
+#ifndef AT_RECURSIVE
+#define AT_RECURSIVE		0x8000
+#endif
+
+int fsopen(const char *fs_name, unsigned int flags);
+int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags);
+int fsconfig(int fsfd, unsigned int cmd, const char *key,
+	     const void *val, int aux);
+int move_mount(int from_dfd, const char *from_pathname, int to_dfd,
+	       const char *to_pathname, unsigned int flags);
+int open_tree(int dirfd, const char *pathname, unsigned int flags);
+int fspick(int dirfd, const char *pathname, unsigned int flags);
+
+#define MAX_OPS 40
+int fsconfig_opts(int fd, char *src, char *tgt, char *opts, bool verbose);
diff --git a/tests/fs_filesystem/fsmount.c b/tests/fs_filesystem/fsmount.c
new file mode 100644
index 0000000..320d82a
--- /dev/null
+++ b/tests/fs_filesystem/fsmount.c
@@ -0,0 +1,89 @@
+#include "fs_common.h"
+
+static void print_usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s -s src -t tgt -f fs_type [-o options] [-v]\n"
+		"Where:\n\t"
+		"-s  Source path\n\t"
+		"-t  Target 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, mfd;
+	char *context, *src = NULL, *tgt = NULL, *fs_type = NULL, *opts = NULL;
+	bool verbose = false;
+
+	while ((opt = getopt(argc, argv, "s:t:f:o:v")) != -1) {
+		switch (opt) {
+		case 's':
+			src = optarg;
+			break;
+		case 't':
+			tgt = 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 || !tgt || !fs_type)
+		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);
+	}
+
+	if (verbose)
+		printf("Mounting\n\tsrc: %s\n\ttgt: %s\n\tfs_type: %s\n\topts: %s\n",
+		       src, tgt, fs_type, opts);
+
+	fsfd = fsopen(fs_type, 0);
+	if (fsfd < 0) {
+		fprintf(stderr, "Failed fsopen(2): %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* config_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;
+	}
+
+	mfd = fsmount(fsfd, 0, 0);
+	if (mfd < 0) {
+		fprintf(stderr, "Failed fsmount(2): %s\n", strerror(errno));
+		return -1;
+	}
+	close(fsfd);
+
+	result = move_mount(mfd, "", AT_FDCWD, tgt, MOVE_MOUNT_F_EMPTY_PATH);
+	if (result < 0) {
+		fprintf(stderr, "Failed move_mount(2): %s\n", strerror(errno));
+		return -1;
+	}
+	close(mfd);
+
+	return 0;
+}
diff --git a/tests/fs_filesystem/fspick.c b/tests/fs_filesystem/fspick.c
new file mode 100644
index 0000000..b1e221d
--- /dev/null
+++ b/tests/fs_filesystem/fspick.c
@@ -0,0 +1,68 @@
+#include "fs_common.h"
+
+static void print_usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s -t tgt -o options [-v]\n"
+		"Where:\n\t"
+		"-t  Target 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, pfd;
+	char *context, *tgt = NULL, *opts = NULL;
+	bool verbose = false;
+
+	while ((opt = getopt(argc, argv, "t:o:v")) != -1) {
+		switch (opt) {
+		case 't':
+			tgt = optarg;
+			break;
+		case 'o':
+			opts = optarg;
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			print_usage(argv[0]);
+		}
+	}
+
+	if (!tgt || !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);
+	}
+
+	if (verbose)
+		printf("Mounting\n\ttgt: %s\n\topts: %s\n", tgt, opts);
+
+	pfd = fspick(AT_FDCWD, tgt, 0);
+	if (pfd < 0) {
+		fprintf(stderr, "Failed fspick(2): %s\n", strerror(errno));
+		return -1;
+	}
+
+	/* config_opts() will return 0 or errno from fsconfig(2) */
+	result = fsconfig_opts(pfd, NULL, tgt, opts, verbose);
+	if (result) {
+		fprintf(stderr, "Failed config_opts\n");
+		return result;
+	}
+
+	close(pfd);
+	return 0;
+}
diff --git a/tests/fs_filesystem/move_mount.c b/tests/fs_filesystem/move_mount.c
new file mode 100644
index 0000000..1b17df9
--- /dev/null
+++ b/tests/fs_filesystem/move_mount.c
@@ -0,0 +1,76 @@
+#include "fs_common.h"
+
+static void print_usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s -s src -t tgt [-v]\n"
+		"Where:\n\t"
+		"-s  Source path\n\t"
+		"-t  Target path\n\t"
+		"-v  Print information.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, result, fd1, fd2, save_errno;
+	char *context, *src = NULL, *tgt = NULL;
+	bool verbose = false;
+
+	while ((opt = getopt(argc, argv, "s:t:v")) != -1) {
+		switch (opt) {
+		case 's':
+			src = optarg;
+			break;
+		case 't':
+			tgt = optarg;
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			print_usage(argv[0]);
+		}
+	}
+
+	if (!src || !tgt)
+		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);
+	}
+
+	if (verbose)
+		printf("Mounting\n\tsrc: %s\n\ttgt: %s\n", src, tgt);
+
+	fd1 = open_tree(AT_FDCWD, src, 0);
+	if (fd1 < 0) {
+		fprintf(stderr, "Failed fd1 open_tree(2): %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	fd2 = open_tree(fd1, "", AT_EMPTY_PATH | OPEN_TREE_CLONE | AT_RECURSIVE);
+	if (fd2 < 0) {
+		fprintf(stderr, "Failed fd2 open_tree(2): %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	result = move_mount(fd2, "", AT_FDCWD, tgt, MOVE_MOUNT_F_EMPTY_PATH);
+	save_errno = errno;
+	if (result < 0) {
+		fprintf(stderr, "Failed move_mount(2): %s\n", strerror(errno));
+		return save_errno;
+	}
+
+	close(fd1);
+	close(fd2);
+	return 0;
+}
diff --git a/tests/fs_filesystem/test b/tests/fs_filesystem/test
new file mode 100755
index 0000000..4ff352d
--- /dev/null
+++ b/tests/fs_filesystem/test
@@ -0,0 +1,835 @@
+#!/usr/bin/perl
+use Test::More;
+
+BEGIN {
+    $basedir = $0;
+    $basedir =~ s|(.*)/[^/]*|$1|;
+
+    # Load common subroutines from filesystem/Filesystem.pm
+    use File::Basename qw(dirname);
+    use Cwd qw(abs_path);
+    use lib dirname( abs_path $0) . '/../filesystem';
+    use Filesystem
+      qw(check_config udisks2_stop udisks2_restart get_loop_dev attach_dev make_fs mk_mntpoint_1 mk_mntpoint_2 cleanup cleanup1 reaper);
+
+    # Some code in tests/filesystem is reused
+    $filesystem_dir = "$basedir/../filesystem";
+    $test_count     = 66;
+
+    # Options: -v = Verbose, -d disable udisks(8) daemon
+    $v              = " ";
+    $disable_udisks = 0;
+    $udisks2_status = 0;
+    foreach $arg (@ARGV) {
+        if ( $arg eq "-v" ) {
+            $v = $arg;
+        }
+        elsif ( $arg eq "-d" ) {
+            $disable_udisks = 1;
+        }
+    }
+
+    # Check if watch and/or named type_transition rules configured
+    ( $addit, $test_watch, $test_name_trans ) =
+      check_config( $basedir, "$filesystem_dir/fanotify_fs" );
+
+    plan tests => ( $test_count += $addit );
+}
+
+# Set initial filesystem type
+$fs_type = "ext4";
+
+# 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();
+}
+
+cleanup($basedir);
+
+############### Test Basic Mount/Unmount ##########################
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$mount_opts1 =
+"quota,usrquota,grpquota,defcontext=system_u:object_r:test_filesystem_file_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$mount_opts1\n";
+$result = system(
+"runcon -t test_filesystem_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $mount_opts1 $v"
+);
+ok( $result eq 0 );
+
+# On RHEL-6, there is a type transition to quota_t when running quotacheck
+# as unconfined_t. Using "runcon `id -Z` quotacheck ..." resolves this.
+print "Running quotacheck(8) to init user/group quota files\n";
+$result = system("runcon `id -Z` quotacheck -ugF vfsv0 $basedir/mntpoint/mp1");
+ok( $result eq 0 );
+
+print "Toggle User & Group quotas on/off\n";
+$result = system(
+"runcon -t test_filesystem_t $filesystem_dir/quotas_test -s $dev -t $basedir/mntpoint/mp1/aquota.user $v"
+);
+ok( $result eq 0 );
+$result = system(
+"runcon -t test_filesystem_t $filesystem_dir/quotas_test -s $dev -t $basedir/mntpoint/mp1/aquota.group $v"
+);
+ok( $result eq 0 );
+
+print "Get statfs(2)\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/statfs_test -t $basedir/mntpoint $v"
+  );
+ok( $result eq 0 );
+
+print
+"Creating 'trans_test_file' and checking context changed via type_transition rule\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/create_file -f $basedir/mntpoint/mp1/trans_test_file -e test_filesystem_filetranscon_t $v"
+  );
+ok( $result eq 0 );
+
+print "Creating 'test_file' and changing its context via setfilecon(3)\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/create_file_change_context -t test_filesystem_filecon_t -f $basedir/mntpoint/mp1/test_file $v"
+  );
+ok( $result eq 0 );
+
+if ($test_name_trans) {
+    print
+"Creating 'name_trans_test_file1' and checking context changed via name-based type_transition rule\n";
+    $result = system(
+"runcon -t test_filesystem_t $filesystem_dir/create_file -f $basedir/mntpoint/mp1/name_trans_test_file1 -e test_filesystem_filenametranscon1_t $v"
+    );
+    ok( $result eq 0 );
+
+    print
+"Creating 'name_trans_test_file2' and checking context changed via name-based type_transition rule\n";
+    $result = system(
+"runcon -t test_filesystem_t $filesystem_dir/create_file -f $basedir/mntpoint/mp1/name_trans_test_file2 -e test_filesystem_filenametranscon2_t $v"
+    );
+    ok( $result eq 0 );
+}
+
+if ($test_watch) {
+    print "fanotify(7) test\n";
+    $result = system(
+"runcon -t test_filesystem_t $filesystem_dir/fanotify_fs $v -t $basedir/mntpoint/mp1"
+    );
+    ok( $result eq 0 );
+}
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Test Move Mount ##########################
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$mount_opts2 =
+"quota,usrquota,grpquota,rootcontext=system_u:object_r:test_filesystem_file_t:s0";
+
+print "Mount on $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_t  $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $mount_opts2 $v"
+);
+ok( $result eq 0 );
+
+mk_mntpoint_2("$basedir/mntpoint");
+
+print "Now move_mount(2) filesystem to $basedir/mntpoint/mp2\n";
+$result = system(
+"runcon -t test_filesystem_t $basedir/move_mount -s $basedir/mntpoint/mp1 -t $basedir/mntpoint/mp2 $v"
+);
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp2\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/umount -t $basedir/mntpoint/mp2 $v"
+  );
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Test Change Mount Options ##########################
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$mount_opts2 =
+"quota,usrquota,grpquota,rootcontext=system_u:object_r:test_filesystem_file_t:s0";
+
+print "Mount on $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_t  $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $mount_opts2 $v"
+);
+ok( $result eq 0 );
+
+$change_opts = "rootcontext=system_u:object_r:test_filesystem_file_t:s0";
+print "Now change options with fspick(2)\n";
+$result = system(
+"runcon -t test_filesystem_t $basedir/fspick -t $basedir/mntpoint/mp1 -o $change_opts $v"
+);
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { relabelfrom } ##########################
+# hooks.c may_context_mount_sb_relabel() FILESYSTEM__RELABELFROM
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_relabelfrom =
+  "defcontext=system_u:object_r:test_filesystem_sb_relabel_no_relabelfrom_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_relabelfrom\n";
+$result = system(
+"runcon -t test_filesystem_sb_relabel_no_relabelfrom_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_relabelfrom $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { relabelto } ##########################
+# hooks.c may_context_mount_sb_relabel() FILESYSTEM__RELABELTO
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_relabelto =
+  "fscontext=system_u:object_r:test_filesystem_sb_relabel_no_relabelto_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_relabelto\n";
+$result = system(
+"runcon -t test_filesystem_sb_relabel_no_relabelto_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_relabelto $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { relabelfrom } ##########################
+# hooks.c may_context_mount_inode_relabel() FILESYSTEM__RELABELFROM
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_relabelfrom =
+  "rootcontext=system_u:object_r:test_filesystem_no_inode_no_relabelfrom_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_relabelfrom\n";
+$result = system(
+"runcon -t test_filesystem_no_inode_no_relabelfrom_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_relabelfrom $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { associate } ##########################
+# hooks.c may_context_mount_inode_relabel() FILESYSTEM__ASSOCIATE
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+
+# This defcontext will trigger denial.
+$opts_no_associate =
+"defcontext=system_u:object_r:test_filesystem_inode_relabel_no_associate_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_associate\n";
+$result = system(
+"runcon -t test_filesystem_inode_relabel_no_associate_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_associate $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { associate } ##########################
+# hooks.c may_create() FILESYSTEM__ASSOCIATE
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+
+# Use this fscontext= to get sensible audit log entry of:
+#  "allow unlabeled_t test_filesystem_may_create_no_associate_t:filesystem associate;"
+$opts_no_associate_file =
+  "fscontext=system_u:object_r:test_filesystem_may_create_no_associate_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_associate_file\n";
+$result = system(
+"runcon -t test_filesystem_may_create_no_associate_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_associate_file $v"
+);
+ok( $result eq 0 );
+
+print "Creating test file $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_may_create_no_associate_t $filesystem_dir/create_file_change_context -t unconfined_t -f $basedir/mntpoint/mp1/test_file $v 2>&1"
+  );
+ok( $result >> 8 eq 13 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_may_create_no_associate_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { quotamod } ##########################
+# hooks.c selinux_quotactl() FILESYSTEM__QUOTAMOD
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_quotamod =
+"quota,usrquota,grpquota,fscontext=system_u:object_r:test_filesystem_no_quotamod_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_quotamod\n";
+$result = system(
+"runcon -t test_filesystem_no_quotamod_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_quotamod $v 2>&1"
+);
+ok( $result eq 0 );
+
+# No need to run quotacheck(8) as never gets far enough to read quota file
+print "Toggle User & Group quotas on/off\n";
+$result = system(
+"runcon -t test_filesystem_no_quotamod_t $filesystem_dir/quotas_test -s $dev -t $basedir/mntpoint/mp1/aquota.user $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_no_quotamod_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { quotaget } ##########################
+# hooks.c selinux_quotactl() FILESYSTEM__QUOTAGET
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_quotaget =
+"quota,usrquota,grpquota,context=system_u:object_r:test_filesystem_no_quotaget_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_quotaget\n";
+$result = system(
+"runcon -t test_filesystem_no_quotaget_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_quotaget $v"
+);
+ok( $result eq 0 );
+
+print "Running quotacheck(8) to init user/group quota files\n";
+$result = system("runcon `id -Z` quotacheck -ugF vfsv0 $basedir/mntpoint/mp1");
+ok( $result eq 0 );
+
+print "Toggle User & Group quotas on/off\n";
+$result = system(
+"runcon -t test_filesystem_no_quotaget_t $filesystem_dir/quotas_test -s $dev -t $basedir/mntpoint/mp1/aquota.user $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_no_quotaget_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny file { quotaon } ##########################
+# hooks.c selinux_quota_on() FILE__QUOTAON
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_quotaon =
+  "quota,usrquota,grpquota,context=system_u:object_r:test_file_no_quotaon_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_quotaon\n";
+$result = system(
+"runcon -t test_file_no_quotaon_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_quotaon $v"
+);
+ok( $result eq 0 );
+
+print "Running quotacheck(8) to init user/group quota files\n";
+$result = system("runcon `id -Z` quotacheck -ugF vfsv0 $basedir/mntpoint/mp1");
+ok( $result eq 0 );
+
+print "Toggle User quotas on/off\n";
+$result = system(
+"runcon -t test_file_no_quotaon_t $filesystem_dir/quotas_test -s $dev -t $basedir/mntpoint/mp1/aquota.user $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_file_no_quotaon_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { mount } ##########################
+# hooks.c selinux_sb_kern_mount() FILESYSTEM__MOUNT
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_mount = "rootcontext=system_u:object_r:test_filesystem_no_mount_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_mount\n";
+$result = system(
+"runcon -t test_filesystem_no_mount_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_mount $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { getattr } ##########################
+# hooks.c selinux_sb_statfs() FILESYSTEM__GETATTR
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_getattr =
+  "rootcontext=system_u:object_r:test_filesystem_no_getattr_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_getattr\n";
+$result = system(
+"runcon -t test_filesystem_no_getattr_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_getattr $v"
+);
+ok( $result eq 0 );
+
+$result = system(
+"runcon -t test_filesystem_no_getattr_t $filesystem_dir/statfs_test -t $basedir/mntpoint $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_no_getattr_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+################ Deny file { mounton } ##########################
+# hooks.c selinux_move_mount() FILE__MOUNTON
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_remount =
+  "rootcontext=system_u:object_r:test_move_mount_no_mounton_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_remount\n";
+$result = system(
+"runcon -t test_move_mount_no_mounton_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_remount $v"
+);
+ok( $result eq 0 );
+
+print "Now move filesystem. This operation should fail\n";
+$result = system(
+"runcon -t test_move_mount_no_mounton_t $basedir/move_mount -s $basedir/mntpoint/mp1 -t $basedir/mntpoint/mp1 $v 2>&1"
+);
+if ( $result eq 0 ) {
+    $kvercur = `uname -r`;
+    chomp($kvercur);
+    $kvercur =~ s/\-.*//;
+    ok( 0,
+"Failed as kernel $kvercur without \"selinux: fix regression introduced by move_mount(2) syscall\" patch"
+    );
+    print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+    $result = system(
+"runcon -t test_move_mount_no_mounton_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+    );
+}
+else {
+    ok( $result >> 8 eq 13 );
+}
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_move_mount_no_mounton_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { unmount } ##########################
+# hooks.c selinux_umount() FILESYSTEM__UNMOUNT
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_unmount =
+  "rootcontext=system_u:object_r:test_filesystem_no_unmount_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_unmount\n";
+$result = system(
+"runcon -t test_filesystem_no_unmount_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_unmount $v"
+);
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_no_unmount_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v 2>&1"
+);
+ok( $result >> 8 eq 13 );
+
+# Make sure it does get unmounted
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { associate }  ##########################
+# hooks.c selinux_inode_setxattr() FILESYSTEM__ASSOCIATE
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$opts_no_associate_xattr =
+"defcontext=system_u:object_r:test_filesystem_inode_setxattr_no_associate_t:s0,fscontext=system_u:object_r:test_filesystem_inode_setxattr_no_associate_t:s0";
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$opts_no_associate_xattr\n";
+$result = system(
+"runcon -t test_filesystem_inode_setxattr_no_associate_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_associate_xattr $v"
+);
+ok( $result eq 0 );
+
+print "Creating test file $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_inode_setxattr_no_associate_t $filesystem_dir/create_file_change_context -t unconfined_t -f $basedir/mntpoint/mp1/test_file $v 2>&1"
+  );
+ok( $result >> 8 eq 13 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_inode_setxattr_no_associate_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+############### Deny filesystem { watch }  ##########################
+# hooks.c selinux_path_notify() FILESYSTEM__WATCH
+if ($test_watch) {
+    mk_mntpoint_1("$basedir/mntpoint");
+    ( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+    make_fs( $fs_type, $dev, $basedir );
+    $opts_no_watch = "context=system_u:object_r:test_filesystem_no_watch_t:s0";
+
+    print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+    print "Using mount options:\n\t$opts_no_watch\n";
+    $result = system(
+"runcon -t test_filesystem_no_watch_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $opts_no_watch $v"
+    );
+    ok( $result eq 0 );
+
+    print "test_fanotify\n";
+    $result = system(
+"runcon -t test_filesystem_no_watch_t $filesystem_dir/fanotify_fs $v -t $basedir/mntpoint/mp1 2>&1"
+    );
+    ok( $result >> 8 eq 13 );
+
+    print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+    $result = system(
+"runcon -t test_filesystem_no_watch_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+    );
+    ok( $result eq 0 );
+
+    print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+    cleanup1( $basedir, $dev );
+}
+
+##########################################################################
+# context     - Useful when mounting filesystems that do not support extended
+#               attributes.
+#   Tested by - Creating a filesystem that has xattrs set to a different value,
+#               then mount with context= and confirm that the files have that
+#               context as well as any newly created files (even if fscreate
+#               was set to something else), and that setfilecon/setxattr() on
+#               files within the mount fails with errno EOPNOTSUPP.
+##########################################################################
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+
+# Mount with xttrs to create a file with specific context.
+$context1_opts =
+  "defcontext=system_u:object_r:test_filesystem_context_file_t:s0";
+
+print "Testing 'context=' mount option\n";
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$context1_opts\n";
+$result = system(
+"runcon -t test_filesystem_context_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $context1_opts $v"
+);
+ok( $result eq 0 );
+
+# Create file with 'test_filesystem_filecon_t' context
+print "Creating test file $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/create_file_change_context -t test_filesystem_filecon_t -f $basedir/mntpoint/mp1/test_file $v"
+  );
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_context_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+# Need to free the loop device, then get new one and attach
+system("losetup -d $dev 2>/dev/null");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+attach_dev( $dev, $basedir );
+
+# Mount again with no xttr support
+$context2_opts = "context=system_u:object_r:test_filesystem_context_file_t:s0";
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$context2_opts\n";
+$result = system(
+"runcon -t test_filesystem_context_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $context2_opts $v"
+);
+ok( $result eq 0 );
+
+# Now check the context on file is system_u:object_r:test_filesystem_context_file_t:s0
+print "Check test file context $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/check_file_context -f $basedir/mntpoint/mp1/test_file -e system_u:object_r:test_filesystem_context_file_t:s0 $v"
+  );
+ok( $result eq 0 );
+
+# Then create a file with 'test_filesystem_filecon_t' context, this should fail with EOPNOTSUPP
+print "Creating test file $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/create_file_change_context -t test_filesystem_filecon_t -f $basedir/mntpoint/mp1/test_file $v 2>/dev/null"
+  );
+ok( $result >> 8 eq 95 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+##########################################################################
+# rootcontext - Explicitly label the root inode of the filesystem being
+#               mounted before that filesystem or inode becomes visible
+#               to userspace.
+#   Tested by - Set mountpoint to unlabeled_t and then check that the
+#               context of the root directory matches rootcontext= after
+#               the mount operation.
+##########################################################################
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$root_opts = "rootcontext=system_u:object_r:test_filesystem_context_file_t:s0";
+
+print "Testing 'rootcontext=' mount option\n";
+
+# Reset mountpoint to 'unlabeled_t' so it is different to any other possible test values.
+print "Resetting MP to unlabeled_t $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/check_mount_context -r -m $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$root_opts\n";
+$result = system(
+"runcon -t test_filesystem_context_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $root_opts $v"
+);
+ok( $result eq 0 );
+
+# Now check the mountpoint is the 'rootcontext=' value
+print "Check MP context $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/check_mount_context -m $basedir/mntpoint/mp1 -e system_u:object_r:test_filesystem_context_file_t:s0 $v"
+  );
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_context_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+##########################################################################
+# defcontext  - Set default security context for unlabeled files.
+#               This overrides the value set for unlabeled files in policy
+#               and requires a filesystem that supports xattr labeling.
+#   Tested by - Create filesystem that has files w/o xattrs and then confirm
+#               that they are mapped to the specified defcontext upon mount,
+#               where defcontext differs from the policy default.
+##########################################################################
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+make_fs( $fs_type, $dev, $basedir );
+$test_opts = "context=system_u:object_r:test_filesystem_context_file_t:s0";
+
+print "Testing 'defcontext=' mount option\n";
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$test_opts\n";
+$result = system(
+"runcon -t test_filesystem_context_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $test_opts $v"
+);
+ok( $result eq 0 );
+
+# Create file, its context will be system_u:object_r:test_filesystem_context_file_t:s0 from $test_opts
+print "Creating test file $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -u system_u -t test_filesystem_fscontext_t $filesystem_dir/create_file -f $basedir/mntpoint/mp1/test_file -e test_filesystem_context_file_t $v"
+  );
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result = system(
+"runcon -t test_filesystem_context_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+);
+ok( $result eq 0 );
+
+# Need to free the loop device, then get new dev one and attach
+system("losetup -d $dev 2>/dev/null");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+attach_dev( $dev, $basedir );
+
+# Mount again with defcontext=
+$defcontext_opts = "defcontext=system_u:object_r:test_filesystem_filecon_t:s0";
+print "Mount $fs_type filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$defcontext_opts\n";
+$result = system(
+"runcon -t test_filesystem_context_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $defcontext_opts $v"
+);
+ok( $result eq 0 );
+
+# Now check the file context is now system_u:object_r:test_filesystem_filecon_t:s0
+print "Check test file context $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/check_file_context -f $basedir/mntpoint/mp1/test_file -e system_u:object_r:test_filesystem_filecon_t:s0 $v"
+  );
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_context_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+##########################################################################
+# fscontext   - Sets the overarching filesystem label to a specific security
+#               context. This filesystem label is separate from the individual
+#               labels on the files.
+#   Tested by - Mount a tmpfs (fs_use_trans) filesystem with fscontext= and
+#               then create a file within it, checking its context.
+##########################################################################
+$fs_type = "tmpfs";
+mk_mntpoint_1("$basedir/mntpoint");
+( $dev, $device_count ) = get_loop_dev( \@device_list, $device_count );
+$fscontext_opts =
+"fscontext=system_u:object_r:test_filesystem_fscontext_fs_t:s0,size=10M,mode=0770";
+
+print "Testing 'fscontext=' mount option\n";
+print "Mount tmpfs filesystem on $basedir/mntpoint/mp1\n";
+print "Using mount options:\n\t$fscontext_opts\n";
+$result = system(
+"runcon -t test_filesystem_fscontext_t $basedir/fsmount -s $dev -t $basedir/mntpoint/mp1 -f $fs_type -o $fscontext_opts $v"
+);
+ok( $result eq 0 );
+
+print "Creating test file $basedir/mntpoint/mp1/test_file\n";
+$result =
+  system(
+"runcon -t test_filesystem_fscontext_t $filesystem_dir/create_file_change_context -t test_filesystem_filecon_t -f $basedir/mntpoint/mp1/test_file $v"
+  );
+ok( $result eq 0 );
+
+print "Unmount filesystem from $basedir/mntpoint/mp1\n";
+$result =
+  system(
+"runcon -t test_filesystem_fscontext_t $filesystem_dir/umount -t $basedir/mntpoint/mp1 $v"
+  );
+ok( $result eq 0 );
+
+print "Removing: $dev $basedir/mntpoint $basedir/fstest\n";
+cleanup1( $basedir, $dev );
+
+reaper( \@device_list, $filesystem_dir, $v );
+
+if ($disable_udisks) {
+    udisks2_restart($udisks2_status);
+}
+
+exit;
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-27  9:32 [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
  2020-01-27  9:32 ` [PATCH V2 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
  2020-01-27  9:32 ` [PATCH V2 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
@ 2020-01-27 17:46 ` Stephen Smalley
  2020-01-29 12:56   ` Richard Haines
  2 siblings, 1 reply; 7+ messages in thread
From: Stephen Smalley @ 2020-01-27 17:46 UTC (permalink / raw)
  To: Richard Haines, selinux, Ondrej Mosnacek, Paul Moore

On 1/27/20 4:32 AM, Richard Haines wrote:
> These patches update the current tests/filesystem to share code (patch 1)
> with the fs*(2) API filesystem tests (patch 2).
> 
> V2 Changes:
> 1) If kernel patch [1] installed move_mount test for denying FILE__MOUNTON
>     should pass. If not installed, display 'Failed as kernel 5.x without
>     "selinux: fix regression introduced by move_mount(2) syscall" patch'
>     (as there is a regression that should be fixed).
>     Note: Kernels 5.2 - 5.5 will fail unless [1] backported. 5.6 is expected
>     to have [1].
> 2) Move policy changes to patch 2.

These look ok to me; we'll see if anyone else objects to the error message.

One other item that occurred to me is that most of the current 
filesystem and fs_filesystem tests are only exercising ext4 regardless 
of the native filesystem in which you run the testsuite (e.g. if I run 
it on a labeled NFS mount most of the tests end up running in the ext4 
filesystem that is created and mounted rather than on labeled NFS 
itself, and likewise if I run it on xfs or btrfs or ...).  For tests 
where it does not matter (e.g. the type_transition tests) it might be 
better to run those on the host/native filesystem directly so we can 
more readily reuse those tests.  Obviously the mount tests themselves 
require some other filesystem besides the one in which the testsuite 
itself resides.  Don't know if people may want to make it easier to 
substitute or add additional filesystem types for testing; you already 
provide a fs_type variable in the test script but that requires patching 
the script and still only supports testing one filesystem type at a time.

> 
> [1] https://lore.kernel.org/selinux/20200117202407.12344-1-sds@tycho.nsa.gov
> 
> Richard Haines (2):
>    selinux-testsuite: Prepare for adding fs*(2) API tests
>    selinux-testsuite: Add fs*(2) API filesystem tests
> 
>   policy/test_filesystem.te        |  18 +-
>   tests/Makefile                   |   6 +
>   tests/filesystem/Filesystem.pm   | 166 ++++++
>   tests/filesystem/test            | 219 ++------
>   tests/fs_filesystem/.gitignore   |   3 +
>   tests/fs_filesystem/Makefile     |  16 +
>   tests/fs_filesystem/fs_common.c  | 110 ++++
>   tests/fs_filesystem/fs_common.h  |  30 ++
>   tests/fs_filesystem/fsmount.c    |  89 ++++
>   tests/fs_filesystem/fspick.c     |  68 +++
>   tests/fs_filesystem/move_mount.c |  76 +++
>   tests/fs_filesystem/test         | 835 +++++++++++++++++++++++++++++++
>   tools/check-syntax               |   2 +-
>   13 files changed, 1455 insertions(+), 183 deletions(-)
>   create mode 100644 tests/filesystem/Filesystem.pm
>   create mode 100644 tests/fs_filesystem/.gitignore
>   create mode 100644 tests/fs_filesystem/Makefile
>   create mode 100644 tests/fs_filesystem/fs_common.c
>   create mode 100644 tests/fs_filesystem/fs_common.h
>   create mode 100644 tests/fs_filesystem/fsmount.c
>   create mode 100644 tests/fs_filesystem/fspick.c
>   create mode 100644 tests/fs_filesystem/move_mount.c
>   create mode 100755 tests/fs_filesystem/test
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-27 17:46 ` [PATCH V2 0/2] " Stephen Smalley
@ 2020-01-29 12:56   ` Richard Haines
  2020-01-29 13:06     ` Stephen Smalley
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Haines @ 2020-01-29 12:56 UTC (permalink / raw)
  To: Stephen Smalley, selinux, Ondrej Mosnacek, Paul Moore

On Mon, 2020-01-27 at 12:46 -0500, Stephen Smalley wrote:
> On 1/27/20 4:32 AM, Richard Haines wrote:
> > These patches update the current tests/filesystem to share code
> > (patch 1)
> > with the fs*(2) API filesystem tests (patch 2).
> > 
> > V2 Changes:
> > 1) If kernel patch [1] installed move_mount test for denying
> > FILE__MOUNTON
> >     should pass. If not installed, display 'Failed as kernel 5.x
> > without
> >     "selinux: fix regression introduced by move_mount(2) syscall"
> > patch'
> >     (as there is a regression that should be fixed).
> >     Note: Kernels 5.2 - 5.5 will fail unless [1] backported. 5.6 is
> > expected
> >     to have [1].
> > 2) Move policy changes to patch 2.
> 
> These look ok to me; we'll see if anyone else objects to the error
> message.
> 
> One other item that occurred to me is that most of the current 
> filesystem and fs_filesystem tests are only exercising ext4
> regardless 
> of the native filesystem in which you run the testsuite (e.g. if I
> run 
> it on a labeled NFS mount most of the tests end up running in the
> ext4 
> filesystem that is created and mounted rather than on labeled NFS 
> itself, and likewise if I run it on xfs or btrfs or ...).  For tests 
> where it does not matter (e.g. the type_transition tests) it might
> be 
> better to run those on the host/native filesystem directly so we can 
> more readily reuse those tests.  Obviously the mount tests
> themselves 
> require some other filesystem besides the one in which the testsuite 
> itself resides.  Don't know if people may want to make it easier to 
> substitute or add additional filesystem types for testing; you
> already 
> provide a fs_type variable in the test script but that requires
> patching 
> the script and still only supports testing one filesystem type at a
> time.

I'll do some work on making the tests use the native filesystem and add
an option to select a different one.
I quess I could add a list of fs to run against from relevant
proc/filesystems entries? (or something else)

I had a go with xfs and found Fedora is configured by default to use
the xfs quota system, however that does not call security hooks
security_quota_on or security_quotactl so not worth testing, otherwise
apart from increasing the block size seems okay.

I also have another patch ready as I noticed that I missed these:
hooks.c selinux_path_notify() FILE__WATCH_SB
hooks.c selinux_path_notify() FILE__WATCH_MOUNT

> 
> > [1] 
> > https://lore.kernel.org/selinux/20200117202407.12344-1-sds@tycho.nsa.gov
> > 
> > Richard Haines (2):
> >    selinux-testsuite: Prepare for adding fs*(2) API tests
> >    selinux-testsuite: Add fs*(2) API filesystem tests
> > 
> >   policy/test_filesystem.te        |  18 +-
> >   tests/Makefile                   |   6 +
> >   tests/filesystem/Filesystem.pm   | 166 ++++++
> >   tests/filesystem/test            | 219 ++------
> >   tests/fs_filesystem/.gitignore   |   3 +
> >   tests/fs_filesystem/Makefile     |  16 +
> >   tests/fs_filesystem/fs_common.c  | 110 ++++
> >   tests/fs_filesystem/fs_common.h  |  30 ++
> >   tests/fs_filesystem/fsmount.c    |  89 ++++
> >   tests/fs_filesystem/fspick.c     |  68 +++
> >   tests/fs_filesystem/move_mount.c |  76 +++
> >   tests/fs_filesystem/test         | 835
> > +++++++++++++++++++++++++++++++
> >   tools/check-syntax               |   2 +-
> >   13 files changed, 1455 insertions(+), 183 deletions(-)
> >   create mode 100644 tests/filesystem/Filesystem.pm
> >   create mode 100644 tests/fs_filesystem/.gitignore
> >   create mode 100644 tests/fs_filesystem/Makefile
> >   create mode 100644 tests/fs_filesystem/fs_common.c
> >   create mode 100644 tests/fs_filesystem/fs_common.h
> >   create mode 100644 tests/fs_filesystem/fsmount.c
> >   create mode 100644 tests/fs_filesystem/fspick.c
> >   create mode 100644 tests/fs_filesystem/move_mount.c
> >   create mode 100755 tests/fs_filesystem/test
> > 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-29 12:56   ` Richard Haines
@ 2020-01-29 13:06     ` Stephen Smalley
  0 siblings, 0 replies; 7+ messages in thread
From: Stephen Smalley @ 2020-01-29 13:06 UTC (permalink / raw)
  To: Richard Haines, selinux, Ondrej Mosnacek, Paul Moore

On 1/29/20 7:56 AM, Richard Haines wrote:
> On Mon, 2020-01-27 at 12:46 -0500, Stephen Smalley wrote:
>> On 1/27/20 4:32 AM, Richard Haines wrote:
>>> These patches update the current tests/filesystem to share code
>>> (patch 1)
>>> with the fs*(2) API filesystem tests (patch 2).
>>>
>>> V2 Changes:
>>> 1) If kernel patch [1] installed move_mount test for denying
>>> FILE__MOUNTON
>>>      should pass. If not installed, display 'Failed as kernel 5.x
>>> without
>>>      "selinux: fix regression introduced by move_mount(2) syscall"
>>> patch'
>>>      (as there is a regression that should be fixed).
>>>      Note: Kernels 5.2 - 5.5 will fail unless [1] backported. 5.6 is
>>> expected
>>>      to have [1].
>>> 2) Move policy changes to patch 2.
>>
>> These look ok to me; we'll see if anyone else objects to the error
>> message.
>>
>> One other item that occurred to me is that most of the current
>> filesystem and fs_filesystem tests are only exercising ext4
>> regardless
>> of the native filesystem in which you run the testsuite (e.g. if I
>> run
>> it on a labeled NFS mount most of the tests end up running in the
>> ext4
>> filesystem that is created and mounted rather than on labeled NFS
>> itself, and likewise if I run it on xfs or btrfs or ...).  For tests
>> where it does not matter (e.g. the type_transition tests) it might
>> be
>> better to run those on the host/native filesystem directly so we can
>> more readily reuse those tests.  Obviously the mount tests
>> themselves
>> require some other filesystem besides the one in which the testsuite
>> itself resides.  Don't know if people may want to make it easier to
>> substitute or add additional filesystem types for testing; you
>> already
>> provide a fs_type variable in the test script but that requires
>> patching
>> the script and still only supports testing one filesystem type at a
>> time.
> 
> I'll do some work on making the tests use the native filesystem and add
> an option to select a different one.
> I quess I could add a list of fs to run against from relevant
> proc/filesystems entries? (or something else)
> 
> I had a go with xfs and found Fedora is configured by default to use
> the xfs quota system, however that does not call security hooks
> security_quota_on or security_quotactl so not worth testing, otherwise
> apart from increasing the block size seems okay.
> 
> I also have another patch ready as I noticed that I missed these:
> hooks.c selinux_path_notify() FILE__WATCH_SB
> hooks.c selinux_path_notify() FILE__WATCH_MOUNT

Make any further changes relative to these patches because I expect one 
of us to merge these barring objections.

Lack of LSM quota-related hooks on xfs seems like a bug / gap in 
coverage that should be fixed.

At least some of the watch permissions are tested by tests/notify/* and 
further tests would logically go there I think.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-27  9:32 ` [PATCH V2 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
@ 2020-01-29 18:21   ` Stephen Smalley
  0 siblings, 0 replies; 7+ messages in thread
From: Stephen Smalley @ 2020-01-29 18:21 UTC (permalink / raw)
  To: Richard Haines, selinux

On 1/27/20 4:32 AM, Richard Haines wrote:
> Test filesystem permissions using the fsopen(2), fsconfig(2), fsmount(2),
> fspick(2) and fsmount(2) api's introduced in kernel 5.2.
> 
> Also tests move_mount(2) using open_tree(2).
> 
> These tests use common code from tests/filesystem.
> 
> Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
> ---
>   policy/test_filesystem.te        |  18 +-
>   tests/Makefile                   |   6 +
>   tests/fs_filesystem/.gitignore   |   3 +
>   tests/fs_filesystem/Makefile     |  16 +
>   tests/fs_filesystem/fs_common.c  | 110 ++++
>   tests/fs_filesystem/fs_common.h  |  30 ++
>   tests/fs_filesystem/fsmount.c    |  89 ++++
>   tests/fs_filesystem/fspick.c     |  68 +++
>   tests/fs_filesystem/move_mount.c |  76 +++
>   tests/fs_filesystem/test         | 835 +++++++++++++++++++++++++++++++
>   10 files changed, 1249 insertions(+), 2 deletions(-)
>   create mode 100644 tests/fs_filesystem/.gitignore
>   create mode 100644 tests/fs_filesystem/Makefile
>   create mode 100644 tests/fs_filesystem/fs_common.c
>   create mode 100644 tests/fs_filesystem/fs_common.h
>   create mode 100644 tests/fs_filesystem/fsmount.c
>   create mode 100644 tests/fs_filesystem/fspick.c
>   create mode 100644 tests/fs_filesystem/move_mount.c
>   create mode 100755 tests/fs_filesystem/test

These are now applied.


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-01-29 18:21 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-27  9:32 [PATCH V2 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
2020-01-27  9:32 ` [PATCH V2 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
2020-01-27  9:32 ` [PATCH V2 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
2020-01-29 18:21   ` Stephen Smalley
2020-01-27 17:46 ` [PATCH V2 0/2] " Stephen Smalley
2020-01-29 12:56   ` Richard Haines
2020-01-29 13:06     ` Stephen Smalley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).