* [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