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) 2012, 2016 by Delphix. All rights reserved. 30# Copyright 2023 RackTop Systems, Inc. 31# 32 33. $STF_SUITE/tests/functional/acl/acl_common.kshlib 34 35# 36# DESCRIPTION: 37# Verify that the write_owner for 38# owner/group/everyone are correct. 39# 40# STRATEGY: 41# 1. Create file and directory in zfs filesystem 42# 2. Set special write_owner ACE to the file and directory 43# 3. Try to chown/chgrp of the file and directory to take owner/group 44# 4. Verify that the owner/group are correct. Follow these rules: 45# (1) If uid is granted the write_owner permission, then it can only do 46# chown to its own uid, or a group that they are a member of. 47# (2) chown/chgrp will fail when write_owner not granted. 48# (3) Superuser will always permit whatever they do. 49# 50 51verify_runnable "both" 52 53function cleanup 54{ 55 [[ -d $basedir ]] && rm -rf $basedir 56 [[ -f $TESTDIR/$ARCHIVEFILE ]] && log_must rm -f $TESTDIR/$ARCHIVEFILE 57 return 0 58} 59 60log_assert "Verify that the chown/chgrp could take owner/group " \ 61 "while permission is granted." 62log_onexit cleanup 63 64# 65# Get the owner of a file/directory 66# 67function get_owner 68{ 69 typeset node=$1 70 71 if [[ -z $node ]]; then 72 log_fail "node are not defined." 73 fi 74 75 echo $(ls -dl $node | awk '{print $3}') 76} 77 78# 79# Get the group of a file/directory 80# 81function get_group 82{ 83 typeset node=$1 84 85 if [[ -z $node ]]; then 86 log_fail "node are not defined." 87 fi 88 89 echo $(ls -dl $node | awk '{print $4}') 90} 91 92 93# 94# Get the group name that a UID belongs to 95# 96function get_user_group 97{ 98 typeset uid=$1 99 typeset value 100 101 if [[ -z $uid ]]; then 102 log_fail "UID not defined." 103 fi 104 105 value=$(id $uid) 106 107 if [[ $? -eq 0 ]]; then 108 value=${value##*\(} 109 value=${value%%\)*} 110 echo $value 111 else 112 log_fail "Invalid UID (uid)." 113 fi 114} 115 116function operate_node_owner 117{ 118 typeset user=$1 119 typeset node=$2 120 typeset old_owner=$3 121 typeset expect_owner=$4 122 typeset ret new_owner 123 124 if [[ $user == "" || $node == "" ]]; then 125 log_fail "user, node are not defined." 126 fi 127 128 su $user -c "chown $expect_owner $node" 129 ret=$? 130 new_owner=$(get_owner $node) 131 132 if [[ $new_owner != $old_owner ]]; then 133 tar xpf $TESTDIR/$ARCHIVEFILE 134 fi 135 136 if [[ $ret -eq 0 ]]; then 137 if [[ $new_owner != $expect_owner ]]; then 138 log_note "Owner not changed as expected " \ 139 "($old_owner|$new_owner|$expect_owner), " \ 140 "but return code is $ret." 141 return 1 142 fi 143 elif [[ $ret -ne 0 && $new_owner != $old_owner ]]; then 144 log_note "Owner changed ($old_owner|$new_owner), " \ 145 "but return code is $ret." 146 return 2 147 fi 148 149 return $ret 150} 151 152function operate_node_group 153{ 154 typeset user=$1 155 typeset node=$2 156 typeset old_group=$3 157 typeset expect_group=$4 158 typeset ret new_group 159 160 if [[ $user == "" || $node == "" ]]; then 161 log_fail "user, node are not defined." 162 fi 163 164 su $user -c "chgrp $expect_group $node" 165 ret=$? 166 new_group=$(get_group $node) 167 168 if [[ $new_group != $old_group ]]; then 169 tar xpf $TESTDIR/$ARCHIVEFILE 170 fi 171 172 if [[ $ret -eq 0 ]]; then 173 if [[ $new_group != $expect_group ]]; then 174 log_note "Group not changed as expected " \ 175 "($old_group|$new_group|$expect_group), " \ 176 "but return code is $ret." 177 return 1 178 fi 179 elif [[ $ret -ne 0 && $new_group != $old_group ]]; then 180 log_note "Group changed ($old_group|$new_group), " \ 181 "but return code is $ret." 182 return 2 183 fi 184 185 return $ret 186} 187 188function logname 189{ 190 typeset acl_target=$1 191 typeset user=$2 192 typeset old=$3 193 typeset new=$4 194 typeset ret="log_mustnot" 195 196 # To super user, read and write deny permission was override. 197 if [[ $user == root ]]; then 198 ret="log_must" 199 elif [[ $user == $new ]] ; then 200 if [[ $user == $old || $acl_target == *:allow ]]; then 201 # with aclimplicit=on, the write_owner:deny 202 # will have no effect and chown/chgrp commands 203 # needs to succeed. 204 if [[ $aclimplicit == on || 205 $acl_target != *@:write_owner:deny ]]; then 206 ret="log_must" 207 fi 208 fi 209 fi 210 211 print $ret 212} 213 214function check_chmod_results 215{ 216 typeset user=$1 217 typeset node=$2 218 typeset flag=$3 219 typeset acl_target=$3:$4 220 typeset g_usr=$5 221 typeset o_usr=$6 222 typeset log old_owner old_group new_owner new_group 223 224 old_owner=$(get_owner $node) 225 old_group=$(get_group $node) 226 227 if [[ $flag == "owner@" || $flag == "everyone@" ]]; then 228 for new_owner in $user "nobody"; do 229 new_group=$(get_user_group $new_owner) 230 231 log=$(logname $acl_target $user \ 232 $old_owner $new_owner) 233 234 $log operate_node_owner $user $node \ 235 $old_owner $new_owner 236 237 $log operate_node_group $user $node \ 238 $old_group $new_group 239 done 240 fi 241 if [[ $flag == "group@" || $flag == "everyone@" ]]; then 242 for new_owner in $g_usr "nobody"; do 243 new_group=$(get_user_group $new_owner) 244 245 log=$(logname $acl_target $g_usr $old_owner \ 246 $new_owner) 247 248 $log operate_node_owner $g_usr $node \ 249 $old_owner $new_owner 250 251 $log operate_node_group $g_usr \ 252 $node $old_group $new_group 253 done 254 fi 255 if [[ $flag == "everyone@" ]]; then 256 for new_owner in $g_usr "nobody"; do 257 new_group=$(get_user_group $new_owner) 258 259 log=$(logname $acl_target $o_usr $old_owner \ 260 $new_owner) 261 262 $log operate_node_owner $o_usr $node \ 263 $old_owner $new_owner 264 265 $log operate_node_group $o_usr $node \ 266 $old_group $new_group 267 done 268 fi 269} 270 271function test_chmod_basic_access 272{ 273 typeset user=$1 274 typeset node=${2%/} 275 typeset g_usr=$3 276 typeset o_usr=$4 277 typeset flag acl_t 278 279 for flag in $a_flag; do 280 for acl_t in $a_access; do 281 log_must su $user -c "chmod A+$flag:$acl_t $node" 282 283 tar cpf $TESTDIR/$ARCHIVEFILE basedir 284 285 check_chmod_results $user $node $flag $acl_t $g_usr \ 286 $o_usr 287 288 log_must su $user -c "chmod A0- $node" 289 done 290 done 291} 292 293function setup_test_files 294{ 295 typeset base_node=$1 296 typeset user=$2 297 typeset group=$3 298 299 rm -rf $base_node 300 301 log_must mkdir -p $base_node 302 log_must chown $user:$group $base_node 303 304 # Prepare all files/sub-dirs for testing. 305 log_must su $user -c "touch $file" 306 log_must su $user -c "chmod 444 $file" 307 log_must su $user -c "mkdir -p $dir" 308 log_must su $user -c "chmod 444 $dir" 309 log_must su $user -c "chmod 555 $base_node" 310} 311 312typeset ARCHIVEFILE=archive.tar 313typeset a_prop="on off" 314typeset a_access="write_owner:allow write_owner:deny" 315typeset a_flag="owner@ group@ everyone@" 316typeset basedir="$TESTDIR/basedir" 317typeset file="$basedir/file" 318typeset dir="$basedir/dir" 319typeset aclimplicit=$(zfs get -Ho value aclimplicit $TESTPOOL/$TESTFS) 320typeset val 321 322cd $TESTDIR 323 324for val in $a_prop; do 325 log_must zfs set aclimplicit=$val $TESTPOOL/$TESTFS 326 aclimplicit=$(zfs get -Ho value aclimplicit $TESTPOOL/$TESTFS) 327 if [[ $val == off ]]; then 328 # aclimplicit=off also needs aclmode=passthrough and 329 # aclinherit=passthrough 330 log_must zfs set aclmode=passthrough $TESTPOOL/$TESTFS 331 log_must zfs set aclinherit=passthrough $TESTPOOL/$TESTFS 332 fi 333 334 setup_test_files $basedir 'root' 'root' 335 test_chmod_basic_access 'root' $file $ZFS_ACL_ADMIN $ZFS_ACL_OTHER1 336 test_chmod_basic_access 'root' $dir $ZFS_ACL_ADMIN $ZFS_ACL_OTHER1 337 rm -rf $basedir 338 339 setup_test_files $basedir $ZFS_ACL_STAFF1 $ZFS_ACL_STAFF_GROUP 340 test_chmod_basic_access $ZFS_ACL_STAFF1 $file $ZFS_ACL_STAFF2 \ 341 $ZFS_ACL_OTHER1 342 test_chmod_basic_access $ZFS_ACL_STAFF1 $dir $ZFS_ACL_STAFF2 \ 343 $ZFS_ACL_OTHER1 344 rm -rf $basedir 345done 346 347# restore defaults, so next test is not affected. 348log_must zfs inherit aclmode $TESTPOOL/$TESTFS 349log_must zfs inherit aclinherit $TESTPOOL/$TESTFS 350log_must zfs inherit aclimplicit $TESTPOOL/$TESTFS 351 352log_pass "Verify that the chown/chgrp could take owner/group " \ 353 "while permission is granted." 354