xref: /illumos-gate/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_inherit_003_pos.ksh (revision bd97c7ce2344fa3252d8785c35895490916bc79b)
1#!/bin/ksh -p
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27
28#
29# Copyright 2016 Nexenta Systems, Inc.
30# Copyright 2023 RackTop Systems, Inc.
31#
32
33. $STF_SUITE/tests/functional/acl/acl_common.kshlib
34
35# DESCRIPTION:
36# Verify chmod have correct behaviour to directory and file when
37# filesystem has the different aclinherit setting
38#
39# STRATEGY:
40# 1. Use both super user and non-super user to run the test case.
41# 2. Create basedir and a set of subdirectores and files within it.
42# 3. Separately chmod basedir with different inherite options,
43#    combine with the variable setting of aclinherit:
44#    "discard", "noallow", "restricted" or "passthrough".
45# 4. Then create nested directories and files like the following.
46#
47#               ofile
48#               odir
49#    chmod -->  basedir -|
50#                        |_ nfile1
51#                        |_ ndir1 _
52#                                  |_ nfile2
53#                                  |_ ndir2 _
54#                                            |_ nfile3
55#                                            |_ ndir3
56#
57# 5. Verify each directories and files have the correct access control
58#    capability.
59
60verify_runnable "both"
61
62function cleanup
63{
64	[[ -f $ofile ]] && log_must rm -f $ofile
65	[[ -d $odir ]] && log_must rm -rf $odir
66	[[ -d $basedir ]] && log_must rm -rf $basedir
67}
68
69log_assert "Verify chmod have correct behaviour to directory and file when" \
70    "filesystem has the different aclinherit setting"
71log_onexit cleanup
72
73# Define inherit flag
74typeset aclinherit_flag=("discard" "noallow" "restricted" "passthrough")
75typeset object_flag=("f-" "-d" "fd")
76typeset strategy_flag=("--" "i-" "-n" "in")
77
78typeset ace_prefix1="owner@"
79typeset ace_prefix2="group@"
80typeset ace_prefix3="everyone@"
81
82# Define the base directory and file
83basedir=$TESTDIR/basedir; ofile=$TESTDIR/ofile; odir=$TESTDIR/odir
84
85# Define the files and directories that will be created after chmod
86ndir1=$basedir/ndir1; ndir2=$ndir1/ndir2; ndir3=$ndir2/ndir3
87nfile1=$basedir/nfile1; nfile2=$ndir1/nfile2; nfile3=$ndir2/nfile3
88
89# Verify all nodes have expected correct access control
90allnodes="$ndir1 $ndir2 $ndir3 $nfile1 $nfile2 $nfile3"
91
92# According to inherited flag, verify subdirectories and files within it has
93# correct inherited access control.
94function verify_inherit #<aclinherit> <object> [strategy]
95{
96	# Define the nodes which will be affected by inherit.
97	typeset inherit_nodes
98	typeset inherit=$1
99	typeset obj=$2
100	typeset str=$3
101
102	log_must usr_exec mkdir -p $ndir3
103	log_must usr_exec touch $nfile1 $nfile2 $nfile3
104
105	# Check if we have any inheritance flags set
106	if [[ $obj != "--" ]]; then
107		# Files should have inherited ACEs only if file_inherit is set
108		if [[ ${obj:0:1} == "f" ]]; then
109			inherit_nodes="$inherit_nodes $nfile1"
110			if [[ ${str:1:1} != "n" ]]; then
111				inherit_nodes="$inherit_nodes $nfile2 $nfile3"
112			fi
113		fi
114
115		# Directories should have inherited ACEs if file_inherit without
116		# no_propagate and/or dir_inherit is set
117		if [[ (${obj:0:1} == "f" && ${str:1:1} != "n") ||
118		    ${obj:1:1} == "d" ]]; then
119			inherit_nodes="$inherit_nodes $ndir1"
120			if [[ ${str:1:1} != "n" ]]; then
121				inherit_nodes="$inherit_nodes $ndir2 $ndir3"
122			fi
123		fi
124	fi
125
126	for node in $allnodes; do
127		typeset -i i=0 count=0 inherited=0
128		typeset expacl perm inh act
129
130		if [[ "$inherit_nodes" == *"$node"* ]]; then
131			inherited=1
132		fi
133
134		while ((i < maxaces)); do
135			# If current node isn't in inherit list, there's
136			# nothing to check, skip to checking trivial ACL
137			if ((inherited == 0)); then
138				((count = maxaces + 1))
139				break
140			fi
141
142			eval expacl=\$acl$i
143			case $inherit in
144			discard)
145				# Do not inherit any ACEs
146				((count = maxaces + 1))
147				break
148				;;
149			noallow)
150				# Only inherit inheritable ACEs that specify
151				# "deny" permissions
152				if [[ $expacl == *":allow" ]] ; then
153					((i = i + 1))
154					continue
155				fi
156				;;
157			restricted)
158				# Remove write_acl and write_owner permissions
159				# when the ACEs is inherited
160				eval expacl=\$acls$i
161				;;
162			passthrough)
163				;;
164			esac
165
166			perm=${expacl%:*}
167			inh=${perm##*:}
168			inh=${inh:0:2}
169			perm=${perm%:*}
170			act=${expacl##*:}
171
172			if [[ -d $node ]]; then
173				# Clear inheritance flags if no_propagate is set
174				if [[ ${str:1:1} == "n" ]]; then
175					inh="--"
176				fi
177				expacl="$perm:$inh"
178				# Set inherit_only if there's a file_inherit
179				# without dir_inherit
180				if [[ ${obj:0:1} == "f" &&
181				    ${obj:1:1} != "d" ]]; then
182					expacl="${expacl}i---I:$act"
183				else
184					expacl="${expacl}----I:$act"
185				fi
186			elif [[ -f $node ]] ; then
187				expacl="$perm:------I:$act"
188			fi
189
190			aclcur=$(get_ACE $node $count compact)
191			aclcur=${aclcur#$count:}
192			if [[ -n $expacl && $expacl != $aclcur ]]; then
193				ls -Vd $basedir
194				ls -Vd $node
195				log_fail "$inherit $i #$count" \
196				    "expected: $expacl, current: $aclcur"
197			fi
198
199			((i = i + 1))
200			((count = count + 1))
201		done
202
203		# There were no non-trivial ACEs to check, do the trivial ones
204		if ((count == maxaces + 1)); then
205			if [[ -d $node ]]; then
206				compare_acls $node $odir
207			elif [[ -f $node ]]; then
208				compare_acls $node $ofile
209			fi
210
211			if (( $? != 0 )); then
212				ls -Vd $basedir
213				ls -Vd $node
214				log_fail "unexpected acl: $node," \
215				    "$inherit ($str)"
216			fi
217		fi
218
219	done
220}
221
222typeset -i i=0 maxaces=6
223typeset acl0 acl1 acl2 acl3 acl4 acl5
224typeset acls0 acls1 acls2 acls3 acls4 acls5
225
226log_must zfs set aclmode=passthrough $TESTPOOL/$TESTFS
227
228for inherit in "${aclinherit_flag[@]}"; do
229	log_must zfs set aclinherit=$inherit $TESTPOOL/$TESTFS
230
231	for user in root $ZFS_ACL_STAFF1; do
232		log_must set_cur_usr $user
233
234		for obj in "${object_flag[@]}"; do
235			for str in "${strategy_flag[@]}"; do
236				typeset inh_opt=$obj
237				((${#str} != 0)) && inh_opt="${inh_opt}${str}--"
238
239				inh_a="${inh_opt}-"
240				inh_b="${inh_opt}I"
241
242				# deny - to verify "noallow"
243				# write_acl/write_owner - to verify "restricted"
244				acl0="$ace_prefix1:rwxp---A-W-Co-:$inh_a:allow"
245				acl1="$ace_prefix2:-------A-W--o-:$inh_a:deny"
246				acl2="$ace_prefix3:-------A-W-Co-:$inh_a:allow"
247				acl3="$ace_prefix1:-------A-W----:$inh_a:deny"
248				acl4="$ace_prefix2:-------A-W----:$inh_a:allow"
249				acl5="$ace_prefix3:-------A-W----:$inh_a:deny"
250
251				# ACEs filtered by write_acl/write_owner
252				acls0="$ace_prefix1:rwxp---A-W----:$inh_b:allow"
253				acls1="$ace_prefix2:-------A-W--o-:$inh_b:deny"
254				acls2="$ace_prefix3:-------A-W----:$inh_b:allow"
255				acls3="$ace_prefix1:-------A-W----:$inh_b:deny"
256				acls4="$ace_prefix2:-------A-W----:$inh_b:allow"
257				acls5="$ace_prefix3:-------A-W----:$inh_b:deny"
258
259				log_must usr_exec mkdir $basedir
260				log_must usr_exec mkdir $odir
261				log_must usr_exec touch $ofile
262
263				((i = maxaces - 1))
264				while ((i >= 0)); do
265					eval acl=\$acl$i
266					log_must usr_exec chmod A+$acl $basedir
267					((i = i - 1))
268				done
269
270				verify_inherit $inherit $obj $str
271
272				log_must usr_exec rm -rf $ofile $odir $basedir
273			done
274		done
275	done
276done
277
278log_pass "Verify chmod inherit behaviour co-op with aclinherit setting passed"
279