1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5*ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6*ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 2284c5a155Smarks * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/types.h> 29fa9e4066Sahrens #include <sys/param.h> 30fa9e4066Sahrens #include <sys/time.h> 31fa9e4066Sahrens #include <sys/systm.h> 32fa9e4066Sahrens #include <sys/sysmacros.h> 33fa9e4066Sahrens #include <sys/resource.h> 34fa9e4066Sahrens #include <sys/vfs.h> 35fa9e4066Sahrens #include <sys/vnode.h> 36fa9e4066Sahrens #include <sys/file.h> 37fa9e4066Sahrens #include <sys/stat.h> 38fa9e4066Sahrens #include <sys/kmem.h> 39fa9e4066Sahrens #include <sys/cmn_err.h> 40fa9e4066Sahrens #include <sys/errno.h> 41fa9e4066Sahrens #include <sys/unistd.h> 42fa9e4066Sahrens #include <sys/fs/zfs.h> 43fa9e4066Sahrens #include <sys/mode.h> 44fa9e4066Sahrens #include <sys/policy.h> 45fa9e4066Sahrens #include <sys/zfs_znode.h> 46fa9e4066Sahrens #include <sys/zfs_acl.h> 47fa9e4066Sahrens #include <sys/zfs_dir.h> 48fa9e4066Sahrens #include <sys/zfs_vfsops.h> 49fa9e4066Sahrens #include <sys/dmu.h> 50fa9e4066Sahrens #include <sys/zap.h> 51fa9e4066Sahrens #include <util/qsort.h> 52fa9e4066Sahrens #include "fs/fs_subr.h" 53fa9e4066Sahrens #include <acl/acl_common.h> 54fa9e4066Sahrens 55fa9e4066Sahrens #define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE 56fa9e4066Sahrens #define DENY ACE_ACCESS_DENIED_ACE_TYPE 57fa9e4066Sahrens 58fa9e4066Sahrens #define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 59fa9e4066Sahrens #define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 60fa9e4066Sahrens ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 61fa9e4066Sahrens #define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 62fa9e4066Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 63fa9e4066Sahrens #define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 64fa9e4066Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 65fa9e4066Sahrens #define WRITE_MASK (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS| \ 66fa9e4066Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_ACL|ACE_WRITE_OWNER) 67fa9e4066Sahrens 68fa9e4066Sahrens #define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 69fa9e4066Sahrens ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 70fa9e4066Sahrens 71fa9e4066Sahrens #define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 72fa9e4066Sahrens ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 73fa9e4066Sahrens 74fa9e4066Sahrens #define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 75fa9e4066Sahrens ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE) 76fa9e4066Sahrens 77fa9e4066Sahrens #define SECURE_NO_INHERIT (ACE_WRITE_ACL|ACE_WRITE_OWNER) 78fa9e4066Sahrens 79fa9e4066Sahrens #define OGE_PAD 6 /* traditional owner/group/everyone ACES */ 80fa9e4066Sahrens 81fa9e4066Sahrens static int zfs_ace_can_use(znode_t *zp, ace_t *); 82fa9e4066Sahrens 83fa9e4066Sahrens static zfs_acl_t * 84fa9e4066Sahrens zfs_acl_alloc(int slots) 85fa9e4066Sahrens { 86fa9e4066Sahrens zfs_acl_t *aclp; 87fa9e4066Sahrens 88fa9e4066Sahrens aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 89fa9e4066Sahrens if (slots != 0) { 90fa9e4066Sahrens aclp->z_acl = kmem_alloc(ZFS_ACL_SIZE(slots), KM_SLEEP); 91fa9e4066Sahrens aclp->z_acl_count = 0; 92fa9e4066Sahrens aclp->z_state = ACL_DATA_ALLOCED; 93fa9e4066Sahrens } else { 94fa9e4066Sahrens aclp->z_state = 0; 95fa9e4066Sahrens } 96fa9e4066Sahrens aclp->z_slots = slots; 97fa9e4066Sahrens return (aclp); 98fa9e4066Sahrens } 99fa9e4066Sahrens 100fa9e4066Sahrens void 101fa9e4066Sahrens zfs_acl_free(zfs_acl_t *aclp) 102fa9e4066Sahrens { 103fa9e4066Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) { 104fa9e4066Sahrens kmem_free(aclp->z_acl, ZFS_ACL_SIZE(aclp->z_slots)); 105fa9e4066Sahrens } 106fa9e4066Sahrens kmem_free(aclp, sizeof (zfs_acl_t)); 107fa9e4066Sahrens } 108fa9e4066Sahrens 109fa9e4066Sahrens static uint32_t 110fa9e4066Sahrens zfs_v4_to_unix(uint32_t access_mask) 111fa9e4066Sahrens { 112fa9e4066Sahrens uint32_t new_mask = 0; 113fa9e4066Sahrens 114fa9e4066Sahrens if (access_mask & (ACE_READ_DATA | ACE_LIST_DIRECTORY)) 115fa9e4066Sahrens new_mask |= S_IROTH; 116fa9e4066Sahrens if (access_mask & (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_ADD_FILE)) 117fa9e4066Sahrens new_mask |= S_IWOTH; 118fa9e4066Sahrens if (access_mask & (ACE_EXECUTE|ACE_READ_NAMED_ATTRS)) 119fa9e4066Sahrens new_mask |= S_IXOTH; 120fa9e4066Sahrens 121fa9e4066Sahrens return (new_mask); 122fa9e4066Sahrens } 123fa9e4066Sahrens 124fa9e4066Sahrens /* 125fa9e4066Sahrens * Convert unix access mask to v4 access mask 126fa9e4066Sahrens */ 127fa9e4066Sahrens static uint32_t 128fa9e4066Sahrens zfs_unix_to_v4(uint32_t access_mask) 129fa9e4066Sahrens { 130fa9e4066Sahrens uint32_t new_mask = 0; 131fa9e4066Sahrens 132fa9e4066Sahrens if (access_mask & 01) 133fa9e4066Sahrens new_mask |= (ACE_EXECUTE); 134fa9e4066Sahrens if (access_mask & 02) { 135fa9e4066Sahrens new_mask |= (ACE_WRITE_DATA); 136fa9e4066Sahrens } if (access_mask & 04) { 137fa9e4066Sahrens new_mask |= ACE_READ_DATA; 138fa9e4066Sahrens } 139fa9e4066Sahrens return (new_mask); 140fa9e4066Sahrens } 141fa9e4066Sahrens 142fa9e4066Sahrens static void 143fa9e4066Sahrens zfs_set_ace(ace_t *zacep, uint32_t access_mask, int access_type, 144fa9e4066Sahrens uid_t uid, int entry_type) 145fa9e4066Sahrens { 146fa9e4066Sahrens zacep->a_access_mask = access_mask; 147fa9e4066Sahrens zacep->a_type = access_type; 148fa9e4066Sahrens zacep->a_who = uid; 149fa9e4066Sahrens zacep->a_flags = entry_type; 150fa9e4066Sahrens } 151fa9e4066Sahrens 152fa9e4066Sahrens static uint64_t 153fa9e4066Sahrens zfs_mode_compute(znode_t *zp, zfs_acl_t *aclp) 154fa9e4066Sahrens { 155fa9e4066Sahrens int i; 156fa9e4066Sahrens int entry_type; 157fa9e4066Sahrens mode_t mode = (zp->z_phys->zp_mode & 158fa9e4066Sahrens (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 159fa9e4066Sahrens mode_t seen = 0; 160fa9e4066Sahrens ace_t *acep; 161fa9e4066Sahrens 162fa9e4066Sahrens for (i = 0, acep = aclp->z_acl; 163fa9e4066Sahrens i != aclp->z_acl_count; i++, acep++) { 164fa9e4066Sahrens entry_type = (acep->a_flags & 0xf040); 165fa9e4066Sahrens if (entry_type == ACE_OWNER) { 166fa9e4066Sahrens if ((acep->a_access_mask & ACE_READ_DATA) && 167fa9e4066Sahrens (!(seen & S_IRUSR))) { 168fa9e4066Sahrens seen |= S_IRUSR; 169fa9e4066Sahrens if (acep->a_type == ALLOW) { 170fa9e4066Sahrens mode |= S_IRUSR; 171fa9e4066Sahrens } 172fa9e4066Sahrens } 173fa9e4066Sahrens if ((acep->a_access_mask & ACE_WRITE_DATA) && 174fa9e4066Sahrens (!(seen & S_IWUSR))) { 175fa9e4066Sahrens seen |= S_IWUSR; 176fa9e4066Sahrens if (acep->a_type == ALLOW) { 177fa9e4066Sahrens mode |= S_IWUSR; 178fa9e4066Sahrens } 179fa9e4066Sahrens } 180fa9e4066Sahrens if ((acep->a_access_mask & ACE_EXECUTE) && 181fa9e4066Sahrens (!(seen & S_IXUSR))) { 182fa9e4066Sahrens seen |= S_IXUSR; 183fa9e4066Sahrens if (acep->a_type == ALLOW) { 184fa9e4066Sahrens mode |= S_IXUSR; 185fa9e4066Sahrens } 186fa9e4066Sahrens } 187fa9e4066Sahrens } else if (entry_type == OWNING_GROUP) { 188fa9e4066Sahrens if ((acep->a_access_mask & ACE_READ_DATA) && 189fa9e4066Sahrens (!(seen & S_IRGRP))) { 190fa9e4066Sahrens seen |= S_IRGRP; 191fa9e4066Sahrens if (acep->a_type == ALLOW) { 192fa9e4066Sahrens mode |= S_IRGRP; 193fa9e4066Sahrens } 194fa9e4066Sahrens } 195fa9e4066Sahrens if ((acep->a_access_mask & ACE_WRITE_DATA) && 196fa9e4066Sahrens (!(seen & S_IWGRP))) { 197fa9e4066Sahrens seen |= S_IWGRP; 198fa9e4066Sahrens if (acep->a_type == ALLOW) { 199fa9e4066Sahrens mode |= S_IWGRP; 200fa9e4066Sahrens } 201fa9e4066Sahrens } 202fa9e4066Sahrens if ((acep->a_access_mask & ACE_EXECUTE) && 203fa9e4066Sahrens (!(seen & S_IXGRP))) { 204fa9e4066Sahrens seen |= S_IXGRP; 205fa9e4066Sahrens if (acep->a_type == ALLOW) { 206fa9e4066Sahrens mode |= S_IXGRP; 207fa9e4066Sahrens } 208fa9e4066Sahrens } 209fa9e4066Sahrens } else if (entry_type == ACE_EVERYONE) { 210fa9e4066Sahrens if ((acep->a_access_mask & ACE_READ_DATA)) { 211fa9e4066Sahrens if (!(seen & S_IRUSR)) { 212fa9e4066Sahrens seen |= S_IRUSR; 213fa9e4066Sahrens if (acep->a_type == ALLOW) { 214fa9e4066Sahrens mode |= S_IRUSR; 215fa9e4066Sahrens } 216fa9e4066Sahrens } 217fa9e4066Sahrens if (!(seen & S_IRGRP)) { 218fa9e4066Sahrens seen |= S_IRGRP; 219fa9e4066Sahrens if (acep->a_type == ALLOW) { 220fa9e4066Sahrens mode |= S_IRGRP; 221fa9e4066Sahrens } 222fa9e4066Sahrens } 223fa9e4066Sahrens if (!(seen & S_IROTH)) { 224fa9e4066Sahrens seen |= S_IROTH; 225fa9e4066Sahrens if (acep->a_type == ALLOW) { 226fa9e4066Sahrens mode |= S_IROTH; 227fa9e4066Sahrens } 228fa9e4066Sahrens } 229fa9e4066Sahrens } 230fa9e4066Sahrens if ((acep->a_access_mask & ACE_WRITE_DATA)) { 231fa9e4066Sahrens if (!(seen & S_IWUSR)) { 232fa9e4066Sahrens seen |= S_IWUSR; 233fa9e4066Sahrens if (acep->a_type == ALLOW) { 234fa9e4066Sahrens mode |= S_IWUSR; 235fa9e4066Sahrens } 236fa9e4066Sahrens } 237fa9e4066Sahrens if (!(seen & S_IWGRP)) { 238fa9e4066Sahrens seen |= S_IWGRP; 239fa9e4066Sahrens if (acep->a_type == ALLOW) { 240fa9e4066Sahrens mode |= S_IWGRP; 241fa9e4066Sahrens } 242fa9e4066Sahrens } 243fa9e4066Sahrens if (!(seen & S_IWOTH)) { 244fa9e4066Sahrens seen |= S_IWOTH; 245fa9e4066Sahrens if (acep->a_type == ALLOW) { 246fa9e4066Sahrens mode |= S_IWOTH; 247fa9e4066Sahrens } 248fa9e4066Sahrens } 249fa9e4066Sahrens } 250fa9e4066Sahrens if ((acep->a_access_mask & ACE_EXECUTE)) { 251fa9e4066Sahrens if (!(seen & S_IXUSR)) { 252fa9e4066Sahrens seen |= S_IXUSR; 253fa9e4066Sahrens if (acep->a_type == ALLOW) { 254fa9e4066Sahrens mode |= S_IXUSR; 255fa9e4066Sahrens } 256fa9e4066Sahrens } 257fa9e4066Sahrens if (!(seen & S_IXGRP)) { 258fa9e4066Sahrens seen |= S_IXGRP; 259fa9e4066Sahrens if (acep->a_type == ALLOW) { 260fa9e4066Sahrens mode |= S_IXGRP; 261fa9e4066Sahrens } 262fa9e4066Sahrens } 263fa9e4066Sahrens if (!(seen & S_IXOTH)) { 264fa9e4066Sahrens seen |= S_IXOTH; 265fa9e4066Sahrens if (acep->a_type == ALLOW) { 266fa9e4066Sahrens mode |= S_IXOTH; 267fa9e4066Sahrens } 268fa9e4066Sahrens } 269fa9e4066Sahrens } 270fa9e4066Sahrens } 271fa9e4066Sahrens } 272fa9e4066Sahrens return (mode); 273fa9e4066Sahrens } 274fa9e4066Sahrens 275fa9e4066Sahrens static zfs_acl_t * 276fa9e4066Sahrens zfs_acl_node_read_internal(znode_t *zp) 277fa9e4066Sahrens { 278fa9e4066Sahrens zfs_acl_t *aclp; 279fa9e4066Sahrens 280fa9e4066Sahrens aclp = zfs_acl_alloc(0); 281fa9e4066Sahrens aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count; 282fa9e4066Sahrens aclp->z_acl = &zp->z_phys->zp_acl.z_ace_data[0]; 283fa9e4066Sahrens 284fa9e4066Sahrens return (aclp); 285fa9e4066Sahrens } 286fa9e4066Sahrens 287fa9e4066Sahrens /* 288fa9e4066Sahrens * Read an external acl object. 289fa9e4066Sahrens */ 290*ea8dc4b6Seschrock static int 291*ea8dc4b6Seschrock zfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp) 292fa9e4066Sahrens { 293fa9e4066Sahrens uint64_t extacl = zp->z_phys->zp_acl.z_acl_extern_obj; 294fa9e4066Sahrens zfs_acl_t *aclp; 295*ea8dc4b6Seschrock int error; 296fa9e4066Sahrens 297fa9e4066Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 298fa9e4066Sahrens 299*ea8dc4b6Seschrock if (zp->z_phys->zp_acl.z_acl_extern_obj == 0) { 300*ea8dc4b6Seschrock *aclpp = zfs_acl_node_read_internal(zp); 301*ea8dc4b6Seschrock return (0); 302*ea8dc4b6Seschrock } 303fa9e4066Sahrens 304fa9e4066Sahrens aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_count); 305fa9e4066Sahrens 306*ea8dc4b6Seschrock error = dmu_read(zp->z_zfsvfs->z_os, extacl, 0, 307fa9e4066Sahrens ZFS_ACL_SIZE(zp->z_phys->zp_acl.z_acl_count), aclp->z_acl); 308*ea8dc4b6Seschrock if (error != 0) { 309*ea8dc4b6Seschrock zfs_acl_free(aclp); 310*ea8dc4b6Seschrock return (error); 311*ea8dc4b6Seschrock } 312fa9e4066Sahrens 313fa9e4066Sahrens aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count; 314fa9e4066Sahrens 315*ea8dc4b6Seschrock *aclpp = aclp; 316*ea8dc4b6Seschrock return (0); 317fa9e4066Sahrens } 318fa9e4066Sahrens 319fa9e4066Sahrens static boolean_t 320fa9e4066Sahrens zfs_acl_valid(znode_t *zp, ace_t *uace, int aclcnt, int *inherit) 321fa9e4066Sahrens { 322fa9e4066Sahrens ace_t *acep; 323fa9e4066Sahrens int i; 324fa9e4066Sahrens 325fa9e4066Sahrens *inherit = 0; 326fa9e4066Sahrens 327fa9e4066Sahrens if (aclcnt > MAX_ACL_ENTRIES || aclcnt <= 0) { 328fa9e4066Sahrens return (B_FALSE); 329fa9e4066Sahrens } 330fa9e4066Sahrens 331fa9e4066Sahrens for (i = 0, acep = uace; i != aclcnt; i++, acep++) { 332fa9e4066Sahrens 333fa9e4066Sahrens /* 334fa9e4066Sahrens * first check type of entry 335fa9e4066Sahrens */ 336fa9e4066Sahrens 337fa9e4066Sahrens switch (acep->a_flags & 0xf040) { 338fa9e4066Sahrens case ACE_OWNER: 339fa9e4066Sahrens acep->a_who = -1; 340fa9e4066Sahrens break; 341fa9e4066Sahrens case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 342fa9e4066Sahrens case ACE_IDENTIFIER_GROUP: 343fa9e4066Sahrens if (acep->a_flags & ACE_GROUP) { 344fa9e4066Sahrens acep->a_who = -1; 345fa9e4066Sahrens } 346fa9e4066Sahrens break; 347fa9e4066Sahrens case ACE_EVERYONE: 348fa9e4066Sahrens acep->a_who = -1; 349fa9e4066Sahrens break; 350fa9e4066Sahrens } 351fa9e4066Sahrens 352fa9e4066Sahrens /* 353fa9e4066Sahrens * next check inheritance level flags 354fa9e4066Sahrens */ 355fa9e4066Sahrens 356fa9e4066Sahrens if (acep->a_type != ALLOW && acep->a_type != DENY) 357fa9e4066Sahrens return (B_FALSE); 358fa9e4066Sahrens 359fa9e4066Sahrens /* 360fa9e4066Sahrens * Only directories should have inheritance flags. 361fa9e4066Sahrens */ 362fa9e4066Sahrens if (ZTOV(zp)->v_type != VDIR && (acep->a_flags & 363fa9e4066Sahrens (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE| 364fa9e4066Sahrens ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE))) { 365fa9e4066Sahrens return (B_FALSE); 366fa9e4066Sahrens } 367fa9e4066Sahrens 368fa9e4066Sahrens if (acep->a_flags & 369fa9e4066Sahrens (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)) 370fa9e4066Sahrens *inherit = 1; 371fa9e4066Sahrens 372fa9e4066Sahrens if (acep->a_flags & 373fa9e4066Sahrens (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 374fa9e4066Sahrens if ((acep->a_flags & (ACE_FILE_INHERIT_ACE| 375fa9e4066Sahrens ACE_DIRECTORY_INHERIT_ACE)) == 0) { 376fa9e4066Sahrens return (B_FALSE); 377fa9e4066Sahrens } 378fa9e4066Sahrens } 379fa9e4066Sahrens } 380fa9e4066Sahrens 381fa9e4066Sahrens return (B_TRUE); 382fa9e4066Sahrens } 383fa9e4066Sahrens /* 384fa9e4066Sahrens * common code for setting acl's. 385fa9e4066Sahrens * 386fa9e4066Sahrens * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 387fa9e4066Sahrens * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 388fa9e4066Sahrens * already checked the acl and knows whether to inherit. 389fa9e4066Sahrens */ 390fa9e4066Sahrens int 391fa9e4066Sahrens zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, dmu_tx_t *tx, int *ihp) 392fa9e4066Sahrens { 393fa9e4066Sahrens int inherit = 0; 394fa9e4066Sahrens int error; 395fa9e4066Sahrens znode_phys_t *zphys = zp->z_phys; 396fa9e4066Sahrens zfs_znode_acl_t *zacl = &zphys->zp_acl; 397fa9e4066Sahrens uint32_t acl_phys_size = ZFS_ACL_SIZE(aclp->z_acl_count); 398fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 399fa9e4066Sahrens uint64_t aoid = zphys->zp_acl.z_acl_extern_obj; 400fa9e4066Sahrens 401fa9e4066Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 402fa9e4066Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 403fa9e4066Sahrens 404fa9e4066Sahrens if (ihp) 405fa9e4066Sahrens inherit = *ihp; /* already determined by caller */ 406fa9e4066Sahrens else if (!zfs_acl_valid(zp, aclp->z_acl, 407fa9e4066Sahrens aclp->z_acl_count, &inherit)) { 408fa9e4066Sahrens return (EINVAL); 409fa9e4066Sahrens } 410fa9e4066Sahrens 411fa9e4066Sahrens dmu_buf_will_dirty(zp->z_dbuf, tx); 412fa9e4066Sahrens 413fa9e4066Sahrens /* 414fa9e4066Sahrens * Will ACL fit internally? 415fa9e4066Sahrens */ 416fa9e4066Sahrens if (aclp->z_acl_count > ACE_SLOT_CNT) { 417fa9e4066Sahrens if (aoid == 0) { 418fa9e4066Sahrens aoid = dmu_object_alloc(zfsvfs->z_os, 419fa9e4066Sahrens DMU_OT_ACL, acl_phys_size, DMU_OT_NONE, 0, tx); 420fa9e4066Sahrens } else { 421fa9e4066Sahrens (void) dmu_object_set_blocksize(zfsvfs->z_os, aoid, 422fa9e4066Sahrens acl_phys_size, 0, tx); 423fa9e4066Sahrens } 424fa9e4066Sahrens zphys->zp_acl.z_acl_extern_obj = aoid; 425fa9e4066Sahrens zphys->zp_acl.z_acl_count = aclp->z_acl_count; 426fa9e4066Sahrens dmu_write(zfsvfs->z_os, aoid, 0, 427fa9e4066Sahrens acl_phys_size, aclp->z_acl, tx); 428fa9e4066Sahrens } else { 429fa9e4066Sahrens /* 430fa9e4066Sahrens * Migrating back embedded? 431fa9e4066Sahrens */ 432fa9e4066Sahrens if (zphys->zp_acl.z_acl_extern_obj) { 433fa9e4066Sahrens error = dmu_object_free(zfsvfs->z_os, 434fa9e4066Sahrens zp->z_phys->zp_acl.z_acl_extern_obj, tx); 435fa9e4066Sahrens if (error) 436fa9e4066Sahrens return (error); 437fa9e4066Sahrens zphys->zp_acl.z_acl_extern_obj = 0; 438fa9e4066Sahrens } 439fa9e4066Sahrens bcopy(aclp->z_acl, zacl->z_ace_data, 440fa9e4066Sahrens aclp->z_acl_count * sizeof (ace_t)); 441fa9e4066Sahrens zacl->z_acl_count = aclp->z_acl_count; 442fa9e4066Sahrens } 443de122929Smarks 444de122929Smarks zp->z_phys->zp_flags &= ~(ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE); 445de122929Smarks if (inherit) { 446fa9e4066Sahrens zp->z_phys->zp_flags |= ZFS_INHERIT_ACE; 447de122929Smarks } else if (ace_trivial(zacl->z_ace_data, zacl->z_acl_count) == 0) { 448de122929Smarks zp->z_phys->zp_flags |= ZFS_ACL_TRIVIAL; 449de122929Smarks } 450fa9e4066Sahrens 451fa9e4066Sahrens zphys->zp_mode = zfs_mode_compute(zp, aclp); 452fa9e4066Sahrens zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 453fa9e4066Sahrens 454fa9e4066Sahrens return (0); 455fa9e4066Sahrens } 456fa9e4066Sahrens 457fa9e4066Sahrens /* 458fa9e4066Sahrens * Create space for slots_needed ACEs to be append 459fa9e4066Sahrens * to aclp. 460fa9e4066Sahrens */ 461fa9e4066Sahrens static void 462fa9e4066Sahrens zfs_acl_append(zfs_acl_t *aclp, int slots_needed) 463fa9e4066Sahrens { 464fa9e4066Sahrens ace_t *newacep; 465fa9e4066Sahrens ace_t *oldaclp; 466fa9e4066Sahrens int slot_cnt; 467fa9e4066Sahrens int slots_left = aclp->z_slots - aclp->z_acl_count; 468fa9e4066Sahrens 469fa9e4066Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 470fa9e4066Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 471fa9e4066Sahrens if (slots_left < slots_needed || aclp->z_state != ACL_DATA_ALLOCED) { 472fa9e4066Sahrens slot_cnt = aclp->z_slots + 1 + (slots_needed - slots_left); 473fa9e4066Sahrens newacep = kmem_alloc(ZFS_ACL_SIZE(slot_cnt), KM_SLEEP); 474fa9e4066Sahrens bcopy(aclp->z_acl, newacep, 475fa9e4066Sahrens ZFS_ACL_SIZE(aclp->z_acl_count)); 476fa9e4066Sahrens oldaclp = aclp->z_acl; 477fa9e4066Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 478fa9e4066Sahrens kmem_free(oldaclp, ZFS_ACL_SIZE(aclp->z_slots)); 479fa9e4066Sahrens aclp->z_acl = newacep; 480fa9e4066Sahrens aclp->z_slots = slot_cnt; 481fa9e4066Sahrens aclp->z_state = ACL_DATA_ALLOCED; 482fa9e4066Sahrens } 483fa9e4066Sahrens } 484fa9e4066Sahrens 485fa9e4066Sahrens /* 486fa9e4066Sahrens * Remove "slot" ACE from aclp 487fa9e4066Sahrens */ 488fa9e4066Sahrens static void 489fa9e4066Sahrens zfs_ace_remove(zfs_acl_t *aclp, int slot) 490fa9e4066Sahrens { 491fa9e4066Sahrens if (aclp->z_acl_count > 1) { 492fa9e4066Sahrens (void) memmove(&aclp->z_acl[slot], 493fa9e4066Sahrens &aclp->z_acl[slot +1], sizeof (ace_t) * 494fa9e4066Sahrens (--aclp->z_acl_count - slot)); 495fa9e4066Sahrens } else 496fa9e4066Sahrens aclp->z_acl_count--; 497fa9e4066Sahrens } 498fa9e4066Sahrens 499fa9e4066Sahrens /* 500fa9e4066Sahrens * Update access mask for prepended ACE 501fa9e4066Sahrens * 502fa9e4066Sahrens * This applies the "groupmask" value for aclmode property. 503fa9e4066Sahrens */ 504fa9e4066Sahrens static void 505fa9e4066Sahrens zfs_acl_prepend_fixup(ace_t *acep, ace_t *origacep, mode_t mode, uid_t owner) 506fa9e4066Sahrens { 507fa9e4066Sahrens 508fa9e4066Sahrens int rmask, wmask, xmask; 509fa9e4066Sahrens int user_ace; 510fa9e4066Sahrens 511fa9e4066Sahrens user_ace = (!(acep->a_flags & 512fa9e4066Sahrens (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP))); 513fa9e4066Sahrens 514fa9e4066Sahrens if (user_ace && (acep->a_who == owner)) { 515fa9e4066Sahrens rmask = S_IRUSR; 516fa9e4066Sahrens wmask = S_IWUSR; 517fa9e4066Sahrens xmask = S_IXUSR; 518fa9e4066Sahrens } else { 519fa9e4066Sahrens rmask = S_IRGRP; 520fa9e4066Sahrens wmask = S_IWGRP; 521fa9e4066Sahrens xmask = S_IXGRP; 522fa9e4066Sahrens } 523fa9e4066Sahrens 524fa9e4066Sahrens if (origacep->a_access_mask & ACE_READ_DATA) { 525fa9e4066Sahrens if (mode & rmask) 526fa9e4066Sahrens acep->a_access_mask &= ~ACE_READ_DATA; 527fa9e4066Sahrens else 528fa9e4066Sahrens acep->a_access_mask |= ACE_READ_DATA; 529fa9e4066Sahrens } 530fa9e4066Sahrens 531fa9e4066Sahrens if (origacep->a_access_mask & ACE_WRITE_DATA) { 532fa9e4066Sahrens if (mode & wmask) 533fa9e4066Sahrens acep->a_access_mask &= ~ACE_WRITE_DATA; 534fa9e4066Sahrens else 535fa9e4066Sahrens acep->a_access_mask |= ACE_WRITE_DATA; 536fa9e4066Sahrens } 537fa9e4066Sahrens 538fa9e4066Sahrens if (origacep->a_access_mask & ACE_APPEND_DATA) { 539fa9e4066Sahrens if (mode & wmask) 540fa9e4066Sahrens acep->a_access_mask &= ~ACE_APPEND_DATA; 541fa9e4066Sahrens else 542fa9e4066Sahrens acep->a_access_mask |= ACE_APPEND_DATA; 543fa9e4066Sahrens } 544fa9e4066Sahrens 545fa9e4066Sahrens if (origacep->a_access_mask & ACE_EXECUTE) { 546fa9e4066Sahrens if (mode & xmask) 547fa9e4066Sahrens acep->a_access_mask &= ~ACE_EXECUTE; 548fa9e4066Sahrens else 549fa9e4066Sahrens acep->a_access_mask |= ACE_EXECUTE; 550fa9e4066Sahrens } 551fa9e4066Sahrens } 552fa9e4066Sahrens 553fa9e4066Sahrens /* 554fa9e4066Sahrens * Apply mode to canonical six ACEs. 555fa9e4066Sahrens */ 556fa9e4066Sahrens static void 557fa9e4066Sahrens zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode) 558fa9e4066Sahrens { 559fa9e4066Sahrens int cnt; 560fa9e4066Sahrens ace_t *acep; 561fa9e4066Sahrens 562fa9e4066Sahrens cnt = aclp->z_acl_count -1; 563fa9e4066Sahrens acep = aclp->z_acl; 564fa9e4066Sahrens 565fa9e4066Sahrens /* 566fa9e4066Sahrens * Fixup final ACEs to match the mode 567fa9e4066Sahrens */ 568fa9e4066Sahrens 569fa9e4066Sahrens ASSERT(cnt >= 5); 570fa9e4066Sahrens adjust_ace_pair(&acep[cnt - 1], mode); /* everyone@ */ 571fa9e4066Sahrens adjust_ace_pair(&acep[cnt - 3], (mode & 0070) >> 3); /* group@ */ 572fa9e4066Sahrens adjust_ace_pair(&acep[cnt - 5], (mode & 0700) >> 6); /* owner@ */ 573fa9e4066Sahrens } 574fa9e4066Sahrens 575fa9e4066Sahrens 576fa9e4066Sahrens static int 577fa9e4066Sahrens zfs_acl_ace_match(ace_t *acep, int allow_deny, int type, int mask) 578fa9e4066Sahrens { 579fa9e4066Sahrens return (acep->a_access_mask == mask && acep->a_type == allow_deny && 580fa9e4066Sahrens ((acep->a_flags & 0xf040) == type)); 581fa9e4066Sahrens } 582fa9e4066Sahrens 583fa9e4066Sahrens /* 584fa9e4066Sahrens * Can prepended ACE be reused? 585fa9e4066Sahrens */ 586fa9e4066Sahrens static int 587fa9e4066Sahrens zfs_reuse_deny(ace_t *acep, int i) 588fa9e4066Sahrens { 589fa9e4066Sahrens int okay_masks; 590fa9e4066Sahrens 591fa9e4066Sahrens if (i < 1) 592fa9e4066Sahrens return (B_FALSE); 593fa9e4066Sahrens 594fa9e4066Sahrens if (acep[i-1].a_type != DENY) 595fa9e4066Sahrens return (B_FALSE); 596fa9e4066Sahrens 597fa9e4066Sahrens if (acep[i-1].a_flags != (acep[i].a_flags & ACE_IDENTIFIER_GROUP)) 598fa9e4066Sahrens return (B_FALSE); 599fa9e4066Sahrens 600fa9e4066Sahrens okay_masks = (acep[i].a_access_mask & OKAY_MASK_BITS); 601fa9e4066Sahrens 602fa9e4066Sahrens if (acep[i-1].a_access_mask & ~okay_masks) 603fa9e4066Sahrens return (B_FALSE); 604fa9e4066Sahrens 605fa9e4066Sahrens return (B_TRUE); 606fa9e4066Sahrens } 607fa9e4066Sahrens 608fa9e4066Sahrens /* 609fa9e4066Sahrens * Create space to prepend an ACE 610fa9e4066Sahrens */ 611fa9e4066Sahrens static void 612fa9e4066Sahrens zfs_acl_prepend(zfs_acl_t *aclp, int i) 613fa9e4066Sahrens { 614fa9e4066Sahrens ace_t *oldaclp = NULL; 615fa9e4066Sahrens ace_t *to, *from; 616fa9e4066Sahrens int slots_left = aclp->z_slots - aclp->z_acl_count; 617fa9e4066Sahrens int oldslots; 618fa9e4066Sahrens int need_free = 0; 619fa9e4066Sahrens 620fa9e4066Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 621fa9e4066Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 622fa9e4066Sahrens 623fa9e4066Sahrens if (slots_left == 0 || aclp->z_state != ACL_DATA_ALLOCED) { 624fa9e4066Sahrens 625fa9e4066Sahrens to = kmem_alloc(ZFS_ACL_SIZE(aclp->z_acl_count + 626fa9e4066Sahrens OGE_PAD), KM_SLEEP); 627fa9e4066Sahrens if (aclp->z_state == ACL_DATA_ALLOCED) 628fa9e4066Sahrens need_free++; 629fa9e4066Sahrens from = aclp->z_acl; 630fa9e4066Sahrens oldaclp = aclp->z_acl; 631fa9e4066Sahrens (void) memmove(to, from, 632fa9e4066Sahrens sizeof (ace_t) * aclp->z_acl_count); 633fa9e4066Sahrens aclp->z_state = ACL_DATA_ALLOCED; 634fa9e4066Sahrens } else { 635fa9e4066Sahrens from = aclp->z_acl; 636fa9e4066Sahrens to = aclp->z_acl; 637fa9e4066Sahrens } 638fa9e4066Sahrens 639fa9e4066Sahrens 640fa9e4066Sahrens (void) memmove(&to[i + 1], &from[i], 641fa9e4066Sahrens sizeof (ace_t) * (aclp->z_acl_count - i)); 642fa9e4066Sahrens 643fa9e4066Sahrens if (oldaclp) { 644fa9e4066Sahrens aclp->z_acl = to; 645fa9e4066Sahrens oldslots = aclp->z_slots; 646fa9e4066Sahrens aclp->z_slots = aclp->z_acl_count + OGE_PAD; 647fa9e4066Sahrens if (need_free) 648fa9e4066Sahrens kmem_free(oldaclp, ZFS_ACL_SIZE(oldslots)); 649fa9e4066Sahrens } 650fa9e4066Sahrens 651fa9e4066Sahrens } 652fa9e4066Sahrens 653fa9e4066Sahrens /* 654fa9e4066Sahrens * Prepend deny ACE 655fa9e4066Sahrens */ 656fa9e4066Sahrens static void 657fa9e4066Sahrens zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, int i, 658fa9e4066Sahrens mode_t mode) 659fa9e4066Sahrens { 660fa9e4066Sahrens ace_t *acep; 661fa9e4066Sahrens 662fa9e4066Sahrens zfs_acl_prepend(aclp, i); 663fa9e4066Sahrens 664fa9e4066Sahrens acep = aclp->z_acl; 665fa9e4066Sahrens zfs_set_ace(&acep[i], 0, DENY, acep[i + 1].a_who, 666fa9e4066Sahrens (acep[i + 1].a_flags & 0xf040)); 667fa9e4066Sahrens zfs_acl_prepend_fixup(&acep[i], &acep[i+1], mode, zp->z_phys->zp_uid); 668fa9e4066Sahrens aclp->z_acl_count++; 669fa9e4066Sahrens } 670fa9e4066Sahrens 671fa9e4066Sahrens /* 672fa9e4066Sahrens * Split an inherited ACE into inherit_only ACE 673fa9e4066Sahrens * and original ACE with inheritance flags stripped off. 674fa9e4066Sahrens */ 675fa9e4066Sahrens static void 676fa9e4066Sahrens zfs_acl_split_ace(zfs_acl_t *aclp, int i) 677fa9e4066Sahrens { 678fa9e4066Sahrens ace_t *acep = aclp->z_acl; 679fa9e4066Sahrens 680fa9e4066Sahrens zfs_acl_prepend(aclp, i); 681fa9e4066Sahrens acep = aclp->z_acl; 682fa9e4066Sahrens acep[i] = acep[i + 1]; 683fa9e4066Sahrens acep[i].a_flags |= ACE_INHERIT_ONLY_ACE; 684fa9e4066Sahrens acep[i + 1].a_flags &= ~ALL_INHERIT; 685fa9e4066Sahrens aclp->z_acl_count++; 686fa9e4066Sahrens } 687fa9e4066Sahrens 688fa9e4066Sahrens /* 689fa9e4066Sahrens * Are ACES started at index i, the canonical six ACES? 690fa9e4066Sahrens */ 691fa9e4066Sahrens static int 692fa9e4066Sahrens zfs_have_canonical_six(zfs_acl_t *aclp, int i) 693fa9e4066Sahrens { 694fa9e4066Sahrens ace_t *acep = aclp->z_acl; 695fa9e4066Sahrens 696fa9e4066Sahrens if ((zfs_acl_ace_match(&acep[i], 697fa9e4066Sahrens DENY, ACE_OWNER, 0) && 698fa9e4066Sahrens zfs_acl_ace_match(&acep[i + 1], ALLOW, ACE_OWNER, 699fa9e4066Sahrens OWNER_ALLOW_MASK) && zfs_acl_ace_match(&acep[i + 2], 700fa9e4066Sahrens DENY, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 3], 701fa9e4066Sahrens ALLOW, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 4], 702fa9e4066Sahrens DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) && 703fa9e4066Sahrens zfs_acl_ace_match(&acep[i + 5], ALLOW, ACE_EVERYONE, 704fa9e4066Sahrens EVERYONE_ALLOW_MASK))) { 705fa9e4066Sahrens return (1); 706fa9e4066Sahrens } else { 707fa9e4066Sahrens return (0); 708fa9e4066Sahrens } 709fa9e4066Sahrens } 710fa9e4066Sahrens 711fa9e4066Sahrens /* 712fa9e4066Sahrens * Apply step 1g, to group entries 713fa9e4066Sahrens * 714fa9e4066Sahrens * Need to deal with corner case where group may have 715fa9e4066Sahrens * greater permissions than owner. If so then limit 716fa9e4066Sahrens * group permissions, based on what extra permissions 717fa9e4066Sahrens * group has. 718fa9e4066Sahrens */ 719fa9e4066Sahrens static void 720fa9e4066Sahrens zfs_fixup_group_entries(ace_t *acep, mode_t mode) 721fa9e4066Sahrens { 722fa9e4066Sahrens mode_t extramode = (mode >> 3) & 07; 723fa9e4066Sahrens mode_t ownermode = (mode >> 6); 724fa9e4066Sahrens 725fa9e4066Sahrens if (acep[0].a_flags & ACE_IDENTIFIER_GROUP) { 726fa9e4066Sahrens 727fa9e4066Sahrens extramode &= ~ownermode; 728fa9e4066Sahrens 729fa9e4066Sahrens if (extramode) { 730fa9e4066Sahrens if (extramode & 04) { 731fa9e4066Sahrens acep[0].a_access_mask &= ~ACE_READ_DATA; 732fa9e4066Sahrens acep[1].a_access_mask &= ~ACE_READ_DATA; 733fa9e4066Sahrens } 734fa9e4066Sahrens if (extramode & 02) { 735fa9e4066Sahrens acep[0].a_access_mask &= 736fa9e4066Sahrens ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 737fa9e4066Sahrens acep[1].a_access_mask &= 738fa9e4066Sahrens ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 739fa9e4066Sahrens } 740fa9e4066Sahrens if (extramode & 01) { 741fa9e4066Sahrens acep[0].a_access_mask &= ~ACE_EXECUTE; 742fa9e4066Sahrens acep[1].a_access_mask &= ~ACE_EXECUTE; 743fa9e4066Sahrens } 744fa9e4066Sahrens } 745fa9e4066Sahrens } 746fa9e4066Sahrens } 747fa9e4066Sahrens 748fa9e4066Sahrens /* 749fa9e4066Sahrens * Apply the chmod algorithm as described 750fa9e4066Sahrens * in PSARC/2002/240 751fa9e4066Sahrens */ 752fa9e4066Sahrens static int 753fa9e4066Sahrens zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp, 754fa9e4066Sahrens dmu_tx_t *tx) 755fa9e4066Sahrens { 756fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 757fa9e4066Sahrens ace_t *acep; 758fa9e4066Sahrens int i; 759fa9e4066Sahrens int error; 760fa9e4066Sahrens int entry_type; 761fa9e4066Sahrens int reuse_deny; 762fa9e4066Sahrens int need_canonical_six = 1; 763de122929Smarks int inherit = 0; 764de122929Smarks int iflags; 765fa9e4066Sahrens 766fa9e4066Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 767fa9e4066Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 768fa9e4066Sahrens 769fa9e4066Sahrens i = 0; 770fa9e4066Sahrens while (i < aclp->z_acl_count) { 771fa9e4066Sahrens acep = aclp->z_acl; 772fa9e4066Sahrens entry_type = (acep[i].a_flags & 0xf040); 773de122929Smarks iflags = (acep[i].a_flags & ALL_INHERIT); 774fa9e4066Sahrens 775fa9e4066Sahrens if ((acep[i].a_type != ALLOW && acep[i].a_type != DENY) || 776de122929Smarks (iflags & ACE_INHERIT_ONLY_ACE)) { 777fa9e4066Sahrens i++; 778de122929Smarks if (iflags) 779de122929Smarks inherit = 1; 780fa9e4066Sahrens continue; 781fa9e4066Sahrens } 782fa9e4066Sahrens 783fa9e4066Sahrens 784fa9e4066Sahrens if (zfsvfs->z_acl_mode == DISCARD) { 785fa9e4066Sahrens zfs_ace_remove(aclp, i); 786fa9e4066Sahrens continue; 787fa9e4066Sahrens } 788fa9e4066Sahrens 789fa9e4066Sahrens /* 790fa9e4066Sahrens * Need to split ace into two? 791fa9e4066Sahrens */ 792de122929Smarks if ((iflags & (ACE_FILE_INHERIT_ACE| 793fa9e4066Sahrens ACE_DIRECTORY_INHERIT_ACE)) && 794de122929Smarks (!(iflags & ACE_INHERIT_ONLY_ACE))) { 795fa9e4066Sahrens zfs_acl_split_ace(aclp, i); 796fa9e4066Sahrens i++; 797de122929Smarks inherit = 1; 798fa9e4066Sahrens continue; 799fa9e4066Sahrens } 800fa9e4066Sahrens 801fa9e4066Sahrens if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 802fa9e4066Sahrens (entry_type == OWNING_GROUP)) { 803fa9e4066Sahrens acep[i].a_access_mask &= ~OGE_CLEAR; 804fa9e4066Sahrens i++; 805fa9e4066Sahrens continue; 806fa9e4066Sahrens 807fa9e4066Sahrens } else { 808fa9e4066Sahrens if (acep[i].a_type == ALLOW) { 809fa9e4066Sahrens 810fa9e4066Sahrens /* 811fa9e4066Sahrens * Check preceding ACE if any, to see 812fa9e4066Sahrens * if we need to prepend a DENY ACE. 813fa9e4066Sahrens * This is only applicable when the acl_mode 814fa9e4066Sahrens * property == groupmask. 815fa9e4066Sahrens */ 816fa9e4066Sahrens if (zfsvfs->z_acl_mode == GROUPMASK) { 817fa9e4066Sahrens 818fa9e4066Sahrens reuse_deny = zfs_reuse_deny(acep, i); 819fa9e4066Sahrens 820fa9e4066Sahrens if (reuse_deny == B_FALSE) { 821fa9e4066Sahrens zfs_acl_prepend_deny(zp, aclp, 822fa9e4066Sahrens i, mode); 823fa9e4066Sahrens i++; 824fa9e4066Sahrens acep = aclp->z_acl; 825fa9e4066Sahrens } else { 826fa9e4066Sahrens zfs_acl_prepend_fixup( 827fa9e4066Sahrens &acep[i - 1], 828fa9e4066Sahrens &acep[i], mode, 829fa9e4066Sahrens zp->z_phys->zp_uid); 830fa9e4066Sahrens } 831fa9e4066Sahrens zfs_fixup_group_entries(&acep[i - 1], 832fa9e4066Sahrens mode); 833fa9e4066Sahrens } 834fa9e4066Sahrens } 835fa9e4066Sahrens i++; 836fa9e4066Sahrens } 837fa9e4066Sahrens } 838fa9e4066Sahrens 839fa9e4066Sahrens /* 840fa9e4066Sahrens * Check out last six aces, if we have six. 841fa9e4066Sahrens */ 842fa9e4066Sahrens 843fa9e4066Sahrens if (aclp->z_acl_count >= 6) { 844fa9e4066Sahrens i = aclp->z_acl_count - 6; 845fa9e4066Sahrens 846fa9e4066Sahrens if (zfs_have_canonical_six(aclp, i)) { 847fa9e4066Sahrens need_canonical_six = 0; 848fa9e4066Sahrens } 849fa9e4066Sahrens } 850fa9e4066Sahrens 851fa9e4066Sahrens if (need_canonical_six) { 852fa9e4066Sahrens 853fa9e4066Sahrens zfs_acl_append(aclp, 6); 854fa9e4066Sahrens i = aclp->z_acl_count; 855fa9e4066Sahrens acep = aclp->z_acl; 856fa9e4066Sahrens zfs_set_ace(&acep[i++], 0, DENY, -1, ACE_OWNER); 857fa9e4066Sahrens zfs_set_ace(&acep[i++], OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER); 858fa9e4066Sahrens zfs_set_ace(&acep[i++], 0, DENY, -1, OWNING_GROUP); 859fa9e4066Sahrens zfs_set_ace(&acep[i++], 0, ALLOW, -1, OWNING_GROUP); 860fa9e4066Sahrens zfs_set_ace(&acep[i++], EVERYONE_DENY_MASK, 861fa9e4066Sahrens DENY, -1, ACE_EVERYONE); 862fa9e4066Sahrens zfs_set_ace(&acep[i++], EVERYONE_ALLOW_MASK, 863fa9e4066Sahrens ALLOW, -1, ACE_EVERYONE); 864fa9e4066Sahrens aclp->z_acl_count += 6; 865fa9e4066Sahrens } 866fa9e4066Sahrens 867fa9e4066Sahrens zfs_acl_fixup_canonical_six(aclp, mode); 868fa9e4066Sahrens 869fa9e4066Sahrens zp->z_phys->zp_mode = mode; 870de122929Smarks error = zfs_aclset_common(zp, aclp, tx, &inherit); 871fa9e4066Sahrens return (error); 872fa9e4066Sahrens } 873fa9e4066Sahrens 874fa9e4066Sahrens 875fa9e4066Sahrens int 876fa9e4066Sahrens zfs_acl_chmod_setattr(znode_t *zp, uint64_t mode, dmu_tx_t *tx) 877fa9e4066Sahrens { 878*ea8dc4b6Seschrock zfs_acl_t *aclp = NULL; 879fa9e4066Sahrens int error; 880fa9e4066Sahrens 881fa9e4066Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 882fa9e4066Sahrens mutex_enter(&zp->z_acl_lock); 883*ea8dc4b6Seschrock error = zfs_acl_node_read(zp, &aclp); 884*ea8dc4b6Seschrock if (error == 0) 885*ea8dc4b6Seschrock error = zfs_acl_chmod(zp, mode, aclp, tx); 886fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 887*ea8dc4b6Seschrock if (aclp) 888*ea8dc4b6Seschrock zfs_acl_free(aclp); 889fa9e4066Sahrens return (error); 890fa9e4066Sahrens } 891fa9e4066Sahrens 892fa9e4066Sahrens /* 893fa9e4066Sahrens * strip off write_owner and write_acl 894fa9e4066Sahrens */ 895fa9e4066Sahrens static void 896fa9e4066Sahrens zfs_securemode_update(zfsvfs_t *zfsvfs, ace_t *acep) 897fa9e4066Sahrens { 898fa9e4066Sahrens if ((zfsvfs->z_acl_inherit == SECURE) && 899fa9e4066Sahrens acep->a_type == ALLOW) 900fa9e4066Sahrens acep->a_access_mask &= ~SECURE_NO_INHERIT; 901fa9e4066Sahrens } 902fa9e4066Sahrens 903fa9e4066Sahrens /* 904fa9e4066Sahrens * inherit inheritable ACEs from parent 905fa9e4066Sahrens */ 906fa9e4066Sahrens static zfs_acl_t * 907fa9e4066Sahrens zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp) 908fa9e4066Sahrens { 909fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 910fa9e4066Sahrens ace_t *pacep; 911fa9e4066Sahrens ace_t *acep; 912fa9e4066Sahrens int ace_cnt = 0; 913fa9e4066Sahrens int pace_cnt; 914fa9e4066Sahrens int i, j; 915fa9e4066Sahrens zfs_acl_t *aclp = NULL; 916fa9e4066Sahrens 917fa9e4066Sahrens i = j = 0; 918fa9e4066Sahrens pace_cnt = paclp->z_acl_count; 919fa9e4066Sahrens pacep = paclp->z_acl; 920fa9e4066Sahrens if (zfsvfs->z_acl_inherit != DISCARD) { 921fa9e4066Sahrens for (i = 0; i != pace_cnt; i++) { 922fa9e4066Sahrens 923fa9e4066Sahrens if (zfsvfs->z_acl_inherit == NOALLOW && 924fa9e4066Sahrens pacep[i].a_type == ALLOW) 925fa9e4066Sahrens continue; 926fa9e4066Sahrens 927fa9e4066Sahrens if (zfs_ace_can_use(zp, &pacep[i])) { 928fa9e4066Sahrens ace_cnt++; 929fa9e4066Sahrens if (!(pacep[i].a_flags & 930fa9e4066Sahrens ACE_NO_PROPAGATE_INHERIT_ACE)) 931fa9e4066Sahrens ace_cnt++; 932fa9e4066Sahrens } 933fa9e4066Sahrens } 934fa9e4066Sahrens } 935fa9e4066Sahrens 936fa9e4066Sahrens aclp = zfs_acl_alloc(ace_cnt + OGE_PAD); 937fa9e4066Sahrens if (ace_cnt && zfsvfs->z_acl_inherit != DISCARD) { 938fa9e4066Sahrens acep = aclp->z_acl; 939fa9e4066Sahrens pacep = paclp->z_acl; 940fa9e4066Sahrens for (i = 0; i != pace_cnt; i++) { 941fa9e4066Sahrens 942fa9e4066Sahrens if (zfsvfs->z_acl_inherit == NOALLOW && 943fa9e4066Sahrens pacep[i].a_type == ALLOW) 944fa9e4066Sahrens continue; 945fa9e4066Sahrens 946fa9e4066Sahrens if (zfs_ace_can_use(zp, &pacep[i])) { 947fa9e4066Sahrens /* 948fa9e4066Sahrens * Now create entry for inherited ace 949fa9e4066Sahrens */ 950fa9e4066Sahrens acep[j] = pacep[i]; 951fa9e4066Sahrens 952fa9e4066Sahrens if (pacep[i].a_flags & 953fa9e4066Sahrens ACE_NO_PROPAGATE_INHERIT_ACE) { 954fa9e4066Sahrens acep[j].a_flags &= ~ALL_INHERIT; 955fa9e4066Sahrens j++; 956fa9e4066Sahrens continue; 957fa9e4066Sahrens } 958fa9e4066Sahrens 959fa9e4066Sahrens if (pacep[i].a_type != ALLOW && 960fa9e4066Sahrens pacep[i].a_type != DENY) { 961fa9e4066Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 962fa9e4066Sahrens j++; 963fa9e4066Sahrens continue; 964fa9e4066Sahrens } 965fa9e4066Sahrens 966fa9e4066Sahrens if (ZTOV(zp)->v_type != VDIR) { 967fa9e4066Sahrens acep[j].a_flags &= ~ALL_INHERIT; 968fa9e4066Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 969fa9e4066Sahrens j++; 970fa9e4066Sahrens continue; 971fa9e4066Sahrens } 972fa9e4066Sahrens 973fa9e4066Sahrens ASSERT(ZTOV(zp)->v_type == VDIR); 974fa9e4066Sahrens 975fa9e4066Sahrens /* 976fa9e4066Sahrens * If we are inheriting an ACE targeted for 97755601ddbSmarks * only files, then make sure inherit_only 97855601ddbSmarks * is on for future propagation. 979fa9e4066Sahrens */ 980fa9e4066Sahrens if ((acep[j].a_flags & (ACE_FILE_INHERIT_ACE | 98155601ddbSmarks ACE_DIRECTORY_INHERIT_ACE)) == 98255601ddbSmarks ACE_FILE_INHERIT_ACE) { 98355601ddbSmarks acep[j].a_flags |= ACE_INHERIT_ONLY_ACE; 98455601ddbSmarks } else { 985fa9e4066Sahrens acep[j].a_flags &= 986fa9e4066Sahrens ~ACE_INHERIT_ONLY_ACE; 98755601ddbSmarks } 988fa9e4066Sahrens 989fa9e4066Sahrens zfs_securemode_update(zfsvfs, &acep[j]); 990fa9e4066Sahrens j++; 991fa9e4066Sahrens } 992fa9e4066Sahrens } 993fa9e4066Sahrens } 994fa9e4066Sahrens aclp->z_acl_count = j; 995fa9e4066Sahrens ASSERT(aclp->z_slots >= aclp->z_acl_count); 996fa9e4066Sahrens 997fa9e4066Sahrens return (aclp); 998fa9e4066Sahrens } 999fa9e4066Sahrens 1000fa9e4066Sahrens /* 1001fa9e4066Sahrens * Create file system object initial permissions 1002fa9e4066Sahrens * including inheritable ACEs. 1003fa9e4066Sahrens */ 1004fa9e4066Sahrens void 1005fa9e4066Sahrens zfs_perm_init(znode_t *zp, znode_t *parent, int flag, 1006fa9e4066Sahrens vattr_t *vap, dmu_tx_t *tx, cred_t *cr) 1007fa9e4066Sahrens { 1008fa9e4066Sahrens uint64_t mode; 1009fa9e4066Sahrens uid_t uid; 1010fa9e4066Sahrens gid_t gid; 1011fa9e4066Sahrens int error; 1012fa9e4066Sahrens int pull_down; 1013fa9e4066Sahrens zfs_acl_t *aclp, *paclp; 1014fa9e4066Sahrens 1015fa9e4066Sahrens mode = MAKEIMODE(vap->va_type, vap->va_mode); 1016fa9e4066Sahrens 1017fa9e4066Sahrens /* 1018fa9e4066Sahrens * Determine uid and gid. 1019fa9e4066Sahrens */ 1020fa9e4066Sahrens if ((flag & (IS_ROOT_NODE | IS_REPLAY)) || 1021fa9e4066Sahrens ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 1022fa9e4066Sahrens uid = vap->va_uid; 1023fa9e4066Sahrens gid = vap->va_gid; 1024fa9e4066Sahrens } else { 1025fa9e4066Sahrens uid = crgetuid(cr); 1026fa9e4066Sahrens if ((vap->va_mask & AT_GID) && 1027fa9e4066Sahrens ((vap->va_gid == parent->z_phys->zp_gid) || 1028fa9e4066Sahrens groupmember(vap->va_gid, cr) || 1029fa9e4066Sahrens secpolicy_vnode_create_gid(cr))) 1030fa9e4066Sahrens gid = vap->va_gid; 1031fa9e4066Sahrens else 1032fa9e4066Sahrens gid = (parent->z_phys->zp_mode & S_ISGID) ? 1033fa9e4066Sahrens parent->z_phys->zp_gid : crgetgid(cr); 1034fa9e4066Sahrens } 1035fa9e4066Sahrens 1036fa9e4066Sahrens /* 1037fa9e4066Sahrens * If we're creating a directory, and the parent directory has the 1038fa9e4066Sahrens * set-GID bit set, set in on the new directory. 1039fa9e4066Sahrens * Otherwise, if the user is neither privileged nor a member of the 1040fa9e4066Sahrens * file's new group, clear the file's set-GID bit. 1041fa9e4066Sahrens */ 1042fa9e4066Sahrens 1043fa9e4066Sahrens if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) 1044fa9e4066Sahrens mode |= S_ISGID; 1045fa9e4066Sahrens else { 1046fa9e4066Sahrens if ((mode & S_ISGID) && 1047fa9e4066Sahrens secpolicy_vnode_setids_setgids(cr, gid) != 0) 1048fa9e4066Sahrens mode &= ~S_ISGID; 1049fa9e4066Sahrens } 1050fa9e4066Sahrens 1051fa9e4066Sahrens zp->z_phys->zp_uid = uid; 1052fa9e4066Sahrens zp->z_phys->zp_gid = gid; 1053fa9e4066Sahrens zp->z_phys->zp_mode = mode; 1054fa9e4066Sahrens 1055fa9e4066Sahrens mutex_enter(&parent->z_lock); 1056fa9e4066Sahrens pull_down = (parent->z_phys->zp_flags & ZFS_INHERIT_ACE); 1057fa9e4066Sahrens if (pull_down) { 1058fa9e4066Sahrens mutex_enter(&parent->z_acl_lock); 1059*ea8dc4b6Seschrock VERIFY(0 == zfs_acl_node_read(parent, &paclp)); 1060fa9e4066Sahrens mutex_exit(&parent->z_acl_lock); 1061fa9e4066Sahrens aclp = zfs_acl_inherit(zp, paclp); 1062fa9e4066Sahrens zfs_acl_free(paclp); 1063fa9e4066Sahrens } else { 1064fa9e4066Sahrens aclp = zfs_acl_alloc(6); 1065fa9e4066Sahrens } 1066fa9e4066Sahrens mutex_exit(&parent->z_lock); 1067fa9e4066Sahrens mutex_enter(&zp->z_lock); 1068fa9e4066Sahrens mutex_enter(&zp->z_acl_lock); 1069fa9e4066Sahrens error = zfs_acl_chmod(zp, mode, aclp, tx); 1070fa9e4066Sahrens mutex_exit(&zp->z_lock); 1071fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 1072fa9e4066Sahrens ASSERT3U(error, ==, 0); 1073fa9e4066Sahrens zfs_acl_free(aclp); 1074fa9e4066Sahrens } 1075fa9e4066Sahrens 1076fa9e4066Sahrens /* 10770a787dc5Smarks * Should ACE be inherited? 1078fa9e4066Sahrens */ 1079fa9e4066Sahrens static int 1080fa9e4066Sahrens zfs_ace_can_use(znode_t *zp, ace_t *acep) 1081fa9e4066Sahrens { 1082fa9e4066Sahrens int vtype = ZTOV(zp)->v_type; 1083fa9e4066Sahrens 1084fa9e4066Sahrens int iflags = (acep->a_flags & 0xf); 1085fa9e4066Sahrens 1086fa9e4066Sahrens if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1087fa9e4066Sahrens return (1); 1088fa9e4066Sahrens else if (iflags & ACE_FILE_INHERIT_ACE) 10890a787dc5Smarks return (!((vtype == VDIR) && 10900a787dc5Smarks (iflags & ACE_NO_PROPAGATE_INHERIT_ACE))); 1091fa9e4066Sahrens return (0); 1092fa9e4066Sahrens } 1093fa9e4066Sahrens 1094fa9e4066Sahrens /* 1095fa9e4066Sahrens * Retrieve a files ACL 1096fa9e4066Sahrens */ 1097fa9e4066Sahrens int 1098fa9e4066Sahrens zfs_getacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr) 1099fa9e4066Sahrens { 1100fa9e4066Sahrens zfs_acl_t *aclp; 1101fa9e4066Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1102fa9e4066Sahrens int error; 1103fa9e4066Sahrens 1104fa9e4066Sahrens if (error = zfs_zaccess(zp, ACE_READ_ACL, cr)) { 1105fa9e4066Sahrens /* 1106fa9e4066Sahrens * If owner of file then allow reading of the 1107fa9e4066Sahrens * ACL. 1108fa9e4066Sahrens */ 1109fa9e4066Sahrens if (crgetuid(cr) != zp->z_phys->zp_uid) 1110fa9e4066Sahrens return (error); 1111fa9e4066Sahrens } 1112fa9e4066Sahrens 1113fa9e4066Sahrens if (mask == 0) 1114fa9e4066Sahrens return (ENOSYS); 1115fa9e4066Sahrens 1116fa9e4066Sahrens mutex_enter(&zp->z_acl_lock); 1117fa9e4066Sahrens 1118*ea8dc4b6Seschrock error = zfs_acl_node_read(zp, &aclp); 1119*ea8dc4b6Seschrock if (error != 0) { 1120*ea8dc4b6Seschrock mutex_exit(&zp->z_acl_lock); 1121*ea8dc4b6Seschrock return (error); 1122*ea8dc4b6Seschrock } 1123*ea8dc4b6Seschrock 1124fa9e4066Sahrens 1125fa9e4066Sahrens if (mask & VSA_ACECNT) { 1126fa9e4066Sahrens vsecp->vsa_aclcnt = aclp->z_acl_count; 1127fa9e4066Sahrens } 1128fa9e4066Sahrens 1129fa9e4066Sahrens if (mask & VSA_ACE) { 1130fa9e4066Sahrens vsecp->vsa_aclentp = kmem_alloc(aclp->z_acl_count * 1131fa9e4066Sahrens sizeof (ace_t), KM_SLEEP); 1132fa9e4066Sahrens bcopy(aclp->z_acl, vsecp->vsa_aclentp, 1133fa9e4066Sahrens aclp->z_acl_count * sizeof (ace_t)); 1134fa9e4066Sahrens } 1135fa9e4066Sahrens 1136fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 1137fa9e4066Sahrens 1138fa9e4066Sahrens zfs_acl_free(aclp); 1139fa9e4066Sahrens 1140fa9e4066Sahrens return (0); 1141fa9e4066Sahrens } 1142fa9e4066Sahrens 1143fa9e4066Sahrens /* 1144fa9e4066Sahrens * Set a files ACL 1145fa9e4066Sahrens */ 1146fa9e4066Sahrens int 1147fa9e4066Sahrens zfs_setacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr) 1148fa9e4066Sahrens { 1149fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1150fa9e4066Sahrens zilog_t *zilog = zfsvfs->z_log; 1151fa9e4066Sahrens ace_t *acep = vsecp->vsa_aclentp; 1152fa9e4066Sahrens int aclcnt = vsecp->vsa_aclcnt; 1153fa9e4066Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1154fa9e4066Sahrens dmu_tx_t *tx; 1155fa9e4066Sahrens int error; 1156fa9e4066Sahrens int inherit; 1157fa9e4066Sahrens zfs_acl_t *aclp; 1158fa9e4066Sahrens uint64_t seq = 0; 1159fa9e4066Sahrens 1160fa9e4066Sahrens if (mask == 0) 1161fa9e4066Sahrens return (EINVAL); 1162fa9e4066Sahrens 1163fa9e4066Sahrens if (!zfs_acl_valid(zp, acep, aclcnt, &inherit)) 1164fa9e4066Sahrens return (EINVAL); 1165fa9e4066Sahrens top: 1166fa9e4066Sahrens error = zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr); 1167fa9e4066Sahrens if (error == EACCES || error == ACCESS_UNDETERMINED) { 1168fa9e4066Sahrens if ((error = secpolicy_vnode_setdac(cr, 1169fa9e4066Sahrens zp->z_phys->zp_uid)) != 0) { 1170fa9e4066Sahrens return (error); 1171fa9e4066Sahrens } 1172fa9e4066Sahrens } else if (error) { 1173fa9e4066Sahrens return (error == EROFS ? error : EPERM); 1174fa9e4066Sahrens } 1175fa9e4066Sahrens 1176fa9e4066Sahrens mutex_enter(&zp->z_lock); 1177fa9e4066Sahrens mutex_enter(&zp->z_acl_lock); 1178fa9e4066Sahrens 1179fa9e4066Sahrens tx = dmu_tx_create(zfsvfs->z_os); 1180fa9e4066Sahrens dmu_tx_hold_bonus(tx, zp->z_id); 1181fa9e4066Sahrens 1182fa9e4066Sahrens if (zp->z_phys->zp_acl.z_acl_extern_obj) { 1183fa9e4066Sahrens dmu_tx_hold_write(tx, zp->z_phys->zp_acl.z_acl_extern_obj, 1184fa9e4066Sahrens 0, ZFS_ACL_SIZE(aclcnt)); 1185fa9e4066Sahrens } else if (aclcnt > ACE_SLOT_CNT) { 1186fa9e4066Sahrens dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, ZFS_ACL_SIZE(aclcnt)); 1187fa9e4066Sahrens } 1188fa9e4066Sahrens 1189fa9e4066Sahrens error = dmu_tx_assign(tx, zfsvfs->z_assign); 1190fa9e4066Sahrens if (error) { 1191fa9e4066Sahrens dmu_tx_abort(tx); 1192fa9e4066Sahrens 1193fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 1194fa9e4066Sahrens mutex_exit(&zp->z_lock); 1195fa9e4066Sahrens 1196fa9e4066Sahrens if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 1197fa9e4066Sahrens txg_wait_open(dmu_objset_pool(zfsvfs->z_os), 0); 1198fa9e4066Sahrens goto top; 1199fa9e4066Sahrens } 1200fa9e4066Sahrens return (error); 1201fa9e4066Sahrens } 1202fa9e4066Sahrens 1203fa9e4066Sahrens aclp = zfs_acl_alloc(aclcnt); 1204fa9e4066Sahrens bcopy(acep, aclp->z_acl, sizeof (ace_t) * aclcnt); 1205fa9e4066Sahrens aclp->z_acl_count = aclcnt; 1206fa9e4066Sahrens error = zfs_aclset_common(zp, aclp, tx, &inherit); 1207fa9e4066Sahrens ASSERT(error == 0); 1208fa9e4066Sahrens 1209fa9e4066Sahrens zfs_acl_free(aclp); 1210fa9e4066Sahrens seq = zfs_log_acl(zilog, tx, TX_ACL, zp, aclcnt, acep); 1211fa9e4066Sahrens dmu_tx_commit(tx); 1212fa9e4066Sahrens done: 1213fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 1214fa9e4066Sahrens mutex_exit(&zp->z_lock); 1215fa9e4066Sahrens 1216fa9e4066Sahrens zil_commit(zilog, seq, 0); 1217fa9e4066Sahrens 1218fa9e4066Sahrens return (error); 1219fa9e4066Sahrens } 1220fa9e4066Sahrens 1221fa9e4066Sahrens static int 1222fa9e4066Sahrens zfs_ace_access(ace_t *zacep, int mode_wanted, int *working_mode) 1223fa9e4066Sahrens { 1224fa9e4066Sahrens if ((*working_mode & mode_wanted) == mode_wanted) { 1225fa9e4066Sahrens return (0); 1226fa9e4066Sahrens } 1227fa9e4066Sahrens 1228fa9e4066Sahrens if (zacep->a_access_mask & mode_wanted) { 1229fa9e4066Sahrens if (zacep->a_type == ALLOW) { 1230fa9e4066Sahrens *working_mode |= (mode_wanted & zacep->a_access_mask); 1231fa9e4066Sahrens if ((*working_mode & mode_wanted) == mode_wanted) 1232fa9e4066Sahrens return (0); 1233fa9e4066Sahrens } else if (zacep->a_type == DENY) { 1234fa9e4066Sahrens return (EACCES); 1235fa9e4066Sahrens } 1236fa9e4066Sahrens } 1237fa9e4066Sahrens 1238fa9e4066Sahrens /* 1239fa9e4066Sahrens * haven't been specifcally denied at this point 1240fa9e4066Sahrens * so return UNDETERMINED. 1241fa9e4066Sahrens */ 1242fa9e4066Sahrens 1243fa9e4066Sahrens return (ACCESS_UNDETERMINED); 1244fa9e4066Sahrens } 1245fa9e4066Sahrens 1246fa9e4066Sahrens 1247fa9e4066Sahrens static int 1248fa9e4066Sahrens zfs_zaccess_common(znode_t *zp, int v4_mode, int *working_mode, cred_t *cr) 1249fa9e4066Sahrens { 1250fa9e4066Sahrens zfs_acl_t *aclp; 1251fa9e4066Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1252fa9e4066Sahrens ace_t *zacep; 1253fa9e4066Sahrens gid_t gid; 1254fa9e4066Sahrens int mode_wanted = v4_mode; 1255fa9e4066Sahrens int cnt; 1256fa9e4066Sahrens int i; 1257*ea8dc4b6Seschrock int error; 1258fa9e4066Sahrens int access_deny = ACCESS_UNDETERMINED; 1259fa9e4066Sahrens uint_t entry_type; 1260fa9e4066Sahrens uid_t uid = crgetuid(cr); 1261fa9e4066Sahrens 1262fa9e4066Sahrens *working_mode = 0; 1263fa9e4066Sahrens 1264fa9e4066Sahrens if (zfsvfs->z_assign >= TXG_INITIAL) /* ZIL replay */ 1265fa9e4066Sahrens return (0); 1266fa9e4066Sahrens 1267fa9e4066Sahrens if ((v4_mode & WRITE_MASK) && 1268fa9e4066Sahrens (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 1269fa9e4066Sahrens (!IS_DEVVP(ZTOV(zp)))) { 1270fa9e4066Sahrens return (EROFS); 1271fa9e4066Sahrens } 1272fa9e4066Sahrens 1273fa9e4066Sahrens mutex_enter(&zp->z_acl_lock); 1274fa9e4066Sahrens 1275*ea8dc4b6Seschrock error = zfs_acl_node_read(zp, &aclp); 1276*ea8dc4b6Seschrock if (error != 0) { 1277*ea8dc4b6Seschrock mutex_exit(&zp->z_acl_lock); 1278*ea8dc4b6Seschrock return (error); 1279*ea8dc4b6Seschrock } 1280*ea8dc4b6Seschrock 1281fa9e4066Sahrens 1282fa9e4066Sahrens zacep = aclp->z_acl; 1283fa9e4066Sahrens cnt = aclp->z_acl_count; 1284fa9e4066Sahrens 1285fa9e4066Sahrens for (i = 0; i != cnt; i++) { 1286fa9e4066Sahrens 1287fa9e4066Sahrens if (zacep[i].a_flags & ACE_INHERIT_ONLY_ACE) 1288fa9e4066Sahrens continue; 1289fa9e4066Sahrens 1290fa9e4066Sahrens entry_type = (zacep[i].a_flags & 0xf040); 1291fa9e4066Sahrens switch (entry_type) { 1292fa9e4066Sahrens case ACE_OWNER: 1293fa9e4066Sahrens if (uid == zp->z_phys->zp_uid) { 1294fa9e4066Sahrens access_deny = zfs_ace_access(&zacep[i], 1295fa9e4066Sahrens mode_wanted, working_mode); 1296fa9e4066Sahrens } 1297fa9e4066Sahrens break; 1298fa9e4066Sahrens case (ACE_IDENTIFIER_GROUP | ACE_GROUP): 1299fa9e4066Sahrens case ACE_IDENTIFIER_GROUP: 1300fa9e4066Sahrens /* 1301fa9e4066Sahrens * Owning group gid is in znode not ACL 1302fa9e4066Sahrens */ 1303fa9e4066Sahrens if (entry_type == (ACE_IDENTIFIER_GROUP | ACE_GROUP)) 1304fa9e4066Sahrens gid = zp->z_phys->zp_gid; 1305fa9e4066Sahrens else 1306fa9e4066Sahrens gid = zacep[i].a_who; 1307fa9e4066Sahrens 1308fa9e4066Sahrens if (groupmember(gid, cr)) { 1309fa9e4066Sahrens access_deny = zfs_ace_access(&zacep[i], 1310fa9e4066Sahrens mode_wanted, working_mode); 1311fa9e4066Sahrens } 1312fa9e4066Sahrens break; 1313fa9e4066Sahrens case ACE_EVERYONE: 1314fa9e4066Sahrens access_deny = zfs_ace_access(&zacep[i], 1315fa9e4066Sahrens mode_wanted, working_mode); 1316fa9e4066Sahrens break; 1317fa9e4066Sahrens 1318fa9e4066Sahrens /* USER Entry */ 1319fa9e4066Sahrens default: 1320fa9e4066Sahrens if (entry_type == 0) { 1321fa9e4066Sahrens if (uid == zacep[i].a_who) { 1322fa9e4066Sahrens access_deny = zfs_ace_access(&zacep[i], 1323fa9e4066Sahrens mode_wanted, working_mode); 1324fa9e4066Sahrens } 1325fa9e4066Sahrens break; 1326fa9e4066Sahrens } 1327fa9e4066Sahrens zfs_acl_free(aclp); 1328fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 1329fa9e4066Sahrens return (EIO); 1330fa9e4066Sahrens } 1331fa9e4066Sahrens 1332fa9e4066Sahrens if (access_deny != ACCESS_UNDETERMINED) 1333fa9e4066Sahrens break; 1334fa9e4066Sahrens 1335fa9e4066Sahrens } 1336fa9e4066Sahrens 1337fa9e4066Sahrens mutex_exit(&zp->z_acl_lock); 1338fa9e4066Sahrens zfs_acl_free(aclp); 1339fa9e4066Sahrens 1340fa9e4066Sahrens return (access_deny); 1341fa9e4066Sahrens } 1342fa9e4066Sahrens 1343fa9e4066Sahrens 1344fa9e4066Sahrens /* 1345fa9e4066Sahrens * Determine whether Access should be granted/denied, invoking least 1346fa9e4066Sahrens * priv subsytem when a deny is determined. 1347fa9e4066Sahrens */ 1348fa9e4066Sahrens int 1349fa9e4066Sahrens zfs_zaccess(znode_t *zp, int mode, cred_t *cr) 1350fa9e4066Sahrens { 1351fa9e4066Sahrens int working_mode = 0; 1352fa9e4066Sahrens int error; 1353fa9e4066Sahrens int is_attr; 1354fa9e4066Sahrens znode_t *xzp; 1355fa9e4066Sahrens znode_t *check_zp = zp; 1356fa9e4066Sahrens 1357fa9e4066Sahrens is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) && 1358fa9e4066Sahrens (ZTOV(zp)->v_type == VDIR)); 1359fa9e4066Sahrens 1360fa9e4066Sahrens /* 1361fa9e4066Sahrens * If attribute then validate against base file 1362fa9e4066Sahrens */ 1363fa9e4066Sahrens if (is_attr) { 1364fa9e4066Sahrens if ((error = zfs_zget(zp->z_zfsvfs, 1365fa9e4066Sahrens zp->z_phys->zp_parent, &xzp)) != 0) { 1366fa9e4066Sahrens return (error); 1367fa9e4066Sahrens } 1368fa9e4066Sahrens check_zp = xzp; 1369fa9e4066Sahrens /* 1370fa9e4066Sahrens * fixup mode to map to xattr perms 1371fa9e4066Sahrens */ 1372fa9e4066Sahrens 1373fa9e4066Sahrens if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 1374fa9e4066Sahrens mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 1375fa9e4066Sahrens mode |= ACE_WRITE_NAMED_ATTRS; 1376fa9e4066Sahrens } 1377fa9e4066Sahrens 1378fa9e4066Sahrens if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 1379fa9e4066Sahrens mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 1380fa9e4066Sahrens mode |= ACE_READ_NAMED_ATTRS; 1381fa9e4066Sahrens } 1382fa9e4066Sahrens } 1383fa9e4066Sahrens 1384fa9e4066Sahrens error = zfs_zaccess_common(check_zp, mode, &working_mode, cr); 1385fa9e4066Sahrens 1386fa9e4066Sahrens if (error == EROFS) { 1387fa9e4066Sahrens if (is_attr) 1388fa9e4066Sahrens VN_RELE(ZTOV(xzp)); 1389fa9e4066Sahrens return (error); 1390fa9e4066Sahrens } 1391fa9e4066Sahrens 1392fa9e4066Sahrens if (error || (working_mode != mode)) { 1393fa9e4066Sahrens error = secpolicy_vnode_access(cr, ZTOV(check_zp), 1394fa9e4066Sahrens check_zp->z_phys->zp_uid, ~zfs_v4_to_unix(working_mode)); 1395fa9e4066Sahrens } 1396fa9e4066Sahrens 1397fa9e4066Sahrens if (is_attr) 1398fa9e4066Sahrens VN_RELE(ZTOV(xzp)); 1399fa9e4066Sahrens 1400fa9e4066Sahrens return (error); 1401fa9e4066Sahrens } 1402fa9e4066Sahrens 1403fa9e4066Sahrens /* 1404fa9e4066Sahrens * Special zaccess function to check for special nfsv4 perm. 1405fa9e4066Sahrens * doesn't call secpolicy_vnode_access() for failure, since that 1406fa9e4066Sahrens * would probably be the wrong policy function to call. 1407fa9e4066Sahrens * instead its up to the caller to handle that situation. 1408fa9e4066Sahrens */ 1409fa9e4066Sahrens 1410fa9e4066Sahrens int 1411fa9e4066Sahrens zfs_zaccess_v4_perm(znode_t *zp, int mode, cred_t *cr) 1412fa9e4066Sahrens { 1413fa9e4066Sahrens int working_mode = 0; 1414fa9e4066Sahrens return (zfs_zaccess_common(zp, mode, &working_mode, cr)); 1415fa9e4066Sahrens } 1416fa9e4066Sahrens 1417fa9e4066Sahrens /* 1418fa9e4066Sahrens * Translate tradition unix VREAD/VWRITE/VEXEC mode into 1419fa9e4066Sahrens * native ACL format and call zfs_zaccess() 1420fa9e4066Sahrens */ 1421fa9e4066Sahrens int 1422fa9e4066Sahrens zfs_zaccess_rwx(znode_t *zp, mode_t mode, cred_t *cr) 1423fa9e4066Sahrens { 1424fa9e4066Sahrens int v4_mode = zfs_unix_to_v4(mode >> 6); 1425fa9e4066Sahrens 1426fa9e4066Sahrens return (zfs_zaccess(zp, v4_mode, cr)); 1427fa9e4066Sahrens } 1428fa9e4066Sahrens 1429fa9e4066Sahrens /* 1430fa9e4066Sahrens * Determine whether Access should be granted/deny, without 1431fa9e4066Sahrens * consulting least priv subsystem. 1432fa9e4066Sahrens * 1433fa9e4066Sahrens * 1434fa9e4066Sahrens * The following chart is the recommended NFSv4 enforcement for 1435fa9e4066Sahrens * ability to delete an object. 1436fa9e4066Sahrens * 1437fa9e4066Sahrens * ------------------------------------------------------- 1438fa9e4066Sahrens * | Parent Dir | Target Object Permissions | 1439fa9e4066Sahrens * | permissions | | 1440fa9e4066Sahrens * ------------------------------------------------------- 1441fa9e4066Sahrens * | | ACL Allows | ACL Denies| Delete | 1442fa9e4066Sahrens * | | Delete | Delete | unspecified| 1443fa9e4066Sahrens * ------------------------------------------------------- 1444fa9e4066Sahrens * | ACL Allows | Permit | Permit | Permit | 1445fa9e4066Sahrens * | DELETE_CHILD | | 1446fa9e4066Sahrens * ------------------------------------------------------- 1447fa9e4066Sahrens * | ACL Denies | Permit | Deny | Deny | 1448fa9e4066Sahrens * | DELETE_CHILD | | | | 1449fa9e4066Sahrens * ------------------------------------------------------- 1450fa9e4066Sahrens * | ACL specifies | | | | 1451fa9e4066Sahrens * | only allow | Permit | Permit | Permit | 1452fa9e4066Sahrens * | write and | | | | 1453fa9e4066Sahrens * | execute | | | | 1454fa9e4066Sahrens * ------------------------------------------------------- 1455fa9e4066Sahrens * | ACL denies | | | | 1456fa9e4066Sahrens * | write and | Permit | Deny | Deny | 1457fa9e4066Sahrens * | execute | | | | 1458fa9e4066Sahrens * ------------------------------------------------------- 1459fa9e4066Sahrens * ^ 1460fa9e4066Sahrens * | 1461fa9e4066Sahrens * No search privilege, can't even look up file? 1462fa9e4066Sahrens * 1463fa9e4066Sahrens */ 1464fa9e4066Sahrens int 1465fa9e4066Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) 1466fa9e4066Sahrens { 1467fa9e4066Sahrens int dzp_working_mode = 0; 1468fa9e4066Sahrens int zp_working_mode = 0; 1469fa9e4066Sahrens int dzp_error, zp_error; 147084c5a155Smarks int error; 1471fa9e4066Sahrens 1472fa9e4066Sahrens /* 1473fa9e4066Sahrens * Arghh, this check is going to require a couple of questions 1474fa9e4066Sahrens * to be asked. We want specific DELETE permissions to 1475fa9e4066Sahrens * take precedence over WRITE/EXECUTE. We don't 1476fa9e4066Sahrens * want an ACL such as this to mess us up. 1477fa9e4066Sahrens * user:sloar:write_data:deny,user:sloar:delete:allow 1478fa9e4066Sahrens * 1479fa9e4066Sahrens * However, deny permissions may ultimately be overridden 1480fa9e4066Sahrens * by secpolicy_vnode_access(). 1481fa9e4066Sahrens */ 1482fa9e4066Sahrens 1483fa9e4066Sahrens dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 1484fa9e4066Sahrens &dzp_working_mode, cr); 1485fa9e4066Sahrens zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, cr); 1486fa9e4066Sahrens 1487fa9e4066Sahrens if (dzp_error == EROFS || zp_error == EROFS) 1488fa9e4066Sahrens return (dzp_error); 1489fa9e4066Sahrens 1490fa9e4066Sahrens /* 1491fa9e4066Sahrens * First handle the first row 1492fa9e4066Sahrens */ 1493fa9e4066Sahrens if (dzp_working_mode & ACE_DELETE_CHILD) 1494fa9e4066Sahrens return (0); 1495fa9e4066Sahrens 1496fa9e4066Sahrens /* 1497fa9e4066Sahrens * Second row 1498fa9e4066Sahrens */ 1499fa9e4066Sahrens 1500fa9e4066Sahrens if (zp_working_mode & ACE_DELETE) 1501fa9e4066Sahrens return (0); 1502fa9e4066Sahrens 1503fa9e4066Sahrens /* 1504fa9e4066Sahrens * Third Row 1505fa9e4066Sahrens */ 1506fa9e4066Sahrens 1507fa9e4066Sahrens dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE, 1508fa9e4066Sahrens &dzp_working_mode, cr); 1509fa9e4066Sahrens 1510fa9e4066Sahrens if (dzp_error == EROFS) 1511fa9e4066Sahrens return (dzp_error); 1512fa9e4066Sahrens 1513fa9e4066Sahrens if (dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) 151484c5a155Smarks goto sticky; 1515fa9e4066Sahrens 1516fa9e4066Sahrens /* 1517fa9e4066Sahrens * Fourth Row 1518fa9e4066Sahrens */ 1519fa9e4066Sahrens 1520fa9e4066Sahrens if (((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0) && 1521fa9e4066Sahrens (zp_working_mode & ACE_DELETE)) 152284c5a155Smarks goto sticky; 152384c5a155Smarks 152484c5a155Smarks error = secpolicy_vnode_access(cr, ZTOV(zp), 152584c5a155Smarks dzp->z_phys->zp_uid, S_IWRITE|S_IEXEC); 152684c5a155Smarks 152784c5a155Smarks if (error) 152884c5a155Smarks return (error); 152984c5a155Smarks 153084c5a155Smarks sticky: 153184c5a155Smarks error = zfs_sticky_remove_access(dzp, zp, cr); 1532fa9e4066Sahrens 153384c5a155Smarks return (error); 1534fa9e4066Sahrens } 1535fa9e4066Sahrens 1536fa9e4066Sahrens int 1537fa9e4066Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 1538fa9e4066Sahrens znode_t *tzp, cred_t *cr) 1539fa9e4066Sahrens { 1540fa9e4066Sahrens int add_perm; 1541fa9e4066Sahrens int error; 1542fa9e4066Sahrens 1543fa9e4066Sahrens add_perm = (ZTOV(szp)->v_type == VDIR) ? 1544fa9e4066Sahrens ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 1545fa9e4066Sahrens 1546fa9e4066Sahrens /* 1547fa9e4066Sahrens * Rename permissions are combination of delete permission + 1548fa9e4066Sahrens * add file/subdir permission. 1549fa9e4066Sahrens */ 1550fa9e4066Sahrens 1551fa9e4066Sahrens /* 1552fa9e4066Sahrens * first make sure we do the delete portion. 1553fa9e4066Sahrens * 1554fa9e4066Sahrens * If that succeeds then check for add_file/add_subdir permissions 1555fa9e4066Sahrens */ 1556fa9e4066Sahrens 1557fa9e4066Sahrens if (error = zfs_zaccess_delete(sdzp, szp, cr)) 1558fa9e4066Sahrens return (error); 1559fa9e4066Sahrens 1560fa9e4066Sahrens /* 1561fa9e4066Sahrens * If we have a tzp, see if we can delete it? 1562fa9e4066Sahrens */ 1563fa9e4066Sahrens if (tzp) { 1564fa9e4066Sahrens if (error = zfs_zaccess_delete(tdzp, tzp, cr)) 1565fa9e4066Sahrens return (error); 1566fa9e4066Sahrens } 1567fa9e4066Sahrens 1568fa9e4066Sahrens /* 1569fa9e4066Sahrens * Now check for add permissions 1570fa9e4066Sahrens */ 157184c5a155Smarks error = zfs_zaccess(tdzp, add_perm, cr); 1572fa9e4066Sahrens 1573fa9e4066Sahrens return (error); 1574fa9e4066Sahrens } 1575