1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5789Sahrens * Common Development and Distribution License, Version 1.0 only 6789Sahrens * (the "License"). You may not use this file except in compliance 7789Sahrens * with the License. 8789Sahrens * 9789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10789Sahrens * or http://www.opensolaris.org/os/licensing. 11789Sahrens * See the License for the specific language governing permissions 12789Sahrens * and limitations under the License. 13789Sahrens * 14789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19789Sahrens * 20789Sahrens * CDDL HEADER END 21789Sahrens */ 22789Sahrens /* 23789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 29789Sahrens #include <sys/types.h> 30789Sahrens #include <sys/param.h> 31789Sahrens #include <sys/time.h> 32789Sahrens #include <sys/systm.h> 33789Sahrens #include <sys/sysmacros.h> 34789Sahrens #include <sys/resource.h> 35789Sahrens #include <sys/vfs.h> 36789Sahrens #include <sys/vnode.h> 37789Sahrens #include <sys/file.h> 38789Sahrens #include <sys/stat.h> 39789Sahrens #include <sys/kmem.h> 40789Sahrens #include <sys/cmn_err.h> 41789Sahrens #include <sys/errno.h> 42789Sahrens #include <sys/unistd.h> 43789Sahrens #include <sys/fs/zfs.h> 44789Sahrens #include <sys/mode.h> 45789Sahrens #include <sys/policy.h> 46789Sahrens #include <sys/zfs_znode.h> 47789Sahrens #include <sys/zfs_acl.h> 48789Sahrens #include <sys/zfs_dir.h> 49789Sahrens #include <sys/zfs_vfsops.h> 50789Sahrens #include <sys/dmu.h> 51789Sahrens #include <sys/zap.h> 52789Sahrens #include <util/qsort.h> 53789Sahrens #include "fs/fs_subr.h" 54789Sahrens #include <acl/acl_common.h> 55789Sahrens 56789Sahrens #define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE 57789Sahrens #define DENY ACE_ACCESS_DENIED_ACE_TYPE 58789Sahrens 59789Sahrens #define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 60789Sahrens #define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 61789Sahrens ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 62789Sahrens #define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 63789Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 64789Sahrens #define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 65789Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 66789Sahrens #define WRITE_MASK (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS| \ 67789Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_ACL|ACE_WRITE_OWNER) 68789Sahrens 69789Sahrens #define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 70789Sahrens ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 71789Sahrens 72789Sahrens #define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 73789Sahrens ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 74789Sahrens 75789Sahrens #define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 76789Sahrens ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE) 77789Sahrens 78789Sahrens #define SECURE_NO_INHERIT (ACE_WRITE_ACL|ACE_WRITE_OWNER) 79789Sahrens 80789Sahrens #define OGE_PAD 6 /* traditional owner/group/everyone ACES */ 81789Sahrens 82789Sahrens static int zfs_ace_can_use(znode_t *zp, ace_t *); 83789Sahrens 84789Sahrens static zfs_acl_t * 85789Sahrens zfs_acl_alloc(int slots) 86789Sahrens { 87789Sahrens zfs_acl_t *aclp; 88789Sahrens 89789Sahrens aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 90789Sahrens if (slots != 0) { 91789Sahrens aclp->z_acl = kmem_alloc(ZFS_ACL_SIZE(slots), KM_SLEEP); 92789Sahrens aclp->z_acl_count = 0; 93789Sahrens aclp->z_state = ACL_DATA_ALLOCED; 94789Sahrens } else { 95789Sahrens aclp->z_state = 0; 96789Sahrens } 97789Sahrens aclp->z_slots = slots; 98789Sahrens return (aclp); 99789Sahrens } 100789Sahrens 101789Sahrens void 102789Sahrens zfs_acl_free(zfs_acl_t *aclp) 103789Sahrens { 104789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) { 105789Sahrens kmem_free(aclp->z_acl, ZFS_ACL_SIZE(aclp->z_slots)); 106789Sahrens } 107789Sahrens kmem_free(aclp, sizeof (zfs_acl_t)); 108789Sahrens } 109789Sahrens 110789Sahrens static uint32_t 111789Sahrens zfs_v4_to_unix(uint32_t access_mask) 112789Sahrens { 113789Sahrens uint32_t new_mask = 0; 114789Sahrens 115789Sahrens if (access_mask & (ACE_READ_DATA | ACE_LIST_DIRECTORY)) 116789Sahrens new_mask |= S_IROTH; 117789Sahrens if (access_mask & (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_ADD_FILE)) 118789Sahrens new_mask |= S_IWOTH; 119789Sahrens if (access_mask & (ACE_EXECUTE|ACE_READ_NAMED_ATTRS)) 120789Sahrens new_mask |= S_IXOTH; 121789Sahrens 122789Sahrens return (new_mask); 123789Sahrens } 124789Sahrens 125789Sahrens /* 126789Sahrens * Convert unix access mask to v4 access mask 127789Sahrens */ 128789Sahrens static uint32_t 129789Sahrens zfs_unix_to_v4(uint32_t access_mask) 130789Sahrens { 131789Sahrens uint32_t new_mask = 0; 132789Sahrens 133789Sahrens if (access_mask & 01) 134789Sahrens new_mask |= (ACE_EXECUTE); 135789Sahrens if (access_mask & 02) { 136789Sahrens new_mask |= (ACE_WRITE_DATA); 137789Sahrens } if (access_mask & 04) { 138789Sahrens new_mask |= ACE_READ_DATA; 139789Sahrens } 140789Sahrens return (new_mask); 141789Sahrens } 142789Sahrens 143789Sahrens static void 144789Sahrens zfs_set_ace(ace_t *zacep, uint32_t access_mask, int access_type, 145789Sahrens uid_t uid, int entry_type) 146789Sahrens { 147789Sahrens zacep->a_access_mask = access_mask; 148789Sahrens zacep->a_type = access_type; 149789Sahrens zacep->a_who = uid; 150789Sahrens zacep->a_flags = entry_type; 151789Sahrens } 152789Sahrens 153789Sahrens static uint64_t 154789Sahrens zfs_mode_compute(znode_t *zp, zfs_acl_t *aclp) 155789Sahrens { 156789Sahrens int i; 157789Sahrens int entry_type; 158789Sahrens mode_t mode = (zp->z_phys->zp_mode & 159789Sahrens (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 160789Sahrens mode_t seen = 0; 161789Sahrens ace_t *acep; 162789Sahrens 163789Sahrens for (i = 0, acep = aclp->z_acl; 164789Sahrens i != aclp->z_acl_count; i++, acep++) { 165789Sahrens entry_type = (acep->a_flags & 0xf040); 166789Sahrens if (entry_type == ACE_OWNER) { 167789Sahrens if ((acep->a_access_mask & ACE_READ_DATA) && 168789Sahrens (!(seen & S_IRUSR))) { 169789Sahrens seen |= S_IRUSR; 170789Sahrens if (acep->a_type == ALLOW) { 171789Sahrens mode |= S_IRUSR; 172789Sahrens } 173789Sahrens } 174789Sahrens if ((acep->a_access_mask & ACE_WRITE_DATA) && 175789Sahrens (!(seen & S_IWUSR))) { 176789Sahrens seen |= S_IWUSR; 177789Sahrens if (acep->a_type == ALLOW) { 178789Sahrens mode |= S_IWUSR; 179789Sahrens } 180789Sahrens } 181789Sahrens if ((acep->a_access_mask & ACE_EXECUTE) && 182789Sahrens (!(seen & S_IXUSR))) { 183789Sahrens seen |= S_IXUSR; 184789Sahrens if (acep->a_type == ALLOW) { 185789Sahrens mode |= S_IXUSR; 186789Sahrens } 187789Sahrens } 188789Sahrens } else if (entry_type == OWNING_GROUP) { 189789Sahrens if ((acep->a_access_mask & ACE_READ_DATA) && 190789Sahrens (!(seen & S_IRGRP))) { 191789Sahrens seen |= S_IRGRP; 192789Sahrens if (acep->a_type == ALLOW) { 193789Sahrens mode |= S_IRGRP; 194789Sahrens } 195789Sahrens } 196789Sahrens if ((acep->a_access_mask & ACE_WRITE_DATA) && 197789Sahrens (!(seen & S_IWGRP))) { 198789Sahrens seen |= S_IWGRP; 199789Sahrens if (acep->a_type == ALLOW) { 200789Sahrens mode |= S_IWGRP; 201789Sahrens } 202789Sahrens } 203789Sahrens if ((acep->a_access_mask & ACE_EXECUTE) && 204789Sahrens (!(seen & S_IXGRP))) { 205789Sahrens seen |= S_IXGRP; 206789Sahrens if (acep->a_type == ALLOW) { 207789Sahrens mode |= S_IXGRP; 208789Sahrens } 209789Sahrens } 210789Sahrens } else if (entry_type == ACE_EVERYONE) { 211789Sahrens if ((acep->a_access_mask & ACE_READ_DATA)) { 212789Sahrens if (!(seen & S_IRUSR)) { 213789Sahrens seen |= S_IRUSR; 214789Sahrens if (acep->a_type == ALLOW) { 215789Sahrens mode |= S_IRUSR; 216789Sahrens } 217789Sahrens } 218789Sahrens if (!(seen & S_IRGRP)) { 219789Sahrens seen |= S_IRGRP; 220789Sahrens if (acep->a_type == ALLOW) { 221789Sahrens mode |= S_IRGRP; 222789Sahrens } 223789Sahrens } 224789Sahrens if (!(seen & S_IROTH)) { 225789Sahrens seen |= S_IROTH; 226789Sahrens if (acep->a_type == ALLOW) { 227789Sahrens mode |= S_IROTH; 228789Sahrens } 229789Sahrens } 230789Sahrens } 231789Sahrens if ((acep->a_access_mask & ACE_WRITE_DATA)) { 232789Sahrens if (!(seen & S_IWUSR)) { 233789Sahrens seen |= S_IWUSR; 234789Sahrens if (acep->a_type == ALLOW) { 235789Sahrens mode |= S_IWUSR; 236789Sahrens } 237789Sahrens } 238789Sahrens if (!(seen & S_IWGRP)) { 239789Sahrens seen |= S_IWGRP; 240789Sahrens if (acep->a_type == ALLOW) { 241789Sahrens mode |= S_IWGRP; 242789Sahrens } 243789Sahrens } 244789Sahrens if (!(seen & S_IWOTH)) { 245789Sahrens seen |= S_IWOTH; 246789Sahrens if (acep->a_type == ALLOW) { 247789Sahrens mode |= S_IWOTH; 248789Sahrens } 249789Sahrens } 250789Sahrens } 251789Sahrens if ((acep->a_access_mask & ACE_EXECUTE)) { 252789Sahrens if (!(seen & S_IXUSR)) { 253789Sahrens seen |= S_IXUSR; 254789Sahrens if (acep->a_type == ALLOW) { 255789Sahrens mode |= S_IXUSR; 256789Sahrens } 257789Sahrens } 258789Sahrens if (!(seen & S_IXGRP)) { 259789Sahrens seen |= S_IXGRP; 260789Sahrens if (acep->a_type == ALLOW) { 261789Sahrens mode |= S_IXGRP; 262789Sahrens } 263789Sahrens } 264789Sahrens if (!(seen & S_IXOTH)) { 265789Sahrens seen |= S_IXOTH; 266789Sahrens if (acep->a_type == ALLOW) { 267789Sahrens mode |= S_IXOTH; 268789Sahrens } 269789Sahrens } 270789Sahrens } 271789Sahrens } 272789Sahrens } 273789Sahrens return (mode); 274789Sahrens } 275789Sahrens 276789Sahrens static zfs_acl_t * 277789Sahrens zfs_acl_node_read_internal(znode_t *zp) 278789Sahrens { 279789Sahrens zfs_acl_t *aclp; 280789Sahrens 281789Sahrens aclp = zfs_acl_alloc(0); 282789Sahrens aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count; 283789Sahrens aclp->z_acl = &zp->z_phys->zp_acl.z_ace_data[0]; 284789Sahrens 285789Sahrens return (aclp); 286789Sahrens } 287789Sahrens 288789Sahrens /* 289789Sahrens * Read an external acl object. 290789Sahrens */ 291789Sahrens zfs_acl_t * 292789Sahrens zfs_acl_node_read(znode_t *zp) 293789Sahrens { 294789Sahrens uint64_t extacl = zp->z_phys->zp_acl.z_acl_extern_obj; 295789Sahrens zfs_acl_t *aclp; 296789Sahrens 297789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 298789Sahrens 299789Sahrens if (zp->z_phys->zp_acl.z_acl_extern_obj == 0) 300789Sahrens return (zfs_acl_node_read_internal(zp)); 301789Sahrens 302789Sahrens aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_count); 303789Sahrens 304789Sahrens dmu_read(zp->z_zfsvfs->z_os, extacl, 0, 305789Sahrens ZFS_ACL_SIZE(zp->z_phys->zp_acl.z_acl_count), aclp->z_acl); 306789Sahrens 307789Sahrens aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count; 308789Sahrens 309789Sahrens return (aclp); 310789Sahrens } 311789Sahrens 312789Sahrens static boolean_t 313789Sahrens zfs_acl_valid(znode_t *zp, ace_t *uace, int aclcnt, int *inherit) 314789Sahrens { 315789Sahrens ace_t *acep; 316789Sahrens int i; 317789Sahrens 318789Sahrens *inherit = 0; 319789Sahrens 320789Sahrens if (aclcnt > MAX_ACL_ENTRIES || aclcnt <= 0) { 321789Sahrens return (B_FALSE); 322789Sahrens } 323789Sahrens 324789Sahrens for (i = 0, acep = uace; i != aclcnt; i++, acep++) { 325789Sahrens 326789Sahrens /* 327789Sahrens * first check type of entry 328789Sahrens */ 329789Sahrens 330789Sahrens switch (acep->a_flags & 0xf040) { 331789Sahrens case ACE_OWNER: 332789Sahrens acep->a_who = -1; 333789Sahrens break; 334789Sahrens case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 335789Sahrens case ACE_IDENTIFIER_GROUP: 336789Sahrens if (acep->a_flags & ACE_GROUP) { 337789Sahrens acep->a_who = -1; 338789Sahrens } 339789Sahrens break; 340789Sahrens case ACE_EVERYONE: 341789Sahrens acep->a_who = -1; 342789Sahrens break; 343789Sahrens } 344789Sahrens 345789Sahrens /* 346789Sahrens * next check inheritance level flags 347789Sahrens */ 348789Sahrens 349789Sahrens if (acep->a_type != ALLOW && acep->a_type != DENY) 350789Sahrens return (B_FALSE); 351789Sahrens 352789Sahrens /* 353789Sahrens * Only directories should have inheritance flags. 354789Sahrens */ 355789Sahrens if (ZTOV(zp)->v_type != VDIR && (acep->a_flags & 356789Sahrens (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE| 357789Sahrens ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE))) { 358789Sahrens return (B_FALSE); 359789Sahrens } 360789Sahrens 361789Sahrens if (acep->a_flags & 362789Sahrens (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)) 363789Sahrens *inherit = 1; 364789Sahrens 365789Sahrens if (acep->a_flags & 366789Sahrens (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 367789Sahrens if ((acep->a_flags & (ACE_FILE_INHERIT_ACE| 368789Sahrens ACE_DIRECTORY_INHERIT_ACE)) == 0) { 369789Sahrens return (B_FALSE); 370789Sahrens } 371789Sahrens } 372789Sahrens } 373789Sahrens 374789Sahrens return (B_TRUE); 375789Sahrens } 376789Sahrens /* 377789Sahrens * common code for setting acl's. 378789Sahrens * 379789Sahrens * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 380789Sahrens * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 381789Sahrens * already checked the acl and knows whether to inherit. 382789Sahrens */ 383789Sahrens int 384789Sahrens zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, dmu_tx_t *tx, int *ihp) 385789Sahrens { 386789Sahrens int inherit = 0; 387789Sahrens int error; 388789Sahrens znode_phys_t *zphys = zp->z_phys; 389789Sahrens zfs_znode_acl_t *zacl = &zphys->zp_acl; 390789Sahrens uint32_t acl_phys_size = ZFS_ACL_SIZE(aclp->z_acl_count); 391789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 392789Sahrens uint64_t aoid = zphys->zp_acl.z_acl_extern_obj; 393789Sahrens 394789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 395789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 396789Sahrens 397789Sahrens if (ihp) 398789Sahrens inherit = *ihp; /* already determined by caller */ 399789Sahrens else if (!zfs_acl_valid(zp, aclp->z_acl, 400789Sahrens aclp->z_acl_count, &inherit)) { 401789Sahrens return (EINVAL); 402789Sahrens } 403789Sahrens 404789Sahrens dmu_buf_will_dirty(zp->z_dbuf, tx); 405789Sahrens 406789Sahrens /* 407789Sahrens * Will ACL fit internally? 408789Sahrens */ 409789Sahrens if (aclp->z_acl_count > ACE_SLOT_CNT) { 410789Sahrens if (aoid == 0) { 411789Sahrens aoid = dmu_object_alloc(zfsvfs->z_os, 412789Sahrens DMU_OT_ACL, acl_phys_size, DMU_OT_NONE, 0, tx); 413789Sahrens } else { 414789Sahrens (void) dmu_object_set_blocksize(zfsvfs->z_os, aoid, 415789Sahrens acl_phys_size, 0, tx); 416789Sahrens } 417789Sahrens zphys->zp_acl.z_acl_extern_obj = aoid; 418789Sahrens zphys->zp_acl.z_acl_count = aclp->z_acl_count; 419789Sahrens dmu_write(zfsvfs->z_os, aoid, 0, 420789Sahrens acl_phys_size, aclp->z_acl, tx); 421789Sahrens } else { 422789Sahrens /* 423789Sahrens * Migrating back embedded? 424789Sahrens */ 425789Sahrens if (zphys->zp_acl.z_acl_extern_obj) { 426789Sahrens error = dmu_object_free(zfsvfs->z_os, 427789Sahrens zp->z_phys->zp_acl.z_acl_extern_obj, tx); 428789Sahrens if (error) 429789Sahrens return (error); 430789Sahrens zphys->zp_acl.z_acl_extern_obj = 0; 431789Sahrens } 432789Sahrens bcopy(aclp->z_acl, zacl->z_ace_data, 433789Sahrens aclp->z_acl_count * sizeof (ace_t)); 434789Sahrens zacl->z_acl_count = aclp->z_acl_count; 435789Sahrens } 436*905Smarks 437*905Smarks zp->z_phys->zp_flags &= ~(ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE); 438*905Smarks if (inherit) { 439789Sahrens zp->z_phys->zp_flags |= ZFS_INHERIT_ACE; 440*905Smarks } else if (ace_trivial(zacl->z_ace_data, zacl->z_acl_count) == 0) { 441*905Smarks zp->z_phys->zp_flags |= ZFS_ACL_TRIVIAL; 442*905Smarks } 443789Sahrens 444789Sahrens zphys->zp_mode = zfs_mode_compute(zp, aclp); 445789Sahrens zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 446789Sahrens 447789Sahrens return (0); 448789Sahrens } 449789Sahrens 450789Sahrens /* 451789Sahrens * Create space for slots_needed ACEs to be append 452789Sahrens * to aclp. 453789Sahrens */ 454789Sahrens static void 455789Sahrens zfs_acl_append(zfs_acl_t *aclp, int slots_needed) 456789Sahrens { 457789Sahrens ace_t *newacep; 458789Sahrens ace_t *oldaclp; 459789Sahrens int slot_cnt; 460789Sahrens int slots_left = aclp->z_slots - aclp->z_acl_count; 461789Sahrens 462789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 463789Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 464789Sahrens if (slots_left < slots_needed || aclp->z_state != ACL_DATA_ALLOCED) { 465789Sahrens slot_cnt = aclp->z_slots + 1 + (slots_needed - slots_left); 466789Sahrens newacep = kmem_alloc(ZFS_ACL_SIZE(slot_cnt), KM_SLEEP); 467789Sahrens bcopy(aclp->z_acl, newacep, 468789Sahrens ZFS_ACL_SIZE(aclp->z_acl_count)); 469789Sahrens oldaclp = aclp->z_acl; 470789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 471789Sahrens kmem_free(oldaclp, ZFS_ACL_SIZE(aclp->z_slots)); 472789Sahrens aclp->z_acl = newacep; 473789Sahrens aclp->z_slots = slot_cnt; 474789Sahrens aclp->z_state = ACL_DATA_ALLOCED; 475789Sahrens } 476789Sahrens } 477789Sahrens 478789Sahrens /* 479789Sahrens * Remove "slot" ACE from aclp 480789Sahrens */ 481789Sahrens static void 482789Sahrens zfs_ace_remove(zfs_acl_t *aclp, int slot) 483789Sahrens { 484789Sahrens if (aclp->z_acl_count > 1) { 485789Sahrens (void) memmove(&aclp->z_acl[slot], 486789Sahrens &aclp->z_acl[slot +1], sizeof (ace_t) * 487789Sahrens (--aclp->z_acl_count - slot)); 488789Sahrens } else 489789Sahrens aclp->z_acl_count--; 490789Sahrens } 491789Sahrens 492789Sahrens /* 493789Sahrens * Update access mask for prepended ACE 494789Sahrens * 495789Sahrens * This applies the "groupmask" value for aclmode property. 496789Sahrens */ 497789Sahrens static void 498789Sahrens zfs_acl_prepend_fixup(ace_t *acep, ace_t *origacep, mode_t mode, uid_t owner) 499789Sahrens { 500789Sahrens 501789Sahrens int rmask, wmask, xmask; 502789Sahrens int user_ace; 503789Sahrens 504789Sahrens user_ace = (!(acep->a_flags & 505789Sahrens (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP))); 506789Sahrens 507789Sahrens if (user_ace && (acep->a_who == owner)) { 508789Sahrens rmask = S_IRUSR; 509789Sahrens wmask = S_IWUSR; 510789Sahrens xmask = S_IXUSR; 511789Sahrens } else { 512789Sahrens rmask = S_IRGRP; 513789Sahrens wmask = S_IWGRP; 514789Sahrens xmask = S_IXGRP; 515789Sahrens } 516789Sahrens 517789Sahrens if (origacep->a_access_mask & ACE_READ_DATA) { 518789Sahrens if (mode & rmask) 519789Sahrens acep->a_access_mask &= ~ACE_READ_DATA; 520789Sahrens else 521789Sahrens acep->a_access_mask |= ACE_READ_DATA; 522789Sahrens } 523789Sahrens 524789Sahrens if (origacep->a_access_mask & ACE_WRITE_DATA) { 525789Sahrens if (mode & wmask) 526789Sahrens acep->a_access_mask &= ~ACE_WRITE_DATA; 527789Sahrens else 528789Sahrens acep->a_access_mask |= ACE_WRITE_DATA; 529789Sahrens } 530789Sahrens 531789Sahrens if (origacep->a_access_mask & ACE_APPEND_DATA) { 532789Sahrens if (mode & wmask) 533789Sahrens acep->a_access_mask &= ~ACE_APPEND_DATA; 534789Sahrens else 535789Sahrens acep->a_access_mask |= ACE_APPEND_DATA; 536789Sahrens } 537789Sahrens 538789Sahrens if (origacep->a_access_mask & ACE_EXECUTE) { 539789Sahrens if (mode & xmask) 540789Sahrens acep->a_access_mask &= ~ACE_EXECUTE; 541789Sahrens else 542789Sahrens acep->a_access_mask |= ACE_EXECUTE; 543789Sahrens } 544789Sahrens } 545789Sahrens 546789Sahrens /* 547789Sahrens * Apply mode to canonical six ACEs. 548789Sahrens */ 549789Sahrens static void 550789Sahrens zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode) 551789Sahrens { 552789Sahrens int cnt; 553789Sahrens ace_t *acep; 554789Sahrens 555789Sahrens cnt = aclp->z_acl_count -1; 556789Sahrens acep = aclp->z_acl; 557789Sahrens 558789Sahrens /* 559789Sahrens * Fixup final ACEs to match the mode 560789Sahrens */ 561789Sahrens 562789Sahrens ASSERT(cnt >= 5); 563789Sahrens adjust_ace_pair(&acep[cnt - 1], mode); /* everyone@ */ 564789Sahrens adjust_ace_pair(&acep[cnt - 3], (mode & 0070) >> 3); /* group@ */ 565789Sahrens adjust_ace_pair(&acep[cnt - 5], (mode & 0700) >> 6); /* owner@ */ 566789Sahrens } 567789Sahrens 568789Sahrens 569789Sahrens static int 570789Sahrens zfs_acl_ace_match(ace_t *acep, int allow_deny, int type, int mask) 571789Sahrens { 572789Sahrens return (acep->a_access_mask == mask && acep->a_type == allow_deny && 573789Sahrens ((acep->a_flags & 0xf040) == type)); 574789Sahrens } 575789Sahrens 576789Sahrens /* 577789Sahrens * Can prepended ACE be reused? 578789Sahrens */ 579789Sahrens static int 580789Sahrens zfs_reuse_deny(ace_t *acep, int i) 581789Sahrens { 582789Sahrens int okay_masks; 583789Sahrens 584789Sahrens if (i < 1) 585789Sahrens return (B_FALSE); 586789Sahrens 587789Sahrens if (acep[i-1].a_type != DENY) 588789Sahrens return (B_FALSE); 589789Sahrens 590789Sahrens if (acep[i-1].a_flags != (acep[i].a_flags & ACE_IDENTIFIER_GROUP)) 591789Sahrens return (B_FALSE); 592789Sahrens 593789Sahrens okay_masks = (acep[i].a_access_mask & OKAY_MASK_BITS); 594789Sahrens 595789Sahrens if (acep[i-1].a_access_mask & ~okay_masks) 596789Sahrens return (B_FALSE); 597789Sahrens 598789Sahrens return (B_TRUE); 599789Sahrens } 600789Sahrens 601789Sahrens /* 602789Sahrens * Create space to prepend an ACE 603789Sahrens */ 604789Sahrens static void 605789Sahrens zfs_acl_prepend(zfs_acl_t *aclp, int i) 606789Sahrens { 607789Sahrens ace_t *oldaclp = NULL; 608789Sahrens ace_t *to, *from; 609789Sahrens int slots_left = aclp->z_slots - aclp->z_acl_count; 610789Sahrens int oldslots; 611789Sahrens int need_free = 0; 612789Sahrens 613789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 614789Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 615789Sahrens 616789Sahrens if (slots_left == 0 || aclp->z_state != ACL_DATA_ALLOCED) { 617789Sahrens 618789Sahrens to = kmem_alloc(ZFS_ACL_SIZE(aclp->z_acl_count + 619789Sahrens OGE_PAD), KM_SLEEP); 620789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 621789Sahrens need_free++; 622789Sahrens from = aclp->z_acl; 623789Sahrens oldaclp = aclp->z_acl; 624789Sahrens (void) memmove(to, from, 625789Sahrens sizeof (ace_t) * aclp->z_acl_count); 626789Sahrens aclp->z_state = ACL_DATA_ALLOCED; 627789Sahrens } else { 628789Sahrens from = aclp->z_acl; 629789Sahrens to = aclp->z_acl; 630789Sahrens } 631789Sahrens 632789Sahrens 633789Sahrens (void) memmove(&to[i + 1], &from[i], 634789Sahrens sizeof (ace_t) * (aclp->z_acl_count - i)); 635789Sahrens 636789Sahrens if (oldaclp) { 637789Sahrens aclp->z_acl = to; 638789Sahrens oldslots = aclp->z_slots; 639789Sahrens aclp->z_slots = aclp->z_acl_count + OGE_PAD; 640789Sahrens if (need_free) 641789Sahrens kmem_free(oldaclp, ZFS_ACL_SIZE(oldslots)); 642789Sahrens } 643789Sahrens 644789Sahrens } 645789Sahrens 646789Sahrens /* 647789Sahrens * Prepend deny ACE 648789Sahrens */ 649789Sahrens static void 650789Sahrens zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, int i, 651789Sahrens mode_t mode) 652789Sahrens { 653789Sahrens ace_t *acep; 654789Sahrens 655789Sahrens zfs_acl_prepend(aclp, i); 656789Sahrens 657789Sahrens acep = aclp->z_acl; 658789Sahrens zfs_set_ace(&acep[i], 0, DENY, acep[i + 1].a_who, 659789Sahrens (acep[i + 1].a_flags & 0xf040)); 660789Sahrens zfs_acl_prepend_fixup(&acep[i], &acep[i+1], mode, zp->z_phys->zp_uid); 661789Sahrens aclp->z_acl_count++; 662789Sahrens } 663789Sahrens 664789Sahrens /* 665789Sahrens * Split an inherited ACE into inherit_only ACE 666789Sahrens * and original ACE with inheritance flags stripped off. 667789Sahrens */ 668789Sahrens static void 669789Sahrens zfs_acl_split_ace(zfs_acl_t *aclp, int i) 670789Sahrens { 671789Sahrens ace_t *acep = aclp->z_acl; 672789Sahrens 673789Sahrens zfs_acl_prepend(aclp, i); 674789Sahrens acep = aclp->z_acl; 675789Sahrens acep[i] = acep[i + 1]; 676789Sahrens acep[i].a_flags |= ACE_INHERIT_ONLY_ACE; 677789Sahrens acep[i + 1].a_flags &= ~ALL_INHERIT; 678789Sahrens aclp->z_acl_count++; 679789Sahrens } 680789Sahrens 681789Sahrens /* 682789Sahrens * Are ACES started at index i, the canonical six ACES? 683789Sahrens */ 684789Sahrens static int 685789Sahrens zfs_have_canonical_six(zfs_acl_t *aclp, int i) 686789Sahrens { 687789Sahrens ace_t *acep = aclp->z_acl; 688789Sahrens 689789Sahrens if ((zfs_acl_ace_match(&acep[i], 690789Sahrens DENY, ACE_OWNER, 0) && 691789Sahrens zfs_acl_ace_match(&acep[i + 1], ALLOW, ACE_OWNER, 692789Sahrens OWNER_ALLOW_MASK) && zfs_acl_ace_match(&acep[i + 2], 693789Sahrens DENY, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 3], 694789Sahrens ALLOW, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 4], 695789Sahrens DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) && 696789Sahrens zfs_acl_ace_match(&acep[i + 5], ALLOW, ACE_EVERYONE, 697789Sahrens EVERYONE_ALLOW_MASK))) { 698789Sahrens return (1); 699789Sahrens } else { 700789Sahrens return (0); 701789Sahrens } 702789Sahrens } 703789Sahrens 704789Sahrens /* 705789Sahrens * Apply step 1g, to group entries 706789Sahrens * 707789Sahrens * Need to deal with corner case where group may have 708789Sahrens * greater permissions than owner. If so then limit 709789Sahrens * group permissions, based on what extra permissions 710789Sahrens * group has. 711789Sahrens */ 712789Sahrens static void 713789Sahrens zfs_fixup_group_entries(ace_t *acep, mode_t mode) 714789Sahrens { 715789Sahrens mode_t extramode = (mode >> 3) & 07; 716789Sahrens mode_t ownermode = (mode >> 6); 717789Sahrens 718789Sahrens if (acep[0].a_flags & ACE_IDENTIFIER_GROUP) { 719789Sahrens 720789Sahrens extramode &= ~ownermode; 721789Sahrens 722789Sahrens if (extramode) { 723789Sahrens if (extramode & 04) { 724789Sahrens acep[0].a_access_mask &= ~ACE_READ_DATA; 725789Sahrens acep[1].a_access_mask &= ~ACE_READ_DATA; 726789Sahrens } 727789Sahrens if (extramode & 02) { 728789Sahrens acep[0].a_access_mask &= 729789Sahrens ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 730789Sahrens acep[1].a_access_mask &= 731789Sahrens ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 732789Sahrens } 733789Sahrens if (extramode & 01) { 734789Sahrens acep[0].a_access_mask &= ~ACE_EXECUTE; 735789Sahrens acep[1].a_access_mask &= ~ACE_EXECUTE; 736789Sahrens } 737789Sahrens } 738789Sahrens } 739789Sahrens } 740789Sahrens 741789Sahrens /* 742789Sahrens * Apply the chmod algorithm as described 743789Sahrens * in PSARC/2002/240 744789Sahrens */ 745789Sahrens static int 746789Sahrens zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp, 747789Sahrens dmu_tx_t *tx) 748789Sahrens { 749789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 750789Sahrens ace_t *acep; 751789Sahrens int i; 752789Sahrens int error; 753789Sahrens int entry_type; 754789Sahrens int reuse_deny; 755789Sahrens int need_canonical_six = 1; 756*905Smarks int inherit = 0; 757*905Smarks int iflags; 758789Sahrens 759789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 760789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 761789Sahrens 762789Sahrens i = 0; 763789Sahrens while (i < aclp->z_acl_count) { 764789Sahrens acep = aclp->z_acl; 765789Sahrens entry_type = (acep[i].a_flags & 0xf040); 766*905Smarks iflags = (acep[i].a_flags & ALL_INHERIT); 767789Sahrens 768789Sahrens if ((acep[i].a_type != ALLOW && acep[i].a_type != DENY) || 769*905Smarks (iflags & ACE_INHERIT_ONLY_ACE)) { 770789Sahrens i++; 771*905Smarks if (iflags) 772*905Smarks inherit = 1; 773789Sahrens continue; 774789Sahrens } 775789Sahrens 776789Sahrens 777789Sahrens if (zfsvfs->z_acl_mode == DISCARD) { 778789Sahrens zfs_ace_remove(aclp, i); 779789Sahrens continue; 780789Sahrens } 781789Sahrens 782789Sahrens /* 783789Sahrens * Need to split ace into two? 784789Sahrens */ 785*905Smarks if ((iflags & (ACE_FILE_INHERIT_ACE| 786789Sahrens ACE_DIRECTORY_INHERIT_ACE)) && 787*905Smarks (!(iflags & ACE_INHERIT_ONLY_ACE))) { 788789Sahrens zfs_acl_split_ace(aclp, i); 789789Sahrens i++; 790*905Smarks inherit = 1; 791789Sahrens continue; 792789Sahrens } 793789Sahrens 794789Sahrens if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 795789Sahrens (entry_type == OWNING_GROUP)) { 796789Sahrens acep[i].a_access_mask &= ~OGE_CLEAR; 797789Sahrens i++; 798789Sahrens continue; 799789Sahrens 800789Sahrens } else { 801789Sahrens if (acep[i].a_type == ALLOW) { 802789Sahrens 803789Sahrens /* 804789Sahrens * Check preceding ACE if any, to see 805789Sahrens * if we need to prepend a DENY ACE. 806789Sahrens * This is only applicable when the acl_mode 807789Sahrens * property == groupmask. 808789Sahrens */ 809789Sahrens if (zfsvfs->z_acl_mode == GROUPMASK) { 810789Sahrens 811789Sahrens reuse_deny = zfs_reuse_deny(acep, i); 812789Sahrens 813789Sahrens if (reuse_deny == B_FALSE) { 814789Sahrens zfs_acl_prepend_deny(zp, aclp, 815789Sahrens i, mode); 816789Sahrens i++; 817789Sahrens acep = aclp->z_acl; 818789Sahrens } else { 819789Sahrens zfs_acl_prepend_fixup( 820789Sahrens &acep[i - 1], 821789Sahrens &acep[i], mode, 822789Sahrens zp->z_phys->zp_uid); 823789Sahrens } 824789Sahrens zfs_fixup_group_entries(&acep[i - 1], 825789Sahrens mode); 826789Sahrens } 827789Sahrens } 828789Sahrens i++; 829789Sahrens } 830789Sahrens } 831789Sahrens 832789Sahrens /* 833789Sahrens * Check out last six aces, if we have six. 834789Sahrens */ 835789Sahrens 836789Sahrens if (aclp->z_acl_count >= 6) { 837789Sahrens i = aclp->z_acl_count - 6; 838789Sahrens 839789Sahrens if (zfs_have_canonical_six(aclp, i)) { 840789Sahrens need_canonical_six = 0; 841789Sahrens } 842789Sahrens } 843789Sahrens 844789Sahrens if (need_canonical_six) { 845789Sahrens 846789Sahrens zfs_acl_append(aclp, 6); 847789Sahrens i = aclp->z_acl_count; 848789Sahrens acep = aclp->z_acl; 849789Sahrens zfs_set_ace(&acep[i++], 0, DENY, -1, ACE_OWNER); 850789Sahrens zfs_set_ace(&acep[i++], OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER); 851789Sahrens zfs_set_ace(&acep[i++], 0, DENY, -1, OWNING_GROUP); 852789Sahrens zfs_set_ace(&acep[i++], 0, ALLOW, -1, OWNING_GROUP); 853789Sahrens zfs_set_ace(&acep[i++], EVERYONE_DENY_MASK, 854789Sahrens DENY, -1, ACE_EVERYONE); 855789Sahrens zfs_set_ace(&acep[i++], EVERYONE_ALLOW_MASK, 856789Sahrens ALLOW, -1, ACE_EVERYONE); 857789Sahrens aclp->z_acl_count += 6; 858789Sahrens } 859789Sahrens 860789Sahrens zfs_acl_fixup_canonical_six(aclp, mode); 861789Sahrens 862789Sahrens zp->z_phys->zp_mode = mode; 863*905Smarks error = zfs_aclset_common(zp, aclp, tx, &inherit); 864789Sahrens return (error); 865789Sahrens } 866789Sahrens 867789Sahrens 868789Sahrens int 869789Sahrens zfs_acl_chmod_setattr(znode_t *zp, uint64_t mode, dmu_tx_t *tx) 870789Sahrens { 871789Sahrens zfs_acl_t *aclp; 872789Sahrens int error; 873789Sahrens 874789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 875789Sahrens mutex_enter(&zp->z_acl_lock); 876789Sahrens aclp = zfs_acl_node_read(zp); 877789Sahrens error = zfs_acl_chmod(zp, mode, aclp, tx); 878789Sahrens mutex_exit(&zp->z_acl_lock); 879789Sahrens zfs_acl_free(aclp); 880789Sahrens return (error); 881789Sahrens } 882789Sahrens 883789Sahrens /* 884789Sahrens * strip off write_owner and write_acl 885789Sahrens */ 886789Sahrens static void 887789Sahrens zfs_securemode_update(zfsvfs_t *zfsvfs, ace_t *acep) 888789Sahrens { 889789Sahrens if ((zfsvfs->z_acl_inherit == SECURE) && 890789Sahrens acep->a_type == ALLOW) 891789Sahrens acep->a_access_mask &= ~SECURE_NO_INHERIT; 892789Sahrens } 893789Sahrens 894789Sahrens /* 895789Sahrens * inherit inheritable ACEs from parent 896789Sahrens */ 897789Sahrens static zfs_acl_t * 898789Sahrens zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp) 899789Sahrens { 900789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 901789Sahrens ace_t *pacep; 902789Sahrens ace_t *acep; 903789Sahrens int ace_cnt = 0; 904789Sahrens int pace_cnt; 905789Sahrens int i, j; 906789Sahrens zfs_acl_t *aclp = NULL; 907789Sahrens 908789Sahrens i = j = 0; 909789Sahrens pace_cnt = paclp->z_acl_count; 910789Sahrens pacep = paclp->z_acl; 911789Sahrens if (zfsvfs->z_acl_inherit != DISCARD) { 912789Sahrens for (i = 0; i != pace_cnt; i++) { 913789Sahrens 914789Sahrens if (zfsvfs->z_acl_inherit == NOALLOW && 915789Sahrens pacep[i].a_type == ALLOW) 916789Sahrens continue; 917789Sahrens 918789Sahrens if (zfs_ace_can_use(zp, &pacep[i])) { 919789Sahrens ace_cnt++; 920789Sahrens if (!(pacep[i].a_flags & 921789Sahrens ACE_NO_PROPAGATE_INHERIT_ACE)) 922789Sahrens ace_cnt++; 923789Sahrens } 924789Sahrens } 925789Sahrens } 926789Sahrens 927789Sahrens aclp = zfs_acl_alloc(ace_cnt + OGE_PAD); 928789Sahrens if (ace_cnt && zfsvfs->z_acl_inherit != DISCARD) { 929789Sahrens acep = aclp->z_acl; 930789Sahrens pacep = paclp->z_acl; 931789Sahrens for (i = 0; i != pace_cnt; i++) { 932789Sahrens 933789Sahrens if (zfsvfs->z_acl_inherit == NOALLOW && 934789Sahrens pacep[i].a_type == ALLOW) 935789Sahrens continue; 936789Sahrens 937789Sahrens if (zfs_ace_can_use(zp, &pacep[i])) { 938789Sahrens /* 939789Sahrens * Now create entry for inherited ace 940789Sahrens */ 941789Sahrens acep[j] = pacep[i]; 942789Sahrens 943789Sahrens if (pacep[i].a_flags & 944789Sahrens ACE_NO_PROPAGATE_INHERIT_ACE) { 945789Sahrens acep[j].a_flags &= ~ALL_INHERIT; 946789Sahrens j++; 947789Sahrens continue; 948789Sahrens } 949789Sahrens 950789Sahrens if (pacep[i].a_type != ALLOW && 951789Sahrens pacep[i].a_type != DENY) { 952789Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 953789Sahrens j++; 954789Sahrens continue; 955789Sahrens } 956789Sahrens 957789Sahrens if (ZTOV(zp)->v_type != VDIR) { 958789Sahrens acep[j].a_flags &= ~ALL_INHERIT; 959789Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 960789Sahrens j++; 961789Sahrens continue; 962789Sahrens } 963789Sahrens 964789Sahrens ASSERT(ZTOV(zp)->v_type == VDIR); 965789Sahrens 966789Sahrens /* 967789Sahrens * If we are inheriting an ACE targeted for 968865Smarks * only files, then make sure inherit_only 969865Smarks * is on for future propagation. 970789Sahrens */ 971789Sahrens if ((acep[j].a_flags & (ACE_FILE_INHERIT_ACE | 972865Smarks ACE_DIRECTORY_INHERIT_ACE)) == 973865Smarks ACE_FILE_INHERIT_ACE) { 974865Smarks acep[j].a_flags |= ACE_INHERIT_ONLY_ACE; 975865Smarks } else { 976789Sahrens acep[j].a_flags &= 977789Sahrens ~ACE_INHERIT_ONLY_ACE; 978865Smarks } 979789Sahrens 980789Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 981789Sahrens j++; 982789Sahrens } 983789Sahrens } 984789Sahrens } 985789Sahrens aclp->z_acl_count = j; 986789Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 987789Sahrens 988789Sahrens return (aclp); 989789Sahrens } 990789Sahrens 991789Sahrens /* 992789Sahrens * Create file system object initial permissions 993789Sahrens * including inheritable ACEs. 994789Sahrens */ 995789Sahrens void 996789Sahrens zfs_perm_init(znode_t *zp, znode_t *parent, int flag, 997789Sahrens vattr_t *vap, dmu_tx_t *tx, cred_t *cr) 998789Sahrens { 999789Sahrens uint64_t mode; 1000789Sahrens uid_t uid; 1001789Sahrens gid_t gid; 1002789Sahrens int error; 1003789Sahrens int pull_down; 1004789Sahrens zfs_acl_t *aclp, *paclp; 1005789Sahrens 1006789Sahrens mode = MAKEIMODE(vap->va_type, vap->va_mode); 1007789Sahrens 1008789Sahrens /* 1009789Sahrens * Determine uid and gid. 1010789Sahrens */ 1011789Sahrens if ((flag & (IS_ROOT_NODE | IS_REPLAY)) || 1012789Sahrens ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 1013789Sahrens uid = vap->va_uid; 1014789Sahrens gid = vap->va_gid; 1015789Sahrens } else { 1016789Sahrens uid = crgetuid(cr); 1017789Sahrens if ((vap->va_mask & AT_GID) && 1018789Sahrens ((vap->va_gid == parent->z_phys->zp_gid) || 1019789Sahrens groupmember(vap->va_gid, cr) || 1020789Sahrens secpolicy_vnode_create_gid(cr))) 1021789Sahrens gid = vap->va_gid; 1022789Sahrens else 1023789Sahrens gid = (parent->z_phys->zp_mode & S_ISGID) ? 1024789Sahrens parent->z_phys->zp_gid : crgetgid(cr); 1025789Sahrens } 1026789Sahrens 1027789Sahrens /* 1028789Sahrens * If we're creating a directory, and the parent directory has the 1029789Sahrens * set-GID bit set, set in on the new directory. 1030789Sahrens * Otherwise, if the user is neither privileged nor a member of the 1031789Sahrens * file's new group, clear the file's set-GID bit. 1032789Sahrens */ 1033789Sahrens 1034789Sahrens if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) 1035789Sahrens mode |= S_ISGID; 1036789Sahrens else { 1037789Sahrens if ((mode & S_ISGID) && 1038789Sahrens secpolicy_vnode_setids_setgids(cr, gid) != 0) 1039789Sahrens mode &= ~S_ISGID; 1040789Sahrens } 1041789Sahrens 1042789Sahrens zp->z_phys->zp_uid = uid; 1043789Sahrens zp->z_phys->zp_gid = gid; 1044789Sahrens zp->z_phys->zp_mode = mode; 1045789Sahrens 1046789Sahrens mutex_enter(&parent->z_lock); 1047789Sahrens pull_down = (parent->z_phys->zp_flags & ZFS_INHERIT_ACE); 1048789Sahrens if (pull_down) { 1049789Sahrens mutex_enter(&parent->z_acl_lock); 1050789Sahrens paclp = zfs_acl_node_read(parent); 1051789Sahrens mutex_exit(&parent->z_acl_lock); 1052789Sahrens aclp = zfs_acl_inherit(zp, paclp); 1053789Sahrens zfs_acl_free(paclp); 1054789Sahrens } else { 1055789Sahrens aclp = zfs_acl_alloc(6); 1056789Sahrens } 1057789Sahrens mutex_exit(&parent->z_lock); 1058789Sahrens mutex_enter(&zp->z_lock); 1059789Sahrens mutex_enter(&zp->z_acl_lock); 1060789Sahrens error = zfs_acl_chmod(zp, mode, aclp, tx); 1061789Sahrens mutex_exit(&zp->z_lock); 1062789Sahrens mutex_exit(&zp->z_acl_lock); 1063789Sahrens ASSERT3U(error, ==, 0); 1064789Sahrens zfs_acl_free(aclp); 1065789Sahrens } 1066789Sahrens 1067789Sahrens /* 1068789Sahrens * Can use be used for inheritance 1069789Sahrens */ 1070789Sahrens static int 1071789Sahrens zfs_ace_can_use(znode_t *zp, ace_t *acep) 1072789Sahrens { 1073789Sahrens int vtype = ZTOV(zp)->v_type; 1074789Sahrens 1075789Sahrens int iflags = (acep->a_flags & 0xf); 1076789Sahrens 1077789Sahrens if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1078789Sahrens return (1); 1079789Sahrens 1080789Sahrens else if (iflags & ACE_FILE_INHERIT_ACE) 1081789Sahrens return (1); 1082789Sahrens 1083789Sahrens return (0); 1084789Sahrens } 1085789Sahrens 1086789Sahrens /* 1087789Sahrens * Retrieve a files ACL 1088789Sahrens */ 1089789Sahrens int 1090789Sahrens zfs_getacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr) 1091789Sahrens { 1092789Sahrens zfs_acl_t *aclp; 1093789Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1094789Sahrens int error; 1095789Sahrens 1096789Sahrens if (error = zfs_zaccess(zp, ACE_READ_ACL, cr)) { 1097789Sahrens /* 1098789Sahrens * If owner of file then allow reading of the 1099789Sahrens * ACL. 1100789Sahrens */ 1101789Sahrens if (crgetuid(cr) != zp->z_phys->zp_uid) 1102789Sahrens return (error); 1103789Sahrens } 1104789Sahrens 1105789Sahrens if (mask == 0) 1106789Sahrens return (ENOSYS); 1107789Sahrens 1108789Sahrens mutex_enter(&zp->z_acl_lock); 1109789Sahrens 1110789Sahrens aclp = zfs_acl_node_read(zp); 1111789Sahrens 1112789Sahrens if (mask & VSA_ACECNT) { 1113789Sahrens vsecp->vsa_aclcnt = aclp->z_acl_count; 1114789Sahrens } 1115789Sahrens 1116789Sahrens if (mask & VSA_ACE) { 1117789Sahrens vsecp->vsa_aclentp = kmem_alloc(aclp->z_acl_count * 1118789Sahrens sizeof (ace_t), KM_SLEEP); 1119789Sahrens bcopy(aclp->z_acl, vsecp->vsa_aclentp, 1120789Sahrens aclp->z_acl_count * sizeof (ace_t)); 1121789Sahrens } 1122789Sahrens 1123789Sahrens mutex_exit(&zp->z_acl_lock); 1124789Sahrens 1125789Sahrens zfs_acl_free(aclp); 1126789Sahrens 1127789Sahrens return (0); 1128789Sahrens } 1129789Sahrens 1130789Sahrens /* 1131789Sahrens * Set a files ACL 1132789Sahrens */ 1133789Sahrens int 1134789Sahrens zfs_setacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr) 1135789Sahrens { 1136789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1137789Sahrens zilog_t *zilog = zfsvfs->z_log; 1138789Sahrens ace_t *acep = vsecp->vsa_aclentp; 1139789Sahrens int aclcnt = vsecp->vsa_aclcnt; 1140789Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1141789Sahrens dmu_tx_t *tx; 1142789Sahrens int error; 1143789Sahrens int inherit; 1144789Sahrens zfs_acl_t *aclp; 1145789Sahrens uint64_t seq = 0; 1146789Sahrens 1147789Sahrens if (mask == 0) 1148789Sahrens return (EINVAL); 1149789Sahrens 1150789Sahrens if (!zfs_acl_valid(zp, acep, aclcnt, &inherit)) 1151789Sahrens return (EINVAL); 1152789Sahrens top: 1153789Sahrens error = zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr); 1154789Sahrens if (error == EACCES || error == ACCESS_UNDETERMINED) { 1155789Sahrens if ((error = secpolicy_vnode_setdac(cr, 1156789Sahrens zp->z_phys->zp_uid)) != 0) { 1157789Sahrens return (error); 1158789Sahrens } 1159789Sahrens } else if (error) { 1160789Sahrens return (error == EROFS ? error : EPERM); 1161789Sahrens } 1162789Sahrens 1163789Sahrens mutex_enter(&zp->z_lock); 1164789Sahrens mutex_enter(&zp->z_acl_lock); 1165789Sahrens 1166789Sahrens tx = dmu_tx_create(zfsvfs->z_os); 1167789Sahrens dmu_tx_hold_bonus(tx, zp->z_id); 1168789Sahrens 1169789Sahrens if (zp->z_phys->zp_acl.z_acl_extern_obj) { 1170789Sahrens dmu_tx_hold_write(tx, zp->z_phys->zp_acl.z_acl_extern_obj, 1171789Sahrens 0, ZFS_ACL_SIZE(aclcnt)); 1172789Sahrens } else if (aclcnt > ACE_SLOT_CNT) { 1173789Sahrens dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, ZFS_ACL_SIZE(aclcnt)); 1174789Sahrens } 1175789Sahrens 1176789Sahrens error = dmu_tx_assign(tx, zfsvfs->z_assign); 1177789Sahrens if (error) { 1178789Sahrens dmu_tx_abort(tx); 1179789Sahrens 1180789Sahrens mutex_exit(&zp->z_acl_lock); 1181789Sahrens mutex_exit(&zp->z_lock); 1182789Sahrens 1183789Sahrens if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1184789Sahrens txg_wait_open(dmu_objset_pool(zfsvfs->z_os), 0); 1185789Sahrens goto top; 1186789Sahrens } 1187789Sahrens return (error); 1188789Sahrens } 1189789Sahrens 1190789Sahrens aclp = zfs_acl_alloc(aclcnt); 1191789Sahrens bcopy(acep, aclp->z_acl, sizeof (ace_t) * aclcnt); 1192789Sahrens aclp->z_acl_count = aclcnt; 1193789Sahrens error = zfs_aclset_common(zp, aclp, tx, &inherit); 1194789Sahrens ASSERT(error == 0); 1195789Sahrens 1196789Sahrens zfs_acl_free(aclp); 1197789Sahrens seq = zfs_log_acl(zilog, tx, TX_ACL, zp, aclcnt, acep); 1198789Sahrens dmu_tx_commit(tx); 1199789Sahrens done: 1200789Sahrens mutex_exit(&zp->z_acl_lock); 1201789Sahrens mutex_exit(&zp->z_lock); 1202789Sahrens 1203789Sahrens zil_commit(zilog, seq, 0); 1204789Sahrens 1205789Sahrens return (error); 1206789Sahrens } 1207789Sahrens 1208789Sahrens static int 1209789Sahrens zfs_ace_access(ace_t *zacep, int mode_wanted, int *working_mode) 1210789Sahrens { 1211789Sahrens if ((*working_mode & mode_wanted) == mode_wanted) { 1212789Sahrens return (0); 1213789Sahrens } 1214789Sahrens 1215789Sahrens if (zacep->a_access_mask & mode_wanted) { 1216789Sahrens if (zacep->a_type == ALLOW) { 1217789Sahrens *working_mode |= (mode_wanted & zacep->a_access_mask); 1218789Sahrens if ((*working_mode & mode_wanted) == mode_wanted) 1219789Sahrens return (0); 1220789Sahrens } else if (zacep->a_type == DENY) { 1221789Sahrens return (EACCES); 1222789Sahrens } 1223789Sahrens } 1224789Sahrens 1225789Sahrens /* 1226789Sahrens * haven't been specifcally denied at this point 1227789Sahrens * so return UNDETERMINED. 1228789Sahrens */ 1229789Sahrens 1230789Sahrens return (ACCESS_UNDETERMINED); 1231789Sahrens } 1232789Sahrens 1233789Sahrens 1234789Sahrens static int 1235789Sahrens zfs_zaccess_common(znode_t *zp, int v4_mode, int *working_mode, cred_t *cr) 1236789Sahrens { 1237789Sahrens zfs_acl_t *aclp; 1238789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1239789Sahrens ace_t *zacep; 1240789Sahrens gid_t gid; 1241789Sahrens int mode_wanted = v4_mode; 1242789Sahrens int cnt; 1243789Sahrens int i; 1244789Sahrens int access_deny = ACCESS_UNDETERMINED; 1245789Sahrens uint_t entry_type; 1246789Sahrens uid_t uid = crgetuid(cr); 1247789Sahrens 1248789Sahrens *working_mode = 0; 1249789Sahrens 1250789Sahrens if (zfsvfs->z_assign >= TXG_INITIAL) /* ZIL replay */ 1251789Sahrens return (0); 1252789Sahrens 1253789Sahrens if ((v4_mode & WRITE_MASK) && 1254789Sahrens (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 1255789Sahrens (!IS_DEVVP(ZTOV(zp)))) { 1256789Sahrens return (EROFS); 1257789Sahrens } 1258789Sahrens 1259789Sahrens mutex_enter(&zp->z_acl_lock); 1260789Sahrens 1261789Sahrens aclp = zfs_acl_node_read(zp); 1262789Sahrens 1263789Sahrens zacep = aclp->z_acl; 1264789Sahrens cnt = aclp->z_acl_count; 1265789Sahrens 1266789Sahrens for (i = 0; i != cnt; i++) { 1267789Sahrens 1268789Sahrens if (zacep[i].a_flags & ACE_INHERIT_ONLY_ACE) 1269789Sahrens continue; 1270789Sahrens 1271789Sahrens entry_type = (zacep[i].a_flags & 0xf040); 1272789Sahrens switch (entry_type) { 1273789Sahrens case ACE_OWNER: 1274789Sahrens if (uid == zp->z_phys->zp_uid) { 1275789Sahrens access_deny = zfs_ace_access(&zacep[i], 1276789Sahrens mode_wanted, working_mode); 1277789Sahrens } 1278789Sahrens break; 1279789Sahrens case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 1280789Sahrens case ACE_IDENTIFIER_GROUP: 1281789Sahrens /* 1282789Sahrens * Owning group gid is in znode not ACL 1283789Sahrens */ 1284789Sahrens if (entry_type == (ACE_IDENTIFIER_GROUP | ACE_GROUP)) 1285789Sahrens gid = zp->z_phys->zp_gid; 1286789Sahrens else 1287789Sahrens gid = zacep[i].a_who; 1288789Sahrens 1289789Sahrens if (groupmember(gid, cr)) { 1290789Sahrens access_deny = zfs_ace_access(&zacep[i], 1291789Sahrens mode_wanted, working_mode); 1292789Sahrens } 1293789Sahrens break; 1294789Sahrens case ACE_EVERYONE: 1295789Sahrens access_deny = zfs_ace_access(&zacep[i], 1296789Sahrens mode_wanted, working_mode); 1297789Sahrens break; 1298789Sahrens 1299789Sahrens /* USER Entry */ 1300789Sahrens default: 1301789Sahrens if (entry_type == 0) { 1302789Sahrens if (uid == zacep[i].a_who) { 1303789Sahrens access_deny = zfs_ace_access(&zacep[i], 1304789Sahrens mode_wanted, working_mode); 1305789Sahrens } 1306789Sahrens break; 1307789Sahrens } 1308789Sahrens zfs_acl_free(aclp); 1309789Sahrens mutex_exit(&zp->z_acl_lock); 1310789Sahrens return (EIO); 1311789Sahrens } 1312789Sahrens 1313789Sahrens if (access_deny != ACCESS_UNDETERMINED) 1314789Sahrens break; 1315789Sahrens 1316789Sahrens } 1317789Sahrens 1318789Sahrens mutex_exit(&zp->z_acl_lock); 1319789Sahrens zfs_acl_free(aclp); 1320789Sahrens 1321789Sahrens return (access_deny); 1322789Sahrens } 1323789Sahrens 1324789Sahrens 1325789Sahrens /* 1326789Sahrens * Determine whether Access should be granted/denied, invoking least 1327789Sahrens * priv subsytem when a deny is determined. 1328789Sahrens */ 1329789Sahrens int 1330789Sahrens zfs_zaccess(znode_t *zp, int mode, cred_t *cr) 1331789Sahrens { 1332789Sahrens int working_mode = 0; 1333789Sahrens int error; 1334789Sahrens int is_attr; 1335789Sahrens znode_t *xzp; 1336789Sahrens znode_t *check_zp = zp; 1337789Sahrens 1338789Sahrens is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) && 1339789Sahrens (ZTOV(zp)->v_type == VDIR)); 1340789Sahrens 1341789Sahrens /* 1342789Sahrens * If attribute then validate against base file 1343789Sahrens */ 1344789Sahrens if (is_attr) { 1345789Sahrens if ((error = zfs_zget(zp->z_zfsvfs, 1346789Sahrens zp->z_phys->zp_parent, &xzp)) != 0) { 1347789Sahrens return (error); 1348789Sahrens } 1349789Sahrens check_zp = xzp; 1350789Sahrens /* 1351789Sahrens * fixup mode to map to xattr perms 1352789Sahrens */ 1353789Sahrens 1354789Sahrens if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 1355789Sahrens mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 1356789Sahrens mode |= ACE_WRITE_NAMED_ATTRS; 1357789Sahrens } 1358789Sahrens 1359789Sahrens if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 1360789Sahrens mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 1361789Sahrens mode |= ACE_READ_NAMED_ATTRS; 1362789Sahrens } 1363789Sahrens } 1364789Sahrens 1365789Sahrens error = zfs_zaccess_common(check_zp, mode, &working_mode, cr); 1366789Sahrens 1367789Sahrens if (error == EROFS) { 1368789Sahrens if (is_attr) 1369789Sahrens VN_RELE(ZTOV(xzp)); 1370789Sahrens return (error); 1371789Sahrens } 1372789Sahrens 1373789Sahrens if (error || (working_mode != mode)) { 1374789Sahrens error = secpolicy_vnode_access(cr, ZTOV(check_zp), 1375789Sahrens check_zp->z_phys->zp_uid, ~zfs_v4_to_unix(working_mode)); 1376789Sahrens } 1377789Sahrens 1378789Sahrens if (is_attr) 1379789Sahrens VN_RELE(ZTOV(xzp)); 1380789Sahrens 1381789Sahrens return (error); 1382789Sahrens } 1383789Sahrens 1384789Sahrens /* 1385789Sahrens * Special zaccess function to check for special nfsv4 perm. 1386789Sahrens * doesn't call secpolicy_vnode_access() for failure, since that 1387789Sahrens * would probably be the wrong policy function to call. 1388789Sahrens * instead its up to the caller to handle that situation. 1389789Sahrens */ 1390789Sahrens 1391789Sahrens int 1392789Sahrens zfs_zaccess_v4_perm(znode_t *zp, int mode, cred_t *cr) 1393789Sahrens { 1394789Sahrens int working_mode = 0; 1395789Sahrens return (zfs_zaccess_common(zp, mode, &working_mode, cr)); 1396789Sahrens } 1397789Sahrens 1398789Sahrens /* 1399789Sahrens * Translate tradition unix VREAD/VWRITE/VEXEC mode into 1400789Sahrens * native ACL format and call zfs_zaccess() 1401789Sahrens */ 1402789Sahrens int 1403789Sahrens zfs_zaccess_rwx(znode_t *zp, mode_t mode, cred_t *cr) 1404789Sahrens { 1405789Sahrens int v4_mode = zfs_unix_to_v4(mode >> 6); 1406789Sahrens 1407789Sahrens return (zfs_zaccess(zp, v4_mode, cr)); 1408789Sahrens } 1409789Sahrens 1410789Sahrens /* 1411789Sahrens * Determine whether Access should be granted/deny, without 1412789Sahrens * consulting least priv subsystem. 1413789Sahrens * 1414789Sahrens * 1415789Sahrens * The following chart is the recommended NFSv4 enforcement for 1416789Sahrens * ability to delete an object. 1417789Sahrens * 1418789Sahrens * ------------------------------------------------------- 1419789Sahrens * | Parent Dir | Target Object Permissions | 1420789Sahrens * | permissions | | 1421789Sahrens * ------------------------------------------------------- 1422789Sahrens * | | ACL Allows | ACL Denies| Delete | 1423789Sahrens * | | Delete | Delete | unspecified| 1424789Sahrens * ------------------------------------------------------- 1425789Sahrens * | ACL Allows | Permit | Permit | Permit | 1426789Sahrens * | DELETE_CHILD | | 1427789Sahrens * ------------------------------------------------------- 1428789Sahrens * | ACL Denies | Permit | Deny | Deny | 1429789Sahrens * | DELETE_CHILD | | | | 1430789Sahrens * ------------------------------------------------------- 1431789Sahrens * | ACL specifies | | | | 1432789Sahrens * | only allow | Permit | Permit | Permit | 1433789Sahrens * | write and | | | | 1434789Sahrens * | execute | | | | 1435789Sahrens * ------------------------------------------------------- 1436789Sahrens * | ACL denies | | | | 1437789Sahrens * | write and | Permit | Deny | Deny | 1438789Sahrens * | execute | | | | 1439789Sahrens * ------------------------------------------------------- 1440789Sahrens * ^ 1441789Sahrens * | 1442789Sahrens * No search privilege, can't even look up file? 1443789Sahrens * 1444789Sahrens */ 1445789Sahrens int 1446789Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) 1447789Sahrens { 1448789Sahrens int dzp_working_mode = 0; 1449789Sahrens int zp_working_mode = 0; 1450789Sahrens int dzp_error, zp_error; 1451789Sahrens 1452789Sahrens /* 1453789Sahrens * Arghh, this check is going to require a couple of questions 1454789Sahrens * to be asked. We want specific DELETE permissions to 1455789Sahrens * take precedence over WRITE/EXECUTE. We don't 1456789Sahrens * want an ACL such as this to mess us up. 1457789Sahrens * user:sloar:write_data:deny,user:sloar:delete:allow 1458789Sahrens * 1459789Sahrens * However, deny permissions may ultimately be overridden 1460789Sahrens * by secpolicy_vnode_access(). 1461789Sahrens */ 1462789Sahrens 1463789Sahrens dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 1464789Sahrens &dzp_working_mode, cr); 1465789Sahrens zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, cr); 1466789Sahrens 1467789Sahrens if (dzp_error == EROFS || zp_error == EROFS) 1468789Sahrens return (dzp_error); 1469789Sahrens 1470789Sahrens /* 1471789Sahrens * First handle the first row 1472789Sahrens */ 1473789Sahrens if (dzp_working_mode & ACE_DELETE_CHILD) 1474789Sahrens return (0); 1475789Sahrens 1476789Sahrens /* 1477789Sahrens * Second row 1478789Sahrens */ 1479789Sahrens 1480789Sahrens if (zp_working_mode & ACE_DELETE) 1481789Sahrens return (0); 1482789Sahrens 1483789Sahrens /* 1484789Sahrens * Third Row 1485789Sahrens */ 1486789Sahrens 1487789Sahrens dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE, 1488789Sahrens &dzp_working_mode, cr); 1489789Sahrens 1490789Sahrens if (dzp_error == EROFS) 1491789Sahrens return (dzp_error); 1492789Sahrens 1493789Sahrens if (dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) 1494789Sahrens return (0); 1495789Sahrens 1496789Sahrens /* 1497789Sahrens * Fourth Row 1498789Sahrens */ 1499789Sahrens 1500789Sahrens if (((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0) && 1501789Sahrens (zp_working_mode & ACE_DELETE)) 1502789Sahrens return (0); 1503789Sahrens 1504789Sahrens return (secpolicy_vnode_access(cr, ZTOV(zp), dzp->z_phys->zp_uid, 1505789Sahrens S_IWRITE|S_IEXEC)); 1506789Sahrens } 1507789Sahrens 1508789Sahrens int 1509789Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 1510789Sahrens znode_t *tzp, cred_t *cr) 1511789Sahrens { 1512789Sahrens int add_perm; 1513789Sahrens int error; 1514789Sahrens 1515789Sahrens add_perm = (ZTOV(szp)->v_type == VDIR) ? 1516789Sahrens ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 1517789Sahrens 1518789Sahrens /* 1519789Sahrens * Rename permissions are combination of delete permission + 1520789Sahrens * add file/subdir permission. 1521789Sahrens */ 1522789Sahrens 1523789Sahrens /* 1524789Sahrens * first make sure we do the delete portion. 1525789Sahrens * 1526789Sahrens * If that succeeds then check for add_file/add_subdir permissions 1527789Sahrens */ 1528789Sahrens 1529789Sahrens if (error = zfs_zaccess_delete(sdzp, szp, cr)) 1530789Sahrens return (error); 1531789Sahrens 1532789Sahrens /* 1533789Sahrens * If we have a tzp, see if we can delete it? 1534789Sahrens */ 1535789Sahrens if (tzp) { 1536789Sahrens if (error = zfs_zaccess_delete(tdzp, tzp, cr)) 1537789Sahrens return (error); 1538789Sahrens } 1539789Sahrens 1540789Sahrens /* 1541789Sahrens * Now check for add permissions 1542789Sahrens */ 1543789Sahrens if (error = zfs_zaccess(sdzp, add_perm, cr)) 1544789Sahrens return (error); 1545789Sahrens 1546789Sahrens error = zfs_sticky_remove_access(sdzp, szp, cr); 1547789Sahrens 1548789Sahrens return (error); 1549789Sahrens } 1550