PageRenderTime 49ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/sys/cddl/zfs/tests/acl/nontrivial/zfs_acl_chmod_aclmode_001_pos.ksh

https://bitbucket.org/freebsd/freebsd-base
Korn Shell | 490 lines | 285 code | 74 blank | 131 comment | 70 complexity | 357b591377826c06d74f618351a479bd MD5 | raw file
  1. #!/usr/local/bin/ksh93 -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. # $FreeBSD$
  23. #
  24. # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
  25. # Use is subject to license terms.
  26. #
  27. # ident "@(#)zfs_acl_chmod_aclmode_001_pos.ksh 1.3 08/08/15 SMI"
  28. #
  29. . $STF_SUITE/tests/acl/acl_common.kshlib
  30. #################################################################################
  31. #
  32. # __stc_assertion_start
  33. #
  34. # ID: zfs_acl_chmod_aclmode_001_pos
  35. #
  36. # DESCRIPTION:
  37. # Verify chmod have correct behaviour to directory and file when
  38. # filesystem has the different aclmode setting
  39. #
  40. # STRATEGY:
  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
  47. # capability.
  48. #
  49. # TESTABILITY: explicit
  50. #
  51. # TEST_AUTOMATION_LEVEL: automated
  52. #
  53. # CODING_STATUS: COMPLETED (2006-03-02)
  54. #
  55. # __stc_assertion_end
  56. #
  57. ################################################################################
  58. verify_runnable "both"
  59. test_requires ZFS_ACL
  60. function cleanup
  61. {
  62. # Cleanup tarfile & basedir.
  63. (( ${#cwd} != 0 )) && cd $cwd
  64. if [[ -f $TARFILE ]]; then
  65. log_must $RM -f $TARFILE
  66. fi
  67. if [[ -d $basedir ]]; then
  68. log_must $RM -rf $basedir
  69. fi
  70. }
  71. log_assert "Verify chmod have correct behaviour to directory and file when " \
  72. "filesystem has the different aclmode setting."
  73. log_onexit cleanup
  74. # Define aclmode flag
  75. set -A aclmode_flag discard groupmask passthrough
  76. set -A ace_prefix "user:$ZFS_ACL_OTHER1" \
  77. "user:$ZFS_ACL_OTHER2" \
  78. "group:$ZFS_ACL_STAFF_GROUP" \
  79. "group:$ZFS_ACL_OTHER_GROUP"
  80. set -A argv "000" "444" "644" "777" "755" "231" "562" "413"
  81. set -A ace_file_preset "read_data" \
  82. "write_data" \
  83. "append_data" \
  84. "execute" \
  85. "read_data/write_data" \
  86. "read_data/write_data/append_data" \
  87. "write_data/append_data" \
  88. "read_data/execute" \
  89. "write_data/append_data/execute" \
  90. "read_data/write_data/append_data/execute"
  91. # Defile the based directory and file
  92. basedir=$TESTDIR/basedir; ofile=$basedir/ofile; odir=$basedir/odir
  93. nfile=$basedir/nfile; ndir=$basedir/ndir
  94. TARFILE=$TESTDIR/tarfile
  95. # Verify all the node have expected correct access control
  96. allnodes="$nfile $ndir"
  97. #
  98. # According to the original bits, the input ACE access and ACE type, return the
  99. # expect bits after 'chmod A0{+|=}'.
  100. #
  101. # $1 isdir indicate if the target is a directory
  102. # $1 bits which was make up of three bit 'rwx'
  103. # $2 bits_limit which was make up of three bit 'rwx'
  104. # $3 ACE access which is read_data, write_data or execute
  105. # $4 ACE type which is allow or deny
  106. #
  107. function cal_bits #isdir bits bits_limit acl_access ctrl
  108. {
  109. typeset -i isdir=$1
  110. typeset -i bits=$2
  111. typeset -i bits_limit=$3
  112. typeset acl_access=$4
  113. typeset -i ctrl=${5:-0}
  114. typeset flagr=0; flagw=0; flagx=0
  115. typeset tmpstr
  116. if (( ctrl == 0 )); then
  117. if (( (( bits & 4 )) == 0 )); then
  118. flagr=1
  119. fi
  120. if (( (( bits & 2 )) == 0 )); then
  121. flagw=1
  122. fi
  123. if (( (( bits & 1 )) == 0 )); then
  124. flagx=1
  125. fi
  126. else
  127. #
  128. # Tricky here:
  129. # (1) flagr is always set to be 1,
  130. # (2) flagw & flagx is set to be 0 only while
  131. # bits_limit has lower permissions than bits
  132. #
  133. flagr=1
  134. flagw=1
  135. flagx=1
  136. if (( (( bits & 2 )) != 0 )) && \
  137. (( (( bits_limit & 2 )) == 0 )) ; then
  138. flagw=0
  139. fi
  140. if (( (( bits & 1 )) != 0 )) && \
  141. (( (( bits_limit & 1 )) == 0 )) ; then
  142. flagx=0
  143. fi
  144. fi
  145. if (( flagr != 0 )); then
  146. if [[ $acl_access == *"read_data"* ]]; then
  147. if (( isdir == 0 )) ; then
  148. tmpstr=${tmpstr}/read_data
  149. else
  150. tmpstr=${tmpstr}/list_directory/read_data
  151. fi
  152. fi
  153. fi
  154. if (( flagw != 0 )); then
  155. if [[ $acl_access == *"write_data"* ]]; then
  156. if (( isdir == 0 )); then
  157. tmpstr=${tmpstr}/write_data
  158. else
  159. tmpstr=${tmpstr}/add_file/write_data
  160. fi
  161. fi
  162. if [[ $acl_access == *"append_data"* ]]; then
  163. if (( isdir == 0 )); then
  164. tmpstr=${tmpstr}/append_data
  165. else
  166. tmpstr=${tmpstr}/add_subdirectory/append_data
  167. fi
  168. fi
  169. fi
  170. if (( flagx != 0 )); then
  171. [[ $acl_access == *"execute"* ]] && \
  172. tmpstr=${tmpstr}/execute
  173. fi
  174. tmpstr=${tmpstr#/}
  175. $ECHO "$tmpstr"
  176. }
  177. #
  178. # To translate an ace if the node is dir
  179. #
  180. # $1 isdir indicate if the target is a directory
  181. # $2 acl to be translated
  182. #
  183. function translate_acl #isdir acl
  184. {
  185. typeset -i isdir=$1
  186. typeset acl=$2
  187. typeset who prefix acltemp action
  188. if (( isdir != 0 )); then
  189. who=${acl%%:*}
  190. prefix=$who
  191. acltemp=${acl#*:}
  192. acltemp=${acltemp%%:*}
  193. prefix=$prefix:$acltemp
  194. action=${acl##*:}
  195. acl=$prefix:$(cal_bits $isdir 7 7 $acl 1):$action
  196. fi
  197. $ECHO "$acl"
  198. }
  199. #
  200. # According to inherited flag, verify subdirectories and files within it has
  201. # correct inherited access control.
  202. #
  203. function verify_aclmode #<aclmode> <node> <newmode>
  204. {
  205. # Define the nodes which will be affected by inherit.
  206. typeset aclmode=$1
  207. typeset node=$2
  208. typeset newmode=$3
  209. # count: the ACE item to fetch
  210. # pass: to mark if the current ACE should apply to the target
  211. # passcnt: counter, if it achieves to maxnumber,
  212. # then no additional ACE should apply.
  213. # step: indicate if the ACE be split during aclmode.
  214. typeset -i count=0 pass=0 passcnt=0 step=0
  215. typeset -i bits=0 obits=0 bits_owner=0 isdir=0
  216. if [[ -d $node ]]; then
  217. (( isdir = 1 ))
  218. fi
  219. (( i = maxnumber - 1 ))
  220. count=0
  221. passcnt=0
  222. while (( i >= 0 )); do
  223. pass=0
  224. step=0
  225. expect1=${acls[$i]}
  226. expect2=""
  227. #
  228. # aclmode=passthrough,
  229. # no changes will be made to the ACL other than
  230. # generating the necessary ACL entries to represent
  231. # the new mode of the file or directory.
  232. #
  233. # aclmode=discard,
  234. # delete all ACL entries that don't represent
  235. # the mode of the file.
  236. #
  237. # aclmode=groupmask,
  238. # reduce user or group permissions. The permissions are
  239. # reduced, such that they are no greater than the group
  240. # permission bits, unless it is a user entry that has the
  241. # same UID as the owner of the file or directory.
  242. # Then, the ACL permissions are reduced so that they are
  243. # no greater than owner permission bits.
  244. #
  245. case $aclmode in
  246. passthrough)
  247. expect1=$(translate_acl $isdir $expect1)
  248. ;;
  249. groupmask)
  250. if [[ $expect1 == *":allow" ]]; then
  251. expect2=$expect1
  252. who=${expect1%%:*}
  253. prefix=$who
  254. acltemp=""
  255. reduce=0
  256. # To determine the mask bits
  257. # according to the entry type.
  258. case $who in
  259. owner@)
  260. pos=1
  261. ;;
  262. group@)
  263. pos=2
  264. ;;
  265. everyone@)
  266. pos=3
  267. ;;
  268. user)
  269. acltemp=${expect1#*:}
  270. acltemp=${acltemp%%:*}
  271. owner=$(get_owner $node)
  272. group=$(get_group $node)
  273. if [[ $acltemp == $owner ]]; then
  274. pos=1
  275. else
  276. pos=2
  277. fi
  278. prefix=$prefix:$acltemp
  279. ;;
  280. group)
  281. acltemp=${expect1#*:}
  282. acltemp=${acltemp%%:*}
  283. pos=2
  284. prefix=$prefix:$acltemp
  285. reduce=1
  286. ;;
  287. esac
  288. obits=$(get_substr $newmode $pos 1)
  289. (( bits = obits ))
  290. #
  291. # permission should no greater than the group permission bits
  292. #
  293. if (( reduce != 0 )); then
  294. (( bits &= $(get_substr $newmode 2 1) ))
  295. # The ACL permissions are reduced so that they are
  296. # no greater than owner permission bits.
  297. (( bits_owner = $(get_substr $newmode 1 1) ))
  298. (( bits &= bits_owner ))
  299. fi
  300. if (( bits < obits )) && [[ -n $acltemp ]]; then
  301. expect2=$prefix:$(cal_bits $isdir $obits $bits_owner $expect2 1):allow
  302. else
  303. expect2=$prefix:$(cal_bits $isdir $obits $obits $expect2 1):allow
  304. fi
  305. priv=$(cal_bits $isdir $obits $bits_owner $expect2 0)
  306. expect1=$prefix:$priv:deny
  307. step=1
  308. else
  309. expect1=$(translate_acl $isdir $expect1)
  310. fi
  311. ;;
  312. discard)
  313. passcnt=maxnumber
  314. break
  315. ;;
  316. esac
  317. if (( pass == 0 )) ; then
  318. # Get the first ACE to do comparison
  319. aclcur=$(get_ACE $node $count)
  320. aclcur=${aclcur#$count:}
  321. if [[ -n $expect1 && $expect1 != $aclcur ]]; then
  322. $LS -vd $node
  323. log_fail "$i #$count " \
  324. "ACE: $aclcur, expect to be " \
  325. "$expect1"
  326. fi
  327. # Get the second ACE (if should have) to do comparison
  328. if (( step > 0 )); then
  329. (( count = count + step ))
  330. aclcur=$(get_ACE $node $count)
  331. aclcur=${aclcur#$count:}
  332. if [[ -n $expect2 && \
  333. $expect2 != $aclcur ]]; then
  334. $LS -vd $node
  335. log_fail "$i #$count " \
  336. "ACE: $aclcur, expect to be " \
  337. "$expect2"
  338. fi
  339. fi
  340. (( count = count + 1 ))
  341. fi
  342. (( i = i - 1 ))
  343. done
  344. #
  345. # If there's no any ACE be checked, it should be identify as
  346. # an normal file/dir, verify it.
  347. #
  348. if (( passcnt == maxnumber )); then
  349. if [[ -d $node ]]; then
  350. compare_acls $node $odir
  351. elif [[ -f $node ]]; then
  352. compare_acls $node $ofile
  353. fi
  354. if [[ $? -ne 0 ]]; then
  355. $LS -vd $node
  356. log_fail "Unexpect acl: $node, $aclmode ($newmode)"
  357. fi
  358. fi
  359. }
  360. typeset -i maxnumber=0
  361. typeset acl
  362. typeset target
  363. cwd=$PWD
  364. cd $TESTDIR
  365. for mode in "${aclmode_flag[@]}"; do
  366. #
  367. # Set different value of aclmode
  368. #
  369. log_must $ZFS set aclmode=$mode $TESTPOOL/$TESTFS
  370. for user in root $ZFS_ACL_STAFF1; do
  371. log_must set_cur_usr $user
  372. log_must usr_exec $MKDIR $basedir
  373. log_must usr_exec $MKDIR $odir
  374. log_must usr_exec $TOUCH $ofile
  375. log_must usr_exec $MKDIR $ndir
  376. log_must usr_exec $TOUCH $nfile
  377. for obj in $allnodes ; do
  378. maxnumber=0
  379. for preset in "${ace_file_preset[@]}"; do
  380. for prefix in "${ace_prefix[@]}"; do
  381. acl=$prefix:$preset
  382. case $(( maxnumber % 2 )) in
  383. 0)
  384. acl=$acl:deny
  385. ;;
  386. 1)
  387. acl=$acl:allow
  388. ;;
  389. esac
  390. #
  391. # Place on the target should succeed.
  392. #
  393. log_must usr_exec $CHMOD A+$acl $obj
  394. acls[$maxnumber]=$acl
  395. (( maxnumber = maxnumber + 1 ))
  396. done
  397. done
  398. # Archive the file and directory
  399. log_must $TAR cpf@ $TARFILE basedir
  400. if [[ -d $obj ]]; then
  401. target=$odir
  402. elif [[ -f $obj ]]; then
  403. target=$ofile
  404. fi
  405. for newmode in "${argv[@]}" ; do
  406. log_must usr_exec $CHMOD $newmode $obj
  407. log_must usr_exec $CHMOD $newmode $target
  408. verify_aclmode $mode $obj $newmode
  409. # Restore the tar archive
  410. log_must $TAR xpf@ $TARFILE
  411. done
  412. done
  413. log_must usr_exec $RM -rf $basedir $TARFILE
  414. done
  415. done
  416. log_pass "Verify chmod behaviour co-op with aclmode setting passed."