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.
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.
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]
24 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
29 # Copyright (c) 2012 by Delphix. All rights reserved.
30 # Copyright 2016 Nexenta Systems, Inc.
34 .
$STF_SUITE/tests
/functional
/acl
/acl_common.kshlib
37 # Verify chmod have correct behaviour on directories and files when
38 # filesystem has the different aclmode setting
41 # 1. Loop super user and non-super user to run the test case.
42 # 2. Create basedir and a set of subdirectores and files within it.
43 # 3. Separately chmod basedir with different aclmode options,
44 # combine with the variable setting of aclmode:
45 # "discard", "groupmask", or "passthrough".
46 # 4. Verify each directories and files have the correct access control
49 verify_runnable
"both"
53 (( ${#cwd} != 0 )) && cd $cwd
55 [[ -f $TARFILE ]] && log_must
$RM -f $TARFILE
56 [[ -d $basedir ]] && log_must
$RM -rf $basedir
59 log_assert
"Verify chmod have correct behaviour to directory and file when" \
60 "filesystem has the different aclmode setting"
63 set -A aclmode_flag
"discard" "groupmask" "passthrough"
66 "user:$ZFS_ACL_OTHER1" \
67 "user:$ZFS_ACL_OTHER2" \
68 "group:$ZFS_ACL_STAFF_GROUP" \
69 "group:$ZFS_ACL_OTHER_GROUP"
71 set -A argv
"000" "444" "644" "777" "755" "231" "562" "413"
73 set -A ace_file_preset \
78 "read_data/write_data" \
79 "read_data/write_data/append_data" \
80 "write_data/append_data" \
82 "write_data/append_data/execute" \
83 "read_data/write_data/append_data/execute"
85 # Define the base directory and file
86 basedir
=$TESTDIR/basedir
; ofile
=$basedir/ofile
; odir
=$basedir/odir
87 nfile
=$basedir/nfile
; ndir
=$basedir/ndir
89 TARFILE
=$TESTDIR/tarfile
91 # Verify all the node have expected correct access control
92 allnodes
="$nfile $ndir"
94 # According to the original bits, the input ACE access and ACE type, return the
95 # expect bits after 'chmod A0{+|=}'.
97 # $1 isdir indicate if the target is a directory
98 # $2 bits which was make up of three bit 'rwx'
99 # $3 bits_limit which was make up of three bit 'rwx'
100 # $4 ACE access which is read_data, write_data or execute
101 # $5 ctrl which is to determine allow or deny according to owner/group bit
102 function cal_bits
# isdir bits bits_limit acl_access ctrl
106 typeset
-i bits_limit
=$3
107 typeset acl_access
=$4
108 typeset
-i ctrl
=${5:-0}
109 typeset flagr
=0 flagw
=0 flagx
=0
112 if (( ctrl
== 0 )); then
113 if (( (( bits
& 4 )) != 0 )); then
116 if (( (( bits
& 2 )) != 0 )); then
119 if (( (( bits
& 1 )) != 0 )); then
123 # Determine ACE as per owner/group bit
128 if (( ((bits
& 4)) != 0 )) && \
129 (( ((bits_limit
& 4)) != 0 )); then
132 if (( ((bits
& 2)) != 0 )) && \
133 (( ((bits_limit
& 2)) != 0 )); then
136 if (( ((bits
& 1)) != 0 )) && \
137 (( ((bits_limit
& 1)) != 0 )); then
142 if ((flagr
!= 0)); then
143 if [[ $acl_access == *"read_data"* ]]; then
144 if [[ $acl_access == *"allow"* &&
145 $passthrough == 0 ]]; then
147 elif ((isdir
== 0)); then
148 tmpstr
=${tmpstr}/read_data
150 tmpstr
=${tmpstr}/list_directory
/read_data
155 if ((flagw
!= 0)); then
156 if [[ $acl_access == *"allow"* && $passthrough == 0 ]]; then
159 if [[ $acl_access == *"write_data"* ]]; then
160 if ((isdir
== 0)); then
161 tmpstr
=${tmpstr}/write_data
163 tmpstr
=${tmpstr}/add_file
/write_data
166 if [[ $acl_access == *"append_data"* ]]; then
167 if ((isdir
== 0)); then
168 tmpstr
=${tmpstr}/append_data
170 tmpstr
=${tmpstr}/add_subdirectory
171 tmpstr
=${tmpstr}/append_data
177 if ((flagx
!= 0)); then
178 if [[ $acl_access == *"execute"* ]]; then
179 if [[ $acl_access == *"allow"* &&
180 $passthrough == 0 ]]; then
183 tmpstr
=${tmpstr}/execute
194 # To translate an ace if the node is dir
196 # $1 isdir indicate if the target is a directory
197 # $2 acl to be translated
199 function translate_acl
# isdir acl
203 typeset who prefix acltemp action
205 if ((isdir
!= 0)); then
209 acltemp
=${acltemp%%:*}
210 prefix
=$prefix:$acltemp
212 acl
=$prefix:$
(cal_bits
$isdir 7 7 $acl 0):$action
218 # To verify if a new ACL is generated as result of
221 # $1 bit indicates whether owner/group bit
222 # $2 newmode indicates the mode changed using chmod
223 # $3 isdir indicate if the target is a directory
225 function check_new_acl
# bit newmode isdir
238 if (( ((bits
& 4)) == 0 )); then
239 if (( ((gbit
& 4)) != 0 || \
240 ((ebit
& 4)) != 0 )); then
241 if ((isdir
== 0)); then
242 new_acl
=${new_acl}${str}read_data
244 new_acl
=${new_acl}${str}list_directory
/read_data
249 if (( ((bits
& 2)) == 0 )); then
250 if (( ((gbit
& 2)) != 0 || \
251 ((ebit
& 2)) != 0 )); then
252 if ((isdir
== 0)); then
253 new_acl
=${new_acl}${str}write_data
/append_data
255 new_acl
=${new_acl}${str}add_file
/write_data
/
256 new_acl
=${new_acl}add_subdirectory
/append_data
262 if (( ((bits
& 1)) == 0 )); then
263 if (( ((gbit
& 1)) != 0 || \
264 ((ebit
& 1)) != 0 )); then
265 new_acl
=${new_acl}${str}execute
268 new_acl
=${new_acl}${dc}
272 function build_new_acl
# newmode isdir
277 if ((flag
== 0)); then
280 status
=$
(check_new_acl
$bit $newmode $isdir)
285 status
=$
(check_new_acl
$bit $newmode $isdir)
287 expect
=$prefix$status:deny
291 # According to inherited flag, verify subdirectories and files within it has
292 # correct inherited access control.
293 function verify_aclmode
# <aclmode> <node> <newmode>
295 # Define the nodes which will be affected by inherit.
300 # count: the ACE item to fetch
301 # pass: to mark if the current ACE should apply to the target
302 # passcnt: counter, if it achieves to maxnumber,
303 # then no additional ACE should apply.
305 typeset
-i count
=0 pass
=0 passcnt
=0
306 typeset
-i bits
=0 obits
=0 bits_owner
=0 isdir
=0
308 typeset
-i acl_count
=$
(count_ACE
$node)
310 ((total_acl
= maxnumber
+ 3))
312 if [[ -d $node ]]; then
316 ((i
= maxnumber
- 1))
325 # aclmode=passthrough,
326 # no changes will be made to the ACL other than
327 # generating the necessary ACL entries to represent
328 # the new mode of the file or directory.
331 # delete all ACL entries that don't represent
332 # the mode of the file.
335 # reduce user or group permissions. The permissions are
336 # reduced, such that they are no greater than the group
337 # permission bits, unless it is a user entry that has the
338 # same UID as the owner of the file or directory.
339 # Then, the ACL permissions are reduced so that they are
340 # no greater than owner permission bits.
345 if ((acl_count
> total_acl
)); then
346 expect1
=$
(build_new_acl
$newmode $isdir)
348 ((total_acl
= total_acl
+ 1))
352 expect1
=$
(translate_acl
$isdir $expect1)
356 if ((acl_count
> total_acl
)); then
357 expect1
=$
(build_new_acl
$newmode $isdir)
359 ((total_acl
= total_acl
+ 1))
361 elif [[ $expect1 == *":allow"* ]]; then
363 aclaction
=${expect1##*:}
367 # To determine the mask bits
368 # according to the entry type.
381 acltemp
=${expect1#*:}
382 acltemp
=${acltemp%%:*}
383 owner
=$
(get_owner
$node)
384 group
=$
(get_group
$node)
385 if [[ $acltemp == $owner ]]; then
390 prefix
=$prefix:$acltemp
393 acltemp
=${expect1#*:}
394 acltemp
=${acltemp%%:*}
396 prefix
=$prefix:$acltemp
401 obits
=${newmode:$pos:1}
403 # permission should be no greater than the
404 # group permission bits
405 if ((reduce
!= 0)); then
406 ((bits
&= ${newmode:1:1}))
407 # The ACL permissions are reduced so
408 # that they are no greater than owner
410 ((bits_owner
= ${newmode:0:1}))
411 ((bits
&= $bits_owner))
414 if ((bits
< obits
)) && [[ -n $acltemp ]]; then
416 new_bit
=$
(cal_bits
$isdir $obits \
417 $bits_owner $expect1 1)
418 expect2
=${expect2}${new_bit}:allow
421 new_bit
=$
(cal_bits
$isdir $obits \
423 expect2
=${expect2}${new_bit}:allow
426 priv
=$
(cal_bits
$isdir $obits $bits_owner \
428 expect1
=$prefix:$priv:$aclaction
430 expect1
=$
(translate_acl
$isdir $expect1)
439 if ((pass
== 0)) ; then
440 # Get the first ACE to do comparison
441 aclcur
=$
(get_ACE
$node $count)
442 aclcur
=${aclcur#$count:}
443 if [[ -n $expect1 && $expect1 != $aclcur ]]; then
445 log_fail
"$aclmode $i #$count " \
446 "ACE: $aclcur, expect to be " \
449 ((count
= count
+ 1))
455 # If there's no any ACE be checked, it should be identify as
456 # an normal file/dir, verify it.
458 if ((passcnt
== maxnumber
)); then
459 if [[ -d $node ]]; then
460 compare_acls
$node $odir
461 elif [[ -f $node ]]; then
462 compare_acls
$node $ofile
465 if [[ $?
-ne 0 ]]; then
467 log_fail
"Unexpect acl: $node, $aclmode ($newmode)"
474 typeset
-i maxnumber
=0
477 typeset
-i passthrough
=0
482 for mode
in "${aclmode_flag[@]}"; do
483 log_must
$ZFS set aclmode
=$mode $TESTPOOL/$TESTFS
485 for user
in root
$ZFS_ACL_STAFF1; do
486 log_must set_cur_usr
$user
488 log_must usr_exec
$MKDIR $basedir
490 log_must usr_exec
$MKDIR $odir
491 log_must usr_exec
$TOUCH $ofile
492 log_must usr_exec
$MKDIR $ndir
493 log_must usr_exec
$TOUCH $nfile
495 for obj
in $allnodes; do
497 for preset
in "${ace_file_preset[@]}"; do
498 for prefix
in "${ace_prefix[@]}"; do
501 case $
((maxnumber
% 2)) in
510 log_must usr_exec
$CHMOD A
+$acl $obj
511 acls
[$maxnumber]=$acl
513 ((maxnumber
= maxnumber
+ 1))
516 # Archive the file and directory
517 log_must
$TAR cpf@
$TARFILE $basedir
519 if [[ -d $obj ]]; then
521 elif [[ -f $obj ]]; then
524 for newmode
in "${argv[@]}"; do
525 log_must usr_exec
$CHMOD $newmode $obj
526 log_must usr_exec
$CHMOD $newmode $target
527 log_must verify_aclmode
$mode $obj $newmode
528 log_must
$TAR xpf@
$TARFILE
532 log_must usr_exec
$RM -rf $basedir $TARFILE
536 log_pass
"Verify chmod behaviour co-op with aclmode setting passed"