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

These patches update the current tests/filesystem (see [1] if not already
installed) to share code (patch 1) with the fs*(2) API filesystem
tests (patch 2).

A test kernel with [2] installed tested selinux_move_mount(), see test
script for comments.

To test fanotify fs watch perm on 5.5+ read [1] first to install CIL module.

Not tested on travis.

[1] https://lore.kernel.org/selinux/20200119111740.61358-1-richard_c_haines@btinternet.com
[2] 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         | 833 +++++++++++++++++++++++++++++++
 tools/check-syntax               |   2 +-
 13 files changed, 1453 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] 9+ messages in thread

* [PATCH 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests
  2020-01-20 11:11 [PATCH 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
@ 2020-01-20 11:11 ` Richard Haines
  2020-01-24 15:12   ` Stephen Smalley
  2020-01-20 11:11 ` [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
  1 sibling, 1 reply; 9+ messages in thread
From: Richard Haines @ 2020-01-20 11:11 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>
---
 policy/test_filesystem.te      |  18 ++-
 tests/filesystem/Filesystem.pm | 166 +++++++++++++++++++++++++
 tests/filesystem/test          | 219 ++++++---------------------------
 tools/check-syntax             |   2 +-
 4 files changed, 222 insertions(+), 183 deletions(-)
 create mode 100644 tests/filesystem/Filesystem.pm

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/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] 9+ messages in thread

* [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-20 11:11 [PATCH 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
  2020-01-20 11:11 ` [PATCH 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
@ 2020-01-20 11:11 ` Richard Haines
  2020-01-21 18:56   ` Stephen Smalley
  2020-01-24 15:13   ` Stephen Smalley
  1 sibling, 2 replies; 9+ messages in thread
From: Richard Haines @ 2020-01-20 11:11 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>
---
 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         | 833 +++++++++++++++++++++++++++++++
 9 files changed, 1231 insertions(+)
 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/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..bda7fcf
--- /dev/null
+++ b/tests/fs_filesystem/test
@@ -0,0 +1,833 @@
+#!/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     = 63;
+
+    # 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" );
+
+    # Set to '1' for testing 'hooks.c selinux_move_mount() FILE__MOUNTON'
+    # Once kernel patch is mainline, add kernel version test.
+    $test_move_mount = 0;
+    if ($test_move_mount) {
+        $test_count += 3;
+    }
+
+    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
+if ($test_move_mount) {
+    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 );
+
+    mk_mntpoint_2("$basedir/mntpoint");
+
+    print "Now move filesystem, should fail\n";
+    $result = system(
+"runcon -t test_move_mount_no_mounton_t $basedir/move_mount -s $basedir/mntpoint/mp2 -t $basedir/mntpoint/mp1 $v 2>&1"
+    );
+    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] 9+ messages in thread

* Re: [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-20 11:11 ` [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
@ 2020-01-21 18:56   ` Stephen Smalley
  2020-01-24 15:13   ` Stephen Smalley
  1 sibling, 0 replies; 9+ messages in thread
From: Stephen Smalley @ 2020-01-21 18:56 UTC (permalink / raw)
  To: Richard Haines, selinux, Paul Moore, Ondrej Mosnacek

On 1/20/20 6:11 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>
> ---
<snip>
> diff --git a/tests/fs_filesystem/test b/tests/fs_filesystem/test
> new file mode 100755
> index 0000000..bda7fcf
> --- /dev/null
> +++ b/tests/fs_filesystem/test
> @@ -0,0 +1,833 @@
> +#!/usr/bin/perl
> +use Test::More;
<snip>
> +    # Set to '1' for testing 'hooks.c selinux_move_mount() FILE__MOUNTON'
> +    # Once kernel patch is mainline, add kernel version test.
> +    $test_move_mount = 0;
> +    if ($test_move_mount) {
> +        $test_count += 3;
> +    }

Wondering what we want the test above for test_move_mount to ultimately 
be.  It could be the first kernel version to include my fix.  That would 
avoid testsuite failures on kernels 5.2 through 5.5 assuming the fix is 
queued for 5.6.  On the other hand, it can be argued that the testsuite 
should fail on those kernels and the fix might end up going to stable 
and being back-ported to stable updates to those kernels, in which case 
testing those kernel versions may ultimately be useful.  Paul, what's 
your preference here?

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

* Re: [PATCH 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests
  2020-01-20 11:11 ` [PATCH 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
@ 2020-01-24 15:12   ` Stephen Smalley
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Smalley @ 2020-01-24 15:12 UTC (permalink / raw)
  To: Richard Haines, selinux

On 1/20/20 6:11 AM, Richard Haines wrote:
> 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>

Acked-by: Stephen Smalley <sds@tycho.nsa.gov>

> ---
>   policy/test_filesystem.te      |  18 ++-
>   tests/filesystem/Filesystem.pm | 166 +++++++++++++++++++++++++
>   tests/filesystem/test          | 219 ++++++---------------------------
>   tools/check-syntax             |   2 +-
>   4 files changed, 222 insertions(+), 183 deletions(-)
>   create mode 100644 tests/filesystem/Filesystem.pm

[...]

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

* Re: [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-20 11:11 ` [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
  2020-01-21 18:56   ` Stephen Smalley
@ 2020-01-24 15:13   ` Stephen Smalley
  2020-01-24 19:17     ` Paul Moore
  1 sibling, 1 reply; 9+ messages in thread
From: Stephen Smalley @ 2020-01-24 15:13 UTC (permalink / raw)
  To: Richard Haines, selinux

On 1/20/20 6:11 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>

Only question I have is whether we want to enable the move_mount test 
unconditionally and let it break on kernels with the regression.  Otherwise,

Acked-by: Stephen Smalley <sds@tycho.nsa.gov>

> ---
>   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         | 833 +++++++++++++++++++++++++++++++
>   9 files changed, 1231 insertions(+)
>   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] 9+ messages in thread

* Re: [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-24 15:13   ` Stephen Smalley
@ 2020-01-24 19:17     ` Paul Moore
  2020-01-24 19:25       ` Stephen Smalley
  2020-01-24 19:41       ` Ondrej Mosnacek
  0 siblings, 2 replies; 9+ messages in thread
From: Paul Moore @ 2020-01-24 19:17 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Richard Haines, selinux

On Fri, Jan 24, 2020 at 10:12 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 1/20/20 6:11 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>
>
> Only question I have is whether we want to enable the move_mount test
> unconditionally and let it break on kernels with the regression.  Otherwise,

Historically we haven't broken the test suite for older kernels, but I
will admit that testing older kernels is no longer a priority for me.

> Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
>
> > ---
> >   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         | 833 +++++++++++++++++++++++++++++++
> >   9 files changed, 1231 insertions(+)
> >   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

-- 
paul moore
www.paul-moore.com

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

* Re: [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-24 19:17     ` Paul Moore
@ 2020-01-24 19:25       ` Stephen Smalley
  2020-01-24 19:41       ` Ondrej Mosnacek
  1 sibling, 0 replies; 9+ messages in thread
From: Stephen Smalley @ 2020-01-24 19:25 UTC (permalink / raw)
  To: Paul Moore; +Cc: Richard Haines, selinux, Ondrej Mosnacek

On 1/24/20 2:17 PM, Paul Moore wrote:
> On Fri, Jan 24, 2020 at 10:12 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
>> On 1/20/20 6:11 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>
>>
>> Only question I have is whether we want to enable the move_mount test
>> unconditionally and let it break on kernels with the regression.  Otherwise,
> 
> Historically we haven't broken the test suite for older kernels, but I
> will admit that testing older kernels is no longer a priority for me.

If it were a new permission, I'd agree that we definitely want it 
conditional on the appropriate kernel version.  Since it is a fix for a 
regression in checking an existing permission, it wasn't as clear to me.
Won't matter for RHEL because the fs_filesystem tests are only enabled 
for >= 5.2 since the new system calls weren't added until then, so none 
of these tests will run on RHEL regardless.  It would only show up on 
Fedora kernels from 5.2 through 5.5 that don't have the fix back-ported.

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

* Re: [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests
  2020-01-24 19:17     ` Paul Moore
  2020-01-24 19:25       ` Stephen Smalley
@ 2020-01-24 19:41       ` Ondrej Mosnacek
  1 sibling, 0 replies; 9+ messages in thread
From: Ondrej Mosnacek @ 2020-01-24 19:41 UTC (permalink / raw)
  To: Paul Moore; +Cc: Stephen Smalley, Richard Haines, SElinux list

On Fri, Jan 24, 2020 at 8:17 PM Paul Moore <paul@paul-moore.com> wrote:
> On Fri, Jan 24, 2020 at 10:12 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> > On 1/20/20 6:11 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>
> >
> > Only question I have is whether we want to enable the move_mount test
> > unconditionally and let it break on kernels with the regression.  Otherwise,
>
> Historically we haven't broken the test suite for older kernels, but I
> will admit that testing older kernels is no longer a priority for me.

I'd say if we expect the bug to be fixed in the stable branches of all
affected (& currently supported) kernel versions, we should just let
the test run unconditionally. I see little value in trying to match
the exact set of broken kernel versions. So my vote is to be strict
and if that turns out to cause too much trouble, we can always add
some check (and be more careful next time).

>
> > Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
> >
> > > ---
> > >   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         | 833 +++++++++++++++++++++++++++++++
> > >   9 files changed, 1231 insertions(+)
> > >   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
>
> --
> paul moore
> www.paul-moore.com
>

-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.


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

end of thread, other threads:[~2020-01-24 19:41 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-20 11:11 [PATCH 0/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
2020-01-20 11:11 ` [PATCH 1/2] selinux-testsuite: Prepare for adding fs*(2) API tests Richard Haines
2020-01-24 15:12   ` Stephen Smalley
2020-01-20 11:11 ` [PATCH 2/2] selinux-testsuite: Add fs*(2) API filesystem tests Richard Haines
2020-01-21 18:56   ` Stephen Smalley
2020-01-24 15:13   ` Stephen Smalley
2020-01-24 19:17     ` Paul Moore
2020-01-24 19:25       ` Stephen Smalley
2020-01-24 19:41       ` Ondrej Mosnacek

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).