1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 225762Smarks * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #include <sys/types.h> 27789Sahrens #include <sys/param.h> 28789Sahrens #include <sys/time.h> 29789Sahrens #include <sys/systm.h> 30789Sahrens #include <sys/sysmacros.h> 31789Sahrens #include <sys/resource.h> 32789Sahrens #include <sys/vfs.h> 33789Sahrens #include <sys/vnode.h> 345331Samw #include <sys/sid.h> 35789Sahrens #include <sys/file.h> 36789Sahrens #include <sys/stat.h> 37789Sahrens #include <sys/kmem.h> 38789Sahrens #include <sys/cmn_err.h> 39789Sahrens #include <sys/errno.h> 40789Sahrens #include <sys/unistd.h> 411576Smarks #include <sys/sdt.h> 42789Sahrens #include <sys/fs/zfs.h> 43789Sahrens #include <sys/mode.h> 44789Sahrens #include <sys/policy.h> 45789Sahrens #include <sys/zfs_znode.h> 465331Samw #include <sys/zfs_fuid.h> 47789Sahrens #include <sys/zfs_acl.h> 48789Sahrens #include <sys/zfs_dir.h> 49789Sahrens #include <sys/zfs_vfsops.h> 50789Sahrens #include <sys/dmu.h> 515331Samw #include <sys/dnode.h> 52789Sahrens #include <sys/zap.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 585331Samw #define MAX_ACE_TYPE ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 597559SMark.Shellenbaum@Sun.COM #define MIN_ACE_TYPE ALLOW 60789Sahrens 61789Sahrens #define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 62789Sahrens #define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 63789Sahrens ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 64789Sahrens #define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 65789Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 66789Sahrens #define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 67789Sahrens ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 685331Samw #define WRITE_MASK_DATA (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS) 695331Samw 705331Samw #define ZFS_CHECKED_MASKS (ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_DATA| \ 715331Samw ACE_READ_NAMED_ATTRS|ACE_WRITE_DATA|ACE_WRITE_ATTRIBUTES| \ 725331Samw ACE_WRITE_NAMED_ATTRS|ACE_APPEND_DATA|ACE_EXECUTE|ACE_WRITE_OWNER| \ 735331Samw ACE_WRITE_ACL|ACE_DELETE|ACE_DELETE_CHILD|ACE_SYNCHRONIZE) 745331Samw 755331Samw #define WRITE_MASK (WRITE_MASK_DATA|ACE_WRITE_ATTRIBUTES|ACE_WRITE_ACL|\ 767057Smarks ACE_WRITE_OWNER|ACE_DELETE|ACE_DELETE_CHILD) 77789Sahrens 78789Sahrens #define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 79789Sahrens ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 80789Sahrens 81789Sahrens #define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 82789Sahrens ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 83789Sahrens 84789Sahrens #define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 855331Samw ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE) 86789Sahrens 876385Smarks #define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) 88789Sahrens 895331Samw #define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\ 905331Samw ZFS_ACL_PROTECTED) 915331Samw 925331Samw #define ZFS_ACL_WIDE_FLAGS (V4_ACL_WIDE_FLAGS|ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|\ 935331Samw ZFS_ACL_OBJ_ACE) 945331Samw 955331Samw static uint16_t 965331Samw zfs_ace_v0_get_type(void *acep) 975331Samw { 985331Samw return (((zfs_oldace_t *)acep)->z_type); 995331Samw } 1005331Samw 1015331Samw static uint16_t 1025331Samw zfs_ace_v0_get_flags(void *acep) 1035331Samw { 1045331Samw return (((zfs_oldace_t *)acep)->z_flags); 1055331Samw } 1065331Samw 1075331Samw static uint32_t 1085331Samw zfs_ace_v0_get_mask(void *acep) 1095331Samw { 1105331Samw return (((zfs_oldace_t *)acep)->z_access_mask); 1115331Samw } 1125331Samw 1135331Samw static uint64_t 1145331Samw zfs_ace_v0_get_who(void *acep) 1155331Samw { 1165331Samw return (((zfs_oldace_t *)acep)->z_fuid); 1175331Samw } 1185331Samw 1195331Samw static void 1205331Samw zfs_ace_v0_set_type(void *acep, uint16_t type) 1215331Samw { 1225331Samw ((zfs_oldace_t *)acep)->z_type = type; 1235331Samw } 1245331Samw 1255331Samw static void 1265331Samw zfs_ace_v0_set_flags(void *acep, uint16_t flags) 1275331Samw { 1285331Samw ((zfs_oldace_t *)acep)->z_flags = flags; 1295331Samw } 1305331Samw 1315331Samw static void 1325331Samw zfs_ace_v0_set_mask(void *acep, uint32_t mask) 1335331Samw { 1345331Samw ((zfs_oldace_t *)acep)->z_access_mask = mask; 1355331Samw } 1365331Samw 1375331Samw static void 1385331Samw zfs_ace_v0_set_who(void *acep, uint64_t who) 1395331Samw { 1405331Samw ((zfs_oldace_t *)acep)->z_fuid = who; 1415331Samw } 1425331Samw 1435331Samw /*ARGSUSED*/ 1445331Samw static size_t 1455331Samw zfs_ace_v0_size(void *acep) 1465331Samw { 1475331Samw return (sizeof (zfs_oldace_t)); 1485331Samw } 1495331Samw 1505331Samw static size_t 1515331Samw zfs_ace_v0_abstract_size(void) 1525331Samw { 1535331Samw return (sizeof (zfs_oldace_t)); 1545331Samw } 1555331Samw 1565331Samw static int 1575331Samw zfs_ace_v0_mask_off(void) 1585331Samw { 1595331Samw return (offsetof(zfs_oldace_t, z_access_mask)); 1605331Samw } 1615331Samw 1625331Samw /*ARGSUSED*/ 1635331Samw static int 1645331Samw zfs_ace_v0_data(void *acep, void **datap) 1655331Samw { 1665331Samw *datap = NULL; 1675331Samw return (0); 1685331Samw } 1695331Samw 1705331Samw static acl_ops_t zfs_acl_v0_ops = { 1715331Samw zfs_ace_v0_get_mask, 1725331Samw zfs_ace_v0_set_mask, 1735331Samw zfs_ace_v0_get_flags, 1745331Samw zfs_ace_v0_set_flags, 1755331Samw zfs_ace_v0_get_type, 1765331Samw zfs_ace_v0_set_type, 1775331Samw zfs_ace_v0_get_who, 1785331Samw zfs_ace_v0_set_who, 1795331Samw zfs_ace_v0_size, 1805331Samw zfs_ace_v0_abstract_size, 1815331Samw zfs_ace_v0_mask_off, 1825331Samw zfs_ace_v0_data 1835331Samw }; 1845331Samw 1855331Samw static uint16_t 1865331Samw zfs_ace_fuid_get_type(void *acep) 1875331Samw { 1885331Samw return (((zfs_ace_hdr_t *)acep)->z_type); 1895331Samw } 1905331Samw 1915331Samw static uint16_t 1925331Samw zfs_ace_fuid_get_flags(void *acep) 1935331Samw { 1945331Samw return (((zfs_ace_hdr_t *)acep)->z_flags); 1955331Samw } 1965331Samw 1975331Samw static uint32_t 1985331Samw zfs_ace_fuid_get_mask(void *acep) 1995331Samw { 2005331Samw return (((zfs_ace_hdr_t *)acep)->z_access_mask); 2015331Samw } 2025331Samw 2035331Samw static uint64_t 2045331Samw zfs_ace_fuid_get_who(void *args) 2055331Samw { 2065331Samw uint16_t entry_type; 2075331Samw zfs_ace_t *acep = args; 2085331Samw 2095331Samw entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 210789Sahrens 2115331Samw if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 2125331Samw entry_type == ACE_EVERYONE) 2135331Samw return (-1); 2145331Samw return (((zfs_ace_t *)acep)->z_fuid); 2155331Samw } 2165331Samw 2175331Samw static void 2185331Samw zfs_ace_fuid_set_type(void *acep, uint16_t type) 2195331Samw { 2205331Samw ((zfs_ace_hdr_t *)acep)->z_type = type; 2215331Samw } 2225331Samw 2235331Samw static void 2245331Samw zfs_ace_fuid_set_flags(void *acep, uint16_t flags) 2255331Samw { 2265331Samw ((zfs_ace_hdr_t *)acep)->z_flags = flags; 2275331Samw } 2285331Samw 2295331Samw static void 2305331Samw zfs_ace_fuid_set_mask(void *acep, uint32_t mask) 2315331Samw { 2325331Samw ((zfs_ace_hdr_t *)acep)->z_access_mask = mask; 2335331Samw } 2345331Samw 2355331Samw static void 2365331Samw zfs_ace_fuid_set_who(void *arg, uint64_t who) 2375331Samw { 2385331Samw zfs_ace_t *acep = arg; 2395331Samw 2405331Samw uint16_t entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 2415331Samw 2425331Samw if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 2435331Samw entry_type == ACE_EVERYONE) 2445331Samw return; 2455331Samw acep->z_fuid = who; 2465331Samw } 2475331Samw 2485331Samw static size_t 2495331Samw zfs_ace_fuid_size(void *acep) 2505331Samw { 2515331Samw zfs_ace_hdr_t *zacep = acep; 2525331Samw uint16_t entry_type; 2535331Samw 2545331Samw switch (zacep->z_type) { 2555331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 2565331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 2575331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 2585331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 2595331Samw return (sizeof (zfs_object_ace_t)); 2605331Samw case ALLOW: 2615331Samw case DENY: 2625331Samw entry_type = 2635331Samw (((zfs_ace_hdr_t *)acep)->z_flags & ACE_TYPE_FLAGS); 2645331Samw if (entry_type == ACE_OWNER || 2657328SMark.Shellenbaum@Sun.COM entry_type == OWNING_GROUP || 2665331Samw entry_type == ACE_EVERYONE) 2675331Samw return (sizeof (zfs_ace_hdr_t)); 2685331Samw /*FALLTHROUGH*/ 2695331Samw default: 2705331Samw return (sizeof (zfs_ace_t)); 2715331Samw } 2725331Samw } 2735331Samw 2745331Samw static size_t 2755331Samw zfs_ace_fuid_abstract_size(void) 2765331Samw { 2775331Samw return (sizeof (zfs_ace_hdr_t)); 2785331Samw } 2795331Samw 2805331Samw static int 2815331Samw zfs_ace_fuid_mask_off(void) 2825331Samw { 2835331Samw return (offsetof(zfs_ace_hdr_t, z_access_mask)); 2845331Samw } 2855331Samw 2865331Samw static int 2875331Samw zfs_ace_fuid_data(void *acep, void **datap) 2885331Samw { 2895331Samw zfs_ace_t *zacep = acep; 2905331Samw zfs_object_ace_t *zobjp; 2915331Samw 2925331Samw switch (zacep->z_hdr.z_type) { 2935331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 2945331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 2955331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 2965331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 2975331Samw zobjp = acep; 2985331Samw *datap = (caddr_t)zobjp + sizeof (zfs_ace_t); 2995331Samw return (sizeof (zfs_object_ace_t) - sizeof (zfs_ace_t)); 3005331Samw default: 3015331Samw *datap = NULL; 3025331Samw return (0); 3035331Samw } 3045331Samw } 3055331Samw 3065331Samw static acl_ops_t zfs_acl_fuid_ops = { 3075331Samw zfs_ace_fuid_get_mask, 3085331Samw zfs_ace_fuid_set_mask, 3095331Samw zfs_ace_fuid_get_flags, 3105331Samw zfs_ace_fuid_set_flags, 3115331Samw zfs_ace_fuid_get_type, 3125331Samw zfs_ace_fuid_set_type, 3135331Samw zfs_ace_fuid_get_who, 3145331Samw zfs_ace_fuid_set_who, 3155331Samw zfs_ace_fuid_size, 3165331Samw zfs_ace_fuid_abstract_size, 3175331Samw zfs_ace_fuid_mask_off, 3185331Samw zfs_ace_fuid_data 3195331Samw }; 3205331Samw 3215331Samw static int 3225331Samw zfs_acl_version(int version) 3235331Samw { 3245331Samw if (version < ZPL_VERSION_FUID) 3255331Samw return (ZFS_ACL_VERSION_INITIAL); 3265331Samw else 3275331Samw return (ZFS_ACL_VERSION_FUID); 3285331Samw } 3295331Samw 3305331Samw static int 3315331Samw zfs_acl_version_zp(znode_t *zp) 3325331Samw { 3335331Samw return (zfs_acl_version(zp->z_zfsvfs->z_version)); 3345331Samw } 335789Sahrens 336789Sahrens static zfs_acl_t * 3375331Samw zfs_acl_alloc(int vers) 338789Sahrens { 339789Sahrens zfs_acl_t *aclp; 340789Sahrens 341789Sahrens aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 3425331Samw list_create(&aclp->z_acl, sizeof (zfs_acl_node_t), 3435331Samw offsetof(zfs_acl_node_t, z_next)); 3445331Samw aclp->z_version = vers; 3455331Samw if (vers == ZFS_ACL_VERSION_FUID) 3465331Samw aclp->z_ops = zfs_acl_fuid_ops; 3475331Samw else 3485331Samw aclp->z_ops = zfs_acl_v0_ops; 3495331Samw return (aclp); 3505331Samw } 3515331Samw 3525331Samw static zfs_acl_node_t * 3535331Samw zfs_acl_node_alloc(size_t bytes) 3545331Samw { 3555331Samw zfs_acl_node_t *aclnode; 3565331Samw 3575331Samw aclnode = kmem_zalloc(sizeof (zfs_acl_node_t), KM_SLEEP); 3585331Samw if (bytes) { 3595331Samw aclnode->z_acldata = kmem_alloc(bytes, KM_SLEEP); 3605331Samw aclnode->z_allocdata = aclnode->z_acldata; 3615331Samw aclnode->z_allocsize = bytes; 3625331Samw aclnode->z_size = bytes; 363789Sahrens } 3645331Samw 3655331Samw return (aclnode); 3665331Samw } 3675331Samw 3685331Samw static void 3695331Samw zfs_acl_node_free(zfs_acl_node_t *aclnode) 3705331Samw { 3715331Samw if (aclnode->z_allocsize) 3725331Samw kmem_free(aclnode->z_allocdata, aclnode->z_allocsize); 3735331Samw kmem_free(aclnode, sizeof (zfs_acl_node_t)); 374789Sahrens } 375789Sahrens 3765489Smarks static void 3775489Smarks zfs_acl_release_nodes(zfs_acl_t *aclp) 378789Sahrens { 3795331Samw zfs_acl_node_t *aclnode; 3805331Samw 3815331Samw while (aclnode = list_head(&aclp->z_acl)) { 3825331Samw list_remove(&aclp->z_acl, aclnode); 3835331Samw zfs_acl_node_free(aclnode); 384789Sahrens } 3855489Smarks aclp->z_acl_count = 0; 3865489Smarks aclp->z_acl_bytes = 0; 3875489Smarks } 3885331Samw 3895489Smarks void 3905489Smarks zfs_acl_free(zfs_acl_t *aclp) 3915489Smarks { 3925489Smarks zfs_acl_release_nodes(aclp); 3935331Samw list_destroy(&aclp->z_acl); 394789Sahrens kmem_free(aclp, sizeof (zfs_acl_t)); 395789Sahrens } 396789Sahrens 3975331Samw static boolean_t 3987559SMark.Shellenbaum@Sun.COM zfs_acl_valid_ace_type(uint_t type, uint_t flags) 3997559SMark.Shellenbaum@Sun.COM { 4007559SMark.Shellenbaum@Sun.COM uint16_t entry_type; 4017559SMark.Shellenbaum@Sun.COM 4027559SMark.Shellenbaum@Sun.COM switch (type) { 4037559SMark.Shellenbaum@Sun.COM case ALLOW: 4047559SMark.Shellenbaum@Sun.COM case DENY: 4057559SMark.Shellenbaum@Sun.COM case ACE_SYSTEM_AUDIT_ACE_TYPE: 4067559SMark.Shellenbaum@Sun.COM case ACE_SYSTEM_ALARM_ACE_TYPE: 4077559SMark.Shellenbaum@Sun.COM entry_type = flags & ACE_TYPE_FLAGS; 4087559SMark.Shellenbaum@Sun.COM return (entry_type == ACE_OWNER || 4097559SMark.Shellenbaum@Sun.COM entry_type == OWNING_GROUP || 4107559SMark.Shellenbaum@Sun.COM entry_type == ACE_EVERYONE || entry_type == 0 || 4117559SMark.Shellenbaum@Sun.COM entry_type == ACE_IDENTIFIER_GROUP); 4127559SMark.Shellenbaum@Sun.COM default: 4137559SMark.Shellenbaum@Sun.COM if (type >= MIN_ACE_TYPE && type <= MAX_ACE_TYPE) 4147559SMark.Shellenbaum@Sun.COM return (B_TRUE); 4157559SMark.Shellenbaum@Sun.COM } 4167559SMark.Shellenbaum@Sun.COM return (B_FALSE); 4177559SMark.Shellenbaum@Sun.COM } 4187559SMark.Shellenbaum@Sun.COM 4197559SMark.Shellenbaum@Sun.COM static boolean_t 4205331Samw zfs_ace_valid(vtype_t obj_type, zfs_acl_t *aclp, uint16_t type, uint16_t iflags) 421789Sahrens { 4225331Samw /* 4235331Samw * first check type of entry 4245331Samw */ 4255331Samw 4267559SMark.Shellenbaum@Sun.COM if (!zfs_acl_valid_ace_type(type, iflags)) 4275331Samw return (B_FALSE); 4285331Samw 4295331Samw switch (type) { 4305331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 4315331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 4325331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 4335331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 4345331Samw if (aclp->z_version < ZFS_ACL_VERSION_FUID) 4355331Samw return (B_FALSE); 4365331Samw aclp->z_hints |= ZFS_ACL_OBJ_ACE; 4375331Samw } 438789Sahrens 4397559SMark.Shellenbaum@Sun.COM /* 4407559SMark.Shellenbaum@Sun.COM * next check inheritance level flags 4417559SMark.Shellenbaum@Sun.COM */ 4427559SMark.Shellenbaum@Sun.COM 4437057Smarks if (obj_type == VDIR && 4447057Smarks (iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 4455331Samw aclp->z_hints |= ZFS_INHERIT_ACE; 4465331Samw 4475331Samw if (iflags & (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 4485331Samw if ((iflags & (ACE_FILE_INHERIT_ACE| 4495331Samw ACE_DIRECTORY_INHERIT_ACE)) == 0) { 4505331Samw return (B_FALSE); 4515331Samw } 4525331Samw } 4535331Samw 4545331Samw return (B_TRUE); 4555331Samw } 4565331Samw 4575331Samw static void * 4585331Samw zfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who, 4595331Samw uint32_t *access_mask, uint16_t *iflags, uint16_t *type) 4605331Samw { 4615331Samw zfs_acl_node_t *aclnode; 4625331Samw 4635331Samw if (start == NULL) { 4645331Samw aclnode = list_head(&aclp->z_acl); 4655331Samw if (aclnode == NULL) 4665331Samw return (NULL); 4675331Samw 4685331Samw aclp->z_next_ace = aclnode->z_acldata; 4695331Samw aclp->z_curr_node = aclnode; 4705331Samw aclnode->z_ace_idx = 0; 4715331Samw } 4725331Samw 4735331Samw aclnode = aclp->z_curr_node; 4745331Samw 4755331Samw if (aclnode == NULL) 4765331Samw return (NULL); 4775331Samw 4785331Samw if (aclnode->z_ace_idx >= aclnode->z_ace_count) { 4795331Samw aclnode = list_next(&aclp->z_acl, aclnode); 4805331Samw if (aclnode == NULL) 4815331Samw return (NULL); 4825331Samw else { 4835331Samw aclp->z_curr_node = aclnode; 4845331Samw aclnode->z_ace_idx = 0; 4855331Samw aclp->z_next_ace = aclnode->z_acldata; 4865331Samw } 4875331Samw } 4885331Samw 4895331Samw if (aclnode->z_ace_idx < aclnode->z_ace_count) { 4905331Samw void *acep = aclp->z_next_ace; 4917559SMark.Shellenbaum@Sun.COM size_t ace_size; 4927559SMark.Shellenbaum@Sun.COM 4937559SMark.Shellenbaum@Sun.COM /* 4947559SMark.Shellenbaum@Sun.COM * Make sure we don't overstep our bounds 4957559SMark.Shellenbaum@Sun.COM */ 4967559SMark.Shellenbaum@Sun.COM ace_size = aclp->z_ops.ace_size(acep); 4977559SMark.Shellenbaum@Sun.COM 4987559SMark.Shellenbaum@Sun.COM if (((caddr_t)acep + ace_size) > 4997559SMark.Shellenbaum@Sun.COM ((caddr_t)aclnode->z_acldata + aclnode->z_size)) { 5007559SMark.Shellenbaum@Sun.COM return (NULL); 5017559SMark.Shellenbaum@Sun.COM } 5027559SMark.Shellenbaum@Sun.COM 5035331Samw *iflags = aclp->z_ops.ace_flags_get(acep); 5045331Samw *type = aclp->z_ops.ace_type_get(acep); 5055331Samw *access_mask = aclp->z_ops.ace_mask_get(acep); 5065331Samw *who = aclp->z_ops.ace_who_get(acep); 5077559SMark.Shellenbaum@Sun.COM aclp->z_next_ace = (caddr_t)aclp->z_next_ace + ace_size; 5085331Samw aclnode->z_ace_idx++; 5095331Samw return ((void *)acep); 5105331Samw } 5115331Samw return (NULL); 5125331Samw } 5135331Samw 5145331Samw /*ARGSUSED*/ 5155331Samw static uint64_t 5165331Samw zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt, 5175331Samw uint16_t *flags, uint16_t *type, uint32_t *mask) 5185331Samw { 5195331Samw zfs_acl_t *aclp = datap; 5205331Samw zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)(uintptr_t)cookie; 5215331Samw uint64_t who; 5225331Samw 5235331Samw acep = zfs_acl_next_ace(aclp, acep, &who, mask, 5245331Samw flags, type); 5255331Samw return ((uint64_t)(uintptr_t)acep); 5265331Samw } 5275331Samw 5285331Samw static zfs_acl_node_t * 5295331Samw zfs_acl_curr_node(zfs_acl_t *aclp) 5305331Samw { 5315331Samw ASSERT(aclp->z_curr_node); 5325331Samw return (aclp->z_curr_node); 5335331Samw } 5345331Samw 5355331Samw /* 5365331Samw * Copy ACE to internal ZFS format. 5375331Samw * While processing the ACL each ACE will be validated for correctness. 5385331Samw * ACE FUIDs will be created later. 5395331Samw */ 5405331Samw int 5415331Samw zfs_copy_ace_2_fuid(vtype_t obj_type, zfs_acl_t *aclp, void *datap, 5425331Samw zfs_ace_t *z_acl, int aclcnt, size_t *size) 5435331Samw { 5445331Samw int i; 5455331Samw uint16_t entry_type; 5465331Samw zfs_ace_t *aceptr = z_acl; 5475331Samw ace_t *acep = datap; 5485331Samw zfs_object_ace_t *zobjacep; 5495331Samw ace_object_t *aceobjp; 5505331Samw 5515331Samw for (i = 0; i != aclcnt; i++) { 5525331Samw aceptr->z_hdr.z_access_mask = acep->a_access_mask; 5535331Samw aceptr->z_hdr.z_flags = acep->a_flags; 5545331Samw aceptr->z_hdr.z_type = acep->a_type; 5555331Samw entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS; 5565331Samw if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP && 5575824Smarks entry_type != ACE_EVERYONE) { 5585824Smarks if (!aclp->z_has_fuids) 5595959Smarks aclp->z_has_fuids = IS_EPHEMERAL(acep->a_who); 5605331Samw aceptr->z_fuid = (uint64_t)acep->a_who; 5615824Smarks } 5625824Smarks 5635331Samw /* 5645331Samw * Make sure ACE is valid 5655331Samw */ 5665331Samw if (zfs_ace_valid(obj_type, aclp, aceptr->z_hdr.z_type, 5675331Samw aceptr->z_hdr.z_flags) != B_TRUE) 5685331Samw return (EINVAL); 5695331Samw 5705331Samw switch (acep->a_type) { 5715331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 5725331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 5735331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 5745331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 5755331Samw zobjacep = (zfs_object_ace_t *)aceptr; 5765331Samw aceobjp = (ace_object_t *)acep; 5775331Samw 5785331Samw bcopy(aceobjp->a_obj_type, zobjacep->z_object_type, 5795331Samw sizeof (aceobjp->a_obj_type)); 5805331Samw bcopy(aceobjp->a_inherit_obj_type, 5815331Samw zobjacep->z_inherit_type, 5825331Samw sizeof (aceobjp->a_inherit_obj_type)); 5835331Samw acep = (ace_t *)((caddr_t)acep + sizeof (ace_object_t)); 5845331Samw break; 5855331Samw default: 5865331Samw acep = (ace_t *)((caddr_t)acep + sizeof (ace_t)); 5875331Samw } 5885331Samw 5895331Samw aceptr = (zfs_ace_t *)((caddr_t)aceptr + 5905331Samw aclp->z_ops.ace_size(aceptr)); 5915331Samw } 5925331Samw 5935331Samw *size = (caddr_t)aceptr - (caddr_t)z_acl; 594789Sahrens 5955331Samw return (0); 5965331Samw } 5975331Samw 5985331Samw /* 5995331Samw * Copy ZFS ACEs to fixed size ace_t layout 6005331Samw */ 6015331Samw static void 6025771Sjp151216 zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr, 6035771Sjp151216 void *datap, int filter) 6045331Samw { 6055331Samw uint64_t who; 6065331Samw uint32_t access_mask; 6075331Samw uint16_t iflags, type; 6085331Samw zfs_ace_hdr_t *zacep = NULL; 6095331Samw ace_t *acep = datap; 6105331Samw ace_object_t *objacep; 6115331Samw zfs_object_ace_t *zobjacep; 6125331Samw size_t ace_size; 6135331Samw uint16_t entry_type; 6145331Samw 6155331Samw while (zacep = zfs_acl_next_ace(aclp, zacep, 6165331Samw &who, &access_mask, &iflags, &type)) { 6175331Samw 6185331Samw switch (type) { 6195331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 6205331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 6215331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 6225331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 6235331Samw if (filter) { 6245331Samw continue; 6255331Samw } 6265331Samw zobjacep = (zfs_object_ace_t *)zacep; 6275331Samw objacep = (ace_object_t *)acep; 6285331Samw bcopy(zobjacep->z_object_type, 6295331Samw objacep->a_obj_type, 6305331Samw sizeof (zobjacep->z_object_type)); 6315331Samw bcopy(zobjacep->z_inherit_type, 6325331Samw objacep->a_inherit_obj_type, 6335331Samw sizeof (zobjacep->z_inherit_type)); 6345331Samw ace_size = sizeof (ace_object_t); 6355331Samw break; 6365331Samw default: 6375331Samw ace_size = sizeof (ace_t); 6385331Samw break; 6395331Samw } 6405331Samw 6415331Samw entry_type = (iflags & ACE_TYPE_FLAGS); 6425331Samw if ((entry_type != ACE_OWNER && 6437328SMark.Shellenbaum@Sun.COM entry_type != OWNING_GROUP && 6445959Smarks entry_type != ACE_EVERYONE)) { 6455959Smarks acep->a_who = zfs_fuid_map_id(zfsvfs, who, 6465959Smarks cr, (entry_type & ACE_IDENTIFIER_GROUP) ? 6475959Smarks ZFS_ACE_GROUP : ZFS_ACE_USER); 6485959Smarks } else { 6495331Samw acep->a_who = (uid_t)(int64_t)who; 6505959Smarks } 6515331Samw acep->a_access_mask = access_mask; 6525331Samw acep->a_flags = iflags; 6535331Samw acep->a_type = type; 6545331Samw acep = (ace_t *)((caddr_t)acep + ace_size); 6555331Samw } 6565331Samw } 6575331Samw 6585331Samw static int 6595331Samw zfs_copy_ace_2_oldace(vtype_t obj_type, zfs_acl_t *aclp, ace_t *acep, 6605331Samw zfs_oldace_t *z_acl, int aclcnt, size_t *size) 6615331Samw { 6625331Samw int i; 6635331Samw zfs_oldace_t *aceptr = z_acl; 6645331Samw 6655331Samw for (i = 0; i != aclcnt; i++, aceptr++) { 6665331Samw aceptr->z_access_mask = acep[i].a_access_mask; 6675331Samw aceptr->z_type = acep[i].a_type; 6685331Samw aceptr->z_flags = acep[i].a_flags; 6695331Samw aceptr->z_fuid = acep[i].a_who; 6705331Samw /* 6715331Samw * Make sure ACE is valid 6725331Samw */ 6735331Samw if (zfs_ace_valid(obj_type, aclp, aceptr->z_type, 6745331Samw aceptr->z_flags) != B_TRUE) 6755331Samw return (EINVAL); 6765331Samw } 6775331Samw *size = (caddr_t)aceptr - (caddr_t)z_acl; 6785331Samw return (0); 6795331Samw } 6805331Samw 6815331Samw /* 6825331Samw * convert old ACL format to new 6835331Samw */ 6845331Samw void 6855331Samw zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp) 6865331Samw { 6875331Samw zfs_oldace_t *oldaclp; 6885331Samw int i; 6895331Samw uint16_t type, iflags; 6905331Samw uint32_t access_mask; 6915331Samw uint64_t who; 6925331Samw void *cookie = NULL; 6935489Smarks zfs_acl_node_t *newaclnode; 6945331Samw 6955331Samw ASSERT(aclp->z_version == ZFS_ACL_VERSION_INITIAL); 6965331Samw /* 6975331Samw * First create the ACE in a contiguous piece of memory 6985331Samw * for zfs_copy_ace_2_fuid(). 6995331Samw * 7005331Samw * We only convert an ACL once, so this won't happen 7015331Samw * everytime. 7025331Samw */ 7035331Samw oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count, 7045331Samw KM_SLEEP); 7055331Samw i = 0; 7065331Samw while (cookie = zfs_acl_next_ace(aclp, cookie, &who, 7075331Samw &access_mask, &iflags, &type)) { 7085331Samw oldaclp[i].z_flags = iflags; 7095331Samw oldaclp[i].z_type = type; 7105331Samw oldaclp[i].z_fuid = who; 7115331Samw oldaclp[i++].z_access_mask = access_mask; 7125331Samw } 7135331Samw 7145331Samw newaclnode = zfs_acl_node_alloc(aclp->z_acl_count * 7155331Samw sizeof (zfs_object_ace_t)); 7165331Samw aclp->z_ops = zfs_acl_fuid_ops; 7175331Samw VERIFY(zfs_copy_ace_2_fuid(ZTOV(zp)->v_type, aclp, oldaclp, 7185331Samw newaclnode->z_acldata, aclp->z_acl_count, 7195331Samw &newaclnode->z_size) == 0); 7205331Samw newaclnode->z_ace_count = aclp->z_acl_count; 7215331Samw aclp->z_version = ZFS_ACL_VERSION; 7225331Samw kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t)); 7235331Samw 7245331Samw /* 7255331Samw * Release all previous ACL nodes 7265331Samw */ 7275331Samw 7285489Smarks zfs_acl_release_nodes(aclp); 7295489Smarks 7305331Samw list_insert_head(&aclp->z_acl, newaclnode); 7315489Smarks 7325489Smarks aclp->z_acl_bytes = newaclnode->z_size; 7335489Smarks aclp->z_acl_count = newaclnode->z_ace_count; 7345489Smarks 735789Sahrens } 736789Sahrens 737789Sahrens /* 738789Sahrens * Convert unix access mask to v4 access mask 739789Sahrens */ 740789Sahrens static uint32_t 741789Sahrens zfs_unix_to_v4(uint32_t access_mask) 742789Sahrens { 743789Sahrens uint32_t new_mask = 0; 744789Sahrens 7455331Samw if (access_mask & S_IXOTH) 7465331Samw new_mask |= ACE_EXECUTE; 7475331Samw if (access_mask & S_IWOTH) 7485331Samw new_mask |= ACE_WRITE_DATA; 7495331Samw if (access_mask & S_IROTH) 750789Sahrens new_mask |= ACE_READ_DATA; 751789Sahrens return (new_mask); 752789Sahrens } 753789Sahrens 754789Sahrens static void 7555331Samw zfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask, 7565331Samw uint16_t access_type, uint64_t fuid, uint16_t entry_type) 757789Sahrens { 7585331Samw uint16_t type = entry_type & ACE_TYPE_FLAGS; 7595331Samw 7605331Samw aclp->z_ops.ace_mask_set(acep, access_mask); 7615331Samw aclp->z_ops.ace_type_set(acep, access_type); 7625331Samw aclp->z_ops.ace_flags_set(acep, entry_type); 7637328SMark.Shellenbaum@Sun.COM if ((type != ACE_OWNER && type != OWNING_GROUP && 7645331Samw type != ACE_EVERYONE)) 7655331Samw aclp->z_ops.ace_who_set(acep, fuid); 766789Sahrens } 767789Sahrens 7685331Samw /* 7695331Samw * Determine mode of file based on ACL. 7705331Samw * Also, create FUIDs for any User/Group ACEs 7715331Samw */ 772789Sahrens static uint64_t 7735771Sjp151216 zfs_mode_fuid_compute(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, 7745771Sjp151216 zfs_fuid_info_t **fuidp, dmu_tx_t *tx) 775789Sahrens { 7765331Samw int entry_type; 7775331Samw mode_t mode; 7785331Samw mode_t seen = 0; 7795331Samw zfs_ace_hdr_t *acep = NULL; 7805331Samw uint64_t who; 7815331Samw uint16_t iflags, type; 7825331Samw uint32_t access_mask; 783789Sahrens 7845331Samw mode = (zp->z_phys->zp_mode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 7855331Samw 7865331Samw while (acep = zfs_acl_next_ace(aclp, acep, &who, 7875331Samw &access_mask, &iflags, &type)) { 7884869Smarks 7897559SMark.Shellenbaum@Sun.COM if (!zfs_acl_valid_ace_type(type, iflags)) 7907559SMark.Shellenbaum@Sun.COM continue; 7917559SMark.Shellenbaum@Sun.COM 7927328SMark.Shellenbaum@Sun.COM entry_type = (iflags & ACE_TYPE_FLAGS); 7937328SMark.Shellenbaum@Sun.COM 7944869Smarks /* 7957328SMark.Shellenbaum@Sun.COM * Skip over owner@, group@ or everyone@ inherit only ACEs 7964869Smarks */ 7977328SMark.Shellenbaum@Sun.COM if ((iflags & ACE_INHERIT_ONLY_ACE) && 7987328SMark.Shellenbaum@Sun.COM (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 7997328SMark.Shellenbaum@Sun.COM entry_type == OWNING_GROUP)) 8004869Smarks continue; 8014869Smarks 802789Sahrens if (entry_type == ACE_OWNER) { 8035331Samw if ((access_mask & ACE_READ_DATA) && 804789Sahrens (!(seen & S_IRUSR))) { 805789Sahrens seen |= S_IRUSR; 8065331Samw if (type == ALLOW) { 807789Sahrens mode |= S_IRUSR; 808789Sahrens } 809789Sahrens } 8105331Samw if ((access_mask & ACE_WRITE_DATA) && 811789Sahrens (!(seen & S_IWUSR))) { 812789Sahrens seen |= S_IWUSR; 8135331Samw if (type == ALLOW) { 814789Sahrens mode |= S_IWUSR; 815789Sahrens } 816789Sahrens } 8175331Samw if ((access_mask & ACE_EXECUTE) && 818789Sahrens (!(seen & S_IXUSR))) { 819789Sahrens seen |= S_IXUSR; 8205331Samw if (type == ALLOW) { 821789Sahrens mode |= S_IXUSR; 822789Sahrens } 823789Sahrens } 824789Sahrens } else if (entry_type == OWNING_GROUP) { 8255331Samw if ((access_mask & ACE_READ_DATA) && 826789Sahrens (!(seen & S_IRGRP))) { 827789Sahrens seen |= S_IRGRP; 8285331Samw if (type == ALLOW) { 829789Sahrens mode |= S_IRGRP; 830789Sahrens } 831789Sahrens } 8325331Samw if ((access_mask & ACE_WRITE_DATA) && 833789Sahrens (!(seen & S_IWGRP))) { 834789Sahrens seen |= S_IWGRP; 8355331Samw if (type == ALLOW) { 836789Sahrens mode |= S_IWGRP; 837789Sahrens } 838789Sahrens } 8395331Samw if ((access_mask & ACE_EXECUTE) && 840789Sahrens (!(seen & S_IXGRP))) { 841789Sahrens seen |= S_IXGRP; 8425331Samw if (type == ALLOW) { 843789Sahrens mode |= S_IXGRP; 844789Sahrens } 845789Sahrens } 846789Sahrens } else if (entry_type == ACE_EVERYONE) { 8475331Samw if ((access_mask & ACE_READ_DATA)) { 848789Sahrens if (!(seen & S_IRUSR)) { 849789Sahrens seen |= S_IRUSR; 8505331Samw if (type == ALLOW) { 851789Sahrens mode |= S_IRUSR; 852789Sahrens } 853789Sahrens } 854789Sahrens if (!(seen & S_IRGRP)) { 855789Sahrens seen |= S_IRGRP; 8565331Samw if (type == ALLOW) { 857789Sahrens mode |= S_IRGRP; 858789Sahrens } 859789Sahrens } 860789Sahrens if (!(seen & S_IROTH)) { 861789Sahrens seen |= S_IROTH; 8625331Samw if (type == ALLOW) { 863789Sahrens mode |= S_IROTH; 864789Sahrens } 865789Sahrens } 866789Sahrens } 8675331Samw if ((access_mask & ACE_WRITE_DATA)) { 868789Sahrens if (!(seen & S_IWUSR)) { 869789Sahrens seen |= S_IWUSR; 8705331Samw if (type == ALLOW) { 871789Sahrens mode |= S_IWUSR; 872789Sahrens } 873789Sahrens } 874789Sahrens if (!(seen & S_IWGRP)) { 875789Sahrens seen |= S_IWGRP; 8765331Samw if (type == ALLOW) { 877789Sahrens mode |= S_IWGRP; 878789Sahrens } 879789Sahrens } 880789Sahrens if (!(seen & S_IWOTH)) { 881789Sahrens seen |= S_IWOTH; 8825331Samw if (type == ALLOW) { 883789Sahrens mode |= S_IWOTH; 884789Sahrens } 885789Sahrens } 886789Sahrens } 8875331Samw if ((access_mask & ACE_EXECUTE)) { 888789Sahrens if (!(seen & S_IXUSR)) { 889789Sahrens seen |= S_IXUSR; 8905331Samw if (type == ALLOW) { 891789Sahrens mode |= S_IXUSR; 892789Sahrens } 893789Sahrens } 894789Sahrens if (!(seen & S_IXGRP)) { 895789Sahrens seen |= S_IXGRP; 8965331Samw if (type == ALLOW) { 897789Sahrens mode |= S_IXGRP; 898789Sahrens } 899789Sahrens } 900789Sahrens if (!(seen & S_IXOTH)) { 901789Sahrens seen |= S_IXOTH; 9025331Samw if (type == ALLOW) { 903789Sahrens mode |= S_IXOTH; 904789Sahrens } 905789Sahrens } 906789Sahrens } 907789Sahrens } 9085331Samw /* 9095331Samw * Now handle FUID create for user/group ACEs 9105331Samw */ 9115331Samw if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) { 9125331Samw aclp->z_ops.ace_who_set(acep, 9135771Sjp151216 zfs_fuid_create(zp->z_zfsvfs, who, cr, 9145959Smarks (entry_type == 0) ? ZFS_ACE_USER : ZFS_ACE_GROUP, 9155959Smarks tx, fuidp)); 9165331Samw } 917789Sahrens } 918789Sahrens return (mode); 919789Sahrens } 920789Sahrens 921789Sahrens static zfs_acl_t * 9225331Samw zfs_acl_node_read_internal(znode_t *zp, boolean_t will_modify) 923789Sahrens { 924789Sahrens zfs_acl_t *aclp; 9255331Samw zfs_acl_node_t *aclnode; 926789Sahrens 9275331Samw aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_version); 9285331Samw 9295331Samw /* 9305331Samw * Version 0 to 1 znode_acl_phys has the size/count fields swapped. 9315331Samw * Version 0 didn't have a size field, only a count. 9325331Samw */ 9335331Samw if (zp->z_phys->zp_acl.z_acl_version == ZFS_ACL_VERSION_INITIAL) { 9345331Samw aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_size; 9355331Samw aclp->z_acl_bytes = ZFS_ACL_SIZE(aclp->z_acl_count); 9365331Samw } else { 9375331Samw aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count; 9385331Samw aclp->z_acl_bytes = zp->z_phys->zp_acl.z_acl_size; 9395331Samw } 9405331Samw 9415331Samw aclnode = zfs_acl_node_alloc(will_modify ? aclp->z_acl_bytes : 0); 9425331Samw aclnode->z_ace_count = aclp->z_acl_count; 9435331Samw if (will_modify) { 9445331Samw bcopy(zp->z_phys->zp_acl.z_ace_data, aclnode->z_acldata, 9455331Samw aclp->z_acl_bytes); 9465331Samw } else { 9475331Samw aclnode->z_size = aclp->z_acl_bytes; 9485331Samw aclnode->z_acldata = &zp->z_phys->zp_acl.z_ace_data[0]; 9495331Samw } 9505331Samw 9515331Samw list_insert_head(&aclp->z_acl, aclnode); 952789Sahrens 953789Sahrens return (aclp); 954789Sahrens } 955789Sahrens 956789Sahrens /* 957789Sahrens * Read an external acl object. 958789Sahrens */ 9591544Seschrock static int 9605331Samw zfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp, boolean_t will_modify) 961789Sahrens { 962789Sahrens uint64_t extacl = zp->z_phys->zp_acl.z_acl_extern_obj; 963789Sahrens zfs_acl_t *aclp; 9645331Samw size_t aclsize; 9655331Samw size_t acl_count; 9665331Samw zfs_acl_node_t *aclnode; 9671544Seschrock int error; 968789Sahrens 969789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 970789Sahrens 9711544Seschrock if (zp->z_phys->zp_acl.z_acl_extern_obj == 0) { 9725331Samw *aclpp = zfs_acl_node_read_internal(zp, will_modify); 9731544Seschrock return (0); 9741544Seschrock } 975789Sahrens 9765331Samw aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_version); 9775331Samw if (zp->z_phys->zp_acl.z_acl_version == ZFS_ACL_VERSION_INITIAL) { 9785331Samw zfs_acl_phys_v0_t *zacl0 = 9795331Samw (zfs_acl_phys_v0_t *)&zp->z_phys->zp_acl; 980789Sahrens 9815331Samw aclsize = ZFS_ACL_SIZE(zacl0->z_acl_count); 9825331Samw acl_count = zacl0->z_acl_count; 9835331Samw } else { 9845331Samw aclsize = zp->z_phys->zp_acl.z_acl_size; 9855331Samw acl_count = zp->z_phys->zp_acl.z_acl_count; 9865331Samw if (aclsize == 0) 9875331Samw aclsize = acl_count * sizeof (zfs_ace_t); 9885331Samw } 9895331Samw aclnode = zfs_acl_node_alloc(aclsize); 9905331Samw list_insert_head(&aclp->z_acl, aclnode); 9911544Seschrock error = dmu_read(zp->z_zfsvfs->z_os, extacl, 0, 9925331Samw aclsize, aclnode->z_acldata); 9935331Samw aclnode->z_ace_count = acl_count; 9945331Samw aclp->z_acl_count = acl_count; 9955331Samw aclp->z_acl_bytes = aclsize; 9965331Samw 9971544Seschrock if (error != 0) { 9981544Seschrock zfs_acl_free(aclp); 9997294Sperrin /* convert checksum errors into IO errors */ 10007294Sperrin if (error == ECKSUM) 10017294Sperrin error = EIO; 10021544Seschrock return (error); 10031544Seschrock } 1004789Sahrens 10051544Seschrock *aclpp = aclp; 10061544Seschrock return (0); 1007789Sahrens } 1008789Sahrens 1009789Sahrens /* 10105331Samw * common code for setting ACLs. 1011789Sahrens * 1012789Sahrens * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 1013789Sahrens * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 1014789Sahrens * already checked the acl and knows whether to inherit. 1015789Sahrens */ 1016789Sahrens int 10175771Sjp151216 zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, 10185771Sjp151216 zfs_fuid_info_t **fuidp, dmu_tx_t *tx) 1019789Sahrens { 1020789Sahrens int error; 1021789Sahrens znode_phys_t *zphys = zp->z_phys; 10225331Samw zfs_acl_phys_t *zacl = &zphys->zp_acl; 1023789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1024789Sahrens uint64_t aoid = zphys->zp_acl.z_acl_extern_obj; 10255331Samw uint64_t off = 0; 10265331Samw dmu_object_type_t otype; 10275331Samw zfs_acl_node_t *aclnode; 1028789Sahrens 1029789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 1030789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1031789Sahrens 10325331Samw dmu_buf_will_dirty(zp->z_dbuf, tx); 1033789Sahrens 10345771Sjp151216 zphys->zp_mode = zfs_mode_fuid_compute(zp, aclp, cr, fuidp, tx); 1035789Sahrens 1036789Sahrens /* 10375331Samw * Decide which opbject type to use. If we are forced to 10385331Samw * use old ACL format than transform ACL into zfs_oldace_t 10395331Samw * layout. 1040789Sahrens */ 10415331Samw if (!zfsvfs->z_use_fuids) { 10425331Samw otype = DMU_OT_OLDACL; 10435331Samw } else { 10445331Samw if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) && 10455331Samw (zfsvfs->z_version >= ZPL_VERSION_FUID)) 10465331Samw zfs_acl_xform(zp, aclp); 10475331Samw ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID); 10485331Samw otype = DMU_OT_ACL; 10495331Samw } 10505331Samw 10515331Samw if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 10525331Samw /* 10535331Samw * If ACL was previously external and we are now 10545331Samw * converting to new ACL format then release old 10555331Samw * ACL object and create a new one. 10565331Samw */ 10575331Samw if (aoid && aclp->z_version != zacl->z_acl_version) { 10585331Samw error = dmu_object_free(zfsvfs->z_os, 10595331Samw zp->z_phys->zp_acl.z_acl_extern_obj, tx); 10605331Samw if (error) 10615331Samw return (error); 10625331Samw aoid = 0; 10635331Samw } 1064789Sahrens if (aoid == 0) { 1065789Sahrens aoid = dmu_object_alloc(zfsvfs->z_os, 10665331Samw otype, aclp->z_acl_bytes, 10675331Samw otype == DMU_OT_ACL ? DMU_OT_SYSACL : DMU_OT_NONE, 10685331Samw otype == DMU_OT_ACL ? DN_MAX_BONUSLEN : 0, tx); 1069789Sahrens } else { 1070789Sahrens (void) dmu_object_set_blocksize(zfsvfs->z_os, aoid, 10715331Samw aclp->z_acl_bytes, 0, tx); 1072789Sahrens } 1073789Sahrens zphys->zp_acl.z_acl_extern_obj = aoid; 10745331Samw for (aclnode = list_head(&aclp->z_acl); aclnode; 10755331Samw aclnode = list_next(&aclp->z_acl, aclnode)) { 10765331Samw if (aclnode->z_ace_count == 0) 10775331Samw continue; 10785331Samw dmu_write(zfsvfs->z_os, aoid, off, 10795331Samw aclnode->z_size, aclnode->z_acldata, tx); 10805331Samw off += aclnode->z_size; 10815331Samw } 1082789Sahrens } else { 10835331Samw void *start = zacl->z_ace_data; 1084789Sahrens /* 1085789Sahrens * Migrating back embedded? 1086789Sahrens */ 1087789Sahrens if (zphys->zp_acl.z_acl_extern_obj) { 1088789Sahrens error = dmu_object_free(zfsvfs->z_os, 10894300Smarks zp->z_phys->zp_acl.z_acl_extern_obj, tx); 1090789Sahrens if (error) 1091789Sahrens return (error); 1092789Sahrens zphys->zp_acl.z_acl_extern_obj = 0; 1093789Sahrens } 10945331Samw 10955331Samw for (aclnode = list_head(&aclp->z_acl); aclnode; 10965331Samw aclnode = list_next(&aclp->z_acl, aclnode)) { 10975331Samw if (aclnode->z_ace_count == 0) 10985331Samw continue; 10995331Samw bcopy(aclnode->z_acldata, start, aclnode->z_size); 11005331Samw start = (caddr_t)start + aclnode->z_size; 11015331Samw } 1102789Sahrens } 1103905Smarks 11045331Samw /* 11055331Samw * If Old version then swap count/bytes to match old 11065331Samw * layout of znode_acl_phys_t. 11075331Samw */ 11085331Samw if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 11095331Samw zphys->zp_acl.z_acl_size = aclp->z_acl_count; 11105331Samw zphys->zp_acl.z_acl_count = aclp->z_acl_bytes; 11115331Samw } else { 11125331Samw zphys->zp_acl.z_acl_size = aclp->z_acl_bytes; 11135331Samw zphys->zp_acl.z_acl_count = aclp->z_acl_count; 1114905Smarks } 1115789Sahrens 11165331Samw zphys->zp_acl.z_acl_version = aclp->z_version; 11175331Samw 11185331Samw /* 11195331Samw * Replace ACL wide bits, but first clear them. 11205331Samw */ 11215331Samw zp->z_phys->zp_flags &= ~ZFS_ACL_WIDE_FLAGS; 11225331Samw 11235331Samw zp->z_phys->zp_flags |= aclp->z_hints; 11245331Samw 11255331Samw if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0) 11265331Samw zp->z_phys->zp_flags |= ZFS_ACL_TRIVIAL; 11275331Samw 1128789Sahrens zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 1129789Sahrens return (0); 1130789Sahrens } 1131789Sahrens 1132789Sahrens /* 1133789Sahrens * Update access mask for prepended ACE 1134789Sahrens * 1135789Sahrens * This applies the "groupmask" value for aclmode property. 1136789Sahrens */ 1137789Sahrens static void 11385331Samw zfs_acl_prepend_fixup(zfs_acl_t *aclp, void *acep, void *origacep, 11395331Samw mode_t mode, uint64_t owner) 1140789Sahrens { 1141789Sahrens int rmask, wmask, xmask; 1142789Sahrens int user_ace; 11435331Samw uint16_t aceflags; 11445331Samw uint32_t origmask, acepmask; 11455331Samw uint64_t fuid; 1146789Sahrens 11475331Samw aceflags = aclp->z_ops.ace_flags_get(acep); 11485331Samw fuid = aclp->z_ops.ace_who_get(acep); 11495331Samw origmask = aclp->z_ops.ace_mask_get(origacep); 11505331Samw acepmask = aclp->z_ops.ace_mask_get(acep); 11515331Samw 11525331Samw user_ace = (!(aceflags & 1153789Sahrens (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP))); 1154789Sahrens 11555331Samw if (user_ace && (fuid == owner)) { 1156789Sahrens rmask = S_IRUSR; 1157789Sahrens wmask = S_IWUSR; 1158789Sahrens xmask = S_IXUSR; 1159789Sahrens } else { 1160789Sahrens rmask = S_IRGRP; 1161789Sahrens wmask = S_IWGRP; 1162789Sahrens xmask = S_IXGRP; 1163789Sahrens } 1164789Sahrens 11655331Samw if (origmask & ACE_READ_DATA) { 11665331Samw if (mode & rmask) { 11675331Samw acepmask &= ~ACE_READ_DATA; 11685331Samw } else { 11695331Samw acepmask |= ACE_READ_DATA; 11705331Samw } 1171789Sahrens } 1172789Sahrens 11735331Samw if (origmask & ACE_WRITE_DATA) { 11745331Samw if (mode & wmask) { 11755331Samw acepmask &= ~ACE_WRITE_DATA; 11765331Samw } else { 11775331Samw acepmask |= ACE_WRITE_DATA; 11785331Samw } 1179789Sahrens } 1180789Sahrens 11815331Samw if (origmask & ACE_APPEND_DATA) { 11825331Samw if (mode & wmask) { 11835331Samw acepmask &= ~ACE_APPEND_DATA; 11845331Samw } else { 11855331Samw acepmask |= ACE_APPEND_DATA; 11865331Samw } 1187789Sahrens } 1188789Sahrens 11895331Samw if (origmask & ACE_EXECUTE) { 11905331Samw if (mode & xmask) { 11915331Samw acepmask &= ~ACE_EXECUTE; 11925331Samw } else { 11935331Samw acepmask |= ACE_EXECUTE; 11945331Samw } 1195789Sahrens } 11965331Samw aclp->z_ops.ace_mask_set(acep, acepmask); 1197789Sahrens } 1198789Sahrens 1199789Sahrens /* 1200789Sahrens * Apply mode to canonical six ACEs. 1201789Sahrens */ 1202789Sahrens static void 1203789Sahrens zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode) 1204789Sahrens { 12055331Samw zfs_acl_node_t *aclnode = list_tail(&aclp->z_acl); 12065331Samw void *acep; 12075331Samw int maskoff = aclp->z_ops.ace_mask_off(); 12085331Samw size_t abstract_size = aclp->z_ops.ace_abstract_size(); 1209789Sahrens 12105331Samw ASSERT(aclnode != NULL); 12115331Samw 12125331Samw acep = (void *)((caddr_t)aclnode->z_acldata + 12135331Samw aclnode->z_size - (abstract_size * 6)); 1214789Sahrens 1215789Sahrens /* 1216789Sahrens * Fixup final ACEs to match the mode 1217789Sahrens */ 1218789Sahrens 12195331Samw adjust_ace_pair_common(acep, maskoff, abstract_size, 12205331Samw (mode & 0700) >> 6); /* owner@ */ 12215331Samw 12225331Samw acep = (caddr_t)acep + (abstract_size * 2); 12235331Samw 12245331Samw adjust_ace_pair_common(acep, maskoff, abstract_size, 12255331Samw (mode & 0070) >> 3); /* group@ */ 12265331Samw 12275331Samw acep = (caddr_t)acep + (abstract_size * 2); 12285331Samw adjust_ace_pair_common(acep, maskoff, 12295331Samw abstract_size, mode); /* everyone@ */ 1230789Sahrens } 1231789Sahrens 1232789Sahrens 1233789Sahrens static int 12345331Samw zfs_acl_ace_match(zfs_acl_t *aclp, void *acep, int allow_deny, 12355331Samw int entry_type, int accessmask) 1236789Sahrens { 12375331Samw uint32_t mask = aclp->z_ops.ace_mask_get(acep); 12385331Samw uint16_t type = aclp->z_ops.ace_type_get(acep); 12395331Samw uint16_t flags = aclp->z_ops.ace_flags_get(acep); 12405331Samw 12415331Samw return (mask == accessmask && type == allow_deny && 12425331Samw ((flags & ACE_TYPE_FLAGS) == entry_type)); 1243789Sahrens } 1244789Sahrens 1245789Sahrens /* 1246789Sahrens * Can prepended ACE be reused? 1247789Sahrens */ 1248789Sahrens static int 12495331Samw zfs_reuse_deny(zfs_acl_t *aclp, void *acep, void *prevacep) 1250789Sahrens { 1251789Sahrens int okay_masks; 12525331Samw uint16_t prevtype; 12535331Samw uint16_t prevflags; 12545331Samw uint16_t flags; 12555331Samw uint32_t mask, prevmask; 1256789Sahrens 12575331Samw if (prevacep == NULL) 1258789Sahrens return (B_FALSE); 1259789Sahrens 12605331Samw prevtype = aclp->z_ops.ace_type_get(prevacep); 12615331Samw prevflags = aclp->z_ops.ace_flags_get(prevacep); 12625331Samw flags = aclp->z_ops.ace_flags_get(acep); 12635331Samw mask = aclp->z_ops.ace_mask_get(acep); 12645331Samw prevmask = aclp->z_ops.ace_mask_get(prevacep); 12655331Samw 12665331Samw if (prevtype != DENY) 1267789Sahrens return (B_FALSE); 1268789Sahrens 12695331Samw if (prevflags != (flags & ACE_IDENTIFIER_GROUP)) 1270789Sahrens return (B_FALSE); 1271789Sahrens 12725331Samw okay_masks = (mask & OKAY_MASK_BITS); 1273789Sahrens 12745331Samw if (prevmask & ~okay_masks) 1275789Sahrens return (B_FALSE); 1276789Sahrens 1277789Sahrens return (B_TRUE); 1278789Sahrens } 1279789Sahrens 1280789Sahrens 12815331Samw /* 12825331Samw * Insert new ACL node into chain of zfs_acl_node_t's 12835331Samw * 12845331Samw * This will result in two possible results. 12855331Samw * 1. If the ACL is currently just a single zfs_acl_node and 12865331Samw * we are prepending the entry then current acl node will have 12875331Samw * a new node inserted above it. 12885331Samw * 12895331Samw * 2. If we are inserting in the middle of current acl node then 12905331Samw * the current node will be split in two and new node will be inserted 12915331Samw * in between the two split nodes. 12925331Samw */ 12935331Samw static zfs_acl_node_t * 12945331Samw zfs_acl_ace_insert(zfs_acl_t *aclp, void *acep) 12955331Samw { 12965331Samw zfs_acl_node_t *newnode; 12975331Samw zfs_acl_node_t *trailernode = NULL; 12985331Samw zfs_acl_node_t *currnode = zfs_acl_curr_node(aclp); 12995331Samw int curr_idx = aclp->z_curr_node->z_ace_idx; 13005331Samw int trailer_count; 13015331Samw size_t oldsize; 1302789Sahrens 13035331Samw newnode = zfs_acl_node_alloc(aclp->z_ops.ace_size(acep)); 13045331Samw newnode->z_ace_count = 1; 13055331Samw 13065331Samw oldsize = currnode->z_size; 13075331Samw 13085331Samw if (curr_idx != 1) { 13095331Samw trailernode = zfs_acl_node_alloc(0); 13105331Samw trailernode->z_acldata = acep; 13115331Samw 13125331Samw trailer_count = currnode->z_ace_count - curr_idx + 1; 13135331Samw currnode->z_ace_count = curr_idx - 1; 13145331Samw currnode->z_size = (caddr_t)acep - (caddr_t)currnode->z_acldata; 13155331Samw trailernode->z_size = oldsize - currnode->z_size; 13165331Samw trailernode->z_ace_count = trailer_count; 1317789Sahrens } 1318789Sahrens 13195331Samw aclp->z_acl_count += 1; 13205331Samw aclp->z_acl_bytes += aclp->z_ops.ace_size(acep); 1321789Sahrens 13225331Samw if (curr_idx == 1) 13235331Samw list_insert_before(&aclp->z_acl, currnode, newnode); 13245331Samw else 13255331Samw list_insert_after(&aclp->z_acl, currnode, newnode); 13265331Samw if (trailernode) { 13275331Samw list_insert_after(&aclp->z_acl, newnode, trailernode); 13285331Samw aclp->z_curr_node = trailernode; 13295331Samw trailernode->z_ace_idx = 1; 1330789Sahrens } 1331789Sahrens 13325331Samw return (newnode); 1333789Sahrens } 1334789Sahrens 1335789Sahrens /* 1336789Sahrens * Prepend deny ACE 1337789Sahrens */ 13385331Samw static void * 13395331Samw zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, void *acep, 1340789Sahrens mode_t mode) 1341789Sahrens { 13425331Samw zfs_acl_node_t *aclnode; 13435331Samw void *newacep; 13445331Samw uint64_t fuid; 13455331Samw uint16_t flags; 1346789Sahrens 13475331Samw aclnode = zfs_acl_ace_insert(aclp, acep); 13485331Samw newacep = aclnode->z_acldata; 13495331Samw fuid = aclp->z_ops.ace_who_get(acep); 13505331Samw flags = aclp->z_ops.ace_flags_get(acep); 13515331Samw zfs_set_ace(aclp, newacep, 0, DENY, fuid, (flags & ACE_TYPE_FLAGS)); 13525331Samw zfs_acl_prepend_fixup(aclp, newacep, acep, mode, zp->z_phys->zp_uid); 13535331Samw 13545331Samw return (newacep); 1355789Sahrens } 1356789Sahrens 1357789Sahrens /* 1358789Sahrens * Split an inherited ACE into inherit_only ACE 1359789Sahrens * and original ACE with inheritance flags stripped off. 1360789Sahrens */ 1361789Sahrens static void 13625331Samw zfs_acl_split_ace(zfs_acl_t *aclp, zfs_ace_hdr_t *acep) 1363789Sahrens { 13645331Samw zfs_acl_node_t *aclnode; 13655435Smarks zfs_acl_node_t *currnode; 13665331Samw void *newacep; 13675331Samw uint16_t type, flags; 13685331Samw uint32_t mask; 13695331Samw uint64_t fuid; 1370789Sahrens 13715331Samw type = aclp->z_ops.ace_type_get(acep); 13725331Samw flags = aclp->z_ops.ace_flags_get(acep); 13735331Samw mask = aclp->z_ops.ace_mask_get(acep); 13745331Samw fuid = aclp->z_ops.ace_who_get(acep); 13755331Samw 13765331Samw aclnode = zfs_acl_ace_insert(aclp, acep); 13775331Samw newacep = aclnode->z_acldata; 13785331Samw 13795331Samw aclp->z_ops.ace_type_set(newacep, type); 13805331Samw aclp->z_ops.ace_flags_set(newacep, flags | ACE_INHERIT_ONLY_ACE); 13815331Samw aclp->z_ops.ace_mask_set(newacep, mask); 13825331Samw aclp->z_ops.ace_type_set(newacep, type); 13835331Samw aclp->z_ops.ace_who_set(newacep, fuid); 13845331Samw aclp->z_next_ace = acep; 13855331Samw flags &= ~ALL_INHERIT; 13865331Samw aclp->z_ops.ace_flags_set(acep, flags); 13875435Smarks currnode = zfs_acl_curr_node(aclp); 13885435Smarks ASSERT(currnode->z_ace_idx >= 1); 13895331Samw currnode->z_ace_idx -= 1; 1390789Sahrens } 1391789Sahrens 1392789Sahrens /* 1393789Sahrens * Are ACES started at index i, the canonical six ACES? 1394789Sahrens */ 1395789Sahrens static int 13965331Samw zfs_have_canonical_six(zfs_acl_t *aclp) 1397789Sahrens { 13985331Samw void *acep; 13995331Samw zfs_acl_node_t *aclnode = list_tail(&aclp->z_acl); 14005331Samw int i = 0; 14015331Samw size_t abstract_size = aclp->z_ops.ace_abstract_size(); 14025331Samw 14035331Samw ASSERT(aclnode != NULL); 1404789Sahrens 14055331Samw if (aclnode->z_ace_count < 6) 14065331Samw return (0); 14075331Samw 14085331Samw acep = (void *)((caddr_t)aclnode->z_acldata + 14095331Samw aclnode->z_size - (aclp->z_ops.ace_abstract_size() * 6)); 14105331Samw 14115331Samw if ((zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 1412789Sahrens DENY, ACE_OWNER, 0) && 14135331Samw zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 14145331Samw ALLOW, ACE_OWNER, OWNER_ALLOW_MASK) && 14155331Samw zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), DENY, 14165331Samw OWNING_GROUP, 0) && zfs_acl_ace_match(aclp, (caddr_t)acep + 14175331Samw (abstract_size * i++), 14185331Samw ALLOW, OWNING_GROUP, 0) && 14195331Samw zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 1420789Sahrens DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) && 14215331Samw zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 14225331Samw ALLOW, ACE_EVERYONE, EVERYONE_ALLOW_MASK))) { 1423789Sahrens return (1); 1424789Sahrens } else { 1425789Sahrens return (0); 1426789Sahrens } 1427789Sahrens } 1428789Sahrens 14295331Samw 1430789Sahrens /* 1431789Sahrens * Apply step 1g, to group entries 1432789Sahrens * 1433789Sahrens * Need to deal with corner case where group may have 1434789Sahrens * greater permissions than owner. If so then limit 1435789Sahrens * group permissions, based on what extra permissions 1436789Sahrens * group has. 1437789Sahrens */ 1438789Sahrens static void 14395331Samw zfs_fixup_group_entries(zfs_acl_t *aclp, void *acep, void *prevacep, 14405331Samw mode_t mode) 1441789Sahrens { 14425331Samw uint32_t prevmask = aclp->z_ops.ace_mask_get(prevacep); 14435331Samw uint32_t mask = aclp->z_ops.ace_mask_get(acep); 14445331Samw uint16_t prevflags = aclp->z_ops.ace_flags_get(prevacep); 1445789Sahrens mode_t extramode = (mode >> 3) & 07; 1446789Sahrens mode_t ownermode = (mode >> 6); 1447789Sahrens 14485331Samw if (prevflags & ACE_IDENTIFIER_GROUP) { 1449789Sahrens 1450789Sahrens extramode &= ~ownermode; 1451789Sahrens 1452789Sahrens if (extramode) { 14535331Samw if (extramode & S_IROTH) { 14545331Samw prevmask &= ~ACE_READ_DATA; 14555331Samw mask &= ~ACE_READ_DATA; 1456789Sahrens } 14575331Samw if (extramode & S_IWOTH) { 14585331Samw prevmask &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 14595331Samw mask &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 1460789Sahrens } 14615331Samw if (extramode & S_IXOTH) { 14625331Samw prevmask &= ~ACE_EXECUTE; 14635331Samw mask &= ~ACE_EXECUTE; 1464789Sahrens } 1465789Sahrens } 1466789Sahrens } 14675331Samw aclp->z_ops.ace_mask_set(acep, mask); 14685331Samw aclp->z_ops.ace_mask_set(prevacep, prevmask); 1469789Sahrens } 1470789Sahrens 1471789Sahrens /* 1472789Sahrens * Apply the chmod algorithm as described 1473789Sahrens * in PSARC/2002/240 1474789Sahrens */ 14755824Smarks static void 14765824Smarks zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp) 1477789Sahrens { 1478789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 14795331Samw void *acep = NULL, *prevacep = NULL; 14805331Samw uint64_t who; 1481789Sahrens int i; 1482789Sahrens int entry_type; 1483789Sahrens int reuse_deny; 1484789Sahrens int need_canonical_six = 1; 14855331Samw uint16_t iflags, type; 14865331Samw uint32_t access_mask; 1487789Sahrens 1488789Sahrens ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1489789Sahrens ASSERT(MUTEX_HELD(&zp->z_lock)); 1490789Sahrens 14915331Samw aclp->z_hints = (zp->z_phys->zp_flags & V4_ACL_WIDE_FLAGS); 14925489Smarks 14935489Smarks /* 14945489Smarks * If discard then just discard all ACL nodes which 14955489Smarks * represent the ACEs. 14965489Smarks * 14975489Smarks * New owner@/group@/everone@ ACEs will be added 14985489Smarks * later. 14995489Smarks */ 15005489Smarks if (zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) 15015489Smarks zfs_acl_release_nodes(aclp); 15025489Smarks 15035331Samw while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 15045331Samw &iflags, &type)) { 15055331Samw 15065331Samw entry_type = (iflags & ACE_TYPE_FLAGS); 15075331Samw iflags = (iflags & ALL_INHERIT); 1508789Sahrens 15095331Samw if ((type != ALLOW && type != DENY) || 1510905Smarks (iflags & ACE_INHERIT_ONLY_ACE)) { 1511905Smarks if (iflags) 15125331Samw aclp->z_hints |= ZFS_INHERIT_ACE; 15135331Samw switch (type) { 15145331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 15155331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 15165331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 15175331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 15185331Samw aclp->z_hints |= ZFS_ACL_OBJ_ACE; 15195331Samw break; 15205331Samw } 15215331Samw goto nextace; 1522789Sahrens } 1523789Sahrens 1524789Sahrens /* 1525789Sahrens * Need to split ace into two? 1526789Sahrens */ 1527905Smarks if ((iflags & (ACE_FILE_INHERIT_ACE| 1528789Sahrens ACE_DIRECTORY_INHERIT_ACE)) && 1529905Smarks (!(iflags & ACE_INHERIT_ONLY_ACE))) { 15305331Samw zfs_acl_split_ace(aclp, acep); 15315331Samw aclp->z_hints |= ZFS_INHERIT_ACE; 15325331Samw goto nextace; 1533789Sahrens } 1534789Sahrens 1535789Sahrens if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 1536789Sahrens (entry_type == OWNING_GROUP)) { 15375331Samw access_mask &= ~OGE_CLEAR; 15385331Samw aclp->z_ops.ace_mask_set(acep, access_mask); 15395331Samw goto nextace; 1540789Sahrens } else { 15415331Samw reuse_deny = B_TRUE; 15425331Samw if (type == ALLOW) { 1543789Sahrens 1544789Sahrens /* 1545789Sahrens * Check preceding ACE if any, to see 1546789Sahrens * if we need to prepend a DENY ACE. 1547789Sahrens * This is only applicable when the acl_mode 1548789Sahrens * property == groupmask. 1549789Sahrens */ 15502676Seschrock if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK) { 1551789Sahrens 15525331Samw reuse_deny = zfs_reuse_deny(aclp, acep, 15535331Samw prevacep); 1554789Sahrens 15555959Smarks if (!reuse_deny) { 15565331Samw prevacep = 15575331Samw zfs_acl_prepend_deny(zp, 15585331Samw aclp, acep, mode); 1559789Sahrens } else { 1560789Sahrens zfs_acl_prepend_fixup( 15615331Samw aclp, prevacep, 15625331Samw acep, mode, 1563789Sahrens zp->z_phys->zp_uid); 1564789Sahrens } 15655331Samw zfs_fixup_group_entries(aclp, acep, 15665331Samw prevacep, mode); 15675331Samw 1568789Sahrens } 1569789Sahrens } 1570789Sahrens } 15715331Samw nextace: 15725331Samw prevacep = acep; 1573789Sahrens } 1574789Sahrens 1575789Sahrens /* 1576789Sahrens * Check out last six aces, if we have six. 1577789Sahrens */ 1578789Sahrens 1579789Sahrens if (aclp->z_acl_count >= 6) { 15805331Samw if (zfs_have_canonical_six(aclp)) { 1581789Sahrens need_canonical_six = 0; 1582789Sahrens } 1583789Sahrens } 1584789Sahrens 1585789Sahrens if (need_canonical_six) { 15865331Samw size_t abstract_size = aclp->z_ops.ace_abstract_size(); 15875331Samw void *zacep; 15885331Samw zfs_acl_node_t *aclnode = 15895331Samw zfs_acl_node_alloc(abstract_size * 6); 1590789Sahrens 15915331Samw aclnode->z_size = abstract_size * 6; 15925331Samw aclnode->z_ace_count = 6; 15935331Samw aclp->z_acl_bytes += aclnode->z_size; 15945331Samw list_insert_tail(&aclp->z_acl, aclnode); 15955331Samw 15965331Samw zacep = aclnode->z_acldata; 15975331Samw 15985331Samw i = 0; 15995331Samw zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 16005331Samw 0, DENY, -1, ACE_OWNER); 16015331Samw zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 16025331Samw OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER); 16035331Samw zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 0, 16045331Samw DENY, -1, OWNING_GROUP); 16055331Samw zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 0, 16065331Samw ALLOW, -1, OWNING_GROUP); 16075331Samw zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 16085331Samw EVERYONE_DENY_MASK, DENY, -1, ACE_EVERYONE); 16095331Samw zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 16105331Samw EVERYONE_ALLOW_MASK, ALLOW, -1, ACE_EVERYONE); 1611789Sahrens aclp->z_acl_count += 6; 1612789Sahrens } 1613789Sahrens 1614789Sahrens zfs_acl_fixup_canonical_six(aclp, mode); 1615789Sahrens } 1616789Sahrens 1617789Sahrens int 16185824Smarks zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) 1619789Sahrens { 1620789Sahrens int error; 1621789Sahrens 16225824Smarks mutex_enter(&zp->z_lock); 1623789Sahrens mutex_enter(&zp->z_acl_lock); 16245824Smarks *aclp = NULL; 16255824Smarks error = zfs_acl_node_read(zp, aclp, B_TRUE); 16261544Seschrock if (error == 0) 16275824Smarks zfs_acl_chmod(zp, mode, *aclp); 1628789Sahrens mutex_exit(&zp->z_acl_lock); 16295824Smarks mutex_exit(&zp->z_lock); 1630789Sahrens return (error); 1631789Sahrens } 1632789Sahrens 1633789Sahrens /* 1634789Sahrens * strip off write_owner and write_acl 1635789Sahrens */ 1636789Sahrens static void 16376385Smarks zfs_restricted_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep) 1638789Sahrens { 16395331Samw uint32_t mask = aclp->z_ops.ace_mask_get(acep); 16405331Samw 16416385Smarks if ((zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) && 16425331Samw (aclp->z_ops.ace_type_get(acep) == ALLOW)) { 16436385Smarks mask &= ~RESTRICTED_CLEAR; 16445331Samw aclp->z_ops.ace_mask_set(acep, mask); 16455331Samw } 16465331Samw } 16475331Samw 16485331Samw /* 16495331Samw * Should ACE be inherited? 16505331Samw */ 16515331Samw static int 16525331Samw zfs_ace_can_use(znode_t *zp, uint16_t acep_flags) 16535331Samw { 16545331Samw int vtype = ZTOV(zp)->v_type; 16555331Samw int iflags = (acep_flags & 0xf); 16565331Samw 16575331Samw if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 16585331Samw return (1); 16595331Samw else if (iflags & ACE_FILE_INHERIT_ACE) 16605331Samw return (!((vtype == VDIR) && 16615331Samw (iflags & ACE_NO_PROPAGATE_INHERIT_ACE))); 16625331Samw return (0); 1663789Sahrens } 1664789Sahrens 1665789Sahrens /* 1666789Sahrens * inherit inheritable ACEs from parent 1667789Sahrens */ 1668789Sahrens static zfs_acl_t * 16696385Smarks zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp, boolean_t *need_chmod) 1670789Sahrens { 1671789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 16725331Samw void *pacep; 16735331Samw void *acep, *acep2; 16745331Samw zfs_acl_node_t *aclnode, *aclnode2; 1675789Sahrens zfs_acl_t *aclp = NULL; 16765331Samw uint64_t who; 16775331Samw uint32_t access_mask; 16785331Samw uint16_t iflags, newflags, type; 16795331Samw size_t ace_size; 16805331Samw void *data1, *data2; 16815331Samw size_t data1sz, data2sz; 16826385Smarks enum vtype vntype = ZTOV(zp)->v_type; 1683789Sahrens 16846385Smarks *need_chmod = B_TRUE; 16855331Samw pacep = NULL; 16867559SMark.Shellenbaum@Sun.COM aclp = zfs_acl_alloc(paclp->z_version); 16872676Seschrock if (zfsvfs->z_acl_inherit != ZFS_ACL_DISCARD) { 16885331Samw while (pacep = zfs_acl_next_ace(paclp, pacep, &who, 16895331Samw &access_mask, &iflags, &type)) { 1690789Sahrens 16917559SMark.Shellenbaum@Sun.COM /* 16927559SMark.Shellenbaum@Sun.COM * don't inherit bogus ACEs 16937559SMark.Shellenbaum@Sun.COM */ 16947559SMark.Shellenbaum@Sun.COM if (!zfs_acl_valid_ace_type(type, iflags)) 16957559SMark.Shellenbaum@Sun.COM continue; 16967559SMark.Shellenbaum@Sun.COM 16972676Seschrock if (zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW && 16985331Samw type == ALLOW) 1699789Sahrens continue; 1700789Sahrens 17015331Samw ace_size = aclp->z_ops.ace_size(pacep); 1702789Sahrens 17036385Smarks if (!zfs_ace_can_use(zp, iflags)) 17046385Smarks continue; 17056385Smarks 17066385Smarks /* 17076385Smarks * If owner@, group@, or everyone@ inheritable 17086385Smarks * then zfs_acl_chmod() isn't needed. 17096385Smarks */ 17106385Smarks if (zfsvfs->z_acl_inherit == 17116385Smarks ZFS_ACL_PASSTHROUGH && 17126385Smarks ((iflags & (ACE_OWNER|ACE_EVERYONE)) || 17136385Smarks ((iflags & OWNING_GROUP) == 17146385Smarks OWNING_GROUP)) && (vntype == VREG || 17156385Smarks (vntype == VDIR && 17166385Smarks (iflags & ACE_DIRECTORY_INHERIT_ACE)))) 17176385Smarks *need_chmod = B_FALSE; 17186385Smarks 17196385Smarks aclnode = zfs_acl_node_alloc(ace_size); 17206385Smarks list_insert_tail(&aclp->z_acl, aclnode); 17216385Smarks acep = aclnode->z_acldata; 17226385Smarks zfs_set_ace(aclp, acep, access_mask, type, 17236385Smarks who, iflags|ACE_INHERITED_ACE); 1724789Sahrens 17256385Smarks /* 17266385Smarks * Copy special opaque data if any 17276385Smarks */ 17286385Smarks if ((data1sz = paclp->z_ops.ace_data(pacep, 17296385Smarks &data1)) != 0) { 17306385Smarks VERIFY((data2sz = aclp->z_ops.ace_data(acep, 17316385Smarks &data2)) == data1sz); 17326385Smarks bcopy(data1, data2, data2sz); 17336385Smarks } 17346385Smarks aclp->z_acl_count++; 17356385Smarks aclnode->z_ace_count++; 17366385Smarks aclp->z_acl_bytes += aclnode->z_size; 17376385Smarks newflags = aclp->z_ops.ace_flags_get(acep); 17386385Smarks 17396385Smarks if (vntype == VDIR) 17406385Smarks aclp->z_hints |= ZFS_INHERIT_ACE; 17416385Smarks 17426385Smarks if ((iflags & ACE_NO_PROPAGATE_INHERIT_ACE) || 17436385Smarks (vntype != VDIR)) { 17446385Smarks newflags &= ~ALL_INHERIT; 17456385Smarks aclp->z_ops.ace_flags_set(acep, 17466385Smarks newflags|ACE_INHERITED_ACE); 17476385Smarks zfs_restricted_update(zfsvfs, aclp, acep); 17486385Smarks continue; 17496385Smarks } 17506385Smarks 17516385Smarks ASSERT(vntype == VDIR); 17526385Smarks 17536385Smarks newflags = aclp->z_ops.ace_flags_get(acep); 17546385Smarks if ((iflags & (ACE_FILE_INHERIT_ACE | 17556385Smarks ACE_DIRECTORY_INHERIT_ACE)) != 17566385Smarks ACE_FILE_INHERIT_ACE) { 17576385Smarks aclnode2 = zfs_acl_node_alloc(ace_size); 17586385Smarks list_insert_tail(&aclp->z_acl, aclnode2); 17596385Smarks acep2 = aclnode2->z_acldata; 17606385Smarks zfs_set_ace(aclp, acep2, 17616385Smarks access_mask, type, who, 17626385Smarks iflags|ACE_INHERITED_ACE); 17636385Smarks newflags |= ACE_INHERIT_ONLY_ACE; 17646385Smarks aclp->z_ops.ace_flags_set(acep, newflags); 17656385Smarks newflags &= ~ALL_INHERIT; 17666385Smarks aclp->z_ops.ace_flags_set(acep2, 17676385Smarks newflags|ACE_INHERITED_ACE); 17681576Smarks 1769789Sahrens /* 17705331Samw * Copy special opaque data if any 1771789Sahrens */ 17726385Smarks if ((data1sz = aclp->z_ops.ace_data(acep, 17735331Samw &data1)) != 0) { 17745331Samw VERIFY((data2sz = 17756385Smarks aclp->z_ops.ace_data(acep2, 17765331Samw &data2)) == data1sz); 17776385Smarks bcopy(data1, data2, data1sz); 17785331Samw } 17795331Samw aclp->z_acl_count++; 17806385Smarks aclnode2->z_ace_count++; 17815331Samw aclp->z_acl_bytes += aclnode->z_size; 17826385Smarks zfs_restricted_update(zfsvfs, aclp, acep2); 17836385Smarks } else { 17846385Smarks newflags |= ACE_INHERIT_ONLY_ACE; 17856385Smarks aclp->z_ops.ace_flags_set(acep, 17866385Smarks newflags|ACE_INHERITED_ACE); 1787789Sahrens } 1788789Sahrens } 1789789Sahrens } 1790789Sahrens return (aclp); 1791789Sahrens } 1792789Sahrens 1793789Sahrens /* 1794789Sahrens * Create file system object initial permissions 1795789Sahrens * including inheritable ACEs. 1796789Sahrens */ 1797789Sahrens void 1798789Sahrens zfs_perm_init(znode_t *zp, znode_t *parent, int flag, 17995331Samw vattr_t *vap, dmu_tx_t *tx, cred_t *cr, 18005331Samw zfs_acl_t *setaclp, zfs_fuid_info_t **fuidp) 1801789Sahrens { 18025959Smarks uint64_t mode, fuid, fgid; 1803789Sahrens int error; 18045331Samw zfsvfs_t *zfsvfs = zp->z_zfsvfs; 18055331Samw zfs_acl_t *aclp = NULL; 18065331Samw zfs_acl_t *paclp; 18075331Samw xvattr_t *xvap = (xvattr_t *)vap; 18085959Smarks gid_t gid; 18096385Smarks boolean_t need_chmod = B_TRUE; 18105331Samw 18115331Samw if (setaclp) 18125331Samw aclp = setaclp; 1813789Sahrens 1814789Sahrens mode = MAKEIMODE(vap->va_type, vap->va_mode); 1815789Sahrens 1816789Sahrens /* 1817789Sahrens * Determine uid and gid. 1818789Sahrens */ 1819789Sahrens if ((flag & (IS_ROOT_NODE | IS_REPLAY)) || 1820789Sahrens ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 18215959Smarks fuid = zfs_fuid_create(zfsvfs, vap->va_uid, cr, 18225331Samw ZFS_OWNER, tx, fuidp); 18235959Smarks fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr, 18245331Samw ZFS_GROUP, tx, fuidp); 18255959Smarks gid = vap->va_gid; 1826789Sahrens } else { 18275959Smarks fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, tx, cr, fuidp); 18285959Smarks fgid = 0; 18295959Smarks if (vap->va_mask & AT_GID) { 18305959Smarks fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr, 18315959Smarks ZFS_GROUP, tx, fuidp); 18325959Smarks gid = vap->va_gid; 18335959Smarks if (fgid != parent->z_phys->zp_gid && 18345959Smarks !groupmember(vap->va_gid, cr) && 18355959Smarks secpolicy_vnode_create_gid(cr) != 0) 18365959Smarks fgid = 0; 18375959Smarks } 18385959Smarks if (fgid == 0) { 18395959Smarks if (parent->z_phys->zp_mode & S_ISGID) { 18405959Smarks fgid = parent->z_phys->zp_gid; 18415959Smarks gid = zfs_fuid_map_id(zfsvfs, fgid, 18425959Smarks cr, ZFS_GROUP); 18435959Smarks } else { 18445959Smarks fgid = zfs_fuid_create_cred(zfsvfs, 18455959Smarks ZFS_GROUP, tx, cr, fuidp); 18465959Smarks gid = crgetgid(cr); 18475959Smarks } 18485331Samw } 1849789Sahrens } 1850789Sahrens 1851789Sahrens /* 1852789Sahrens * If we're creating a directory, and the parent directory has the 1853789Sahrens * set-GID bit set, set in on the new directory. 1854789Sahrens * Otherwise, if the user is neither privileged nor a member of the 1855789Sahrens * file's new group, clear the file's set-GID bit. 1856789Sahrens */ 1857789Sahrens 18585959Smarks if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) { 1859789Sahrens mode |= S_ISGID; 18605959Smarks } else { 1861789Sahrens if ((mode & S_ISGID) && 1862789Sahrens secpolicy_vnode_setids_setgids(cr, gid) != 0) 1863789Sahrens mode &= ~S_ISGID; 1864789Sahrens } 1865789Sahrens 18665959Smarks zp->z_phys->zp_uid = fuid; 18675959Smarks zp->z_phys->zp_gid = fgid; 1868789Sahrens zp->z_phys->zp_mode = mode; 1869789Sahrens 18705331Samw if (aclp == NULL) { 18715331Samw mutex_enter(&parent->z_lock); 18727057Smarks if ((ZTOV(parent)->v_type == VDIR && 18737328SMark.Shellenbaum@Sun.COM (parent->z_phys->zp_flags & ZFS_INHERIT_ACE)) && 18747328SMark.Shellenbaum@Sun.COM !(zp->z_phys->zp_flags & ZFS_XATTR)) { 18755331Samw mutex_enter(&parent->z_acl_lock); 18765331Samw VERIFY(0 == zfs_acl_node_read(parent, &paclp, B_FALSE)); 18775331Samw mutex_exit(&parent->z_acl_lock); 18786385Smarks aclp = zfs_acl_inherit(zp, paclp, &need_chmod); 18795331Samw zfs_acl_free(paclp); 18805331Samw } else { 18815331Samw aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); 18825331Samw } 18835331Samw mutex_exit(&parent->z_lock); 18845331Samw mutex_enter(&zp->z_lock); 18855331Samw mutex_enter(&zp->z_acl_lock); 18866385Smarks if (need_chmod) 18876385Smarks zfs_acl_chmod(zp, mode, aclp); 1888789Sahrens } else { 18895331Samw mutex_enter(&zp->z_lock); 18905331Samw mutex_enter(&zp->z_acl_lock); 1891789Sahrens } 18925331Samw 18935331Samw /* Force auto_inherit on all new directory objects */ 18945331Samw if (vap->va_type == VDIR) 18955331Samw aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 18965331Samw 18975771Sjp151216 error = zfs_aclset_common(zp, aclp, cr, fuidp, tx); 18985331Samw 18995331Samw /* Set optional attributes if any */ 19005331Samw if (vap->va_mask & AT_XVATTR) 19015331Samw zfs_xvattr_set(zp, xvap); 19025331Samw 1903789Sahrens mutex_exit(&zp->z_lock); 1904789Sahrens mutex_exit(&zp->z_acl_lock); 1905789Sahrens ASSERT3U(error, ==, 0); 1906789Sahrens 19075959Smarks if (aclp != setaclp) 19085331Samw zfs_acl_free(aclp); 1909789Sahrens } 1910789Sahrens 1911789Sahrens /* 1912789Sahrens * Retrieve a files ACL 1913789Sahrens */ 1914789Sahrens int 19155331Samw zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1916789Sahrens { 1917789Sahrens zfs_acl_t *aclp; 19185331Samw ulong_t mask; 1919789Sahrens int error; 19205331Samw int count = 0; 19215331Samw int largeace = 0; 1922789Sahrens 19235331Samw mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT | 19245331Samw VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 19255331Samw 19265331Samw if (error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)) 19275331Samw return (error); 1928789Sahrens 1929789Sahrens if (mask == 0) 1930789Sahrens return (ENOSYS); 1931789Sahrens 1932789Sahrens mutex_enter(&zp->z_acl_lock); 1933789Sahrens 19345331Samw error = zfs_acl_node_read(zp, &aclp, B_FALSE); 19351544Seschrock if (error != 0) { 19361544Seschrock mutex_exit(&zp->z_acl_lock); 19371544Seschrock return (error); 19381544Seschrock } 19391544Seschrock 19405331Samw /* 19415331Samw * Scan ACL to determine number of ACEs 19425331Samw */ 19435331Samw if ((zp->z_phys->zp_flags & ZFS_ACL_OBJ_ACE) && 19445331Samw !(mask & VSA_ACE_ALLTYPES)) { 19455331Samw void *zacep = NULL; 19465331Samw uint64_t who; 19475331Samw uint32_t access_mask; 19485331Samw uint16_t type, iflags; 19495331Samw 19505331Samw while (zacep = zfs_acl_next_ace(aclp, zacep, 19515331Samw &who, &access_mask, &iflags, &type)) { 19525331Samw switch (type) { 19535331Samw case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 19545331Samw case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 19555331Samw case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 19565331Samw case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 19575331Samw largeace++; 19585331Samw continue; 19595331Samw default: 19605331Samw count++; 19615331Samw } 19625331Samw } 19635331Samw vsecp->vsa_aclcnt = count; 19645331Samw } else 19655331Samw count = aclp->z_acl_count; 1966789Sahrens 1967789Sahrens if (mask & VSA_ACECNT) { 19685331Samw vsecp->vsa_aclcnt = count; 1969789Sahrens } 1970789Sahrens 1971789Sahrens if (mask & VSA_ACE) { 19725331Samw size_t aclsz; 19735331Samw 19745331Samw zfs_acl_node_t *aclnode = list_head(&aclp->z_acl); 19755331Samw 19765331Samw aclsz = count * sizeof (ace_t) + 19775331Samw sizeof (ace_object_t) * largeace; 19785331Samw 19795331Samw vsecp->vsa_aclentp = kmem_alloc(aclsz, KM_SLEEP); 19805331Samw vsecp->vsa_aclentsz = aclsz; 19815331Samw 19825331Samw if (aclp->z_version == ZFS_ACL_VERSION_FUID) 19835771Sjp151216 zfs_copy_fuid_2_ace(zp->z_zfsvfs, aclp, cr, 19845331Samw vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES)); 19855331Samw else { 19865331Samw bcopy(aclnode->z_acldata, vsecp->vsa_aclentp, 19875331Samw count * sizeof (ace_t)); 19885331Samw } 19895331Samw } 19905331Samw if (mask & VSA_ACE_ACLFLAGS) { 19915331Samw vsecp->vsa_aclflags = 0; 19925331Samw if (zp->z_phys->zp_flags & ZFS_ACL_DEFAULTED) 19935331Samw vsecp->vsa_aclflags |= ACL_DEFAULTED; 19945331Samw if (zp->z_phys->zp_flags & ZFS_ACL_PROTECTED) 19955331Samw vsecp->vsa_aclflags |= ACL_PROTECTED; 19965331Samw if (zp->z_phys->zp_flags & ZFS_ACL_AUTO_INHERIT) 19975331Samw vsecp->vsa_aclflags |= ACL_AUTO_INHERIT; 1998789Sahrens } 1999789Sahrens 2000789Sahrens mutex_exit(&zp->z_acl_lock); 2001789Sahrens 2002789Sahrens zfs_acl_free(aclp); 2003789Sahrens 2004789Sahrens return (0); 2005789Sahrens } 2006789Sahrens 20075331Samw int 20085331Samw zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type, 20095331Samw vsecattr_t *vsecp, zfs_acl_t **zaclp) 20105331Samw { 20115331Samw zfs_acl_t *aclp; 20125331Samw zfs_acl_node_t *aclnode; 20135331Samw int aclcnt = vsecp->vsa_aclcnt; 20145331Samw int error; 20155331Samw 20165331Samw if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0) 20175331Samw return (EINVAL); 20185331Samw 20195331Samw aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version)); 20205331Samw 20215331Samw aclp->z_hints = 0; 20225331Samw aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t)); 20235331Samw if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 20245331Samw if ((error = zfs_copy_ace_2_oldace(obj_type, aclp, 20255331Samw (ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata, 20265331Samw aclcnt, &aclnode->z_size)) != 0) { 20275331Samw zfs_acl_free(aclp); 20285331Samw zfs_acl_node_free(aclnode); 20295331Samw return (error); 20305331Samw } 20315331Samw } else { 20325331Samw if ((error = zfs_copy_ace_2_fuid(obj_type, aclp, 20335331Samw vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt, 20345331Samw &aclnode->z_size)) != 0) { 20355331Samw zfs_acl_free(aclp); 20365331Samw zfs_acl_node_free(aclnode); 20375331Samw return (error); 20385331Samw } 20395331Samw } 20405331Samw aclp->z_acl_bytes = aclnode->z_size; 20415331Samw aclnode->z_ace_count = aclcnt; 20425331Samw aclp->z_acl_count = aclcnt; 20435331Samw list_insert_head(&aclp->z_acl, aclnode); 20445331Samw 20455331Samw /* 20465331Samw * If flags are being set then add them to z_hints 20475331Samw */ 20485331Samw if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) { 20495331Samw if (vsecp->vsa_aclflags & ACL_PROTECTED) 20505331Samw aclp->z_hints |= ZFS_ACL_PROTECTED; 20515331Samw if (vsecp->vsa_aclflags & ACL_DEFAULTED) 20525331Samw aclp->z_hints |= ZFS_ACL_DEFAULTED; 20535331Samw if (vsecp->vsa_aclflags & ACL_AUTO_INHERIT) 20545331Samw aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 20555331Samw } 20565331Samw 20575331Samw *zaclp = aclp; 20585331Samw 20595331Samw return (0); 20605331Samw } 20615331Samw 2062789Sahrens /* 2063789Sahrens * Set a files ACL 2064789Sahrens */ 2065789Sahrens int 20665331Samw zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 2067789Sahrens { 2068789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2069789Sahrens zilog_t *zilog = zfsvfs->z_log; 2070789Sahrens ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 2071789Sahrens dmu_tx_t *tx; 2072789Sahrens int error; 2073789Sahrens zfs_acl_t *aclp; 20745331Samw zfs_fuid_info_t *fuidp = NULL; 2075789Sahrens 2076789Sahrens if (mask == 0) 20774300Smarks return (ENOSYS); 2078789Sahrens 20795331Samw if (zp->z_phys->zp_flags & ZFS_IMMUTABLE) 20805331Samw return (EPERM); 20815331Samw 20825331Samw if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) 20835331Samw return (error); 20845331Samw 20855331Samw error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, &aclp); 20865331Samw if (error) 20875331Samw return (error); 20885331Samw 20895331Samw /* 20905331Samw * If ACL wide flags aren't being set then preserve any 20915331Samw * existing flags. 20925331Samw */ 20935331Samw if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { 20945331Samw aclp->z_hints |= (zp->z_phys->zp_flags & V4_ACL_WIDE_FLAGS); 20955331Samw } 2096789Sahrens top: 20975331Samw if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) { 20985331Samw zfs_acl_free(aclp); 20995331Samw return (error); 2100789Sahrens } 2101789Sahrens 2102789Sahrens mutex_enter(&zp->z_lock); 2103789Sahrens mutex_enter(&zp->z_acl_lock); 2104789Sahrens 2105789Sahrens tx = dmu_tx_create(zfsvfs->z_os); 2106789Sahrens dmu_tx_hold_bonus(tx, zp->z_id); 2107789Sahrens 2108789Sahrens if (zp->z_phys->zp_acl.z_acl_extern_obj) { 21095331Samw /* Are we upgrading ACL? */ 21105331Samw if (zfsvfs->z_version <= ZPL_VERSION_FUID && 21115331Samw zp->z_phys->zp_acl.z_acl_version == 21125331Samw ZFS_ACL_VERSION_INITIAL) { 21135331Samw dmu_tx_hold_free(tx, 21145331Samw zp->z_phys->zp_acl.z_acl_extern_obj, 21155331Samw 0, DMU_OBJECT_END); 21165331Samw dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 21175824Smarks 0, aclp->z_acl_bytes); 21185331Samw } else { 21195331Samw dmu_tx_hold_write(tx, 21205331Samw zp->z_phys->zp_acl.z_acl_extern_obj, 21215331Samw 0, aclp->z_acl_bytes); 21225331Samw } 21235331Samw } else if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 21245331Samw dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); 21255331Samw } 21265824Smarks if (aclp->z_has_fuids) { 21275824Smarks if (zfsvfs->z_fuid_obj == 0) { 21285824Smarks dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 21295331Samw dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 21305824Smarks FUID_SIZE_ESTIMATE(zfsvfs)); 21315824Smarks dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL); 21325824Smarks } else { 21335824Smarks dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 21345824Smarks dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 21355824Smarks FUID_SIZE_ESTIMATE(zfsvfs)); 21365824Smarks } 2137789Sahrens } 2138789Sahrens 2139789Sahrens error = dmu_tx_assign(tx, zfsvfs->z_assign); 2140789Sahrens if (error) { 2141789Sahrens mutex_exit(&zp->z_acl_lock); 2142789Sahrens mutex_exit(&zp->z_lock); 2143789Sahrens 2144789Sahrens if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 21452113Sahrens dmu_tx_wait(tx); 21462113Sahrens dmu_tx_abort(tx); 2147789Sahrens goto top; 2148789Sahrens } 21492113Sahrens dmu_tx_abort(tx); 21505331Samw zfs_acl_free(aclp); 2151789Sahrens return (error); 2152789Sahrens } 2153789Sahrens 21545771Sjp151216 error = zfs_aclset_common(zp, aclp, cr, &fuidp, tx); 2155789Sahrens ASSERT(error == 0); 2156789Sahrens 21575331Samw zfs_log_acl(zilog, tx, zp, vsecp, fuidp); 21585331Samw 21595331Samw if (fuidp) 21605331Samw zfs_fuid_info_free(fuidp); 2161789Sahrens zfs_acl_free(aclp); 2162789Sahrens dmu_tx_commit(tx); 2163789Sahrens done: 2164789Sahrens mutex_exit(&zp->z_acl_lock); 2165789Sahrens mutex_exit(&zp->z_lock); 2166789Sahrens 2167789Sahrens return (error); 2168789Sahrens } 2169789Sahrens 21705331Samw /* 21715331Samw * working_mode returns the permissions that were not granted 21725331Samw */ 2173789Sahrens static int 21745331Samw zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, 21755331Samw boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) 2176789Sahrens { 2177789Sahrens zfs_acl_t *aclp; 2178789Sahrens zfsvfs_t *zfsvfs = zp->z_zfsvfs; 21791544Seschrock int error; 2180789Sahrens uid_t uid = crgetuid(cr); 21815331Samw uint64_t who; 21825331Samw uint16_t type, iflags; 21835331Samw uint16_t entry_type; 21845331Samw uint32_t access_mask; 21856056Smarks uint32_t deny_mask = 0; 21865331Samw zfs_ace_hdr_t *acep = NULL; 21875331Samw boolean_t checkit; 21885331Samw uid_t fowner; 21895331Samw uid_t gowner; 21905331Samw 21915331Samw /* 21925331Samw * Short circuit empty requests 21935331Samw */ 21945331Samw if (v4_mode == 0) 21955331Samw return (0); 21965331Samw 21975331Samw *check_privs = B_TRUE; 2198789Sahrens 21992638Sperrin if (zfsvfs->z_assign >= TXG_INITIAL) { /* ZIL replay */ 22002638Sperrin *working_mode = 0; 22012638Sperrin return (0); 22022638Sperrin } 2203789Sahrens 22042638Sperrin *working_mode = v4_mode; 2205789Sahrens 2206789Sahrens if ((v4_mode & WRITE_MASK) && 2207789Sahrens (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 2208789Sahrens (!IS_DEVVP(ZTOV(zp)))) { 22095331Samw *check_privs = B_FALSE; 2210789Sahrens return (EROFS); 2211789Sahrens } 2212789Sahrens 22135331Samw /* 22145331Samw * Only check for READONLY on non-directories. 22155331Samw */ 22165331Samw if ((v4_mode & WRITE_MASK_DATA) && 22175331Samw (((ZTOV(zp)->v_type != VDIR) && 22185331Samw (zp->z_phys->zp_flags & (ZFS_READONLY | ZFS_IMMUTABLE))) || 22195331Samw (ZTOV(zp)->v_type == VDIR && 22205331Samw (zp->z_phys->zp_flags & ZFS_IMMUTABLE)))) { 22215331Samw *check_privs = B_FALSE; 22225331Samw return (EPERM); 22235331Samw } 22245331Samw 22255331Samw if ((v4_mode & (ACE_DELETE | ACE_DELETE_CHILD)) && 22265331Samw (zp->z_phys->zp_flags & ZFS_NOUNLINK)) { 22275331Samw *check_privs = B_FALSE; 22285331Samw return (EPERM); 22295331Samw } 22305331Samw 22315331Samw if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) && 22325331Samw (zp->z_phys->zp_flags & ZFS_AV_QUARANTINED))) { 22335331Samw *check_privs = B_FALSE; 22345331Samw return (EACCES); 22355331Samw } 22365331Samw 22375331Samw /* 22385331Samw * The caller requested that the ACL check be skipped. This 22395331Samw * would only happen if the caller checked VOP_ACCESS() with a 22405331Samw * 32 bit ACE mask and already had the appropriate permissions. 22415331Samw */ 22425331Samw if (skipaclchk) { 22435331Samw *working_mode = 0; 22445331Samw return (0); 22455331Samw } 22465331Samw 22475771Sjp151216 zfs_fuid_map_ids(zp, cr, &fowner, &gowner); 22485331Samw 2249789Sahrens mutex_enter(&zp->z_acl_lock); 2250789Sahrens 22515331Samw error = zfs_acl_node_read(zp, &aclp, B_FALSE); 22521544Seschrock if (error != 0) { 22531544Seschrock mutex_exit(&zp->z_acl_lock); 22541544Seschrock return (error); 22551544Seschrock } 22561544Seschrock 22575331Samw while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 22585331Samw &iflags, &type)) { 2259789Sahrens 22607559SMark.Shellenbaum@Sun.COM if (!zfs_acl_valid_ace_type(type, iflags)) 22617559SMark.Shellenbaum@Sun.COM continue; 22627559SMark.Shellenbaum@Sun.COM 22637057Smarks if (ZTOV(zp)->v_type == VDIR && (iflags & ACE_INHERIT_ONLY_ACE)) 2264789Sahrens continue; 2265789Sahrens 22665331Samw entry_type = (iflags & ACE_TYPE_FLAGS); 22675331Samw 22685331Samw checkit = B_FALSE; 22695331Samw 2270789Sahrens switch (entry_type) { 2271789Sahrens case ACE_OWNER: 22725331Samw if (uid == fowner) 22735331Samw checkit = B_TRUE; 2274789Sahrens break; 22755331Samw case OWNING_GROUP: 22765331Samw who = gowner; 22775331Samw /*FALLTHROUGH*/ 2278789Sahrens case ACE_IDENTIFIER_GROUP: 22795331Samw checkit = zfs_groupmember(zfsvfs, who, cr); 2280789Sahrens break; 2281789Sahrens case ACE_EVERYONE: 22825331Samw checkit = B_TRUE; 2283789Sahrens break; 2284789Sahrens 2285789Sahrens /* USER Entry */ 2286789Sahrens default: 2287789Sahrens if (entry_type == 0) { 22885331Samw uid_t newid; 22895331Samw 22905959Smarks newid = zfs_fuid_map_id(zfsvfs, who, cr, 22915959Smarks ZFS_ACE_USER); 22925331Samw if (newid != IDMAP_WK_CREATOR_OWNER_UID && 22935331Samw uid == newid) 22945331Samw checkit = B_TRUE; 2295789Sahrens break; 22965331Samw } else { 22975331Samw zfs_acl_free(aclp); 22985331Samw mutex_exit(&zp->z_acl_lock); 22995331Samw return (EIO); 2300789Sahrens } 23015331Samw } 23025331Samw 23035331Samw if (checkit) { 23046056Smarks uint32_t mask_matched = (access_mask & *working_mode); 23056056Smarks 23066056Smarks if (mask_matched) { 23076056Smarks if (type == DENY) 23086056Smarks deny_mask |= mask_matched; 23096056Smarks 23106056Smarks *working_mode &= ~mask_matched; 23115331Samw } 2312789Sahrens } 2313789Sahrens 23146056Smarks /* Are we done? */ 23156056Smarks if (*working_mode == 0) 2316789Sahrens break; 2317789Sahrens } 2318789Sahrens 2319789Sahrens mutex_exit(&zp->z_acl_lock); 2320789Sahrens zfs_acl_free(aclp); 23216056Smarks 23226056Smarks /* Put the found 'denies' back on the working mode */ 23237163Smarks if (deny_mask) { 23247163Smarks *working_mode |= deny_mask; 23256056Smarks return (EACCES); 23267163Smarks } else if (*working_mode) { 23277163Smarks return (-1); 23287163Smarks } 23296056Smarks 23306056Smarks return (0); 2331789Sahrens } 2332789Sahrens 23335331Samw static int 23345331Samw zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, 23355331Samw cred_t *cr) 23365331Samw { 23375331Samw if (*working_mode != ACE_WRITE_DATA) 23385331Samw return (EACCES); 23395331Samw 23405331Samw return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, 23415331Samw check_privs, B_FALSE, cr)); 23425331Samw } 2343789Sahrens 2344789Sahrens /* 2345789Sahrens * Determine whether Access should be granted/denied, invoking least 2346789Sahrens * priv subsytem when a deny is determined. 2347789Sahrens */ 2348789Sahrens int 23495331Samw zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) 2350789Sahrens { 23515331Samw uint32_t working_mode; 23525331Samw int error; 23535331Samw int is_attr; 23545331Samw zfsvfs_t *zfsvfs = zp->z_zfsvfs; 23555331Samw boolean_t check_privs; 23565331Samw znode_t *xzp; 23575331Samw znode_t *check_zp = zp; 2358789Sahrens 2359789Sahrens is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) && 2360789Sahrens (ZTOV(zp)->v_type == VDIR)); 2361789Sahrens 2362789Sahrens /* 2363789Sahrens * If attribute then validate against base file 2364789Sahrens */ 2365789Sahrens if (is_attr) { 2366789Sahrens if ((error = zfs_zget(zp->z_zfsvfs, 2367789Sahrens zp->z_phys->zp_parent, &xzp)) != 0) { 2368789Sahrens return (error); 2369789Sahrens } 23705331Samw 2371789Sahrens check_zp = xzp; 23725331Samw 2373789Sahrens /* 2374789Sahrens * fixup mode to map to xattr perms 2375789Sahrens */ 2376789Sahrens 2377789Sahrens if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 2378789Sahrens mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 2379789Sahrens mode |= ACE_WRITE_NAMED_ATTRS; 2380789Sahrens } 2381789Sahrens 2382789Sahrens if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 2383789Sahrens mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 2384789Sahrens mode |= ACE_READ_NAMED_ATTRS; 2385789Sahrens } 2386789Sahrens } 2387789Sahrens 23885331Samw if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, 23895331Samw &check_privs, skipaclchk, cr)) == 0) { 23905331Samw if (is_attr) 23915331Samw VN_RELE(ZTOV(xzp)); 23925331Samw return (0); 23935331Samw } 2394789Sahrens 23955959Smarks if (error && !check_privs) { 2396789Sahrens if (is_attr) 2397789Sahrens VN_RELE(ZTOV(xzp)); 2398789Sahrens return (error); 2399789Sahrens } 2400789Sahrens 24015331Samw if (error && (flags & V_APPEND)) { 24025331Samw error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr); 24035331Samw } 24045331Samw 24055331Samw if (error && check_privs) { 24065331Samw uid_t owner; 24075331Samw mode_t checkmode = 0; 24085331Samw 24095959Smarks owner = zfs_fuid_map_id(zfsvfs, check_zp->z_phys->zp_uid, cr, 24105959Smarks ZFS_OWNER); 24115331Samw 24125331Samw /* 24135331Samw * First check for implicit owner permission on 24145331Samw * read_acl/read_attributes 24155331Samw */ 24165331Samw 24175331Samw error = 0; 24185331Samw ASSERT(working_mode != 0); 24195331Samw 24205331Samw if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) && 24215331Samw owner == crgetuid(cr))) 24225331Samw working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 24235331Samw 24245331Samw if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2425*7624SMark.Shellenbaum@Sun.COM ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 24265331Samw checkmode |= VREAD; 24275331Samw if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2428*7624SMark.Shellenbaum@Sun.COM ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 24295331Samw checkmode |= VWRITE; 24305331Samw if (working_mode & ACE_EXECUTE) 24315331Samw checkmode |= VEXEC; 24325331Samw 24335331Samw if (checkmode) 24345331Samw error = secpolicy_vnode_access(cr, ZTOV(check_zp), 24355331Samw owner, checkmode); 24365331Samw 24375331Samw if (error == 0 && (working_mode & ACE_WRITE_OWNER)) 2438*7624SMark.Shellenbaum@Sun.COM error = secpolicy_vnode_chown(cr, B_TRUE); 24395331Samw if (error == 0 && (working_mode & ACE_WRITE_ACL)) 24405331Samw error = secpolicy_vnode_setdac(cr, owner); 24415331Samw 24425331Samw if (error == 0 && (working_mode & 24435331Samw (ACE_DELETE|ACE_DELETE_CHILD))) 24445331Samw error = secpolicy_vnode_remove(cr); 24455331Samw 2446*7624SMark.Shellenbaum@Sun.COM if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) { 2447*7624SMark.Shellenbaum@Sun.COM error = secpolicy_vnode_chown(cr, B_FALSE); 2448*7624SMark.Shellenbaum@Sun.COM } 24495331Samw if (error == 0) { 24505331Samw /* 24515331Samw * See if any bits other than those already checked 24525331Samw * for are still present. If so then return EACCES 24535331Samw */ 24545331Samw if (working_mode & ~(ZFS_CHECKED_MASKS)) { 24555331Samw error = EACCES; 24565331Samw } 24575331Samw } 2458789Sahrens } 2459789Sahrens 2460789Sahrens if (is_attr) 2461789Sahrens VN_RELE(ZTOV(xzp)); 2462789Sahrens 2463789Sahrens return (error); 2464789Sahrens } 2465789Sahrens 2466789Sahrens /* 24675331Samw * Translate traditional unix VREAD/VWRITE/VEXEC mode into 24685331Samw * native ACL format and call zfs_zaccess() 2469789Sahrens */ 2470789Sahrens int 24715331Samw zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) 2472789Sahrens { 24735331Samw return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); 2474789Sahrens } 2475789Sahrens 2476789Sahrens /* 24775331Samw * Access function for secpolicy_vnode_setattr 2478789Sahrens */ 2479789Sahrens int 24805331Samw zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) 2481789Sahrens { 2482789Sahrens int v4_mode = zfs_unix_to_v4(mode >> 6); 2483789Sahrens 24845331Samw return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr)); 2485789Sahrens } 2486789Sahrens 24872604Smarks static int 24886257Smarks zfs_delete_final_check(znode_t *zp, znode_t *dzp, 24896257Smarks mode_t missing_perms, cred_t *cr) 24902604Smarks { 24912604Smarks int error; 24925331Samw uid_t downer; 24935331Samw zfsvfs_t *zfsvfs = zp->z_zfsvfs; 24942604Smarks 24955959Smarks downer = zfs_fuid_map_id(zfsvfs, dzp->z_phys->zp_uid, cr, ZFS_OWNER); 24965331Samw 24976257Smarks error = secpolicy_vnode_access(cr, ZTOV(dzp), downer, missing_perms); 24982604Smarks 24992604Smarks if (error == 0) 25002604Smarks error = zfs_sticky_remove_access(dzp, zp, cr); 25012604Smarks 25022604Smarks return (error); 25032604Smarks } 25042604Smarks 2505789Sahrens /* 2506789Sahrens * Determine whether Access should be granted/deny, without 2507789Sahrens * consulting least priv subsystem. 2508789Sahrens * 2509789Sahrens * 2510789Sahrens * The following chart is the recommended NFSv4 enforcement for 2511789Sahrens * ability to delete an object. 2512789Sahrens * 2513789Sahrens * ------------------------------------------------------- 2514789Sahrens * | Parent Dir | Target Object Permissions | 2515789Sahrens * | permissions | | 2516789Sahrens * ------------------------------------------------------- 2517789Sahrens * | | ACL Allows | ACL Denies| Delete | 2518789Sahrens * | | Delete | Delete | unspecified| 2519789Sahrens * ------------------------------------------------------- 2520789Sahrens * | ACL Allows | Permit | Permit | Permit | 2521789Sahrens * | DELETE_CHILD | | 2522789Sahrens * ------------------------------------------------------- 2523789Sahrens * | ACL Denies | Permit | Deny | Deny | 2524789Sahrens * | DELETE_CHILD | | | | 2525789Sahrens * ------------------------------------------------------- 2526789Sahrens * | ACL specifies | | | | 2527789Sahrens * | only allow | Permit | Permit | Permit | 2528789Sahrens * | write and | | | | 2529789Sahrens * | execute | | | | 2530789Sahrens * ------------------------------------------------------- 2531789Sahrens * | ACL denies | | | | 2532789Sahrens * | write and | Permit | Deny | Deny | 2533789Sahrens * | execute | | | | 2534789Sahrens * ------------------------------------------------------- 2535789Sahrens * ^ 2536789Sahrens * | 2537789Sahrens * No search privilege, can't even look up file? 2538789Sahrens * 2539789Sahrens */ 2540789Sahrens int 2541789Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) 2542789Sahrens { 25435331Samw uint32_t dzp_working_mode = 0; 25445331Samw uint32_t zp_working_mode = 0; 2545789Sahrens int dzp_error, zp_error; 25466257Smarks mode_t missing_perms; 25475331Samw boolean_t dzpcheck_privs = B_TRUE; 25485331Samw boolean_t zpcheck_privs = B_TRUE; 2549789Sahrens 2550789Sahrens /* 25516257Smarks * We want specific DELETE permissions to 2552789Sahrens * take precedence over WRITE/EXECUTE. We don't 2553789Sahrens * want an ACL such as this to mess us up. 25542604Smarks * user:joe:write_data:deny,user:joe:delete:allow 2555789Sahrens * 2556789Sahrens * However, deny permissions may ultimately be overridden 2557789Sahrens * by secpolicy_vnode_access(). 25586257Smarks * 25596257Smarks * We will ask for all of the necessary permissions and then 25606257Smarks * look at the working modes from the directory and target object 25616257Smarks * to determine what was found. 2562789Sahrens */ 2563789Sahrens 25645331Samw if (zp->z_phys->zp_flags & (ZFS_IMMUTABLE | ZFS_NOUNLINK)) 25655331Samw return (EPERM); 25665331Samw 25676257Smarks /* 25687163Smarks * First row 25696257Smarks * If the directory permissions allow the delete, we are done. 25706257Smarks */ 25717163Smarks if ((dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 25726257Smarks &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0) 25736257Smarks return (0); 2574789Sahrens 25756257Smarks /* 25766257Smarks * If target object has delete permission then we are done 25776257Smarks */ 25786257Smarks if ((zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, 25796257Smarks &zpcheck_privs, B_FALSE, cr)) == 0) 25806257Smarks return (0); 25816257Smarks 25827163Smarks ASSERT(dzp_error && zp_error); 25837163Smarks 25846257Smarks if (!dzpcheck_privs) 2585789Sahrens return (dzp_error); 25867163Smarks if (!zpcheck_privs) 25876257Smarks return (zp_error); 2588789Sahrens 2589789Sahrens /* 2590789Sahrens * Second row 25917163Smarks * 25927163Smarks * If directory returns EACCES then delete_child was denied 25937163Smarks * due to deny delete_child. In this case send the request through 25947163Smarks * secpolicy_vnode_remove(). We don't use zfs_delete_final_check() 25957163Smarks * since that *could* allow the delete based on write/execute permission 25967163Smarks * and we want delete permissions to override write/execute. 2597789Sahrens */ 2598789Sahrens 25992604Smarks if (dzp_error == EACCES) 26007163Smarks return (secpolicy_vnode_remove(cr)); 26012604Smarks 26022604Smarks /* 2603789Sahrens * Third Row 26046257Smarks * only need to see if we have write/execute on directory. 2605789Sahrens */ 2606789Sahrens 26077163Smarks if ((dzp_error = zfs_zaccess_common(dzp, ACE_EXECUTE|ACE_WRITE_DATA, 26087163Smarks &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0) 26092604Smarks return (zfs_sticky_remove_access(dzp, zp, cr)); 2610789Sahrens 26117163Smarks if (!dzpcheck_privs) 26127163Smarks return (dzp_error); 26137163Smarks 2614789Sahrens /* 26157163Smarks * Fourth row 2616789Sahrens */ 2617789Sahrens 26187163Smarks missing_perms = (dzp_working_mode & ACE_WRITE_DATA) ? VWRITE : 0; 26197163Smarks missing_perms |= (dzp_working_mode & ACE_EXECUTE) ? VEXEC : 0; 26207163Smarks 26217163Smarks ASSERT(missing_perms); 2622789Sahrens 26236257Smarks return (zfs_delete_final_check(zp, dzp, missing_perms, cr)); 26247163Smarks 2625789Sahrens } 2626789Sahrens 2627789Sahrens int 2628789Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 2629789Sahrens znode_t *tzp, cred_t *cr) 2630789Sahrens { 2631789Sahrens int add_perm; 2632789Sahrens int error; 2633789Sahrens 26345331Samw if (szp->z_phys->zp_flags & ZFS_AV_QUARANTINED) 26355331Samw return (EACCES); 26365331Samw 2637789Sahrens add_perm = (ZTOV(szp)->v_type == VDIR) ? 2638789Sahrens ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 2639789Sahrens 2640789Sahrens /* 2641789Sahrens * Rename permissions are combination of delete permission + 2642789Sahrens * add file/subdir permission. 2643789Sahrens */ 2644789Sahrens 2645789Sahrens /* 2646789Sahrens * first make sure we do the delete portion. 2647789Sahrens * 2648789Sahrens * If that succeeds then check for add_file/add_subdir permissions 2649789Sahrens */ 2650789Sahrens 2651789Sahrens if (error = zfs_zaccess_delete(sdzp, szp, cr)) 2652789Sahrens return (error); 2653789Sahrens 2654789Sahrens /* 2655789Sahrens * If we have a tzp, see if we can delete it? 2656789Sahrens */ 2657789Sahrens if (tzp) { 2658789Sahrens if (error = zfs_zaccess_delete(tdzp, tzp, cr)) 2659789Sahrens return (error); 2660789Sahrens } 2661789Sahrens 2662789Sahrens /* 2663789Sahrens * Now check for add permissions 2664789Sahrens */ 26655331Samw error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); 2666789Sahrens 2667789Sahrens return (error); 2668789Sahrens } 2669