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 } 436789Sahrens if (inherit) 437789Sahrens zp->z_phys->zp_flags |= ZFS_INHERIT_ACE; 438789Sahrens else 439789Sahrens zp->z_phys->zp_flags &= ~ZFS_INHERIT_ACE; 440789Sahrens 441789Sahrens zphys->zp_mode = zfs_mode_compute(zp, aclp); 442789Sahrens zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 443789Sahrens 444789Sahrens return (0); 445789Sahrens } 446789Sahrens 447789Sahrens /* 448789Sahrens * Create space for slots_needed ACEs to be append 449789Sahrens * to aclp. 450789Sahrens */ 451789Sahrens static void 452789Sahrens zfs_acl_append(zfs_acl_t *aclp, int slots_needed) 453789Sahrens { 454789Sahrens ace_t *newacep; 455789Sahrens ace_t *oldaclp; 456789Sahrens int slot_cnt; 457789Sahrens int slots_left = aclp->z_slots - aclp->z_acl_count; 458789Sahrens 459789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 460789Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 461789Sahrens if (slots_left < slots_needed || aclp->z_state != ACL_DATA_ALLOCED) { 462789Sahrens slot_cnt = aclp->z_slots + 1 + (slots_needed - slots_left); 463789Sahrens newacep = kmem_alloc(ZFS_ACL_SIZE(slot_cnt), KM_SLEEP); 464789Sahrens bcopy(aclp->z_acl, newacep, 465789Sahrens ZFS_ACL_SIZE(aclp->z_acl_count)); 466789Sahrens oldaclp = aclp->z_acl; 467789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 468789Sahrens kmem_free(oldaclp, ZFS_ACL_SIZE(aclp->z_slots)); 469789Sahrens aclp->z_acl = newacep; 470789Sahrens aclp->z_slots = slot_cnt; 471789Sahrens aclp->z_state = ACL_DATA_ALLOCED; 472789Sahrens } 473789Sahrens } 474789Sahrens 475789Sahrens /* 476789Sahrens * Remove "slot" ACE from aclp 477789Sahrens */ 478789Sahrens static void 479789Sahrens zfs_ace_remove(zfs_acl_t *aclp, int slot) 480789Sahrens { 481789Sahrens if (aclp->z_acl_count > 1) { 482789Sahrens (void) memmove(&aclp->z_acl[slot], 483789Sahrens &aclp->z_acl[slot +1], sizeof (ace_t) * 484789Sahrens (--aclp->z_acl_count - slot)); 485789Sahrens } else 486789Sahrens aclp->z_acl_count--; 487789Sahrens } 488789Sahrens 489789Sahrens /* 490789Sahrens * Update access mask for prepended ACE 491789Sahrens * 492789Sahrens * This applies the "groupmask" value for aclmode property. 493789Sahrens */ 494789Sahrens static void 495789Sahrens zfs_acl_prepend_fixup(ace_t *acep, ace_t *origacep, mode_t mode, uid_t owner) 496789Sahrens { 497789Sahrens 498789Sahrens int rmask, wmask, xmask; 499789Sahrens int user_ace; 500789Sahrens 501789Sahrens user_ace = (!(acep->a_flags & 502789Sahrens (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP))); 503789Sahrens 504789Sahrens if (user_ace && (acep->a_who == owner)) { 505789Sahrens rmask = S_IRUSR; 506789Sahrens wmask = S_IWUSR; 507789Sahrens xmask = S_IXUSR; 508789Sahrens } else { 509789Sahrens rmask = S_IRGRP; 510789Sahrens wmask = S_IWGRP; 511789Sahrens xmask = S_IXGRP; 512789Sahrens } 513789Sahrens 514789Sahrens if (origacep->a_access_mask & ACE_READ_DATA) { 515789Sahrens if (mode & rmask) 516789Sahrens acep->a_access_mask &= ~ACE_READ_DATA; 517789Sahrens else 518789Sahrens acep->a_access_mask |= ACE_READ_DATA; 519789Sahrens } 520789Sahrens 521789Sahrens if (origacep->a_access_mask & ACE_WRITE_DATA) { 522789Sahrens if (mode & wmask) 523789Sahrens acep->a_access_mask &= ~ACE_WRITE_DATA; 524789Sahrens else 525789Sahrens acep->a_access_mask |= ACE_WRITE_DATA; 526789Sahrens } 527789Sahrens 528789Sahrens if (origacep->a_access_mask & ACE_APPEND_DATA) { 529789Sahrens if (mode & wmask) 530789Sahrens acep->a_access_mask &= ~ACE_APPEND_DATA; 531789Sahrens else 532789Sahrens acep->a_access_mask |= ACE_APPEND_DATA; 533789Sahrens } 534789Sahrens 535789Sahrens if (origacep->a_access_mask & ACE_EXECUTE) { 536789Sahrens if (mode & xmask) 537789Sahrens acep->a_access_mask &= ~ACE_EXECUTE; 538789Sahrens else 539789Sahrens acep->a_access_mask |= ACE_EXECUTE; 540789Sahrens } 541789Sahrens } 542789Sahrens 543789Sahrens /* 544789Sahrens * Apply mode to canonical six ACEs. 545789Sahrens */ 546789Sahrens static void 547789Sahrens zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode) 548789Sahrens { 549789Sahrens int cnt; 550789Sahrens ace_t *acep; 551789Sahrens 552789Sahrens cnt = aclp->z_acl_count -1; 553789Sahrens acep = aclp->z_acl; 554789Sahrens 555789Sahrens /* 556789Sahrens * Fixup final ACEs to match the mode 557789Sahrens */ 558789Sahrens 559789Sahrens ASSERT(cnt >= 5); 560789Sahrens adjust_ace_pair(&acep[cnt - 1], mode); /* everyone@ */ 561789Sahrens adjust_ace_pair(&acep[cnt - 3], (mode & 0070) >> 3); /* group@ */ 562789Sahrens adjust_ace_pair(&acep[cnt - 5], (mode & 0700) >> 6); /* owner@ */ 563789Sahrens } 564789Sahrens 565789Sahrens 566789Sahrens static int 567789Sahrens zfs_acl_ace_match(ace_t *acep, int allow_deny, int type, int mask) 568789Sahrens { 569789Sahrens return (acep->a_access_mask == mask && acep->a_type == allow_deny && 570789Sahrens ((acep->a_flags & 0xf040) == type)); 571789Sahrens } 572789Sahrens 573789Sahrens /* 574789Sahrens * Can prepended ACE be reused? 575789Sahrens */ 576789Sahrens static int 577789Sahrens zfs_reuse_deny(ace_t *acep, int i) 578789Sahrens { 579789Sahrens int okay_masks; 580789Sahrens 581789Sahrens if (i < 1) 582789Sahrens return (B_FALSE); 583789Sahrens 584789Sahrens if (acep[i-1].a_type != DENY) 585789Sahrens return (B_FALSE); 586789Sahrens 587789Sahrens if (acep[i-1].a_flags != (acep[i].a_flags & ACE_IDENTIFIER_GROUP)) 588789Sahrens return (B_FALSE); 589789Sahrens 590789Sahrens okay_masks = (acep[i].a_access_mask & OKAY_MASK_BITS); 591789Sahrens 592789Sahrens if (acep[i-1].a_access_mask & ~okay_masks) 593789Sahrens return (B_FALSE); 594789Sahrens 595789Sahrens return (B_TRUE); 596789Sahrens } 597789Sahrens 598789Sahrens /* 599789Sahrens * Create space to prepend an ACE 600789Sahrens */ 601789Sahrens static void 602789Sahrens zfs_acl_prepend(zfs_acl_t *aclp, int i) 603789Sahrens { 604789Sahrens ace_t *oldaclp = NULL; 605789Sahrens ace_t *to, *from; 606789Sahrens int slots_left = aclp->z_slots - aclp->z_acl_count; 607789Sahrens int oldslots; 608789Sahrens int need_free = 0; 609789Sahrens 610789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 611789Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 612789Sahrens 613789Sahrens if (slots_left == 0 || aclp->z_state != ACL_DATA_ALLOCED) { 614789Sahrens 615789Sahrens to = kmem_alloc(ZFS_ACL_SIZE(aclp->z_acl_count + 616789Sahrens OGE_PAD), KM_SLEEP); 617789Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 618789Sahrens need_free++; 619789Sahrens from = aclp->z_acl; 620789Sahrens oldaclp = aclp->z_acl; 621789Sahrens (void) memmove(to, from, 622789Sahrens sizeof (ace_t) * aclp->z_acl_count); 623789Sahrens aclp->z_state = ACL_DATA_ALLOCED; 624789Sahrens } else { 625789Sahrens from = aclp->z_acl; 626789Sahrens to = aclp->z_acl; 627789Sahrens } 628789Sahrens 629789Sahrens 630789Sahrens (void) memmove(&to[i + 1], &from[i], 631789Sahrens sizeof (ace_t) * (aclp->z_acl_count - i)); 632789Sahrens 633789Sahrens if (oldaclp) { 634789Sahrens aclp->z_acl = to; 635789Sahrens oldslots = aclp->z_slots; 636789Sahrens aclp->z_slots = aclp->z_acl_count + OGE_PAD; 637789Sahrens if (need_free) 638789Sahrens kmem_free(oldaclp, ZFS_ACL_SIZE(oldslots)); 639789Sahrens } 640789Sahrens 641789Sahrens } 642789Sahrens 643789Sahrens /* 644789Sahrens * Prepend deny ACE 645789Sahrens */ 646789Sahrens static void 647789Sahrens zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, int i, 648789Sahrens mode_t mode) 649789Sahrens { 650789Sahrens ace_t *acep; 651789Sahrens 652789Sahrens zfs_acl_prepend(aclp, i); 653789Sahrens 654789Sahrens acep = aclp->z_acl; 655789Sahrens zfs_set_ace(&acep[i], 0, DENY, acep[i + 1].a_who, 656789Sahrens (acep[i + 1].a_flags & 0xf040)); 657789Sahrens zfs_acl_prepend_fixup(&acep[i], &acep[i+1], mode, zp->z_phys->zp_uid); 658789Sahrens aclp->z_acl_count++; 659789Sahrens } 660789Sahrens 661789Sahrens /* 662789Sahrens * Split an inherited ACE into inherit_only ACE 663789Sahrens * and original ACE with inheritance flags stripped off. 664789Sahrens */ 665789Sahrens static void 666789Sahrens zfs_acl_split_ace(zfs_acl_t *aclp, int i) 667789Sahrens { 668789Sahrens ace_t *acep = aclp->z_acl; 669789Sahrens 670789Sahrens zfs_acl_prepend(aclp, i); 671789Sahrens acep = aclp->z_acl; 672789Sahrens acep[i] = acep[i + 1]; 673789Sahrens acep[i].a_flags |= ACE_INHERIT_ONLY_ACE; 674789Sahrens acep[i + 1].a_flags &= ~ALL_INHERIT; 675789Sahrens aclp->z_acl_count++; 676789Sahrens } 677789Sahrens 678789Sahrens /* 679789Sahrens * Are ACES started at index i, the canonical six ACES? 680789Sahrens */ 681789Sahrens static int 682789Sahrens zfs_have_canonical_six(zfs_acl_t *aclp, int i) 683789Sahrens { 684789Sahrens ace_t *acep = aclp->z_acl; 685789Sahrens 686789Sahrens if ((zfs_acl_ace_match(&acep[i], 687789Sahrens DENY, ACE_OWNER, 0) && 688789Sahrens zfs_acl_ace_match(&acep[i + 1], ALLOW, ACE_OWNER, 689789Sahrens OWNER_ALLOW_MASK) && zfs_acl_ace_match(&acep[i + 2], 690789Sahrens DENY, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 3], 691789Sahrens ALLOW, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 4], 692789Sahrens DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) && 693789Sahrens zfs_acl_ace_match(&acep[i + 5], ALLOW, ACE_EVERYONE, 694789Sahrens EVERYONE_ALLOW_MASK))) { 695789Sahrens return (1); 696789Sahrens } else { 697789Sahrens return (0); 698789Sahrens } 699789Sahrens } 700789Sahrens 701789Sahrens /* 702789Sahrens * Apply step 1g, to group entries 703789Sahrens * 704789Sahrens * Need to deal with corner case where group may have 705789Sahrens * greater permissions than owner. If so then limit 706789Sahrens * group permissions, based on what extra permissions 707789Sahrens * group has. 708789Sahrens */ 709789Sahrens static void 710789Sahrens zfs_fixup_group_entries(ace_t *acep, mode_t mode) 711789Sahrens { 712789Sahrens mode_t extramode = (mode >> 3) & 07; 713789Sahrens mode_t ownermode = (mode >> 6); 714789Sahrens 715789Sahrens if (acep[0].a_flags & ACE_IDENTIFIER_GROUP) { 716789Sahrens 717789Sahrens extramode &= ~ownermode; 718789Sahrens 719789Sahrens if (extramode) { 720789Sahrens if (extramode & 04) { 721789Sahrens acep[0].a_access_mask &= ~ACE_READ_DATA; 722789Sahrens acep[1].a_access_mask &= ~ACE_READ_DATA; 723789Sahrens } 724789Sahrens if (extramode & 02) { 725789Sahrens acep[0].a_access_mask &= 726789Sahrens ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 727789Sahrens acep[1].a_access_mask &= 728789Sahrens ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 729789Sahrens } 730789Sahrens if (extramode & 01) { 731789Sahrens acep[0].a_access_mask &= ~ACE_EXECUTE; 732789Sahrens acep[1].a_access_mask &= ~ACE_EXECUTE; 733789Sahrens } 734789Sahrens } 735789Sahrens } 736789Sahrens } 737789Sahrens 738789Sahrens /* 739789Sahrens * Apply the chmod algorithm as described 740789Sahrens * in PSARC/2002/240 741789Sahrens */ 742789Sahrens static int 743789Sahrens zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp, 744789Sahrens dmu_tx_t *tx) 745789Sahrens { 746789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 747789Sahrens ace_t *acep; 748789Sahrens int i; 749789Sahrens int error; 750789Sahrens int entry_type; 751789Sahrens int reuse_deny; 752789Sahrens int need_canonical_six = 1; 753789Sahrens 754789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 755789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 756789Sahrens 757789Sahrens i = 0; 758789Sahrens while (i < aclp->z_acl_count) { 759789Sahrens acep = aclp->z_acl; 760789Sahrens entry_type = (acep[i].a_flags & 0xf040); 761789Sahrens 762789Sahrens if ((acep[i].a_type != ALLOW && acep[i].a_type != DENY) || 763789Sahrens (acep[i].a_flags & ACE_INHERIT_ONLY_ACE)) { 764789Sahrens i++; 765789Sahrens continue; 766789Sahrens } 767789Sahrens 768789Sahrens 769789Sahrens if (zfsvfs->z_acl_mode == DISCARD) { 770789Sahrens zfs_ace_remove(aclp, i); 771789Sahrens continue; 772789Sahrens } 773789Sahrens 774789Sahrens /* 775789Sahrens * Need to split ace into two? 776789Sahrens */ 777789Sahrens if ((acep[i].a_flags & (ACE_FILE_INHERIT_ACE| 778789Sahrens ACE_DIRECTORY_INHERIT_ACE)) && 779789Sahrens (!(acep[i].a_flags & ACE_INHERIT_ONLY_ACE))) { 780789Sahrens zfs_acl_split_ace(aclp, i); 781789Sahrens i++; 782789Sahrens continue; 783789Sahrens } 784789Sahrens 785789Sahrens if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 786789Sahrens (entry_type == OWNING_GROUP)) { 787789Sahrens acep[i].a_access_mask &= ~OGE_CLEAR; 788789Sahrens i++; 789789Sahrens continue; 790789Sahrens 791789Sahrens } else { 792789Sahrens if (acep[i].a_type == ALLOW) { 793789Sahrens 794789Sahrens /* 795789Sahrens * Check preceding ACE if any, to see 796789Sahrens * if we need to prepend a DENY ACE. 797789Sahrens * This is only applicable when the acl_mode 798789Sahrens * property == groupmask. 799789Sahrens */ 800789Sahrens if (zfsvfs->z_acl_mode == GROUPMASK) { 801789Sahrens 802789Sahrens reuse_deny = zfs_reuse_deny(acep, i); 803789Sahrens 804789Sahrens if (reuse_deny == B_FALSE) { 805789Sahrens zfs_acl_prepend_deny(zp, aclp, 806789Sahrens i, mode); 807789Sahrens i++; 808789Sahrens acep = aclp->z_acl; 809789Sahrens } else { 810789Sahrens zfs_acl_prepend_fixup( 811789Sahrens &acep[i - 1], 812789Sahrens &acep[i], mode, 813789Sahrens zp->z_phys->zp_uid); 814789Sahrens } 815789Sahrens zfs_fixup_group_entries(&acep[i - 1], 816789Sahrens mode); 817789Sahrens } 818789Sahrens } 819789Sahrens i++; 820789Sahrens } 821789Sahrens } 822789Sahrens 823789Sahrens /* 824789Sahrens * Check out last six aces, if we have six. 825789Sahrens */ 826789Sahrens 827789Sahrens if (aclp->z_acl_count >= 6) { 828789Sahrens i = aclp->z_acl_count - 6; 829789Sahrens 830789Sahrens if (zfs_have_canonical_six(aclp, i)) { 831789Sahrens need_canonical_six = 0; 832789Sahrens } 833789Sahrens } 834789Sahrens 835789Sahrens if (need_canonical_six) { 836789Sahrens 837789Sahrens zfs_acl_append(aclp, 6); 838789Sahrens i = aclp->z_acl_count; 839789Sahrens acep = aclp->z_acl; 840789Sahrens zfs_set_ace(&acep[i++], 0, DENY, -1, ACE_OWNER); 841789Sahrens zfs_set_ace(&acep[i++], OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER); 842789Sahrens zfs_set_ace(&acep[i++], 0, DENY, -1, OWNING_GROUP); 843789Sahrens zfs_set_ace(&acep[i++], 0, ALLOW, -1, OWNING_GROUP); 844789Sahrens zfs_set_ace(&acep[i++], EVERYONE_DENY_MASK, 845789Sahrens DENY, -1, ACE_EVERYONE); 846789Sahrens zfs_set_ace(&acep[i++], EVERYONE_ALLOW_MASK, 847789Sahrens ALLOW, -1, ACE_EVERYONE); 848789Sahrens aclp->z_acl_count += 6; 849789Sahrens } 850789Sahrens 851789Sahrens zfs_acl_fixup_canonical_six(aclp, mode); 852789Sahrens 853789Sahrens zp->z_phys->zp_mode = mode; 854789Sahrens error = zfs_aclset_common(zp, aclp, tx, NULL); 855789Sahrens return (error); 856789Sahrens } 857789Sahrens 858789Sahrens 859789Sahrens int 860789Sahrens zfs_acl_chmod_setattr(znode_t *zp, uint64_t mode, dmu_tx_t *tx) 861789Sahrens { 862789Sahrens zfs_acl_t *aclp; 863789Sahrens int error; 864789Sahrens 865789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 866789Sahrens mutex_enter(&zp->z_acl_lock); 867789Sahrens aclp = zfs_acl_node_read(zp); 868789Sahrens error = zfs_acl_chmod(zp, mode, aclp, tx); 869789Sahrens mutex_exit(&zp->z_acl_lock); 870789Sahrens zfs_acl_free(aclp); 871789Sahrens return (error); 872789Sahrens } 873789Sahrens 874789Sahrens /* 875789Sahrens * strip off write_owner and write_acl 876789Sahrens */ 877789Sahrens static void 878789Sahrens zfs_securemode_update(zfsvfs_t *zfsvfs, ace_t *acep) 879789Sahrens { 880789Sahrens if ((zfsvfs->z_acl_inherit == SECURE) && 881789Sahrens acep->a_type == ALLOW) 882789Sahrens acep->a_access_mask &= ~SECURE_NO_INHERIT; 883789Sahrens } 884789Sahrens 885789Sahrens /* 886789Sahrens * inherit inheritable ACEs from parent 887789Sahrens */ 888789Sahrens static zfs_acl_t * 889789Sahrens zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp) 890789Sahrens { 891789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 892789Sahrens ace_t *pacep; 893789Sahrens ace_t *acep; 894789Sahrens int ace_cnt = 0; 895789Sahrens int pace_cnt; 896789Sahrens int i, j; 897789Sahrens zfs_acl_t *aclp = NULL; 898789Sahrens 899789Sahrens i = j = 0; 900789Sahrens pace_cnt = paclp->z_acl_count; 901789Sahrens pacep = paclp->z_acl; 902789Sahrens if (zfsvfs->z_acl_inherit != DISCARD) { 903789Sahrens for (i = 0; i != pace_cnt; i++) { 904789Sahrens 905789Sahrens if (zfsvfs->z_acl_inherit == NOALLOW && 906789Sahrens pacep[i].a_type == ALLOW) 907789Sahrens continue; 908789Sahrens 909789Sahrens if (zfs_ace_can_use(zp, &pacep[i])) { 910789Sahrens ace_cnt++; 911789Sahrens if (!(pacep[i].a_flags & 912789Sahrens ACE_NO_PROPAGATE_INHERIT_ACE)) 913789Sahrens ace_cnt++; 914789Sahrens } 915789Sahrens } 916789Sahrens } 917789Sahrens 918789Sahrens aclp = zfs_acl_alloc(ace_cnt + OGE_PAD); 919789Sahrens if (ace_cnt && zfsvfs->z_acl_inherit != DISCARD) { 920789Sahrens acep = aclp->z_acl; 921789Sahrens pacep = paclp->z_acl; 922789Sahrens for (i = 0; i != pace_cnt; i++) { 923789Sahrens 924789Sahrens if (zfsvfs->z_acl_inherit == NOALLOW && 925789Sahrens pacep[i].a_type == ALLOW) 926789Sahrens continue; 927789Sahrens 928789Sahrens if (zfs_ace_can_use(zp, &pacep[i])) { 929789Sahrens /* 930789Sahrens * Now create entry for inherited ace 931789Sahrens */ 932789Sahrens acep[j] = pacep[i]; 933789Sahrens 934789Sahrens if (pacep[i].a_flags & 935789Sahrens ACE_NO_PROPAGATE_INHERIT_ACE) { 936789Sahrens acep[j].a_flags &= ~ALL_INHERIT; 937789Sahrens j++; 938789Sahrens continue; 939789Sahrens } 940789Sahrens 941789Sahrens if (pacep[i].a_type != ALLOW && 942789Sahrens pacep[i].a_type != DENY) { 943789Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 944789Sahrens j++; 945789Sahrens continue; 946789Sahrens } 947789Sahrens 948789Sahrens if (ZTOV(zp)->v_type != VDIR) { 949789Sahrens acep[j].a_flags &= ~ALL_INHERIT; 950789Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 951789Sahrens j++; 952789Sahrens continue; 953789Sahrens } 954789Sahrens 955789Sahrens ASSERT(ZTOV(zp)->v_type == VDIR); 956789Sahrens 957789Sahrens /* 958789Sahrens * If we are inheriting an ACE targeted for 959*865Smarks * only files, then make sure inherit_only 960*865Smarks * is on for future propagation. 961789Sahrens */ 962789Sahrens if ((acep[j].a_flags & (ACE_FILE_INHERIT_ACE | 963*865Smarks ACE_DIRECTORY_INHERIT_ACE)) == 964*865Smarks ACE_FILE_INHERIT_ACE) { 965*865Smarks acep[j].a_flags |= ACE_INHERIT_ONLY_ACE; 966*865Smarks } else { 967789Sahrens acep[j].a_flags &= 968789Sahrens ~ACE_INHERIT_ONLY_ACE; 969*865Smarks } 970789Sahrens 971789Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 972789Sahrens j++; 973789Sahrens } 974789Sahrens } 975789Sahrens } 976789Sahrens aclp->z_acl_count = j; 977789Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 978789Sahrens 979789Sahrens return (aclp); 980789Sahrens } 981789Sahrens 982789Sahrens /* 983789Sahrens * Create file system object initial permissions 984789Sahrens * including inheritable ACEs. 985789Sahrens */ 986789Sahrens void 987789Sahrens zfs_perm_init(znode_t *zp, znode_t *parent, int flag, 988789Sahrens vattr_t *vap, dmu_tx_t *tx, cred_t *cr) 989789Sahrens { 990789Sahrens uint64_t mode; 991789Sahrens uid_t uid; 992789Sahrens gid_t gid; 993789Sahrens int error; 994789Sahrens int pull_down; 995789Sahrens zfs_acl_t *aclp, *paclp; 996789Sahrens 997789Sahrens mode = MAKEIMODE(vap->va_type, vap->va_mode); 998789Sahrens 999789Sahrens /* 1000789Sahrens * Determine uid and gid. 1001789Sahrens */ 1002789Sahrens if ((flag & (IS_ROOT_NODE | IS_REPLAY)) || 1003789Sahrens ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 1004789Sahrens uid = vap->va_uid; 1005789Sahrens gid = vap->va_gid; 1006789Sahrens } else { 1007789Sahrens uid = crgetuid(cr); 1008789Sahrens if ((vap->va_mask & AT_GID) && 1009789Sahrens ((vap->va_gid == parent->z_phys->zp_gid) || 1010789Sahrens groupmember(vap->va_gid, cr) || 1011789Sahrens secpolicy_vnode_create_gid(cr))) 1012789Sahrens gid = vap->va_gid; 1013789Sahrens else 1014789Sahrens gid = (parent->z_phys->zp_mode & S_ISGID) ? 1015789Sahrens parent->z_phys->zp_gid : crgetgid(cr); 1016789Sahrens } 1017789Sahrens 1018789Sahrens /* 1019789Sahrens * If we're creating a directory, and the parent directory has the 1020789Sahrens * set-GID bit set, set in on the new directory. 1021789Sahrens * Otherwise, if the user is neither privileged nor a member of the 1022789Sahrens * file's new group, clear the file's set-GID bit. 1023789Sahrens */ 1024789Sahrens 1025789Sahrens if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) 1026789Sahrens mode |= S_ISGID; 1027789Sahrens else { 1028789Sahrens if ((mode & S_ISGID) && 1029789Sahrens secpolicy_vnode_setids_setgids(cr, gid) != 0) 1030789Sahrens mode &= ~S_ISGID; 1031789Sahrens } 1032789Sahrens 1033789Sahrens zp->z_phys->zp_uid = uid; 1034789Sahrens zp->z_phys->zp_gid = gid; 1035789Sahrens zp->z_phys->zp_mode = mode; 1036789Sahrens 1037789Sahrens mutex_enter(&parent->z_lock); 1038789Sahrens pull_down = (parent->z_phys->zp_flags & ZFS_INHERIT_ACE); 1039789Sahrens if (pull_down) { 1040789Sahrens mutex_enter(&parent->z_acl_lock); 1041789Sahrens paclp = zfs_acl_node_read(parent); 1042789Sahrens mutex_exit(&parent->z_acl_lock); 1043789Sahrens aclp = zfs_acl_inherit(zp, paclp); 1044789Sahrens zfs_acl_free(paclp); 1045789Sahrens } else { 1046789Sahrens aclp = zfs_acl_alloc(6); 1047789Sahrens } 1048789Sahrens mutex_exit(&parent->z_lock); 1049789Sahrens mutex_enter(&zp->z_lock); 1050789Sahrens mutex_enter(&zp->z_acl_lock); 1051789Sahrens error = zfs_acl_chmod(zp, mode, aclp, tx); 1052789Sahrens mutex_exit(&zp->z_lock); 1053789Sahrens mutex_exit(&zp->z_acl_lock); 1054789Sahrens ASSERT3U(error, ==, 0); 1055789Sahrens zfs_acl_free(aclp); 1056789Sahrens } 1057789Sahrens 1058789Sahrens /* 1059789Sahrens * Can use be used for inheritance 1060789Sahrens */ 1061789Sahrens static int 1062789Sahrens zfs_ace_can_use(znode_t *zp, ace_t *acep) 1063789Sahrens { 1064789Sahrens int vtype = ZTOV(zp)->v_type; 1065789Sahrens 1066789Sahrens int iflags = (acep->a_flags & 0xf); 1067789Sahrens 1068789Sahrens if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1069789Sahrens return (1); 1070789Sahrens 1071789Sahrens else if (iflags & ACE_FILE_INHERIT_ACE) 1072789Sahrens return (1); 1073789Sahrens 1074789Sahrens return (0); 1075789Sahrens } 1076789Sahrens 1077789Sahrens /* 1078789Sahrens * Retrieve a files ACL 1079789Sahrens */ 1080789Sahrens int 1081789Sahrens zfs_getacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr) 1082789Sahrens { 1083789Sahrens zfs_acl_t *aclp; 1084789Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1085789Sahrens int error; 1086789Sahrens 1087789Sahrens if (error = zfs_zaccess(zp, ACE_READ_ACL, cr)) { 1088789Sahrens /* 1089789Sahrens * If owner of file then allow reading of the 1090789Sahrens * ACL. 1091789Sahrens */ 1092789Sahrens if (crgetuid(cr) != zp->z_phys->zp_uid) 1093789Sahrens return (error); 1094789Sahrens } 1095789Sahrens 1096789Sahrens if (mask == 0) 1097789Sahrens return (ENOSYS); 1098789Sahrens 1099789Sahrens mutex_enter(&zp->z_acl_lock); 1100789Sahrens 1101789Sahrens aclp = zfs_acl_node_read(zp); 1102789Sahrens 1103789Sahrens if (mask & VSA_ACECNT) { 1104789Sahrens vsecp->vsa_aclcnt = aclp->z_acl_count; 1105789Sahrens } 1106789Sahrens 1107789Sahrens if (mask & VSA_ACE) { 1108789Sahrens vsecp->vsa_aclentp = kmem_alloc(aclp->z_acl_count * 1109789Sahrens sizeof (ace_t), KM_SLEEP); 1110789Sahrens bcopy(aclp->z_acl, vsecp->vsa_aclentp, 1111789Sahrens aclp->z_acl_count * sizeof (ace_t)); 1112789Sahrens } 1113789Sahrens 1114789Sahrens mutex_exit(&zp->z_acl_lock); 1115789Sahrens 1116789Sahrens zfs_acl_free(aclp); 1117789Sahrens 1118789Sahrens return (0); 1119789Sahrens } 1120789Sahrens 1121789Sahrens /* 1122789Sahrens * Set a files ACL 1123789Sahrens */ 1124789Sahrens int 1125789Sahrens zfs_setacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr) 1126789Sahrens { 1127789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1128789Sahrens zilog_t *zilog = zfsvfs->z_log; 1129789Sahrens ace_t *acep = vsecp->vsa_aclentp; 1130789Sahrens int aclcnt = vsecp->vsa_aclcnt; 1131789Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1132789Sahrens dmu_tx_t *tx; 1133789Sahrens int error; 1134789Sahrens int inherit; 1135789Sahrens zfs_acl_t *aclp; 1136789Sahrens uint64_t seq = 0; 1137789Sahrens 1138789Sahrens if (mask == 0) 1139789Sahrens return (EINVAL); 1140789Sahrens 1141789Sahrens if (!zfs_acl_valid(zp, acep, aclcnt, &inherit)) 1142789Sahrens return (EINVAL); 1143789Sahrens top: 1144789Sahrens error = zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr); 1145789Sahrens if (error == EACCES || error == ACCESS_UNDETERMINED) { 1146789Sahrens if ((error = secpolicy_vnode_setdac(cr, 1147789Sahrens zp->z_phys->zp_uid)) != 0) { 1148789Sahrens return (error); 1149789Sahrens } 1150789Sahrens } else if (error) { 1151789Sahrens return (error == EROFS ? error : EPERM); 1152789Sahrens } 1153789Sahrens 1154789Sahrens mutex_enter(&zp->z_lock); 1155789Sahrens mutex_enter(&zp->z_acl_lock); 1156789Sahrens 1157789Sahrens tx = dmu_tx_create(zfsvfs->z_os); 1158789Sahrens dmu_tx_hold_bonus(tx, zp->z_id); 1159789Sahrens 1160789Sahrens if (zp->z_phys->zp_acl.z_acl_extern_obj) { 1161789Sahrens dmu_tx_hold_write(tx, zp->z_phys->zp_acl.z_acl_extern_obj, 1162789Sahrens 0, ZFS_ACL_SIZE(aclcnt)); 1163789Sahrens } else if (aclcnt > ACE_SLOT_CNT) { 1164789Sahrens dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, ZFS_ACL_SIZE(aclcnt)); 1165789Sahrens } 1166789Sahrens 1167789Sahrens error = dmu_tx_assign(tx, zfsvfs->z_assign); 1168789Sahrens if (error) { 1169789Sahrens dmu_tx_abort(tx); 1170789Sahrens 1171789Sahrens mutex_exit(&zp->z_acl_lock); 1172789Sahrens mutex_exit(&zp->z_lock); 1173789Sahrens 1174789Sahrens if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1175789Sahrens txg_wait_open(dmu_objset_pool(zfsvfs->z_os), 0); 1176789Sahrens goto top; 1177789Sahrens } 1178789Sahrens return (error); 1179789Sahrens } 1180789Sahrens 1181789Sahrens aclp = zfs_acl_alloc(aclcnt); 1182789Sahrens bcopy(acep, aclp->z_acl, sizeof (ace_t) * aclcnt); 1183789Sahrens aclp->z_acl_count = aclcnt; 1184789Sahrens error = zfs_aclset_common(zp, aclp, tx, &inherit); 1185789Sahrens ASSERT(error == 0); 1186789Sahrens 1187789Sahrens zfs_acl_free(aclp); 1188789Sahrens seq = zfs_log_acl(zilog, tx, TX_ACL, zp, aclcnt, acep); 1189789Sahrens dmu_tx_commit(tx); 1190789Sahrens done: 1191789Sahrens mutex_exit(&zp->z_acl_lock); 1192789Sahrens mutex_exit(&zp->z_lock); 1193789Sahrens 1194789Sahrens zil_commit(zilog, seq, 0); 1195789Sahrens 1196789Sahrens return (error); 1197789Sahrens } 1198789Sahrens 1199789Sahrens static int 1200789Sahrens zfs_ace_access(ace_t *zacep, int mode_wanted, int *working_mode) 1201789Sahrens { 1202789Sahrens if ((*working_mode & mode_wanted) == mode_wanted) { 1203789Sahrens return (0); 1204789Sahrens } 1205789Sahrens 1206789Sahrens if (zacep->a_access_mask & mode_wanted) { 1207789Sahrens if (zacep->a_type == ALLOW) { 1208789Sahrens *working_mode |= (mode_wanted & zacep->a_access_mask); 1209789Sahrens if ((*working_mode & mode_wanted) == mode_wanted) 1210789Sahrens return (0); 1211789Sahrens } else if (zacep->a_type == DENY) { 1212789Sahrens return (EACCES); 1213789Sahrens } 1214789Sahrens } 1215789Sahrens 1216789Sahrens /* 1217789Sahrens * haven't been specifcally denied at this point 1218789Sahrens * so return UNDETERMINED. 1219789Sahrens */ 1220789Sahrens 1221789Sahrens return (ACCESS_UNDETERMINED); 1222789Sahrens } 1223789Sahrens 1224789Sahrens 1225789Sahrens static int 1226789Sahrens zfs_zaccess_common(znode_t *zp, int v4_mode, int *working_mode, cred_t *cr) 1227789Sahrens { 1228789Sahrens zfs_acl_t *aclp; 1229789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1230789Sahrens ace_t *zacep; 1231789Sahrens gid_t gid; 1232789Sahrens int mode_wanted = v4_mode; 1233789Sahrens int cnt; 1234789Sahrens int i; 1235789Sahrens int access_deny = ACCESS_UNDETERMINED; 1236789Sahrens uint_t entry_type; 1237789Sahrens uid_t uid = crgetuid(cr); 1238789Sahrens 1239789Sahrens *working_mode = 0; 1240789Sahrens 1241789Sahrens if (zfsvfs->z_assign >= TXG_INITIAL) /* ZIL replay */ 1242789Sahrens return (0); 1243789Sahrens 1244789Sahrens if ((v4_mode & WRITE_MASK) && 1245789Sahrens (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 1246789Sahrens (!IS_DEVVP(ZTOV(zp)))) { 1247789Sahrens return (EROFS); 1248789Sahrens } 1249789Sahrens 1250789Sahrens mutex_enter(&zp->z_acl_lock); 1251789Sahrens 1252789Sahrens aclp = zfs_acl_node_read(zp); 1253789Sahrens 1254789Sahrens zacep = aclp->z_acl; 1255789Sahrens cnt = aclp->z_acl_count; 1256789Sahrens 1257789Sahrens for (i = 0; i != cnt; i++) { 1258789Sahrens 1259789Sahrens if (zacep[i].a_flags & ACE_INHERIT_ONLY_ACE) 1260789Sahrens continue; 1261789Sahrens 1262789Sahrens entry_type = (zacep[i].a_flags & 0xf040); 1263789Sahrens switch (entry_type) { 1264789Sahrens case ACE_OWNER: 1265789Sahrens if (uid == zp->z_phys->zp_uid) { 1266789Sahrens access_deny = zfs_ace_access(&zacep[i], 1267789Sahrens mode_wanted, working_mode); 1268789Sahrens } 1269789Sahrens break; 1270789Sahrens case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 1271789Sahrens case ACE_IDENTIFIER_GROUP: 1272789Sahrens /* 1273789Sahrens * Owning group gid is in znode not ACL 1274789Sahrens */ 1275789Sahrens if (entry_type == (ACE_IDENTIFIER_GROUP | ACE_GROUP)) 1276789Sahrens gid = zp->z_phys->zp_gid; 1277789Sahrens else 1278789Sahrens gid = zacep[i].a_who; 1279789Sahrens 1280789Sahrens if (groupmember(gid, cr)) { 1281789Sahrens access_deny = zfs_ace_access(&zacep[i], 1282789Sahrens mode_wanted, working_mode); 1283789Sahrens } 1284789Sahrens break; 1285789Sahrens case ACE_EVERYONE: 1286789Sahrens access_deny = zfs_ace_access(&zacep[i], 1287789Sahrens mode_wanted, working_mode); 1288789Sahrens break; 1289789Sahrens 1290789Sahrens /* USER Entry */ 1291789Sahrens default: 1292789Sahrens if (entry_type == 0) { 1293789Sahrens if (uid == zacep[i].a_who) { 1294789Sahrens access_deny = zfs_ace_access(&zacep[i], 1295789Sahrens mode_wanted, working_mode); 1296789Sahrens } 1297789Sahrens break; 1298789Sahrens } 1299789Sahrens zfs_acl_free(aclp); 1300789Sahrens mutex_exit(&zp->z_acl_lock); 1301789Sahrens return (EIO); 1302789Sahrens } 1303789Sahrens 1304789Sahrens if (access_deny != ACCESS_UNDETERMINED) 1305789Sahrens break; 1306789Sahrens 1307789Sahrens } 1308789Sahrens 1309789Sahrens mutex_exit(&zp->z_acl_lock); 1310789Sahrens zfs_acl_free(aclp); 1311789Sahrens 1312789Sahrens return (access_deny); 1313789Sahrens } 1314789Sahrens 1315789Sahrens 1316789Sahrens /* 1317789Sahrens * Determine whether Access should be granted/denied, invoking least 1318789Sahrens * priv subsytem when a deny is determined. 1319789Sahrens */ 1320789Sahrens int 1321789Sahrens zfs_zaccess(znode_t *zp, int mode, cred_t *cr) 1322789Sahrens { 1323789Sahrens int working_mode = 0; 1324789Sahrens int error; 1325789Sahrens int is_attr; 1326789Sahrens znode_t *xzp; 1327789Sahrens znode_t *check_zp = zp; 1328789Sahrens 1329789Sahrens is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) && 1330789Sahrens (ZTOV(zp)->v_type == VDIR)); 1331789Sahrens 1332789Sahrens /* 1333789Sahrens * If attribute then validate against base file 1334789Sahrens */ 1335789Sahrens if (is_attr) { 1336789Sahrens if ((error = zfs_zget(zp->z_zfsvfs, 1337789Sahrens zp->z_phys->zp_parent, &xzp)) != 0) { 1338789Sahrens return (error); 1339789Sahrens } 1340789Sahrens check_zp = xzp; 1341789Sahrens /* 1342789Sahrens * fixup mode to map to xattr perms 1343789Sahrens */ 1344789Sahrens 1345789Sahrens if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 1346789Sahrens mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 1347789Sahrens mode |= ACE_WRITE_NAMED_ATTRS; 1348789Sahrens } 1349789Sahrens 1350789Sahrens if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 1351789Sahrens mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 1352789Sahrens mode |= ACE_READ_NAMED_ATTRS; 1353789Sahrens } 1354789Sahrens } 1355789Sahrens 1356789Sahrens error = zfs_zaccess_common(check_zp, mode, &working_mode, cr); 1357789Sahrens 1358789Sahrens if (error == EROFS) { 1359789Sahrens if (is_attr) 1360789Sahrens VN_RELE(ZTOV(xzp)); 1361789Sahrens return (error); 1362789Sahrens } 1363789Sahrens 1364789Sahrens if (error || (working_mode != mode)) { 1365789Sahrens error = secpolicy_vnode_access(cr, ZTOV(check_zp), 1366789Sahrens check_zp->z_phys->zp_uid, ~zfs_v4_to_unix(working_mode)); 1367789Sahrens } 1368789Sahrens 1369789Sahrens if (is_attr) 1370789Sahrens VN_RELE(ZTOV(xzp)); 1371789Sahrens 1372789Sahrens return (error); 1373789Sahrens } 1374789Sahrens 1375789Sahrens /* 1376789Sahrens * Special zaccess function to check for special nfsv4 perm. 1377789Sahrens * doesn't call secpolicy_vnode_access() for failure, since that 1378789Sahrens * would probably be the wrong policy function to call. 1379789Sahrens * instead its up to the caller to handle that situation. 1380789Sahrens */ 1381789Sahrens 1382789Sahrens int 1383789Sahrens zfs_zaccess_v4_perm(znode_t *zp, int mode, cred_t *cr) 1384789Sahrens { 1385789Sahrens int working_mode = 0; 1386789Sahrens return (zfs_zaccess_common(zp, mode, &working_mode, cr)); 1387789Sahrens } 1388789Sahrens 1389789Sahrens /* 1390789Sahrens * Translate tradition unix VREAD/VWRITE/VEXEC mode into 1391789Sahrens * native ACL format and call zfs_zaccess() 1392789Sahrens */ 1393789Sahrens int 1394789Sahrens zfs_zaccess_rwx(znode_t *zp, mode_t mode, cred_t *cr) 1395789Sahrens { 1396789Sahrens int v4_mode = zfs_unix_to_v4(mode >> 6); 1397789Sahrens 1398789Sahrens return (zfs_zaccess(zp, v4_mode, cr)); 1399789Sahrens } 1400789Sahrens 1401789Sahrens /* 1402789Sahrens * Determine whether Access should be granted/deny, without 1403789Sahrens * consulting least priv subsystem. 1404789Sahrens * 1405789Sahrens * 1406789Sahrens * The following chart is the recommended NFSv4 enforcement for 1407789Sahrens * ability to delete an object. 1408789Sahrens * 1409789Sahrens * ------------------------------------------------------- 1410789Sahrens * | Parent Dir | Target Object Permissions | 1411789Sahrens * | permissions | | 1412789Sahrens * ------------------------------------------------------- 1413789Sahrens * | | ACL Allows | ACL Denies| Delete | 1414789Sahrens * | | Delete | Delete | unspecified| 1415789Sahrens * ------------------------------------------------------- 1416789Sahrens * | ACL Allows | Permit | Permit | Permit | 1417789Sahrens * | DELETE_CHILD | | 1418789Sahrens * ------------------------------------------------------- 1419789Sahrens * | ACL Denies | Permit | Deny | Deny | 1420789Sahrens * | DELETE_CHILD | | | | 1421789Sahrens * ------------------------------------------------------- 1422789Sahrens * | ACL specifies | | | | 1423789Sahrens * | only allow | Permit | Permit | Permit | 1424789Sahrens * | write and | | | | 1425789Sahrens * | execute | | | | 1426789Sahrens * ------------------------------------------------------- 1427789Sahrens * | ACL denies | | | | 1428789Sahrens * | write and | Permit | Deny | Deny | 1429789Sahrens * | execute | | | | 1430789Sahrens * ------------------------------------------------------- 1431789Sahrens * ^ 1432789Sahrens * | 1433789Sahrens * No search privilege, can't even look up file? 1434789Sahrens * 1435789Sahrens */ 1436789Sahrens int 1437789Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) 1438789Sahrens { 1439789Sahrens int dzp_working_mode = 0; 1440789Sahrens int zp_working_mode = 0; 1441789Sahrens int dzp_error, zp_error; 1442789Sahrens 1443789Sahrens /* 1444789Sahrens * Arghh, this check is going to require a couple of questions 1445789Sahrens * to be asked. We want specific DELETE permissions to 1446789Sahrens * take precedence over WRITE/EXECUTE. We don't 1447789Sahrens * want an ACL such as this to mess us up. 1448789Sahrens * user:sloar:write_data:deny,user:sloar:delete:allow 1449789Sahrens * 1450789Sahrens * However, deny permissions may ultimately be overridden 1451789Sahrens * by secpolicy_vnode_access(). 1452789Sahrens */ 1453789Sahrens 1454789Sahrens dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 1455789Sahrens &dzp_working_mode, cr); 1456789Sahrens zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, cr); 1457789Sahrens 1458789Sahrens if (dzp_error == EROFS || zp_error == EROFS) 1459789Sahrens return (dzp_error); 1460789Sahrens 1461789Sahrens /* 1462789Sahrens * First handle the first row 1463789Sahrens */ 1464789Sahrens if (dzp_working_mode & ACE_DELETE_CHILD) 1465789Sahrens return (0); 1466789Sahrens 1467789Sahrens /* 1468789Sahrens * Second row 1469789Sahrens */ 1470789Sahrens 1471789Sahrens if (zp_working_mode & ACE_DELETE) 1472789Sahrens return (0); 1473789Sahrens 1474789Sahrens /* 1475789Sahrens * Third Row 1476789Sahrens */ 1477789Sahrens 1478789Sahrens dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE, 1479789Sahrens &dzp_working_mode, cr); 1480789Sahrens 1481789Sahrens if (dzp_error == EROFS) 1482789Sahrens return (dzp_error); 1483789Sahrens 1484789Sahrens if (dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) 1485789Sahrens return (0); 1486789Sahrens 1487789Sahrens /* 1488789Sahrens * Fourth Row 1489789Sahrens */ 1490789Sahrens 1491789Sahrens if (((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0) && 1492789Sahrens (zp_working_mode & ACE_DELETE)) 1493789Sahrens return (0); 1494789Sahrens 1495789Sahrens return (secpolicy_vnode_access(cr, ZTOV(zp), dzp->z_phys->zp_uid, 1496789Sahrens S_IWRITE|S_IEXEC)); 1497789Sahrens } 1498789Sahrens 1499789Sahrens int 1500789Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 1501789Sahrens znode_t *tzp, cred_t *cr) 1502789Sahrens { 1503789Sahrens int add_perm; 1504789Sahrens int error; 1505789Sahrens 1506789Sahrens add_perm = (ZTOV(szp)->v_type == VDIR) ? 1507789Sahrens ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 1508789Sahrens 1509789Sahrens /* 1510789Sahrens * Rename permissions are combination of delete permission + 1511789Sahrens * add file/subdir permission. 1512789Sahrens */ 1513789Sahrens 1514789Sahrens /* 1515789Sahrens * first make sure we do the delete portion. 1516789Sahrens * 1517789Sahrens * If that succeeds then check for add_file/add_subdir permissions 1518789Sahrens */ 1519789Sahrens 1520789Sahrens if (error = zfs_zaccess_delete(sdzp, szp, cr)) 1521789Sahrens return (error); 1522789Sahrens 1523789Sahrens /* 1524789Sahrens * If we have a tzp, see if we can delete it? 1525789Sahrens */ 1526789Sahrens if (tzp) { 1527789Sahrens if (error = zfs_zaccess_delete(tdzp, tzp, cr)) 1528789Sahrens return (error); 1529789Sahrens } 1530789Sahrens 1531789Sahrens /* 1532789Sahrens * Now check for add permissions 1533789Sahrens */ 1534789Sahrens if (error = zfs_zaccess(sdzp, add_perm, cr)) 1535789Sahrens return (error); 1536789Sahrens 1537789Sahrens error = zfs_sticky_remove_access(sdzp, szp, cr); 1538789Sahrens 1539789Sahrens return (error); 1540789Sahrens } 1541