Whamcloud - gitweb
LU-11607 tests: replace lustre_version/fstype - large-lun
[fs/lustre-release.git] / lustre / tests / sanity-selinux.sh
old mode 100644 (file)
new mode 100755 (executable)
index d86c11c..c3990be
@@ -1,5 +1,13 @@
 #!/bin/bash
 #
+# NOTE
+# In order to be able to do the runcon commands in test_4,
+# the SELinux policy must allow transitions from unconfined_t
+# to user_t and guest_t:
+# #============= unconfined_r ==============
+# allow unconfined_r guest_r;
+# allow unconfined_r user_r;
+#
 # Run select tests by setting ONLY, or as arguments to the script.
 # Skip specific tests by setting EXCEPT.
 #
@@ -24,12 +32,13 @@ require_dsh_mds || exit 0
 
 [ "$SLOW" = "no" ] && EXCEPT_SLOW="xxx"
 
+RUNAS_CMD=${RUNAS_CMD:-runas}
 # $RUNAS_ID may get set incorrectly somewhere else
 [ $UID -eq 0 -a $RUNAS_ID -eq 0 ] &&
        error "RUNAS_ID set to 0, but UID is also 0!"
 
 #
-# global variables of this sanity
+# global variables of this  sanity
 #
 
 check_selinux() {
@@ -40,13 +49,10 @@ check_selinux() {
                 "but it must be enforced to run sanity-selinux" && exit 0
        fi
        local selinux_policy=$(sestatus |
-                              awk -F':' '$1 == "Loaded policy name" {print $2}' |
-                              xargs)
+               awk -F':' '$1 == "Loaded policy name" {print $2}' | xargs)
        if [ -z "$selinux_policy" ]; then
            selinux_policy=$(sestatus |
-                            awk -F':' '$1 == "Policy from config file"
-                                    {print $2}' |
-                            xargs)
+               awk -F':' '$1 == "Policy from config file" {print $2}' | xargs)
        fi
        [ "$selinux_policy" == "targeted" ] ||
                error "Accepting only targeted policy"
@@ -131,7 +137,7 @@ test_2b() {
        mds_path=${mds_path#/}
 
        $LFS setdirstripe -i0 -c1 ${DIR}/$tdir || error "create dir failed"
-       $LFS mkdir -c0 $dirname1 || error "cannot 'lfs mkdir' $dirname1"
+       $LFS mkdir -c0 -i0 $dirname1 || error "cannot 'lfs mkdir' $dirname1"
 
        local xattrval=$(check_selinux_xattr "mds1" $mds_path)
 
@@ -152,88 +158,58 @@ test_2b() {
 run_test 2b "create dir with lfs and check security.selinux xattr is set on MDT"
 
 test_3() {
-       local filename=$DIR/df3
-
-       # get current mapping of runasid, and save it
-       local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
-       local sename=$(semanage login -l |
-                      awk -v uname=$uname '$1==uname {print $2}')
-       local serange=$(semanage login -l |
-                       awk -v uname=$uname '$1==uname {print $3}')
+       local filename=$DIR/$tdir/df3
+       local level=$(id -Z | cut -d':' -f4-)
+       local unconctx="-u unconfined_u -r unconfined_r -t unconfined_t \
+                       -l $level"
 
-       # change mapping of runasid to unconfined_u
-       semanage login -a -s unconfined_u $uname ||
-               error "unable to map $uname to unconfined_u"
+       mkdir -p $DIR/$tdir
+       chmod 777 $DIR/$tdir
 
        # "access" Lustre
-       echo "${uname} mapped as unconfined_u: touch $filename"
-       $PDSH ${uname}@localhost "touch $filename" ||
+       echo "As unconfined_u: touch $filename"
+       $RUNAS_CMD -u $RUNAS_ID runcon $unconctx touch $filename ||
                error "can't touch $filename"
-       echo "${uname} mapped as unconfined_u: rm -f $filename"
-       $PDSH ${uname}@localhost "rm -f $filename" ||
+       echo "As unconfined_u: rm -f $filename"
+       $RUNAS_CMD -u $RUNAS_ID runcon $unconctx rm -f $filename ||
                error "can't remove $filename"
 
-       # restore original mapping of runasid
-       if [ -n "$sename" ]; then
-               if [ -n "$serange" ]; then
-                       semanage login -a -s $sename -r $serange $uname ||
-                               error "unable to restore mapping for $uname"
-               else
-                       semanage login -a -s $sename $uname ||
-                               error "unable to restore mapping for $uname"
-               fi
-       else
-               semanage login -d $uname
-       fi
-
        return 0
 }
 run_test 3 "access with unconfined user"
 
 test_4() {
-       local filename=$DIR/df4
-
-       # get current mapping of runasid, and save it
-       local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
-       local sename=$(semanage login -l |
-                             awk -v uname=$uname '$1==uname {print $2}')
-       local serange=$(semanage login -l |
-                        awk -v uname=$uname '$1==uname {print $3}')
+       local filename=$DIR/$tdir/df4
+       local guestctx="-u guest_u -r guest_r -t guest_t -l s0"
+       local usrctx="-u user_u -r user_r -t user_t -l s0"
+
+       sesearch --role_allow | grep -q "allow unconfined_r user_r"
+       if [ $? -ne 0 ]; then
+           skip "SELinux policy module must allow transition from \
+                  unconfined_r to user_r for this test." && exit 0
+       fi
+       sesearch --role_allow | grep -q "allow unconfined_r guest_r"
+       if [ $? -ne 0 ]; then
+           skip "SELinux policy module must allow transition from \
+                  unconfined_r to guest_r for this test." && exit 0
+       fi
 
-       # change mapping of runasid to guest_u
-       semanage login -a -s guest_u $uname ||
-               error "unable to map $uname to guest_u"
+       mkdir -p $DIR/$tdir
+       chmod 777 $DIR/$tdir
 
        # "access" Lustre
-       echo "${uname} mapped as guest_u: touch $filename"
-       $PDSH ${uname}@localhost "touch $filename" &&
+       echo "As guest_u: touch $filename"
+       $RUNAS_CMD -u $RUNAS_ID runcon $guestctx touch $filename &&
                error "touch $filename should have failed"
 
-       # change mapping of runasid to user_u
-       semanage login -a -s user_u $uname ||
-               error "unable to map $uname to user_u"
-
        # "access" Lustre
-       echo "${uname} mapped as user_u: touch $filename"
-       $PDSH ${uname}@localhost "touch $filename" ||
+       echo "As user_u: touch $filename"
+       $RUNAS_CMD -u $RUNAS_ID runcon $usrctx touch $filename ||
                error "can't touch $filename"
-       echo "${uname} mapped as user_u: rm -f $filename"
-       $PDSH ${uname}@localhost "rm -f $filename" ||
+       echo "As user_u: rm -f $filename"
+       $RUNAS_CMD -u $RUNAS_ID runcon $usrctx rm -f $filename ||
                error "can't remove $filename"
 
-       # restore original mapping of runasid
-       if [ -n "$sename" ]; then
-               if [ -n "$serange" ]; then
-                       semanage login -a -s $sename -r $serange $uname ||
-                               error "unable to restore mapping for $uname"
-               else
-                       semanage login -a -s $sename $uname ||
-                               error "unable to restore mapping for $uname"
-               fi
-       else
-               semanage login -d $uname
-       fi
-
        return 0
 }
 run_test 4 "access with specific SELinux user"
@@ -281,24 +257,28 @@ test_10() {
        local secctxseen=$(ls -lZ $filename1 | awk '{print $4}' | cut -d: -f3)
 
        [ "$newsecctx" == "$secctxseen" ] ||
-               error "sec context seen from 1st mount point is not correct"
+               error_ignore LU-6784 \
+                   "sec context seen from 1st mount point is not correct"
 
        return 0
 }
 run_test 10 "[consistency] concurrent security context change"
 
 test_20a() {
-       local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
-       local filename1=$DIR/df20a
-       local filename2=$DIR2/df20a
+       local filename1=$DIR/$tdir/df20a
+       local filename2=$DIR2/$tdir/df20a
        local req_delay=20
+       local unconctx="-u unconfined_u -r unconfined_r -t unconfined_t -l s0"
+
+       mkdir -p $DIR/$tdir
+       chmod 777 $DIR/$tdir
 
        # sleep some time in ll_create_nd()
        #define OBD_FAIL_LLITE_CREATE_FILE_PAUSE   0x1409
        do_facet client "$LCTL set_param fail_val=$req_delay fail_loc=0x1409"
 
        # create file on first mount point
-       $PDSH ${uname}@localhost "touch $filename1" &
+       $RUNAS_CMD -u $RUNAS_ID runcon $unconctx touch $filename1 &
        local touchpid=$!
        sleep 5
 
@@ -324,17 +304,20 @@ test_20a() {
 run_test 20a "[atomicity] concurrent access from another client (file)"
 
 test_20b() {
-       local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
-       local dirname1=$DIR/dd20b
-       local dirname2=$DIR2/dd20b
+       local dirname1=$DIR/$tdir/dd20b
+       local dirname2=$DIR2/$tdir/dd20b
        local req_delay=20
+       local unconctx="-u unconfined_u -r unconfined_r -t unconfined_t -l s0"
+
+       mkdir -p $DIR/$tdir
+       chmod 777 $DIR/$tdir
 
        # sleep some time in ll_create_nd()
        #define OBD_FAIL_LLITE_NEWNODE_PAUSE     0x140a
        do_facet client "$LCTL set_param fail_val=$req_delay fail_loc=0x140a"
 
        # create file on first mount point
-       $PDSH ${uname}@localhost "mkdir $dirname1" &
+       $RUNAS_CMD -u $RUNAS_ID runcon $unconctx mkdir $dirname1 &
        local mkdirpid=$!
        sleep 5
 
@@ -371,7 +354,7 @@ test_20c() {
        do_facet client "$LCTL set_param fail_val=$req_delay fail_loc=0x140b"
 
        # create file on first mount point
-       lfs mkdir -c0 $dirname1 &
+       $LFS mkdir -c0 -i0 $dirname1 &
        local mkdirpid=$!
        sleep 5
 
@@ -398,8 +381,424 @@ test_20c() {
 }
 run_test 20c "[atomicity] concurrent access from another client (dir via lfs)"
 
+cleanup_20d() {
+       umount_client $MOUNT || error "umount $MOUNT failed"
+       mountcli
+}
+
+trace_cmd() {
+       local cmd="$@"
+       local xattr_prefix=$(grep -E \
+               "#define[[:space:]]+XATTR_SECURITY_PREFIX[[:space:]]+" \
+               /usr/include/linux/xattr.h 2>/dev/null |
+               awk '{print $3}' | sed s+\"++g)
+       local xattr_suffix=$(grep -E \
+               "#define[[:space:]]+XATTR_SELINUX_SUFFIX[[:space:]]+" \
+               /usr/include/linux/xattr.h 2>/dev/null |
+               awk '{print $3}' | sed s+\"++g)
+       local xattr_name=${xattr_prefix}${xattr_suffix}
+
+       [ -z "$xattr_name" ] && xattr_name="security.selinux"
+
+       # umount client
+       if [ "$MOUNT_2" ] && $(grep -q $MOUNT2' ' /proc/mounts); then
+               umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+       fi
+       if $(grep -q $MOUNT' ' /proc/mounts); then
+               umount_client $MOUNT || error "umount $MOUNT failed"
+       fi
+       lustre_rmmod
+       # remount client
+       mount_client $MOUNT ${MOUNT_OPTS} || error "mount client failed"
+
+       $LCTL set_param debug=+info
+       $LCTL clear
+
+       echo $cmd
+       eval $cmd
+
+       $LCTL dk | grep "get xattr '${xattr_name}'"
+       [ $? -eq 0 ] && error "get xattr event was triggered" || true
+}
+
+test_20d() {
+       if [ "$MDS1_VERSION" -lt $(version_code 2.12.50) ] ||
+          [ "$CLIENT_VERSION" -lt $(version_code 2.12.50) ]; then
+               skip "Need version >= 2.12.50"
+       fi
+       [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
+
+       stack_trap cleanup_20d EXIT
+
+       local dirname=$DIR/$tdir/subdir
+
+       mkdir -p $DIR/$tdir
+       mkdir $dirname
+
+       trace_cmd stat $dirname
+       trace_cmd touch $dirname/f1
+       trace_cmd stat $dirname/f1
+       trace_cmd cat $dirname/f1
+       dd if=/dev/zero of=$dirname/f1 bs=1M count=10
+       trace_cmd /usr/bin/truncate -s 10240 $dirname/f1
+       trace_cmd lfs setstripe -E -1 -S 4M $dirname/f2
+       trace_cmd lfs migrate -E -1 -S 256K $dirname/f2
+       trace_cmd lfs setdirstripe -i 1 $dirname/d2
+       trace_cmd lfs migrate -m 0 $dirname/d2
+
+       lfs setdirstripe -i 1 -c 1 $dirname/d3
+       dirname=$dirname/d3/subdir
+       mkdir $dirname
+
+       trace_cmd stat $dirname
+       trace_cmd touch $dirname/f1
+       trace_cmd stat $dirname/f1
+       trace_cmd cat $dirname/f1
+       dd if=/dev/zero of=$dirname/f1 bs=1M count=10
+       trace_cmd /usr/bin/truncate -s 10240 $dirname/f1
+       trace_cmd lfs setstripe -E -1 -S 4M $dirname/f2
+       trace_cmd lfs migrate -E -1 -S 256K $dirname/f2
+}
+run_test 20d "[atomicity] avoid getxattr for security context"
+
+check_nodemap() {
+       local nm=$1
+       local key=$2
+       local val=$3
+       local i
+
+       if [ "$nm" == "active" ]; then
+               proc_param="active"
+       else
+               proc_param="$nm.$key"
+       fi
+       is_sync=false
+       for i in $(seq 1 20); do
+               out=$(do_facet mds1 $LCTL get_param -n \
+                                  nodemap.$proc_param 2>/dev/null)
+               echo "On mds1, ${proc_param} = $out"
+               [ "$val" == "$out" ] && is_sync=true && break
+               sleep 1
+       done
+       if ! $is_sync; then
+               error "$proc_param not updated on mds1 after 20 secs"
+       fi
+}
+
+create_nodemap() {
+       local nm=$1
+       local sepol
+       local client_ip=$(host_nids_address $HOSTNAME $NETTYPE)
+       local client_nid=$(h2nettype $client_ip)
+
+       do_facet mgs $LCTL nodemap_activate 1
+
+       do_facet mgs $LCTL nodemap_add $nm
+       do_facet mgs $LCTL nodemap_add_range \
+                       --name $nm --range $client_nid
+       do_facet mgs $LCTL nodemap_modify --name $nm \
+                       --property admin --value 1
+       do_facet mgs $LCTL nodemap_modify --name $nm \
+                       --property trusted --value 1
+
+       check_nodemap $nm admin_nodemap 1
+       check_nodemap $nm trusted_nodemap 1
+
+       sepol=$(l_getsepol | cut -d':' -f2- | xargs)
+       do_facet mgs $LCTL set_param nodemap.$nm.sepol="$sepol"
+       do_facet mgs $LCTL set_param -P nodemap.$nm.sepol="$sepol"
+
+       check_nodemap $nm sepol $sepol
+}
+
+remove_nodemap() {
+       local nm=$1
+
+       do_facet mgs $LCTL nodemap_del $nm
+
+       do_facet mgs $LCTL nodemap_activate 0
+
+       check_nodemap active x  0
+}
+
+test_21a() {
+       [ "$MDS1_VERSION" -lt $(version_code 2.11.56) ] &&
+               skip "Need MDS >= 2.11.56"
+
+       local sepol
+
+       # umount client
+       if [ "$MOUNT_2" ] && $(grep -q $MOUNT2' ' /proc/mounts); then
+               umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+       fi
+       if $(grep -q $MOUNT' ' /proc/mounts); then
+               umount_client $MOUNT || error "umount $MOUNT failed"
+       fi
+
+       # create nodemap entry with sepol
+       create_nodemap c0
+
+       if $GSS_SK; then
+               # update mount option with skpath
+               MOUNT_OPTS=$(add_sk_mntflag $MOUNT_OPTS)
+               export SK_UNIQUE_NM=true
+
+               # load specific key on servers
+               do_nodes $(comma_list $(all_server_nodes)) "lgss_sk -t server \
+                                                   -l $SK_PATH/nodemap/c0.key"
+
+               # set perms for per-nodemap keys else permission denied
+               do_nodes $(comma_list $(all_server_nodes)) \
+                "keyctl show | grep lustre | cut -c1-11 |
+                               sed -e 's/ //g;' |
+                               xargs -IX keyctl setperm X 0x3f3f3f3f"
+
+       fi
+
+       # mount client without sending sepol
+       mount_client $MOUNT $MOUNT_OPTS &&
+               error "client mount without sending sepol should be refused"
+
+       # mount client with sepol
+       echo -1 > /sys/module/ptlrpc/parameters/send_sepol
+       mount_client $MOUNT $MOUNT_OPTS ||
+               error "client mount with sepol failed"
+
+       # umount client
+       umount_client $MOUNT || error "umount $MOUNT failed"
+
+       # store wrong sepol in nodemap
+       sepol="0:policy:0:0000000000000000000000000000000000000000000000000000000000000000"
+       do_facet mgs $LCTL set_param nodemap.c0.sepol="$sepol"
+       do_facet mgs $LCTL set_param -P nodemap.c0.sepol="$sepol"
+       check_nodemap c0 sepol $sepol
+
+       # mount client with sepol
+       mount_client $MOUNT $MOUNT_OPTS &&
+               error "client mount without matching sepol should be refused"
+
+       # remove nodemap
+       remove_nodemap c0
+
+       if $GSS_SK; then
+               export SK_UNIQUE_NM=false
+       fi
+
+       # remount client normally
+       echo 0 > /sys/module/ptlrpc/parameters/send_sepol
+       mountcli || error "normal client mount failed"
+}
+run_test 21a "Send sepol at connect"
+
+test_21b() {
+       [ "$MDS1_VERSION" -lt $(version_code 2.11.56) ] &&
+               skip "Need MDS >= 2.11.56"
+
+       local sepol
+
+       mkdir -p $DIR/$tdir || error "failed to create $DIR/$tdir"
+       echo test > $DIR/$tdir/toopen ||
+               error "failed to write to $DIR/$tdir/toopen"
+       touch $DIR/$tdir/ftoremove ||
+               error "failed to create $DIR/$tdir/ftoremove"
+       touch $DIR/$tdir/ftoremove2 ||
+               error "failed to create $DIR/$tdir/ftoremove2"
+       touch $DIR/$tdir/ftoremove3 ||
+               error "failed to create $DIR/$tdir/ftoremove3"
+       touch $DIR/$tdir/ftoremove4 ||
+               error "failed to create $DIR/$tdir/ftoremove4"
+       mkdir $DIR/$tdir/dtoremove ||
+               error "failed to create $DIR/$tdir/dtoremove"
+       mkdir $DIR/$tdir/dtoremove2 ||
+               error "failed to create $DIR/$tdir/dtoremove2"
+       mkdir $DIR/$tdir/dtoremove3 ||
+               error "failed to create $DIR/$tdir/dtoremove3"
+       mkdir $DIR/$tdir/dtoremove4 ||
+               error "failed to create $DIR/$tdir/dtoremove4"
+       touch $DIR/$tdir/ftorename ||
+               error "failed to create $DIR/$tdir/ftorename"
+       mkdir $DIR/$tdir/dtorename ||
+               error "failed to create $DIR/$tdir/dtorename"
+       setfattr -n user.myattr -v myval $DIR/$tdir/toopen ||
+               error "failed to set xattr on $DIR/$tdir/toopen"
+       echo 3 > /proc/sys/vm/drop_caches
+
+       # create nodemap entry with sepol
+       create_nodemap c0
+
+       if $GSS_SK; then
+               export SK_UNIQUE_NM=true
+
+               # load specific key on servers
+               do_nodes $(comma_list $(all_server_nodes)) "lgss_sk -t server \
+                                                   -l $SK_PATH/nodemap/c0.key"
+
+               # set perms for per-nodemap keys else permission denied
+               do_nodes $(comma_list $(all_server_nodes)) \
+                "keyctl show | grep lustre | cut -c1-11 |
+                               sed -e 's/ //g;' |
+                               xargs -IX keyctl setperm X 0x3f3f3f3f"
+
+       fi
+
+       # metadata ops without sending sepol
+       touch $DIR/$tdir/f0 && error "touch (1)"
+       lfs setstripe -c1 $DIR/$tdir/f1 && error "lfs setstripe (1)"
+       mkdir $DIR/$tdir/d0 && error "mkdir (1)"
+       lfs setdirstripe -i0 -c1 $DIR/$tdir/d1 && error "lfs setdirstripe (1)"
+       cat $DIR/$tdir/toopen && error "cat (1)"
+       rm -f $DIR/$tdir/ftoremove && error "rm (1)"
+       rmdir $DIR/$tdir/dtoremove && error "rmdir (1)"
+       mv $DIR/$tdir/ftorename $DIR/$tdir/ftorename2 && error "mv (1)"
+       mv $DIR/$tdir/dtorename $DIR/$tdir/dtorename2 && error "mv (2)"
+       getfattr -n user.myattr $DIR/$tdir/toopen && error "getfattr (1)"
+       setfattr -n user.myattr -v myval2 $DIR/$tdir/toopen &&
+               error "setfattr (1)"
+       chattr +i $DIR/$tdir/toopen && error "chattr (1)"
+       lsattr $DIR/$tdir/toopen && error "lsattr (1)"
+       chattr -i $DIR/$tdir/toopen && error "chattr (1)"
+       ln -s $DIR/$tdir/toopen $DIR/$tdir/toopen_sl1 && error "symlink (1)"
+       ln $DIR/$tdir/toopen $DIR/$tdir/toopen_hl1 && error "hardlink (1)"
+
+       # metadata ops with sepol
+       echo -1 > /sys/module/ptlrpc/parameters/send_sepol
+       touch $DIR/$tdir/f2 || error "touch (2)"
+       lfs setstripe -c1 $DIR/$tdir/f3 || error "lfs setstripe (2)"
+       mkdir $DIR/$tdir/d2 || error "mkdir (2)"
+       lfs setdirstripe -i0 -c1 $DIR/$tdir/d3 || error "lfs setdirstripe (2)"
+       cat $DIR/$tdir/toopen || error "cat (2)"
+       rm -f $DIR/$tdir/ftoremove || error "rm (2)"
+       rmdir $DIR/$tdir/dtoremove || error "rmdir (2)"
+       mv $DIR/$tdir/ftorename $DIR/$tdir/ftorename2 || error "mv (3)"
+       mv $DIR/$tdir/dtorename $DIR/$tdir/dtorename2 || error "mv (4)"
+       getfattr -n user.myattr $DIR/$tdir/toopen || error "getfattr (2)"
+       setfattr -n user.myattr -v myval2 $DIR/$tdir/toopen ||
+               error "setfattr (2)"
+       chattr +i $DIR/$tdir/toopen || error "chattr (2)"
+       lsattr $DIR/$tdir/toopen || error "lsattr (2)"
+       chattr -i $DIR/$tdir/toopen || error "chattr (2)"
+       ln -s $DIR/$tdir/toopen $DIR/$tdir/toopen_sl2 || error "symlink (2)"
+       ln $DIR/$tdir/toopen $DIR/$tdir/toopen_hl2 || error "hardlink (2)"
+       echo 3 > /proc/sys/vm/drop_caches
+
+       # store wrong sepol in nodemap
+       sepol="0:policy:0:0000000000000000000000000000000000000000000000000000000000000000"
+       do_facet mgs $LCTL set_param nodemap.c0.sepol="$sepol"
+       do_facet mgs $LCTL set_param -P nodemap.c0.sepol="$sepol"
+       check_nodemap c0 sepol $sepol
+
+       # metadata ops with sepol
+       touch $DIR/$tdir/f4 && error "touch (3)"
+       lfs setstripe -c1 $DIR/$tdir/f5 && error "lfs setstripe (3)"
+       mkdir $DIR/$tdir/d4 && error "mkdir (3)"
+       lfs setdirstripe -i0 -c1 $DIR/$tdir/d5 && error "lfs setdirstripe (3)"
+       cat $DIR/$tdir/toopen && error "cat (3)"
+       rm -f $DIR/$tdir/ftoremove2 && error "rm (3)"
+       rmdir $DIR/$tdir/dtoremove2 && error "rmdir (3)"
+       mv $DIR/$tdir/ftorename2 $DIR/$tdir/ftorename && error "mv (5)"
+       mv $DIR/$tdir/dtorename2 $DIR/$tdir/dtorename && error "mv (6)"
+       getfattr -n user.myattr $DIR/$tdir/toopen && error "getfattr (3)"
+       setfattr -n user.myattr -v myval3 $DIR/$tdir/toopen &&
+               error "setfattr (3)"
+       chattr +i $DIR/$tdir/toopen && error "chattr (3)"
+       lsattr $DIR/$tdir/toopen && error "lsattr (3)"
+       chattr -i $DIR/$tdir/toopen && error "chattr (3)"
+       ln -s $DIR/$tdir/toopen $DIR/$tdir/toopen_sl3 && error "symlink (3)"
+       ln $DIR/$tdir/toopen $DIR/$tdir/toopen_hl3 && error "hardlink (3)"
+
+       # reset correct sepol
+       sepol=$(l_getsepol | cut -d':' -f2- | xargs)
+       do_facet mgs $LCTL set_param nodemap.c0.sepol="$sepol"
+       do_facet mgs $LCTL set_param -P nodemap.c0.sepol="$sepol"
+       check_nodemap c0 sepol $sepol
+
+       # metadata ops with sepol every 10 seconds only
+       echo 10 > /sys/module/ptlrpc/parameters/send_sepol
+       touch $DIR/$tdir/f6 || error "touch (4)"
+       lfs setstripe -c1 $DIR/$tdir/f7 || error "lfs setstripe (4)"
+       mkdir $DIR/$tdir/d6 || error "mkdir (4)"
+       lfs setdirstripe -i0 -c1 $DIR/$tdir/d7 || error "lfs setdirstripe (4)"
+       cat $DIR/$tdir/toopen || error "cat (4)"
+       rm -f $DIR/$tdir/ftoremove2 || error "rm (4)"
+       rmdir $DIR/$tdir/dtoremove2 || error "rmdir (4)"
+       mv $DIR/$tdir/ftorename2 $DIR/$tdir/ftorename || error "mv (7)"
+       mv $DIR/$tdir/dtorename2 $DIR/$tdir/dtorename || error "mv (8)"
+       getfattr -n user.myattr $DIR/$tdir/toopen || error "getfattr (4)"
+       setfattr -n user.myattr -v myval3 $DIR/$tdir/toopen ||
+               error "setfattr (4)"
+       chattr +i $DIR/$tdir/toopen || error "chattr (4)"
+       lsattr $DIR/$tdir/toopen || error "lsattr (4)"
+       chattr -i $DIR/$tdir/toopen || error "chattr (4)"
+       ln -s $DIR/$tdir/toopen $DIR/$tdir/toopen_sl4 || error "symlink (4)"
+       ln $DIR/$tdir/toopen $DIR/$tdir/toopen_hl4 || error "hardlink (4)"
+       echo 3 > /proc/sys/vm/drop_caches
+
+       # change one SELinux boolean value
+       sebool=$(getsebool deny_ptrace | awk '{print $3}')
+       if [ "$sebool" == "off" ]; then
+               setsebool -P deny_ptrace on
+       else
+               setsebool -P deny_ptrace off
+       fi
+
+       # sepol should not be checked yet, so metadata ops without matching
+       # sepol should succeed
+       touch $DIR/$tdir/f8 || error "touch (5)"
+       lfs setstripe -c1 $DIR/$tdir/f9 || error "lfs setstripe (5)"
+       mkdir $DIR/$tdir/d8 || error "mkdir (5)"
+       lfs setdirstripe -i0 -c1 $DIR/$tdir/d9 || error "lfs setdirstripe (5)"
+       cat $DIR/$tdir/toopen || error "cat (5)"
+       rm -f $DIR/$tdir/ftoremove3 || error "rm (5)"
+       rmdir $DIR/$tdir/dtoremove3 || error "rmdir (5)"
+       mv $DIR/$tdir/ftorename $DIR/$tdir/ftorename2 || error "mv (9)"
+       mv $DIR/$tdir/dtorename $DIR/$tdir/dtorename2 || error "mv (10)"
+       getfattr -n user.myattr $DIR/$tdir/toopen || error "getfattr (5)"
+       setfattr -n user.myattr -v myval4 $DIR/$tdir/toopen ||
+               error "setfattr (5)"
+       chattr +i $DIR/$tdir/toopen || error "chattr (5)"
+       lsattr $DIR/$tdir/toopen || error "lsattr (5)"
+       chattr -i $DIR/$tdir/toopen || error "chattr (5)"
+       ln -s $DIR/$tdir/toopen $DIR/$tdir/toopen_sl5 || error "symlink (5)"
+       ln $DIR/$tdir/toopen $DIR/$tdir/toopen_hl5 || error "hardlink (5)"
+       echo 3 > /proc/sys/vm/drop_caches
+
+       sleep 10
+       # metadata ops without matching sepol: should fail now
+       touch $DIR/$tdir/f10 && error "touch (6)"
+       lfs setstripe -c1 $DIR/$tdir/f11 && error "lfs setstripe (6)"
+       mkdir $DIR/$tdir/d10 && error "mkdir (6)"
+       lfs setdirstripe -i0 -c1 $DIR/$tdir/d11 && error "lfs setdirstripe (6)"
+       cat $DIR/$tdir/toopen && error "cat (6)"
+       rm -f $DIR/$tdir/ftoremove4 && error "rm (6)"
+       rmdir $DIR/$tdir/dtoremove4 && error "rmdir (6)"
+       mv $DIR/$tdir/ftorename2 $DIR/$tdir/ftorename && error "mv (11)"
+       mv $DIR/$tdir/dtorename2 $DIR/$tdir/dtorename && error "mv (12)"
+       getfattr -n user.myattr $DIR/$tdir/toopen && error "getfattr (6)"
+       setfattr -n user.myattr -v myval5 $DIR/$tdir/toopen &&
+               error "setfattr (6)"
+       chattr +i $DIR/$tdir/toopen && error "chattr (6)"
+       lsattr $DIR/$tdir/toopen && error "lsattr (6)"
+       chattr -i $DIR/$tdir/toopen && error "chattr (6)"
+       ln -s $DIR/$tdir/toopen $DIR/$tdir/toopen_sl6 && error "symlink (6)"
+       ln $DIR/$tdir/toopen $DIR/$tdir/toopen_hl6 && error "hardlink (6)"
+
+       # restore SELinux boolean value
+       if [ "$sebool" == "off" ]; then
+               setsebool -P deny_ptrace off
+       else
+               setsebool -P deny_ptrace on
+       fi
+
+       # remove nodemap
+       remove_nodemap c0
+       echo 0 > /sys/module/ptlrpc/parameters/send_sepol
+
+       if $GSS_SK; then
+               export SK_UNIQUE_NM=false
+       fi
+}
+run_test 21b "Send sepol for metadata ops"
 
 complete $SECONDS
 check_and_cleanup_lustre
 exit_status
-