1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or https://opensource.org/licenses/CDDL-1.0.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27#
28# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
29# Copyright 2016 Nexenta Systems, Inc.
30# Copyright (c) 2018 George Melikov. All Rights Reserved.
31#
32
33. $STF_SUITE/include/libtest.shlib
34. $STF_SUITE/tests/functional/delegate/delegate.cfg
35
36#
37# Cleanup exist user/group.
38#
39function cleanup_user_group
40{
41	typeset i
42	for i in $STAFF1 $STAFF2 $OTHER1 $OTHER2 ; do
43		del_user $i
44	done
45	for i in $STAFF_GROUP $OTHER_GROUP ; do
46		del_group $i
47	done
48
49	return 0
50}
51
52#
53# Restore test file system to the original status.
54#
55function restore_root_datasets
56{
57	destroy_dataset "$ROOT_TESTFS" "-Rf"
58	log_must zfs create $ROOT_TESTFS
59
60	if is_global_zone ; then
61		destroy_dataset "$ROOT_TESTVOL" "-Rf"
62		log_must zfs create -V $VOLSIZE $ROOT_TESTVOL
63		block_device_wait
64	fi
65
66	return 0
67}
68
69#
70# Verify the specified user have permission on the dataset
71#
72# $1 dataset
73# $2 permissions which are separated by comma(,)
74# $3-n users
75#
76function verify_perm
77{
78	typeset dtst=$1
79	typeset permissions=$2
80	shift 2
81
82	if [[ -z $@ || -z $permissions || -z $dtst ]]; then
83		return 1
84	fi
85
86	typeset type=$(get_prop type $dtst)
87	permissions=$(echo $permissions | tr -s "," " ")
88
89	typeset user
90	for user in $@; do
91		typeset perm
92		for perm in $permissions; do
93			typeset -i ret=1
94			if [[ $type == "filesystem" ]]; then
95				check_fs_perm $user $perm $dtst
96				ret=$?
97			elif [[ $type == "volume" ]]; then
98				check_vol_perm $user $perm $dtst
99				ret=$?
100			fi
101
102			log_note "Check $type $user $perm $dtst"
103			if ((ret != 0)) ; then
104				log_note "Fail: $user should have $perm" \
105					"on $dtst"
106				return 1
107			fi
108		done
109	done
110
111	return 0
112}
113
114#
115# Verify the specified user have no permission on the dataset
116#
117# $1 dataset
118# $2 permissions which are separated by comma(,)
119# $3-n users
120#
121function verify_noperm
122{
123	typeset dtst=$1
124	typeset permissions=$2
125	shift 2
126
127	if [[ -z $@ || -z $permissions || -z $dtst ]]; then
128		return 1
129	fi
130
131	typeset type=$(get_prop type $dtst)
132	permissions=$(echo $permissions | tr -s "," " ")
133
134	typeset user
135	for user in $@; do
136		typeset perm
137		for perm in $permissions; do
138			typeset -i ret=1
139			if [[ $type == "filesystem" ]]; then
140				check_fs_perm $user $perm $dtst
141				ret=$?
142			elif [[ $type == "volume" ]]; then
143				check_vol_perm $user $perm $dtst
144				ret=$?
145			fi
146
147			if ((ret == 0)) ; then
148				log_note "Fail: $user should not have $perm " \
149					"on $dtst"
150				return 1
151			fi
152		done
153	done
154
155	return 0
156}
157
158function common_perm
159{
160	typeset user=$1
161	typeset perm=$2
162	typeset dtst=$3
163
164	case $perm in
165		send)
166			verify_send $user $perm $dtst
167			;;
168		allow)
169			verify_allow $user $perm $dtst
170			;;
171		userprop)
172			verify_userprop $user $perm $dtst
173			;;
174		compression|checksum|readonly)
175			verify_ccr $user $perm $dtst
176			;;
177		copies)
178			verify_copies $user $perm $dtst
179			;;
180		reservation)
181			verify_reservation $user $perm $dtst
182			;;
183		*)
184			return 1
185			;;
186	esac
187}
188
189function check_fs_perm
190{
191	typeset user=$1
192	typeset perm=$2
193	typeset fs=$3
194
195	case $perm in
196		create)
197			verify_fs_create $user $perm $fs
198			;;
199		destroy)
200			verify_fs_destroy $user $perm $fs
201			;;
202		snapshot)
203			verify_fs_snapshot $user $perm $fs
204			;;
205		rollback)
206			verify_fs_rollback $user $perm $fs
207			;;
208		clone)
209			verify_fs_clone $user $perm $fs
210			;;
211		rename)
212			verify_fs_rename $user $perm $fs
213			;;
214		mount)
215			verify_fs_mount $user $perm $fs
216			;;
217		share)
218			verify_fs_share $user $perm $fs
219			;;
220		mountpoint)
221			verify_fs_mountpoint $user $perm $fs
222			;;
223		promote)
224			verify_fs_promote $user $perm $fs
225			;;
226		canmount)
227			verify_fs_canmount $user $perm $fs
228			;;
229		dnodesize)
230			verify_fs_dnodesize $user $perm $fs
231			;;
232		recordsize)
233			verify_fs_recordsize $user $perm $fs
234			;;
235		quota)
236			verify_fs_quota $user $perm $fs
237			;;
238		aclmode)
239			verify_fs_aclmode $user $perm $fs
240			;;
241		aclinherit)
242			verify_fs_aclinherit $user $perm $fs
243			;;
244		snapdir)
245			verify_fs_snapdir $user $perm $fs
246			;;
247		atime|exec|devices|setuid|xattr)
248			verify_fs_aedsx $user $perm $fs
249			;;
250		zoned)
251			verify_fs_zoned $user $perm $fs
252			;;
253		sharenfs)
254			verify_fs_sharenfs $user $perm $fs
255			;;
256		receive)
257			verify_fs_receive $user $perm $fs
258			;;
259		*)
260			common_perm $user $perm $fs
261			;;
262	esac
263}
264
265function check_vol_perm
266{
267	typeset user=$1
268	typeset perm=$2
269	typeset vol=$3
270
271	case $perm in
272		destroy)
273			verify_vol_destroy $user $perm $vol
274			;;
275		snapshot)
276			verify_vol_snapshot $user $perm $vol
277			;;
278		rollback)
279			verify_vol_rollback $user $perm $vol
280			;;
281		clone)
282			verify_vol_clone $user $perm $vol
283			;;
284		rename)
285			verify_vol_rename $user $perm $vol
286			;;
287		promote)
288			verify_vol_promote $user $perm $vol
289			;;
290		volsize)
291			verify_vol_volsize $user $perm $vol
292			;;
293		*)
294			common_perm $user $perm $vol
295			;;
296	esac
297}
298
299function setup_unallow_testenv
300{
301	log_must restore_root_datasets
302
303	log_must zfs create $SUBFS
304
305	for dtst in $DATASETS ; do
306		log_must zfs allow -l $STAFF1 $LOCAL_SET $dtst
307		log_must zfs allow -d $STAFF2 $DESC_SET  $dtst
308		log_must zfs allow $OTHER1 $LOCAL_DESC_SET $dtst
309		log_must zfs allow $OTHER2 $LOCAL_DESC_SET $dtst
310
311		log_must verify_perm $dtst $LOCAL_SET $STAFF1
312		log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER1
313		log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2
314		if [[ $dtst == $ROOT_TESTFS ]]; then
315			log_must verify_perm $SUBFS $DESC_SET $STAFF2
316			log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1
317			log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2
318		fi
319	done
320}
321
322#
323# Verify permission send for specified user on the dataset
324# $1 user
325# $2 permission
326# $3 dataset
327#
328function verify_send
329{
330	typeset user=$1
331	typeset perm=$2
332	typeset dtst=$3
333
334	typeset oldval
335	typeset stamp=${perm}.${user}.$RANDOM
336	typeset snap=$dtst@snap.$stamp
337
338	typeset -i ret=1
339
340	log_must zfs snapshot $snap
341	typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
342	typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
343
344	user_run $user eval "zfs send $snap > $bak_user"
345	log_must eval "zfs send $snap > $bak_root"
346
347	if [ "$(cksum < $bak_user)" = "$(cksum < $bak_root)" ]; then
348		ret=0
349	fi
350
351	rm -rf $bak_user $bak_root
352
353	return $ret
354}
355
356function verify_fs_receive
357{
358	typeset user=$1
359	typeset perm=$2
360	typeset fs=$3
361
362	typeset dtst
363	typeset stamp=${perm}.${user}.$RANDOM
364	typeset newfs=$fs/newfs.$stamp
365	typeset newvol=$fs/newvol.$stamp
366	typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
367	typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
368
369	log_must zfs create $newfs
370	typeset datasets="$newfs"
371	if is_global_zone ; then
372		log_must zfs create -V $VOLSIZE $newvol
373		block_device_wait
374		datasets="$newfs $newvol"
375	fi
376
377	for dtst in $datasets ; do
378
379		typeset dtstsnap=$dtst@snap.$stamp
380		log_must zfs snapshot $dtstsnap
381
382		log_must eval "zfs send $dtstsnap > $bak_root"
383		log_must_busy zfs destroy -rf $dtst
384
385		user_run $user eval "zfs receive $dtst < $bak_root"
386		if datasetexists $dtstsnap ; then
387			return 1
388		fi
389
390		log_must zfs allow $user create $fs
391		user_run $user eval "zfs receive $dtst < $bak_root"
392		log_must zfs unallow $user create $fs
393		if datasetexists $dtstsnap ; then
394			return 1
395		fi
396
397		log_must zfs allow $user mount $fs
398		user_run $user eval "zfs receive $dtst < $bak_root"
399		log_must zfs unallow $user mount $fs
400		if datasetexists $dtstsnap ; then
401			return 1
402		fi
403
404		log_must zfs allow $user mount,create $fs
405		user_run $user eval "zfs receive $dtst < $bak_root"
406		log_must zfs unallow $user mount,create $fs
407		if ! datasetexists $dtstsnap ; then
408			return 1
409		fi
410
411		# check the data integrity
412		log_must eval "zfs send $dtstsnap > $bak_user"
413		log_must_busy zfs destroy -rf $dtst
414		log_must eval "zfs receive $dtst < $bak_root"
415		log_must eval "zfs send $dtstsnap > $bak_root"
416		log_must_busy zfs destroy -rf $dtst
417		if [ "$(cksum < $bak_user)" != "$(cksum < $bak_root)" ]; then
418			return 1
419		fi
420
421		rm -rf $bak_user $bak_root
422
423	done
424
425	return 0
426}
427
428function verify_userprop
429{
430	typeset user=$1
431	typeset perm=$2
432	typeset dtst=$3
433
434	typeset stamp=${perm}.${user}.$RANDOM
435
436	user_run $user zfs set "$user:ts=$stamp" $dtst
437	sync_pool ${dtst%%/*}
438	if [[ $stamp != $(get_prop "$user:ts" $dtst) ]]; then
439		return 1
440	fi
441
442	return 0
443}
444
445function verify_ccr
446{
447	typeset user=$1
448	typeset perm=$2
449	typeset dtst=$3
450
451	typeset oldval
452
453	set -A modes "on" "off"
454	oldval=$(get_prop $perm $dtst)
455	if [[ $oldval == "on" ]]; then
456		n=1
457	elif [[ $oldval == "off" ]]; then
458		n=0
459	fi
460	log_note "$user zfs set $perm=${modes[$n]} $dtst"
461	user_run $user zfs set $perm=${modes[$n]} $dtst
462	if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
463		return 1
464	fi
465
466	return 0
467}
468
469function verify_copies
470{
471	typeset user=$1
472	typeset perm=$2
473	typeset dtst=$3
474
475	typeset oldval
476
477	set -A modes 1 2 3
478	oldval=$(get_prop $perm $dtst)
479	if [[ $oldval -eq 1 ]]; then
480		n=1
481	elif [[ $oldval -eq 2 ]]; then
482		n=2
483	elif [[ $oldval -eq 3 ]]; then
484		n=0
485	fi
486	log_note "$user zfs set $perm=${modes[$n]} $dtst"
487	user_run $user zfs set $perm=${modes[$n]} $dtst
488	if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
489		return 1
490	fi
491
492	return 0
493}
494
495function verify_reservation
496{
497	typeset user=$1
498	typeset perm=$2
499	typeset dtst=$3
500
501	typeset value32m=$(( 1024 * 1024 * 32 ))
502	typeset oldval=$(get_prop reservation $dtst)
503	user_run $user zfs set reservation=$value32m $dtst
504	if [[ $value32m != $(get_prop reservation $dtst) ]]; then
505		log_must zfs set reservation=$oldval $dtst
506		return 1
507	fi
508
509	log_must zfs set reservation=$oldval $dtst
510	return 0
511}
512
513function verify_fs_create
514{
515	typeset user=$1
516	typeset perm=$2
517	typeset fs=$3
518
519	typeset stamp=${perm}.${user}.$RANDOM
520	typeset newfs=$fs/nfs.$stamp
521	typeset newvol=$fs/nvol.$stamp
522
523	user_run $user zfs create $newfs
524	if datasetexists $newfs ; then
525		return 1
526	fi
527
528	log_must zfs allow $user mount $fs
529	user_run $user zfs create $newfs
530	log_must zfs unallow $user mount $fs
531	if ! datasetexists $newfs ; then
532		return 1
533	fi
534
535	log_must zfs destroy $newfs
536
537	if is_global_zone ; then
538		# mount permission is required for sparse volume
539		user_run $user zfs create -V 150m -s $newvol
540		block_device_wait
541		if datasetexists $newvol ; then
542			return 1
543		fi
544
545		log_must zfs allow $user mount $fs
546		user_run $user zfs create -V 150m -s $newvol
547		log_must zfs unallow $user mount $fs
548		if ! datasetexists $newvol ; then
549			return 1
550		fi
551
552		block_device_wait
553		log_must zfs destroy $newvol
554		block_device_wait
555
556		# mount and reserveration permission are
557		# required for normal volume
558		user_run $user zfs create -V 150m $newvol
559		block_device_wait
560		if datasetexists $newvol ; then
561			return 1
562		fi
563
564		log_must zfs allow $user mount $fs
565		user_run $user zfs create -V 150m $newvol
566		block_device_wait
567		log_must zfs unallow $user mount $fs
568		if datasetexists $newvol ; then
569			return 1
570		fi
571
572		log_must zfs allow $user reservation $fs
573		user_run $user zfs create -V 150m $newvol
574		block_device_wait
575		log_must zfs unallow $user reservation $fs
576		if datasetexists $newvol ; then
577			return 1
578		fi
579
580		log_must zfs allow $user refreservation $fs
581		user_run $user zfs create -V 150m $newvol
582		block_device_wait
583		log_must zfs unallow $user refreservation $fs
584		if datasetexists $newvol ; then
585			return 1
586		fi
587
588		log_must zfs allow $user mount $fs
589		log_must zfs allow $user reservation $fs
590		log_must zfs allow $user refreservation $fs
591		user_run $user zfs create -V 150m $newvol
592		log_must zfs unallow $user mount $fs
593		log_must zfs unallow $user reservation $fs
594		log_must zfs unallow $user refreservation $fs
595		if ! datasetexists $newvol ; then
596			return 1
597		fi
598
599		block_device_wait
600		log_must zfs destroy $newvol
601		block_device_wait
602	fi
603
604	return 0
605}
606
607function verify_fs_destroy
608{
609	typeset user=$1
610	typeset perm=$2
611	typeset fs=$3
612
613	if ! ismounted $fs ; then
614		user_run $user zfs destroy $fs
615		if datasetexists $fs ; then
616			return 1
617		fi
618	fi
619
620	if ismounted $fs ; then
621		user_run $user zfs destroy $fs
622		if ! datasetexists $fs ; then
623			return 1
624		fi
625
626		# mount permission is required
627		log_must zfs allow $user mount $fs
628		user_run $user zfs destroy $fs
629		if datasetexists $fs ; then
630			return 1
631		fi
632	fi
633
634	return 0
635}
636
637# Verify that given the correct delegation, a regular user can:
638#	Take a snapshot of an unmounted dataset
639# 	Take a snapshot of a mounted dataset
640#	Create a snapshot by making a directory in the .zfs/snapshot directory
641function verify_fs_snapshot
642{
643	typeset user=$1
644	typeset perm=$2
645	typeset fs=$3
646
647	typeset stamp=${perm}.${user}.$RANDOM
648	typeset snap=$fs@snap.$stamp
649	typeset mntpt=$(get_prop mountpoint $fs)
650
651	if [[ "yes" == $(get_prop mounted $fs) ]]; then
652		log_must zfs umount $fs
653	fi
654
655	user_run $user zfs snapshot $snap
656	if ! datasetexists $snap ; then
657		return 1
658	fi
659	log_must zfs destroy $snap
660
661	if [[ "no" == $(get_prop mounted $fs) ]]; then
662		log_must zfs mount $fs
663	fi
664
665	user_run $user zfs snapshot $snap
666	if ! datasetexists $snap ; then
667		return 1
668	fi
669	log_must zfs destroy $snap
670
671	# Creating snaps via mkdir is not supported on FreeBSD
672	if ! is_freebsd; then
673		typeset snapdir=${mntpt}/.zfs/snapshot/snap.$stamp
674		user_run $user mkdir $snapdir
675		if ! datasetexists $snap ; then
676			return 1
677		fi
678		log_must zfs destroy $snap
679	fi
680
681	return 0
682}
683
684function verify_fs_rollback
685{
686	typeset user=$1
687	typeset perm=$2
688	typeset fs=$3
689
690	typeset oldval
691	typeset stamp=${perm}.${user}.$RANDOM
692	typeset snap=$fs@snap.$stamp
693	typeset mntpt=$(get_prop mountpoint $fs)
694
695	oldval=$(datasetcksum $fs)
696	log_must zfs snapshot $snap
697
698	if ! ismounted $fs; then
699		log_must zfs mount $fs
700	fi
701	log_must touch $mntpt/testfile.$stamp
702
703	user_run $user zfs rollback -R $snap
704	if is_global_zone ; then
705		if [[ $oldval != $(datasetcksum $fs) ]]; then
706			return 1
707		fi
708	else
709		# datasetcksum can not be used in local zone
710		if [[ -e $mntpt/testfile.$stamp ]]; then
711			return 1
712		fi
713	fi
714
715	return 0
716}
717
718function verify_fs_clone
719{
720	typeset user=$1
721	typeset perm=$2
722	typeset fs=$3
723
724	typeset stamp=${perm}.${user}.$RANDOM
725	typeset basefs=${fs%/*}
726	typeset snap=$fs@snap.$stamp
727	typeset clone=$basefs/cfs.$stamp
728
729	log_must zfs snapshot $snap
730	user_run $user zfs clone $snap $clone
731	if datasetexists $clone ; then
732		return 1
733	fi
734
735	log_must zfs allow $user create $basefs
736	user_run $user zfs clone $snap $clone
737	log_must zfs unallow $user create $basefs
738	if datasetexists $clone ; then
739		return 1
740	fi
741
742	log_must zfs allow $user mount $basefs
743	user_run $user zfs clone $snap $clone
744	log_must zfs unallow $user mount $basefs
745	if datasetexists $clone ; then
746		return 1
747	fi
748
749	log_must zfs allow $user mount $basefs
750	log_must zfs allow $user create $basefs
751	user_run $user zfs clone $snap $clone
752	log_must zfs unallow $user create $basefs
753	log_must zfs unallow $user mount $basefs
754	if ! datasetexists $clone ; then
755		return 1
756	fi
757
758	log_must zfs destroy -R $snap
759
760	return 0
761}
762
763function verify_fs_rename
764{
765	typeset user=$1
766	typeset perm=$2
767	typeset fs=$3
768
769	typeset stamp=${perm}.${user}.$RANDOM
770	typeset basefs=${fs%/*}
771	typeset snap=$fs@snap.$stamp
772	typeset renamefs=$basefs/nfs.$stamp
773
774	if ! ismounted $fs; then
775		log_must zfs mount $fs
776	fi
777
778	# case 1
779	user_run $user zfs rename $fs $renamefs
780	if datasetexists $renamefs ; then
781		return 1
782	fi
783
784	# case 2
785	log_must zfs allow $user create $basefs
786	user_run $user zfs rename $fs $renamefs
787	log_must zfs unallow $user create $basefs
788	if datasetexists $renamefs ; then
789		return 1
790	fi
791
792	# case 3
793	log_must zfs allow $user mount $basefs
794	user_run $user zfs rename $fs $renamefs
795	log_must zfs unallow $user mount $basefs
796	if datasetexists $renamefs ; then
797		return 1
798	fi
799
800	# case 4
801	log_must zfs allow $user mount $fs
802	user_run $user zfs rename $fs $renamefs
803	if datasetexists $renamefs ; then
804		log_must zfs unallow $user mount $renamefs
805		return 1
806	fi
807	log_must zfs unallow $user mount $fs
808
809	# case 5
810	log_must zfs allow $user create $basefs
811	log_must zfs allow $user mount $fs
812	user_run $user zfs rename $fs $renamefs
813	log_must zfs unallow $user create $basefs
814	if datasetexists $renamefs ; then
815		log_must zfs unallow $user mount $renamefs
816		return 1
817	fi
818	log_must zfs unallow $user mount $fs
819
820	# case 6
821	log_must zfs allow $user mount $basefs
822	log_must zfs allow $user mount $fs
823	user_run $user zfs rename $fs $renamefs
824	log_must zfs unallow $user mount $basefs
825	if datasetexists $renamefs ; then
826		log_must zfs unallow $user mount $renamefs
827		return 1
828	fi
829	log_must zfs unallow $user mount $fs
830
831	# case 7
832	log_must zfs allow $user create $basefs
833	log_must zfs allow $user mount $basefs
834	user_run $user zfs rename $fs $renamefs
835	log_must zfs unallow $user mount $basefs
836	log_must zfs unallow $user create $basefs
837	if ! datasetexists $renamefs ; then
838		return 1
839	fi
840
841	log_must zfs rename $renamefs $fs
842
843	return 0
844}
845
846function verify_fs_mount
847{
848	typeset user=$1
849	typeset perm=$2
850	typeset fs=$3
851
852	typeset stamp=${perm}.${user}.$RANDOM
853	typeset mntpt=$(get_prop mountpoint $fs)
854	typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
855
856	if ismounted $fs ; then
857		user_run $user zfs unmount $fs
858		if ismounted $fs ; then
859			return 1
860		fi
861	fi
862
863	if ! ismounted $fs ; then
864		log_must zfs set -u mountpoint=$newmntpt $fs
865		log_must rm -rf $newmntpt
866		log_must mkdir $newmntpt
867
868		user_run $user zfs mount $fs
869		if ismounted $fs ; then
870			return 1
871		fi
872
873		# mountpoint's owner must be the user
874		log_must chown $user $newmntpt
875		user_run $user zfs mount $fs
876		if ! ismounted $fs ; then
877			return 1
878		fi
879		log_must zfs umount $fs
880		log_must rm -rf $newmntpt
881		log_must zfs set -u mountpoint=$mntpt $fs
882	fi
883
884	return 0
885}
886
887function verify_fs_share
888{
889	typeset user=$1
890	typeset perm=$2
891	typeset fs=$3
892	typeset -i ret=0
893
894	svcadm enable -rs nfs/server
895	typeset stat=$(svcs -H -o STA nfs/server:default)
896	if [[ $stat != "ON" ]]; then
897		log_fail "Could not enable nfs/server"
898	fi
899
900	log_must zfs set sharenfs=on $fs
901	zfs unshare $fs
902
903	user_run $user zfs share $fs
904	if ! is_shared $fs; then
905		ret=1
906	fi
907
908	zfs unshare $fs
909	log_must zfs set sharenfs=off $fs
910
911	return $ret
912}
913
914function verify_fs_mountpoint
915{
916	typeset user=$1
917	typeset perm=$2
918	typeset fs=$3
919
920	typeset stamp=${perm}.${user}.$RANDOM
921	typeset mntpt=$(get_prop mountpoint $fs)
922	typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
923
924	if ! ismounted $fs ; then
925		user_run $user zfs set mountpoint=$newmntpt $fs
926		if [[ $newmntpt != \
927			$(get_prop mountpoint $fs) ]] ; then
928			return 1
929		fi
930		log_must zfs set mountpoint=$mntpt $fs
931	fi
932
933	if ismounted $fs ; then
934		user_run $user zfs set mountpoint=$newmntpt $fs
935		if [[ $mntpt != $(get_prop mountpoint $fs) ]]; then
936			return 1
937		fi
938
939		# require mount permission when fs is mounted
940		log_must zfs allow $user mount $fs
941		user_run $user zfs set mountpoint=$newmntpt $fs
942		log_must zfs unallow $user mount $fs
943		if [[ $newmntpt != \
944			$(get_prop mountpoint $fs) ]] ; then
945			return 1
946		fi
947		log_must zfs set mountpoint=$mntpt $fs
948	fi
949
950	return 0
951}
952
953function verify_fs_promote
954{
955	typeset user=$1
956	typeset perm=$2
957	typeset fs=$3
958
959	typeset stamp=${perm}.${user}.$RANDOM
960	typeset basefs=${fs%/*}
961	typeset snap=$fs@snap.$stamp
962	typeset clone=$basefs/cfs.$stamp
963
964	log_must zfs snapshot $snap
965	log_must zfs clone $snap $clone
966	log_must zfs promote $clone
967
968	typeset fs_orig=$(get_prop origin $fs)
969	typeset clone_orig=$(get_prop origin $clone)
970
971	user_run $user zfs promote $fs
972	# promote should fail if original fs does not have
973	# promote permission
974	if [[ $fs_orig != $(get_prop origin $fs) || \
975		$clone_orig != $(get_prop origin $clone) ]]; then
976		return 1
977	fi
978
979	log_must zfs allow $user promote $clone
980	user_run $user zfs promote $fs
981	log_must zfs unallow $user promote $clone
982	if [[ $fs_orig != $(get_prop origin $fs) || \
983		$clone_orig != $(get_prop origin $clone) ]]; then
984		return 1
985	fi
986
987	log_must zfs allow $user mount $fs
988	user_run $user zfs promote $fs
989	log_must zfs unallow $user mount $fs
990	if [[ $fs_orig != $(get_prop origin $fs) || \
991		$clone_orig != $(get_prop origin $clone) ]]; then
992		return 1
993	fi
994
995	log_must zfs allow $user mount $fs
996	log_must zfs allow $user promote $clone
997	user_run $user zfs promote $fs
998	log_must zfs unallow $user promote $clone
999	log_must zfs unallow $user mount $fs
1000	if [[ $snap != $(get_prop origin $clone) || \
1001		$clone_orig != $(get_prop origin $fs) ]]; then
1002		return 1
1003	fi
1004
1005	return 0
1006}
1007
1008function verify_fs_canmount
1009{
1010	typeset user=$1
1011	typeset perm=$2
1012	typeset fs=$3
1013
1014	typeset oldval
1015	typeset stamp=${perm}.${user}.$RANDOM
1016
1017	if ! ismounted $fs ; then
1018		set -A modes "on" "off"
1019		oldval=$(get_prop $perm $fs)
1020		if [[ $oldval == "on" ]]; then
1021			n=1
1022		elif [[ $oldval == "off" ]]; then
1023			n=0
1024		fi
1025		log_note "$user zfs set $perm=${modes[$n]} $fs"
1026		user_run $user zfs set $perm=${modes[$n]} $fs
1027		if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
1028			return 1
1029		fi
1030	fi
1031
1032
1033	# fs is mounted
1034	if ismounted $fs ; then
1035		# property value does not change if
1036		# no mount permission
1037		set -A modes "on" "off"
1038		oldval=$(get_prop $perm $fs)
1039		if [[ $oldval == "on" ]]; then
1040			n=1
1041		elif [[ $oldval == "off" ]]; then
1042			n=0
1043		fi
1044		log_note "$user zfs set $perm=${modes[$n]} $fs"
1045		log_must zfs allow $user mount $fs
1046		user_run $user zfs set $perm=${modes[$n]} $fs
1047		log_must zfs unallow $user mount $fs
1048		if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
1049			return 1
1050		fi
1051	fi
1052
1053	return 0
1054}
1055
1056function verify_fs_recordsize
1057{
1058	typeset user=$1
1059	typeset perm=$2
1060	typeset fs=$3
1061
1062	typeset value8k=$(( 1024 * 8 ))
1063	user_run $user zfs set recordsize=$value8k $fs
1064	if [[ $value8k != $(get_prop recordsize $fs) ]]; then
1065		return 1
1066	fi
1067
1068	return 0
1069}
1070
1071function verify_fs_dnodesize
1072{
1073	typeset user=$1
1074	typeset perm=$2
1075	typeset fs=$3
1076	value="2k"
1077
1078	user_run $user zfs set dnodesize=$value $fs
1079	if [[ $value != $(get_prop dnodesize $fs) ]]; then
1080		return 1
1081	fi
1082
1083	return 0
1084}
1085
1086function verify_fs_quota
1087{
1088	typeset user=$1
1089	typeset perm=$2
1090	typeset fs=$3
1091
1092	typeset value32m=$(( 1024 * 1024 * 32 ))
1093	user_run $user zfs set quota=$value32m $fs
1094	if [[ $value32m != $(get_prop quota $fs) ]]; then
1095		return 1
1096	fi
1097
1098	return 0
1099}
1100
1101function verify_fs_aclmode
1102{
1103	typeset user=$1
1104	typeset perm=$2
1105	typeset fs=$3
1106
1107	typeset oldval
1108	set -A modes "discard" "groupmask" "passthrough"
1109	oldval=$(get_prop $perm $fs)
1110	if [[ $oldval == "discard" ]]; then
1111		n=1
1112	elif [[ $oldval == "groupmask" ]]; then
1113		n=2
1114	elif [[ $oldval == "passthrough" ]]; then
1115		n=0
1116	fi
1117	log_note "$user zfs set aclmode=${modes[$n]} $fs"
1118	user_run $user zfs set aclmode=${modes[$n]} $fs
1119	if [[ ${modes[$n]} != $(get_prop aclmode $fs) ]]; then
1120		return 1
1121	fi
1122
1123	return 0
1124}
1125
1126function verify_fs_aclinherit
1127{
1128	typeset user=$1
1129	typeset perm=$2
1130	typeset fs=$3
1131
1132	#
1133	# PSARC/2008/231 change the default value of aclinherit to "restricted"
1134	# but still keep the old interface of "secure"
1135	#
1136
1137	typeset oldval
1138	set -A modes "discard" "noallow" "secure" "passthrough"
1139	oldval=$(get_prop $perm $fs)
1140	if [[ $oldval == "discard" ]]; then
1141		n=1
1142	elif [[ $oldval == "noallow" ]]; then
1143		n=2
1144	elif [[ $oldval == "secure" || $oldval == "restricted" ]]; then
1145		n=3
1146	elif [[ $oldval == "passthrough" ]]; then
1147		n=0
1148	fi
1149	log_note "$user zfs set aclinherit=${modes[$n]} $fs"
1150	user_run $user zfs set aclinherit=${modes[$n]} $fs
1151
1152	typeset newval=$(get_prop aclinherit $fs)
1153	if [[ ${modes[$n]} == "secure" && $newval == "restricted" ]]; then
1154		return 0
1155	elif [[ ${modes[$n]} != $(get_prop aclinherit $fs) ]]; then
1156		return 1
1157	fi
1158
1159	return 0
1160}
1161
1162function verify_fs_snapdir
1163{
1164	typeset user=$1
1165	typeset perm=$2
1166	typeset fs=$3
1167
1168	typeset oldval
1169	set -A modes "visible" "hidden"
1170	oldval=$(get_prop $perm $fs)
1171	if [[ $oldval == "visible" ]]; then
1172		n=1
1173	elif [[ $oldval == "hidden" ]]; then
1174		n=0
1175	fi
1176	log_note "$user zfs set snapdir=${modes[$n]} $fs"
1177	user_run $user zfs set snapdir=${modes[$n]} $fs
1178	if [[ ${modes[$n]} != $(get_prop snapdir $fs) ]]; then
1179		return 1
1180	fi
1181
1182	return 0
1183}
1184
1185function verify_fs_aedsx
1186{
1187	typeset user=$1
1188	typeset perm=$2
1189	typeset fs=$3
1190
1191	typeset oldval
1192	set -A modes "on" "off"
1193	oldval=$(get_prop $perm $fs)
1194	if [[ $oldval == "on" ]]; then
1195		n=1
1196	elif [[ $oldval == "off" ]]; then
1197		n=0
1198	fi
1199	log_note "$user zfs set $perm=${modes[$n]} $fs"
1200	user_run $user zfs set $perm=${modes[$n]} $fs
1201	if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
1202		return 1
1203	fi
1204
1205	return 0
1206}
1207
1208function verify_fs_zoned
1209{
1210	typeset user=$1
1211	typeset perm=$2
1212	typeset fs=$3
1213
1214	typeset oldval
1215	set -A modes "on" "off"
1216	oldval=$(get_prop $perm $fs)
1217	if [[ $oldval == "on" ]]; then
1218		n=1
1219	elif [[ $oldval == "off" ]]; then
1220		n=0
1221	fi
1222	log_note "$user zfs set $perm=${modes[$n]} $fs"
1223	if is_global_zone ; then
1224		if ! ismounted $fs ; then
1225			user_run $user zfs set \
1226				$perm=${modes[$n]} $fs
1227			if [[ ${modes[$n]} != \
1228				$(get_prop $perm $fs) ]]; then
1229				return 1
1230			fi
1231			if [[ $n -eq 0 ]]; then
1232				log_mustnot zfs mount $fs
1233			else
1234				log_must zfs mount $fs
1235			fi
1236		fi
1237
1238		if ismounted $fs; then
1239			# n always is 1 in this case
1240			user_run $user zfs set \
1241				$perm=${modes[$n]} $fs
1242			if [[ $oldval != \
1243				$(get_prop $perm $fs) ]]; then
1244				return 1
1245			fi
1246
1247			# mount permission is needed
1248			# to make zoned=on
1249			log_must zfs allow $user mount $fs
1250			user_run $user zfs set \
1251				$perm=${modes[$n]} $fs
1252			log_must zfs unallow $user mount $fs
1253			if [[ ${modes[$n]} != \
1254				$(get_prop $perm $fs) ]]; then
1255				return 1
1256			fi
1257		fi
1258	fi
1259
1260	if ! is_global_zone; then
1261		user_run $user zfs set $perm=${modes[$n]} $fs
1262		if [[ $oldval != $(get_prop $perm $fs) ]]; then
1263			return 1
1264		fi
1265	fi
1266
1267	return 0
1268}
1269
1270function verify_fs_sharenfs
1271{
1272	typeset user=$1
1273	typeset perm=$2
1274	typeset fs=$3
1275	typeset nmode omode
1276
1277	omode=$(get_prop $perm $fs)
1278	if [[ $omode == "off" ]]; then
1279		nmode="on"
1280	else
1281		nmode="off"
1282	fi
1283
1284	log_note "$user zfs set $perm=$nmode $fs"
1285	user_run $user zfs set $perm=$nmode $fs
1286	if [[ $(get_prop $perm $fs) != $nmode ]]; then
1287		return 1
1288	fi
1289
1290	log_note "$user zfs set $perm=$omode $fs"
1291	user_run $user zfs set $perm=$omode $fs
1292	if [[ $(get_prop $perm $fs) != $omode ]]; then
1293		return 1
1294	fi
1295
1296	return 0
1297}
1298
1299function verify_vol_destroy
1300{
1301	typeset user=$1
1302	typeset perm=$2
1303	typeset vol=$3
1304
1305	user_run $user zfs destroy $vol
1306	if ! datasetexists $vol ; then
1307		return 1
1308	fi
1309
1310	# mount permission is required
1311	log_must zfs allow $user mount $vol
1312	user_run $user zfs destroy $vol
1313	if datasetexists $vol ; then
1314		return 1
1315	fi
1316
1317	return 0
1318}
1319
1320function verify_vol_snapshot
1321{
1322	typeset user=$1
1323	typeset perm=$2
1324	typeset vol=$3
1325
1326	typeset stamp=${perm}.${user}.$RANDOM
1327	typeset basevol=${vol%/*}
1328	typeset snap=$vol@snap.$stamp
1329
1330	user_run $user zfs snapshot $snap
1331	if datasetexists $snap ; then
1332		return 1
1333	fi
1334
1335	log_must zfs allow $user mount $vol
1336	user_run $user zfs snapshot $snap
1337	log_must zfs unallow $user mount $vol
1338	if ! datasetexists $snap ; then
1339		return 1
1340	fi
1341
1342	return 0
1343}
1344
1345function verify_vol_rollback
1346{
1347	typeset user=$1
1348	typeset perm=$2
1349	typeset vol=$3
1350
1351	typeset stamp=${perm}.${user}.$RANDOM
1352	typeset basevol=${vol%/*}
1353	typeset snap=$vol@snap.$stamp
1354
1355	typeset oldval
1356	log_must zfs snapshot $snap
1357	oldval=$(datasetcksum $vol)
1358
1359	log_must dd if=/dev/urandom of=$ZVOL_RDEVDIR/$vol \
1360		bs=512 count=1
1361
1362	user_run $user zfs rollback -R $snap
1363	sleep 10
1364	if [[ $oldval == $(datasetcksum $vol) ]]; then
1365		return 1
1366	fi
1367
1368	# rollback on volume has to be with mount permission
1369	log_must zfs allow $user mount $vol
1370	user_run $user zfs rollback -R $snap
1371	sleep 10
1372	log_must zfs unallow $user mount $vol
1373	if [[ $oldval != $(datasetcksum $vol) ]]; then
1374		return 1
1375	fi
1376
1377	return 0
1378}
1379
1380function verify_vol_clone
1381{
1382	typeset user=$1
1383	typeset perm=$2
1384	typeset vol=$3
1385
1386	typeset stamp=${perm}.${user}.$RANDOM
1387	typeset basevol=${vol%/*}
1388	typeset snap=$vol@snap.$stamp
1389	typeset clone=$basevol/cvol.$stamp
1390
1391	log_must zfs snapshot $snap
1392
1393	user_run $user zfs clone $snap $clone
1394	if datasetexists $clone ; then
1395		return 1
1396	fi
1397
1398	log_must zfs allow $user create $basevol
1399	user_run $user zfs clone $snap $clone
1400	log_must zfs unallow $user create $basevol
1401	if datasetexists $clone ; then
1402		return 1
1403	fi
1404
1405	log_must zfs allow $user mount $basevol
1406	user_run $user zfs clone $snap $clone
1407	log_must zfs unallow $user mount $basevol
1408	if datasetexists $clone ; then
1409		return 1
1410	fi
1411
1412	# require create permission on parent and
1413	# mount permission on itself as well
1414	log_must zfs allow $user mount $basevol
1415	log_must zfs allow $user create $basevol
1416	user_run $user zfs clone $snap $clone
1417	log_must zfs unallow $user create $basevol
1418	log_must zfs unallow $user mount $basevol
1419	if ! datasetexists $clone ; then
1420		return 1
1421	fi
1422
1423	return 0
1424}
1425
1426function verify_vol_rename
1427{
1428	typeset user=$1
1429	typeset perm=$2
1430	typeset vol=$3
1431
1432	typeset stamp=${perm}.${user}.$RANDOM
1433	typeset basevol=${vol%/*}
1434	typeset snap=$vol@snap.$stamp
1435	typeset clone=$basevol/cvol.$stamp
1436	typeset renamevol=$basevol/nvol.$stamp
1437
1438	user_run $user zfs rename $vol $renamevol
1439	if datasetexists $renamevol ; then
1440		return 1
1441	fi
1442
1443	log_must zfs allow $user create $basevol
1444	user_run $user zfs rename $vol $renamevol
1445	log_must zfs unallow $user create $basevol
1446	if datasetexists $renamevol ; then
1447		return 1
1448	fi
1449
1450	log_must zfs allow $user mount $basevol
1451	user_run $user zfs rename $vol $renamevol
1452	log_must zfs unallow $user mount $basevol
1453	if datasetexists $renamevol ; then
1454		return 1
1455	fi
1456
1457	# require both create permission on parent and
1458	# mount permission on parent as well
1459	log_must zfs allow $user mount $basevol
1460	log_must zfs allow $user create $basevol
1461	user_run $user zfs rename $vol $renamevol
1462	log_must zfs unallow $user mount $basevol
1463	log_must zfs unallow $user create $basevol
1464	if ! datasetexists $renamevol ; then
1465		return 1
1466	fi
1467
1468	log_must zfs rename $renamevol $vol
1469
1470	return 0
1471}
1472
1473function verify_vol_promote
1474{
1475	typeset user=$1
1476	typeset perm=$2
1477	typeset vol=$3
1478
1479	typeset stamp=${perm}.${user}.$RANDOM
1480	typeset basevol=${vol%/*}
1481	typeset snap=$vol@snap.$stamp
1482	typeset clone=$basevol/cvol.$stamp
1483
1484	log_must zfs snapshot $snap
1485	log_must zfs clone $snap $clone
1486	log_must zfs promote $clone
1487
1488	typeset vol_orig=$(get_prop origin $vol)
1489	typeset clone_orig=$(get_prop origin $clone)
1490
1491	# promote should fail if $vol and $clone
1492	# miss either mount or promote permission
1493	# case 1
1494	user_run $user zfs promote $vol
1495	if [[ $vol_orig != $(get_prop origin $vol) || \
1496		$clone_orig != $(get_prop origin $clone) ]];
1497	then
1498		return 1
1499	fi
1500
1501	# promote should fail if $vol and $clone
1502	# miss either mount or promote permission
1503	# case 2
1504	log_must zfs allow $user promote $clone
1505	user_run $user zfs promote $vol
1506	log_must zfs unallow $user promote $clone
1507	if [[ $vol_orig != $(get_prop origin $vol) || \
1508		$clone_orig != $(get_prop origin $clone) ]];
1509	then
1510		return 1
1511	fi
1512
1513	# promote should fail if $vol and $clone
1514	# miss either mount or promote permission
1515	# case 3
1516	log_must zfs allow $user mount $vol
1517	user_run $user zfs promote $vol
1518	log_must zfs unallow $user mount $vol
1519	if [[ $vol_orig != $(get_prop origin $vol) || \
1520		$clone_orig != $(get_prop origin $clone) ]];
1521	then
1522		return 1
1523	fi
1524
1525	# promote should fail if $vol and $clone
1526	# miss either mount or promote permission
1527	# case 4
1528	log_must zfs allow $user mount $clone
1529	user_run $user zfs promote $vol
1530	log_must zfs unallow $user mount $clone
1531	if [[ $vol_orig != $(get_prop origin $vol) || \
1532		$clone_orig != $(get_prop origin $clone) ]];
1533	then
1534		return 1
1535	fi
1536
1537	# promote should fail if $vol and $clone
1538	# miss either mount or promote permission
1539	# case 5
1540	log_must zfs allow $user promote $clone
1541	log_must zfs allow $user mount $vol
1542	user_run $user zfs promote $vol
1543	log_must zfs unallow $user promote $clone
1544	log_must zfs unallow $user mount $vol
1545	if [[ $vol_orig != $(get_prop origin $vol) || \
1546		$clone_orig != $(get_prop origin $clone) ]];
1547	then
1548		return 1
1549	fi
1550
1551	# promote should fail if $vol and $clone
1552	# miss either mount or promote permission
1553	# case 6
1554	log_must zfs allow $user promote $clone
1555	log_must zfs allow $user mount $clone
1556	user_run $user zfs promote $vol
1557	log_must zfs unallow $user promote $clone
1558	log_must zfs unallow $user mount $vol
1559	if [[ $vol_orig != $(get_prop origin $vol) || \
1560		$clone_orig != $(get_prop origin $clone) ]];
1561	then
1562		return 1
1563	fi
1564
1565	# promote should fail if $vol and $clone
1566	# miss either mount or promote permission
1567	# case 7
1568	log_must zfs allow $user mount $vol
1569	log_must zfs allow $user mount $clone
1570	user_run $user zfs promote $vol
1571	log_must zfs unallow $user mount $vol
1572	log_must zfs unallow $user mount $clone
1573	if [[ $vol_orig != $(get_prop origin $vol) || \
1574		$clone_orig != $(get_prop origin $clone) ]];
1575	then
1576		return 1
1577	fi
1578
1579	# promote only succeeds when $vol and $clone
1580	# have both mount and promote permission
1581	# case 8
1582	log_must zfs allow $user promote $clone
1583	log_must zfs allow $user mount $vol
1584	log_must zfs allow $user mount $clone
1585	user_run $user zfs promote $vol
1586	log_must zfs unallow $user promote $clone
1587	log_must zfs unallow $user mount $vol
1588	log_must zfs unallow $user mount $clone
1589	if [[ $snap != $(get_prop origin $clone) || \
1590		$clone_orig != $(get_prop origin $vol) ]]; then
1591		return 1
1592	fi
1593
1594	return 0
1595}
1596
1597function verify_vol_volsize
1598{
1599	typeset user=$1
1600	typeset perm=$2
1601	typeset vol=$3
1602
1603	typeset oldval
1604	oldval=$(get_prop volsize $vol)
1605	(( newval = oldval * 2 ))
1606
1607	reserv_size=$(get_prop refreservation $vol)
1608
1609	if [[ "0" == $reserv_size ]]; then
1610		# sparse volume
1611		user_run $user zfs set volsize=$newval $vol
1612		if [[ $oldval == $(get_prop volsize $vol) ]];
1613		then
1614			return 1
1615		fi
1616
1617	else
1618		# normal volume, reservation permission
1619		# is required
1620		user_run $user zfs set volsize=$newval $vol
1621		if [[ $newval == $(get_prop volsize $vol) ]];
1622		then
1623			return 1
1624		fi
1625
1626		log_must zfs allow $user reservation $vol
1627		log_must zfs allow $user refreservation $vol
1628		user_run $user zfs set volsize=$newval $vol
1629		log_must zfs unallow $user reservation $vol
1630		log_must zfs unallow $user refreservation $vol
1631		if [[ $oldval == $(get_prop volsize $vol) ]];
1632		then
1633			return 1
1634		fi
1635	fi
1636
1637	return 0
1638}
1639
1640function verify_allow
1641{
1642	typeset user=$1
1643	typeset perm=$2
1644	typeset dtst=$3
1645
1646	typeset -i ret
1647
1648	user_run $user zfs allow $user allow $dtst && return 1
1649
1650	log_must zfs allow $user copies $dtst
1651	user_run $user zfs allow $user copies $dtst
1652	ret=$?
1653	log_must zfs unallow $user copies $dtst
1654	[ $ret -ne 1 ]
1655
1656}
1657