# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # # Copyright (c) 2013, 2016 by Delphix. All rights reserved. # Copyright 2016 Nexenta Systems, Inc. # Copyright 2023 Bill Sommerfeld # . $STF_SUITE/include/libtest.shlib . $STF_SUITE/tests/functional/delegate/delegate.cfg # # Cleanup exist user/group. # function cleanup_user_group { typeset i for i in $STAFF1 $STAFF2 $OTHER1 $OTHER2 ; do del_user $i done for i in $STAFF_GROUP $OTHER_GROUP ; do del_group $i done return 0 } # # Restore test file system to the original status. # function restore_root_datasets { if datasetexists $ROOT_TESTFS ; then log_must zfs destroy -Rf $ROOT_TESTFS fi log_must zfs create $ROOT_TESTFS if is_global_zone ; then if datasetexists $ROOT_TESTVOL ; then log_must zfs destroy -Rf $ROOT_TESTVOL fi log_must zfs create -V $VOLSIZE $ROOT_TESTVOL fi return 0 } # # Verify the specified user have permission on the dataset # # $1 dataset # $2 permissions which are separated by comma(,) # $3-n users # function verify_perm { typeset dtst=$1 typeset permissions=$2 shift 2 if [[ -z $@ || -z $permissions || -z $dtst ]]; then return 1 fi typeset type=$(get_prop type $dtst) permissions=$(echo $permissions | tr -s "," " ") typeset user for user in $@; do typeset perm for perm in $permissions; do typeset -i ret=1 if [[ $type == "filesystem" ]]; then check_fs_perm $user $perm $dtst ret=$? elif [[ $type == "volume" ]]; then check_vol_perm $user $perm $dtst ret=$? fi if ((ret != 0)) ; then log_note "Fail: $user should have $perm " \ "on $dtst" return 1 fi done done return 0 } # # Verify the specified user have no permission on the dataset # # $1 dataset # $2 permissions which are separated by comma(,) # $3-n users # function verify_noperm { typeset dtst=$1 typeset permissions=$2 shift 2 if [[ -z $@ || -z $permissions || -z $dtst ]]; then return 1 fi typeset type=$(get_prop type $dtst) permissions=$(echo $permissions | tr -s "," " ") typeset user for user in $@; do typeset perm for perm in $permissions; do typeset -i ret=1 if [[ $type == "filesystem" ]]; then check_fs_perm $user $perm $dtst ret=$? elif [[ $type == "volume" ]]; then check_vol_perm $user $perm $dtst ret=$? fi if ((ret == 0)) ; then log_note "Fail: $user should not have $perm " \ "on $dtst" return 1 fi done done return 0 } function common_perm { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset -i ret=1 case $perm in send) verify_send $user $perm $dtst ret=$? ;; allow) verify_allow $user $perm $dtst ret=$? ;; userprop) verify_userprop $user $perm $dtst ret=$? ;; compression|checksum|readonly) verify_ccr $user $perm $dtst ret=$? ;; copies) verify_copies $user $perm $dtst ret=$? ;; reservation) verify_reservation $user $perm $dtst ret=$? ;; *) ret=1 ;; esac return $ret } function check_fs_perm { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset -i ret=1 case $perm in create) verify_fs_create $user $perm $fs ret=$? ;; destroy) verify_fs_destroy $user $perm $fs ret=$? ;; snapshot) verify_fs_snapshot $user $perm $fs ret=$? ;; rollback) verify_fs_rollback $user $perm $fs ret=$? ;; clone) verify_fs_clone $user $perm $fs ret=$? ;; rename) verify_fs_rename $user $perm $fs ret=$? ;; mount) verify_fs_mount $user $perm $fs ret=$? ;; share) verify_fs_share $user $perm $fs ret=$? ;; mountpoint) verify_fs_mountpoint $user $perm $fs ret=$? ;; promote) verify_fs_promote $user $perm $fs ret=$? ;; canmount) verify_fs_canmount $user $perm $fs ret=$? ;; dnodesize) verify_fs_dnodesize $user $perm $fs ret=$? ;; recordsize) verify_fs_recordsize $user $perm $fs ret=$? ;; quota) verify_fs_quota $user $perm $fs ret=$? ;; aclmode) verify_fs_aclmode $user $perm $fs ret=$? ;; aclinherit) verify_fs_aclinherit $user $perm $fs ret=$? ;; snapdir) verify_fs_snapdir $user $perm $fs ret=$? ;; atime|exec|devices|setuid|xattr) verify_fs_aedsx $user $perm $fs ret=$? ;; zoned) verify_fs_zoned $user $perm $fs ret=$? ;; sharenfs) verify_fs_sharenfs $user $perm $fs ret=$? ;; receive) verify_fs_receive $user $perm $fs ret=$? ;; *) common_perm $user $perm $fs ret=$? ;; esac return $ret } function check_vol_perm { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset -i ret=1 case $perm in destroy) verify_vol_destroy $user $perm $vol ret=$? ;; snapshot) verify_vol_snapshot $user $perm $vol ret=$? ;; rollback) verify_vol_rollback $user $perm $vol ret=$? ;; clone) verify_vol_clone $user $perm $vol ret=$? ;; rename) verify_vol_rename $user $perm $vol ret=$? ;; promote) verify_vol_promote $user $perm $vol ret=$? ;; volsize) verify_vol_volsize $user $perm $vol ret=$? ;; *) common_perm $user $perm $vol ret=$? ;; esac return $ret } function setup_unallow_testenv { log_must restore_root_datasets log_must zfs create $SUBFS for dtst in $DATASETS ; do log_must zfs allow -l $STAFF1 $LOCAL_SET $dtst log_must zfs allow -d $STAFF2 $DESC_SET $dtst log_must zfs allow $OTHER1 $LOCAL_DESC_SET $dtst log_must zfs allow $OTHER2 $LOCAL_DESC_SET $dtst log_must verify_perm $dtst $LOCAL_SET $STAFF1 log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER1 log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2 if [[ $dtst == $ROOT_TESTFS ]]; then log_must verify_perm $SUBFS $DESC_SET $STAFF2 log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1 log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2 fi done return 0 } # # Verify permission send for specified user on the dataset # $1 user # $2 permission # $3 dataset # function verify_send { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset oldval typeset stamp=${perm}.${user}.$RANDOM typeset snap=$dtst@snap.$stamp typeset -i ret=1 log_must zfs snapshot $snap typeset bak_user=/tmp/bak.$user.$stamp typeset bak_root=/tmp/bak.root.$stamp user_run $user eval "zfs send $snap > $bak_user" log_must eval "zfs send $snap > $bak_root" if [[ $(checksum $bak_user) == $(checksum $bak_root) ]]; then ret=0 fi rm -rf $bak_user > /dev/null rm -rf $bak_root > /dev/null return $ret } function verify_fs_receive { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset dtst typeset stamp=${perm}.${user}.$RANDOM typeset newfs=$fs/newfs.$stamp typeset newvol=$fs/newvol.$stamp typeset bak_user=/tmp/bak.$user.$stamp typeset bak_root=/tmp/bak.root.$stamp log_must zfs create $newfs typeset datasets="$newfs" if is_global_zone ; then log_must zfs create -V $VOLSIZE $newvol datasets="$newfs $newvol" fi for dtst in $datasets ; do typeset dtstsnap=$dtst@snap.$stamp log_must zfs snapshot $dtstsnap log_must eval "zfs send $dtstsnap > $bak_root" log_must zfs destroy -rf $dtst user_run $user eval "zfs receive $dtst < $bak_root" if datasetexists $dtstsnap ; then return 1 fi log_must zfs allow $user create $fs user_run $user eval "zfs receive $dtst < $bak_root" log_must zfs unallow $user create $fs if datasetexists $dtstsnap ; then return 1 fi log_must zfs allow $user mount $fs user_run $user eval "zfs receive $dtst < $bak_root" log_must zfs unallow $user mount $fs if datasetexists $dtstsnap ; then return 1 fi log_must zfs allow $user mount,create $fs user_run $user eval "zfs receive $dtst < $bak_root" log_must zfs unallow $user mount,create $fs if ! datasetexists $dtstsnap ; then return 1 fi # check the data integrity log_must eval "zfs send $dtstsnap > $bak_user" log_must zfs destroy -rf $dtst log_must eval "zfs receive $dtst < $bak_root" log_must eval "zfs send $dtstsnap > $bak_root" log_must zfs destroy -rf $dtst if [[ $(checksum $bak_user) != $(checksum $bak_root) ]]; then return 1 fi rm -rf $bak_user > /dev/null rm -rf $bak_root > /dev/null done return 0 } function verify_userprop { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset stamp=${perm}.${user}.$RANDOM user_run $user zfs set "$user:ts=$stamp" $dtst sync_pool ${dtst%%/*} if [[ $stamp != $(get_prop "$user:ts" $dtst) ]]; then return 1 fi user_run $user zfs inherit "$user:ts" $dtst return 0 } function verify_ccr { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset oldval set -A modes "on" "off" oldval=$(get_prop $perm $dtst) if [[ $oldval == "on" ]]; then n=1 elif [[ $oldval == "off" ]]; then n=0 fi log_note "$user zfs set $perm=${modes[$n]} $dtst" user_run $user zfs set $perm=${modes[$n]} $dtst if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then return 1 fi return 0 } function verify_copies { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset oldval set -A modes 1 2 3 oldval=$(get_prop $perm $dtst) if [[ $oldval -eq 1 ]]; then n=1 elif [[ $oldval -eq 2 ]]; then n=2 elif [[ $oldval -eq 3 ]]; then n=0 fi log_note "$user zfs set $perm=${modes[$n]} $dtst" user_run $user zfs set $perm=${modes[$n]} $dtst if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then return 1 fi return 0 } function verify_reservation { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset value32m=$(( 1024 * 1024 * 32 )) typeset oldval=$(get_prop reservation $dtst) user_run $user zfs set reservation=$value32m $dtst if [[ $value32m != $(get_prop reservation $dtst) ]]; then log_must zfs set reservation=$oldval $dtst return 1 fi log_must zfs set reservation=$oldval $dtst return 0 } function verify_fs_create { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset newfs=$fs/nfs.$stamp typeset newvol=$fs/nvol.$stamp user_run $user zfs create $newfs if datasetexists $newfs ; then return 1 fi log_must zfs allow $user mount $fs user_run $user zfs create $newfs log_must zfs unallow $user mount $fs if ! datasetexists $newfs ; then return 1 fi log_must zfs destroy $newfs if is_global_zone ; then # mount permission is required for sparse volume user_run $user zfs create -V 150m -s $newvol if datasetexists $newvol ; then return 1 fi log_must zfs allow $user mount $fs user_run $user zfs create -V 150m -s $newvol log_must zfs unallow $user mount $fs if ! datasetexists $newvol ; then return 1 fi log_must zfs destroy $newvol # mount and reserveration permission are # required for normal volume user_run $user zfs create -V 150m $newvol if datasetexists $newvol ; then return 1 fi log_must zfs allow $user mount $fs user_run $user zfs create -V 150m $newvol log_must zfs unallow $user mount $fs if datasetexists $newvol ; then return 1 fi log_must zfs allow $user reservation $fs user_run $user zfs create -V 150m $newvol log_must zfs unallow $user reservation $fs if datasetexists $newvol ; then return 1 fi log_must zfs allow $user refreservation $fs user_run $user zfs create -V 150m $newvol log_must zfs unallow $user refreservation $fs if datasetexists $newvol ; then return 1 fi log_must zfs allow $user mount $fs log_must zfs allow $user reservation $fs log_must zfs allow $user refreservation $fs user_run $user zfs create -V 150m $newvol log_must zfs unallow $user mount $fs log_must zfs unallow $user reservation $fs log_must zfs unallow $user refreservation $fs if ! datasetexists $newvol ; then return 1 fi log_must zfs destroy $newvol fi return 0 } function verify_fs_destroy { typeset user=$1 typeset perm=$2 typeset fs=$3 if ! ismounted $fs ; then user_run $user zfs destroy $fs if datasetexists $fs ; then return 1 fi fi if ismounted $fs ; then user_run $user zfs destroy $fs if ! datasetexists $fs ; then return 1 fi # mount permission is required log_must zfs allow $user mount $fs user_run $user zfs destroy $fs if datasetexists $fs ; then return 1 fi fi return 0 } # Verify that given the correct delegation, a regular user can: # Take a snapshot of an unmounted dataset # Take a snapshot of an mounted dataset # Create a snapshot by making a directory in the .zfs/snapshot directory function verify_fs_snapshot { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset snap=$fs@snap.$stamp typeset mntpt=$(get_prop mountpoint $fs) if [[ "yes" == $(get_prop mounted $fs) ]]; then log_must zfs umount $fs fi user_run $user zfs snapshot $snap if ! datasetexists $snap ; then return 1 fi log_must zfs destroy $snap if [[ "no" == $(get_prop mounted $fs) ]]; then log_must zfs mount $fs fi user_run $user zfs snapshot $snap if ! datasetexists $snap ; then return 1 fi log_must zfs destroy $snap typeset snapdir=${mntpt}/.zfs/snapshot/snap.$stamp user_run $user mkdir $snapdir if ! datasetexists $snap ; then return 1 fi log_must zfs destroy $snap return 0 } function verify_fs_rollback { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset oldval typeset stamp=${perm}.${user}.$RANDOM typeset snap=$fs@snap.$stamp typeset mntpt=$(get_prop mountpoint $fs) oldval=$(datasetcksum $fs) log_must zfs snapshot $snap if ! ismounted $fs; then log_must zfs mount $fs fi log_must touch $mntpt/testfile.$stamp user_run $user zfs rollback -R $snap if is_global_zone ; then if [[ $oldval != $(datasetcksum $fs) ]]; then return 1 fi else # datasetcksum can not be used in local zone if [[ -e $mntpt/testfile.$stamp ]]; then return 1 fi fi return 0 } function verify_fs_clone { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basefs=${fs%/*} typeset snap=$fs@snap.$stamp typeset clone=$basefs/cfs.$stamp log_must zfs snapshot $snap user_run $user zfs clone $snap $clone if datasetexists $clone ; then return 1 fi log_must zfs allow $user create $basefs user_run $user zfs clone $snap $clone log_must zfs unallow $user create $basefs if datasetexists $clone ; then return 1 fi log_must zfs allow $user mount $basefs user_run $user zfs clone $snap $clone log_must zfs unallow $user mount $basefs if datasetexists $clone ; then return 1 fi log_must zfs allow $user mount $basefs log_must zfs allow $user create $basefs user_run $user zfs clone $snap $clone log_must zfs unallow $user create $basefs log_must zfs unallow $user mount $basefs if ! datasetexists $clone ; then return 1 fi log_must zfs destroy -R $snap return 0 } function verify_fs_rename { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basefs=${fs%/*} typeset snap=$fs@snap.$stamp typeset renamefs=$basefs/nfs.$stamp if ! ismounted $fs; then log_must zfs mount $fs fi # case 1 user_run $user zfs rename $fs $renamefs if datasetexists $renamefs ; then return 1 fi # case 2 log_must zfs allow $user create $basefs user_run $user zfs rename $fs $renamefs log_must zfs unallow $user create $basefs if datasetexists $renamefs ; then return 1 fi # case 3 log_must zfs allow $user mount $basefs user_run $user zfs rename $fs $renamefs log_must zfs unallow $user mount $basefs if datasetexists $renamefs ; then return 1 fi # case 4 log_must zfs allow $user mount $fs user_run $user zfs rename $fs $renamefs if datasetexists $renamefs ; then log_must zfs unallow $user mount $renamefs return 1 fi log_must zfs unallow $user mount $fs # case 5 log_must zfs allow $user create $basefs log_must zfs allow $user mount $fs user_run $user zfs rename $fs $renamefs log_must zfs unallow $user create $basefs if datasetexists $renamefs ; then log_must zfs unallow $user mount $renamefs return 1 fi log_must zfs unallow $user mount $fs # case 6 log_must zfs allow $user mount $basefs log_must zfs allow $user mount $fs user_run $user zfs rename $fs $renamefs log_must zfs unallow $user mount $basefs if datasetexists $renamefs ; then log_must zfs unallow $user mount $renamefs return 1 fi log_must zfs unallow $user mount $fs # case 7 log_must zfs allow $user create $basefs log_must zfs allow $user mount $basefs user_run $user zfs rename $fs $renamefs log_must zfs unallow $user mount $basefs log_must zfs unallow $user create $basefs if ! datasetexists $renamefs ; then return 1 fi log_must zfs rename $renamefs $fs return 0 } function verify_fs_mount { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset mntpt=$(get_prop mountpoint $fs) typeset newmntpt=/tmp/mnt.$stamp if ismounted $fs ; then user_run $user zfs unmount $fs if ismounted $fs ; then return 1 fi fi if ! ismounted $fs ; then log_must zfs set mountpoint=$newmntpt $fs log_must rm -rf $newmntpt log_must mkdir $newmntpt user_run $user zfs mount $fs if ismounted $fs ; then return 1 fi # mountpoint's owner must be the user log_must chown $user $newmntpt user_run $user zfs mount $fs if ! ismounted $fs ; then return 1 fi log_must zfs umount $fs log_must rm -rf $newmntpt log_must zfs set mountpoint=$mntpt $fs fi return 0 } function verify_fs_share { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset -i ret=0 svcadm enable -rs nfs/server typeset stat=$(svcs -H -o STA nfs/server:default) if [[ $stat != "ON" ]]; then log_fail "Could not enable nfs/server" fi log_must zfs set sharenfs=on $fs zfs unshare $fs user_run $user zfs share $fs if ! is_shared $fs; then ret=1 fi zfs unshare $fs log_must zfs set sharenfs=off $fs return $ret } function verify_fs_mountpoint { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset mntpt=$(get_prop mountpoint $fs) typeset newmntpt=/tmp/mnt.$stamp if ! ismounted $fs ; then user_run $user zfs set mountpoint=$newmntpt $fs if [[ $newmntpt != \ $(get_prop mountpoint $fs) ]] ; then return 1 fi log_must zfs set mountpoint=$mntpt $fs fi if ismounted $fs ; then user_run $user zfs set mountpoint=$newmntpt $fs if [[ $mntpt != $(get_prop mountpoint $fs) ]]; then return 1 fi # require mount permission when fs is mounted log_must zfs allow $user mount $fs user_run $user zfs set mountpoint=$newmntpt $fs log_must zfs unallow $user mount $fs if [[ $newmntpt != \ $(get_prop mountpoint $fs) ]] ; then return 1 fi log_must zfs set mountpoint=$mntpt $fs fi return 0 } function verify_fs_promote { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basefs=${fs%/*} typeset snap=$fs@snap.$stamp typeset clone=$basefs/cfs.$stamp log_must zfs snapshot $snap log_must zfs clone $snap $clone log_must zfs promote $clone typeset fs_orig=$(get_prop origin $fs) typeset clone_orig=$(get_prop origin $clone) user_run $user zfs promote $fs # promote should fail if original fs does not have # promote permission if [[ $fs_orig != $(get_prop origin $fs) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi log_must zfs allow $user promote $clone user_run $user zfs promote $fs log_must zfs unallow $user promote $clone if [[ $fs_orig != $(get_prop origin $fs) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi log_must zfs allow $user mount $fs user_run $user zfs promote $fs log_must zfs unallow $user mount $fs if [[ $fs_orig != $(get_prop origin $fs) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi log_must zfs allow $user mount $fs log_must zfs allow $user promote $clone user_run $user zfs promote $fs log_must zfs unallow $user promote $clone log_must zfs unallow $user mount $fs if [[ $snap != $(get_prop origin $clone) || \ $clone_orig != $(get_prop origin $fs) ]]; then return 1 fi return 0 } function verify_fs_canmount { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset oldval typeset stamp=${perm}.${user}.$RANDOM if ! ismounted $fs ; then set -A modes "on" "off" oldval=$(get_prop $perm $fs) if [[ $oldval == "on" ]]; then n=1 elif [[ $oldval == "off" ]]; then n=0 fi log_note "$user zfs set $perm=${modes[$n]} $fs" user_run $user zfs set $perm=${modes[$n]} $fs if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then return 1 fi fi # fs is mounted if ismounted $fs ; then # property value does not change if # no mount permission set -A modes "on" "off" oldval=$(get_prop $perm $fs) if [[ $oldval == "on" ]]; then n=1 elif [[ $oldval == "off" ]]; then n=0 fi log_note "$user zfs set $perm=${modes[$n]} $fs" log_must zfs allow $user mount $fs user_run $user zfs set $perm=${modes[$n]} $fs log_must zfs unallow $user mount $fs if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then return 1 fi fi return 0 } function verify_fs_recordsize { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset value8k=$(( 1024 * 8 )) user_run $user zfs set recordsize=$value8k $fs if [[ $value8k != $(get_prop recordsize $fs) ]]; then return 1 fi return 0 } function verify_fs_dnodesize { typeset user=$1 typeset perm=$2 typeset fs=$3 value="2k" user_run $user zfs set dnodesize=$value $fs if [[ $value != $(get_prop dnodesize $fs) ]]; then return 1 fi return 0 } function verify_fs_quota { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset value32m=$(( 1024 * 1024 * 32 )) user_run $user zfs set quota=$value32m $fs if [[ $value32m != $(get_prop quota $fs) ]]; then return 1 fi return 0 } function verify_fs_aclmode { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset oldval set -A modes "discard" "groupmask" "passthrough" oldval=$(get_prop $perm $fs) if [[ $oldval == "discard" ]]; then n=1 elif [[ $oldval == "groupmask" ]]; then n=2 elif [[ $oldval == "passthrough" ]]; then n=0 fi log_note "$user zfs set aclmode=${modes[$n]} $fs" user_run $user zfs set aclmode=${modes[$n]} $fs if [[ ${modes[$n]} != $(get_prop aclmode $fs) ]]; then return 1 fi return 0 } function verify_fs_aclinherit { typeset user=$1 typeset perm=$2 typeset fs=$3 # # PSARC/2008/231 change the default value of aclinherit to "restricted" # but still keep the old interface of "secure" # typeset oldval set -A modes "discard" "noallow" "secure" "passthrough" oldval=$(get_prop $perm $fs) if [[ $oldval == "discard" ]]; then n=1 elif [[ $oldval == "noallow" ]]; then n=2 elif [[ $oldval == "secure" || $oldval == "restricted" ]]; then n=3 elif [[ $oldval == "passthrough" ]]; then n=0 fi log_note "$user zfs set aclinherit=${modes[$n]} $fs" user_run $user zfs set aclinherit=${modes[$n]} $fs typeset newval=$(get_prop aclinherit $fs) if [[ ${modes[$n]} == "secure" && $newval == "restricted" ]]; then return 0 elif [[ ${modes[$n]} != $(get_prop aclinherit $fs) ]]; then return 1 fi return 0 } function verify_fs_snapdir { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset oldval set -A modes "visible" "hidden" oldval=$(get_prop $perm $fs) if [[ $oldval == "visible" ]]; then n=1 elif [[ $oldval == "hidden" ]]; then n=0 fi log_note "$user zfs set snapdir=${modes[$n]} $fs" user_run $user zfs set snapdir=${modes[$n]} $fs if [[ ${modes[$n]} != $(get_prop snapdir $fs) ]]; then return 1 fi return 0 } function verify_fs_aedsx { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset oldval set -A modes "on" "off" oldval=$(get_prop $perm $fs) if [[ $oldval == "on" ]]; then n=1 elif [[ $oldval == "off" ]]; then n=0 fi log_note "$user zfs set $perm=${modes[$n]} $fs" user_run $user zfs set $perm=${modes[$n]} $fs if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then return 1 fi return 0 } function verify_fs_zoned { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset oldval set -A modes "on" "off" oldval=$(get_prop $perm $fs) if [[ $oldval == "on" ]]; then n=1 elif [[ $oldval == "off" ]]; then n=0 fi log_note "$user zfs set $perm=${modes[$n]} $fs" if is_global_zone ; then if ! ismounted $fs ; then user_run $user zfs set \ $perm=${modes[$n]} $fs if [[ ${modes[$n]} != \ $(get_prop $perm $fs) ]]; then return 1 fi if [[ $n -eq 0 ]]; then log_mustnot zfs mount $fs else log_must zfs mount $fs fi fi if ismounted $fs; then # n always is 1 in this case user_run $user zfs set \ $perm=${modes[$n]} $fs if [[ $oldval != \ $(get_prop $perm $fs) ]]; then return 1 fi # mount permission is needed # to make zoned=on log_must zfs allow $user mount $fs user_run $user zfs set \ $perm=${modes[$n]} $fs log_must zfs unallow $user mount $fs if [[ ${modes[$n]} != \ $(get_prop $perm $fs) ]]; then return 1 fi fi fi if ! is_global_zone; then user_run $user zfs set $perm=${modes[$n]} $fs if [[ $oldval != $(get_prop $perm $fs) ]]; then return 1 fi fi return 0 } function verify_fs_sharenfs { typeset user=$1 typeset perm=$2 typeset fs=$3 typeset nmode omode omode=$(get_prop $perm $fs) if [[ $omode == "off" ]]; then nmode="on" else nmode="off" fi log_note "$user zfs set $perm=$nmode $fs" user_run $user zfs set $perm=$nmode $fs if [[ $(get_prop $perm $fs) != $nmode ]]; then return 1 fi log_note "$user zfs set $perm=$omode $fs" user_run $user zfs set $perm=$omode $fs if [[ $(get_prop $perm $fs) != $omode ]]; then return 1 fi return 0 } function verify_vol_destroy { typeset user=$1 typeset perm=$2 typeset vol=$3 user_run $user zfs destroy $vol if ! datasetexists $vol ; then return 1 fi # mount permission is required log_must zfs allow $user mount $vol user_run $user zfs destroy $vol if datasetexists $vol ; then return 1 fi return 0 } function verify_vol_snapshot { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basevol=${vol%/*} typeset snap=$vol@snap.$stamp user_run $user zfs snapshot $snap if datasetexists $snap ; then return 1 fi log_must zfs allow $user mount $vol user_run $user zfs snapshot $snap log_must zfs unallow $user mount $vol if ! datasetexists $snap ; then return 1 fi return 0 } function verify_vol_rollback { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basevol=${vol%/*} typeset snap=$vol@snap.$stamp typeset oldval log_must zfs snapshot $snap oldval=$(datasetcksum $vol) log_must dd if=/dev/random of=/dev/zvol/rdsk/$vol \ bs=512 count=1 user_run $user zfs rollback -R $snap sleep 10 if [[ $oldval == $(datasetcksum $vol) ]]; then return 1 fi # rollback on volume has to be with mount permission log_must zfs allow $user mount $vol user_run $user zfs rollback -R $snap sleep 10 log_must zfs unallow $user mount $vol if [[ $oldval != $(datasetcksum $vol) ]]; then return 1 fi return 0 } function verify_vol_clone { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basevol=${vol%/*} typeset snap=$vol@snap.$stamp typeset clone=$basevol/cvol.$stamp log_must zfs snapshot $snap user_run $user zfs clone $snap $clone if datasetexists $clone ; then return 1 fi log_must zfs allow $user create $basevol user_run $user zfs clone $snap $clone log_must zfs unallow $user create $basevol if datasetexists $clone ; then return 1 fi log_must zfs allow $user mount $basevol user_run $user zfs clone $snap $clone log_must zfs unallow $user mount $basevol if datasetexists $clone ; then return 1 fi # require create permission on parent and # mount permission on itself as well log_must zfs allow $user mount $basevol log_must zfs allow $user create $basevol user_run $user zfs clone $snap $clone log_must zfs unallow $user create $basevol log_must zfs unallow $user mount $basevol if ! datasetexists $clone ; then return 1 fi return 0 } function verify_vol_rename { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basevol=${vol%/*} typeset snap=$vol@snap.$stamp typeset clone=$basevol/cvol.$stamp typeset renamevol=$basevol/nvol.$stamp user_run $user zfs rename $vol $renamevol if datasetexists $renamevol ; then return 1 fi log_must zfs allow $user create $basevol user_run $user zfs rename $vol $renamevol log_must zfs unallow $user create $basevol if datasetexists $renamevol ; then return 1 fi log_must zfs allow $user mount $basevol user_run $user zfs rename $vol $renamevol log_must zfs unallow $user mount $basevol if datasetexists $renamevol ; then return 1 fi # require both create permission on parent and # mount permission on parent as well log_must zfs allow $user mount $basevol log_must zfs allow $user create $basevol user_run $user zfs rename $vol $renamevol log_must zfs unallow $user mount $basevol log_must zfs unallow $user create $basevol if ! datasetexists $renamevol ; then return 1 fi log_must zfs rename $renamevol $vol return 0 } function verify_vol_promote { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset stamp=${perm}.${user}.$RANDOM typeset basevol=${vol%/*} typeset snap=$vol@snap.$stamp typeset clone=$basevol/cvol.$stamp log_must zfs snapshot $snap log_must zfs clone $snap $clone log_must zfs promote $clone typeset vol_orig=$(get_prop origin $vol) typeset clone_orig=$(get_prop origin $clone) # promote should fail if $vol and $clone # miss either mount or promote permission # case 1 user_run $user zfs promote $vol if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote should fail if $vol and $clone # miss either mount or promote permission # case 2 log_must zfs allow $user promote $clone user_run $user zfs promote $vol log_must zfs unallow $user promote $clone if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote should fail if $vol and $clone # miss either mount or promote permission # case 3 log_must zfs allow $user mount $vol user_run $user zfs promote $vol log_must zfs unallow $user mount $vol if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote should fail if $vol and $clone # miss either mount or promote permission # case 4 log_must zfs allow $user mount $clone user_run $user zfs promote $vol log_must zfs unallow $user mount $clone if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote should fail if $vol and $clone # miss either mount or promote permission # case 5 log_must zfs allow $user promote $clone log_must zfs allow $user mount $vol user_run $user zfs promote $vol log_must zfs unallow $user promote $clone log_must zfs unallow $user mount $vol if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote should fail if $vol and $clone # miss either mount or promote permission # case 6 log_must zfs allow $user promote $clone log_must zfs allow $user mount $clone user_run $user zfs promote $vol log_must zfs unallow $user promote $clone log_must zfs unallow $user mount $vol if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote should fail if $vol and $clone # miss either mount or promote permission # case 7 log_must zfs allow $user mount $vol log_must zfs allow $user mount $clone user_run $user zfs promote $vol log_must zfs unallow $user mount $vol log_must zfs unallow $user mount $clone if [[ $vol_orig != $(get_prop origin $vol) || \ $clone_orig != $(get_prop origin $clone) ]]; then return 1 fi # promote only succeeds when $vol and $clone # have both mount and promote permission # case 8 log_must zfs allow $user promote $clone log_must zfs allow $user mount $vol log_must zfs allow $user mount $clone user_run $user zfs promote $vol log_must zfs unallow $user promote $clone log_must zfs unallow $user mount $vol log_must zfs unallow $user mount $clone if [[ $snap != $(get_prop origin $clone) || \ $clone_orig != $(get_prop origin $vol) ]]; then return 1 fi return 0 } function verify_vol_volsize { typeset user=$1 typeset perm=$2 typeset vol=$3 typeset oldval oldval=$(get_prop volsize $vol) (( newval = oldval * 2 )) reserv_size=$(get_prop refreservation $vol) if [[ "0" == $reserv_size ]]; then # sparse volume user_run $user zfs set volsize=$newval $vol if [[ $oldval == $(get_prop volsize $vol) ]]; then return 1 fi else # normal volume, reservation permission # is required user_run $user zfs set volsize=$newval $vol if [[ $newval == $(get_prop volsize $vol) ]]; then return 1 fi log_must zfs allow $user reservation $vol log_must zfs allow $user refreservation $vol user_run $user zfs set volsize=$newval $vol log_must zfs unallow $user reservation $vol log_must zfs unallow $user refreservation $vol if [[ $oldval == $(get_prop volsize $vol) ]]; then return 1 fi fi return 0 } function verify_allow { typeset user=$1 typeset perm=$2 typeset dtst=$3 typeset -i ret user_run $user zfs allow $user allow $dtst ret=$? if [[ $ret -eq 0 ]]; then return 1 fi log_must zfs allow $user copies $dtst user_run $user zfs allow $user copies $dtst ret=$? log_must zfs unallow $user copies $dtst if [[ $ret -eq 1 ]]; then return 1 fi return 0 } function verify_allow_output { typeset dtst=$1 shift cat >>/tmp/allow_template.$$ < 0 )); do typeset section=$1 typeset content=$2 cat >>/tmp/allow_template.$$ </tmp/allow_output.$$ typeset -i ret log_must diff -u /tmp/allow_template.$$ /tmp/allow_output.$$ ret=$? rm -f /tmp/allow_template.$$ /tmp/allow_output.$$ if [[ $ret -eq 0 ]]; then return 0 fi return 1 }