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 2009 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27 28# 29# Copyright (c) 2016 by Delphix. All rights reserved. 30# 31 32. $STF_SUITE/tests/functional/acl/acl_common.kshlib 33 34# 35# DESCRIPTION: 36# chmod A{+|-|=} read_data|write_data|execute for owner@ group@ or 37# everyone@ correctly alters mode bits . 38# 39# STRATEGY: 40# 1. Loop root and non-root user. 41# 2. Get the random initial map. 42# 3. Get the random ACL string. 43# 4. Separately chmod +|-|= read_data|write_data|execute 44# 5. Check map bits 45# 46 47verify_runnable "both" 48 49log_assert "chmod A{+|-|=} read_data|write_data|execute for owner@, group@ " \ 50 "or everyone@ correctly alters mode bits." 51log_onexit cleanup 52 53set -A bits 0 1 2 3 4 5 6 7 54set -A a_flag owner group everyone 55set -A a_access read_data write_data execute 56set -A a_type allow deny 57 58# 59# Get a random item from an array. 60# 61# $1 the base set 62# 63function random_select #array_name 64{ 65 typeset arr_name=$1 66 typeset -i ind 67 68 eval typeset -i cnt=\${#${arr_name}[@]} 69 (( ind = $RANDOM % cnt )) 70 71 eval print \${${arr_name}[$ind]} 72} 73 74# 75# Create a random string according to array name, the item number and 76# separated tag. 77# 78# $1 array name where the function get the elements 79# $2 the items number which you want to form the random string 80# $3 the separated tag 81# 82function form_random_str #<array_name> <count> <sep> 83{ 84 typeset arr_name=$1 85 typeset -i count=${2:-1} 86 typeset sep=${3:-""} 87 88 typeset str="" 89 while (( count > 0 )); do 90 str="${str}$(random_select $arr_name)${sep}" 91 92 (( count -= 1 )) 93 done 94 95 print $str 96} 97 98# 99# According to the original bits, the input ACE access and ACE type, return the 100# expect bits after 'chmod A0{+|=}'. 101# 102# $1 bits which was make up of three bit 'rwx' 103# $2 ACE access which is read_data, write_data or execute 104# $3 ACE type which is allow or deny 105# 106function cal_bits #bits acl_access acl_type 107{ 108 typeset bits=$1 109 typeset acl_access=$2 110 typeset acl_type=$3 111 set -A bit r w x 112 113 typeset tmpbits="" 114 typeset -i i=0 115 while (( i < 3 )); do 116 if [[ $acl_access == *"${a_access[i]}"* ]]; then 117 if [[ $acl_type == "allow" ]]; then 118 tmpbits="$tmpbits${bit[i]}" 119 elif [[ $acl_type == "deny" ]]; then 120 tmpbits="${tmpbits}-" 121 fi 122 else 123 tmpbits="$tmpbits${bits:$i:1}" 124 fi 125 126 (( i += 1 )) 127 done 128 129 echo "$tmpbits" 130} 131 132# 133# Based on the initial node map before chmod and the ace-spec, check if chmod 134# has the correct behaven to map bits. 135# 136function check_test_result #init_mode node acl_flag acl_access a_type 137{ 138 typeset init_mode=$1 139 typeset node=$2 140 typeset acl_flag=$3 141 typeset acl_access=$4 142 typeset acl_type=$5 143 144 typeset -L3 u_bits=$init_mode 145 typeset g_bits=${init_mode:3:3} 146 typeset -R3 o_bits=$init_mode 147 148 if [[ $acl_flag == "owner" || $acl_flag == "everyone" ]]; then 149 u_bits=$(cal_bits $u_bits $acl_access $acl_type) 150 fi 151 if [[ $acl_flag == "group" || $acl_flag == "everyone" ]]; then 152 g_bits=$(cal_bits $g_bits $acl_access $acl_type) 153 fi 154 if [[ $acl_flag == "everyone" ]]; then 155 o_bits=$(cal_bits $o_bits $acl_access $acl_type) 156 fi 157 158 typeset cur_mode=$(get_mode $node) 159 cur_mode=${cur_mode:1:9} 160 161 if [[ $cur_mode == $u_bits$g_bits$o_bits ]]; then 162 log_note "SUCCESS: Current map($cur_mode) == " \ 163 "expected map($u_bits$g_bits$o_bits)" 164 else 165 log_fail "FAIL: Current map($cur_mode) != " \ 166 "expected map($u_bits$g_bits$o_bits)" 167 fi 168} 169 170function test_chmod_map #<node> 171{ 172 typeset node=$1 173 typeset init_mask acl_flag acl_access acl_type 174 typeset -i cnt 175 176 if (( ${#node} == 0 )); then 177 log_fail "FAIL: file name or directory name is not defined." 178 fi 179 180 # Get the initial map 181 init_mask=$(form_random_str bits 3) 182 # Get ACL flag, access & type 183 acl_flag=$(form_random_str a_flag) 184 (( cnt = ($RANDOM % ${#a_access[@]}) + 1 )) 185 acl_access=$(form_random_str a_access $cnt '/') 186 acl_access=${acl_access%/} 187 acl_type=$(form_random_str a_type) 188 189 typeset acl_spec=${acl_flag}@:${acl_access}:${acl_type} 190 191 # Set the initial map and back the initial ACEs 192 typeset orig_ace=/tmp/orig_ace.$$ 193 typeset cur_ace=/tmp/cur_ace.$$ 194 195 for operator in "A0+" "A0="; do 196 log_must usr_exec chmod $init_mask $node 197 init_mode=$(get_mode $node) 198 init_mode=${init_mode:1:9} 199 log_must usr_exec eval "ls -vd $node > $orig_ace" 200 201 # To "A=", firstly add one ACE which can't modify map 202 if [[ $operator == "A0=" ]]; then 203 log_must chmod A0+user:$ZFS_ACL_OTHER1:execute:deny \ 204 $node 205 fi 206 log_must usr_exec chmod $operator$acl_spec $node 207 check_test_result \ 208 $init_mode $node $acl_flag $acl_access $acl_type 209 210 # Check "chmod A-" 211 log_must usr_exec chmod A0- $node 212 log_must usr_exec eval "ls -vd $node > $cur_ace" 213 214 if diff $orig_ace $cur_ace; then 215 log_note "SUCCESS: current ACEs are equal to " \ 216 "original ACEs. 'chmod A-' succeeded." 217 else 218 log_fail "FAIL: 'chmod A-' failed." 219 fi 220 done 221 222 [[ -f $orig_ace ]] && log_must usr_exec rm -f $orig_ace 223 [[ -f $cur_ace ]] && log_must usr_exec rm -f $cur_ace 224} 225 226for user in root $ZFS_ACL_STAFF1; do 227 set_cur_usr $user 228 229 typeset -i loop_cnt=20 230 while (( loop_cnt > 0 )); do 231 log_must usr_exec touch $testfile 232 test_chmod_map $testfile 233 log_must rm -f $testfile 234 235 log_must usr_exec mkdir $testdir 236 test_chmod_map $testdir 237 log_must rm -rf $testdir 238 239 (( loop_cnt -= 1 )) 240 done 241done 242 243log_pass "chmod A{+|-|=} read_data|write_data|execute for owner@, group@ " \ 244 "or everyone@ correctly alters mode bits passed." 245