Path: blob/main/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
48774 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/21/*22* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.23* Copyright (c) 2013 by Delphix. All rights reserved.24* Copyright 2014 Nexenta Systems, Inc. All rights reserved.25*/262728#include <sys/types.h>29#include <sys/param.h>30#include <sys/time.h>31#include <sys/sysmacros.h>32#include <sys/vfs.h>33#include <sys/vnode.h>34#include <sys/sid.h>35#include <sys/file.h>36#include <sys/stat.h>37#include <sys/kmem.h>38#include <sys/cmn_err.h>39#include <sys/errno.h>40#include <sys/fs/zfs.h>41#include <sys/policy.h>42#include <sys/zfs_znode.h>43#include <sys/zfs_fuid.h>44#include <sys/zfs_acl.h>45#include <sys/zfs_dir.h>46#include <sys/zfs_quota.h>47#include <sys/zfs_vfsops.h>48#include <sys/dmu.h>49#include <sys/dnode.h>50#include <sys/zap.h>51#include <sys/sa.h>52#include <sys/trace_acl.h>53#include <sys/zpl.h>5455#define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE56#define DENY ACE_ACCESS_DENIED_ACE_TYPE57#define MAX_ACE_TYPE ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE58#define MIN_ACE_TYPE ALLOW5960#define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP)61#define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \62ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE)63#define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \64ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS)65#define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \66ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS)6768#define ZFS_CHECKED_MASKS (ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_DATA| \69ACE_READ_NAMED_ATTRS|ACE_WRITE_DATA|ACE_WRITE_ATTRIBUTES| \70ACE_WRITE_NAMED_ATTRS|ACE_APPEND_DATA|ACE_EXECUTE|ACE_WRITE_OWNER| \71ACE_WRITE_ACL|ACE_DELETE|ACE_DELETE_CHILD|ACE_SYNCHRONIZE)7273#define WRITE_MASK_DATA (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS)74#define WRITE_MASK_ATTRS (ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES| \75ACE_DELETE|ACE_DELETE_CHILD)76#define WRITE_MASK (WRITE_MASK_DATA|WRITE_MASK_ATTRS)7778#define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \79ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE)8081#define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \82ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE)8384#define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \85ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE)8687#define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER)8889#define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\90ZFS_ACL_PROTECTED)9192#define ZFS_ACL_WIDE_FLAGS (V4_ACL_WIDE_FLAGS|ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|\93ZFS_ACL_OBJ_ACE)9495#define ALL_MODE_EXECS (S_IXUSR | S_IXGRP | S_IXOTH)9697#define IDMAP_WK_CREATOR_OWNER_UID 2147483648U9899static uint16_t100zfs_ace_v0_get_type(void *acep)101{102return (((zfs_oldace_t *)acep)->z_type);103}104105static uint16_t106zfs_ace_v0_get_flags(void *acep)107{108return (((zfs_oldace_t *)acep)->z_flags);109}110111static uint32_t112zfs_ace_v0_get_mask(void *acep)113{114return (((zfs_oldace_t *)acep)->z_access_mask);115}116117static uint64_t118zfs_ace_v0_get_who(void *acep)119{120return (((zfs_oldace_t *)acep)->z_fuid);121}122123static void124zfs_ace_v0_set_type(void *acep, uint16_t type)125{126((zfs_oldace_t *)acep)->z_type = type;127}128129static void130zfs_ace_v0_set_flags(void *acep, uint16_t flags)131{132((zfs_oldace_t *)acep)->z_flags = flags;133}134135static void136zfs_ace_v0_set_mask(void *acep, uint32_t mask)137{138((zfs_oldace_t *)acep)->z_access_mask = mask;139}140141static void142zfs_ace_v0_set_who(void *acep, uint64_t who)143{144((zfs_oldace_t *)acep)->z_fuid = who;145}146147static size_t148zfs_ace_v0_size(void *acep)149{150(void) acep;151return (sizeof (zfs_oldace_t));152}153154static size_t155zfs_ace_v0_abstract_size(void)156{157return (sizeof (zfs_oldace_t));158}159160static int161zfs_ace_v0_mask_off(void)162{163return (offsetof(zfs_oldace_t, z_access_mask));164}165166static int167zfs_ace_v0_data(void *acep, void **datap)168{169(void) acep;170*datap = NULL;171return (0);172}173174static const acl_ops_t zfs_acl_v0_ops = {175.ace_mask_get = zfs_ace_v0_get_mask,176.ace_mask_set = zfs_ace_v0_set_mask,177.ace_flags_get = zfs_ace_v0_get_flags,178.ace_flags_set = zfs_ace_v0_set_flags,179.ace_type_get = zfs_ace_v0_get_type,180.ace_type_set = zfs_ace_v0_set_type,181.ace_who_get = zfs_ace_v0_get_who,182.ace_who_set = zfs_ace_v0_set_who,183.ace_size = zfs_ace_v0_size,184.ace_abstract_size = zfs_ace_v0_abstract_size,185.ace_mask_off = zfs_ace_v0_mask_off,186.ace_data = zfs_ace_v0_data187};188189static uint16_t190zfs_ace_fuid_get_type(void *acep)191{192return (((zfs_ace_hdr_t *)acep)->z_type);193}194195static uint16_t196zfs_ace_fuid_get_flags(void *acep)197{198return (((zfs_ace_hdr_t *)acep)->z_flags);199}200201static uint32_t202zfs_ace_fuid_get_mask(void *acep)203{204return (((zfs_ace_hdr_t *)acep)->z_access_mask);205}206207static uint64_t208zfs_ace_fuid_get_who(void *args)209{210uint16_t entry_type;211zfs_ace_t *acep = args;212213entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS;214215if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP ||216entry_type == ACE_EVERYONE)217return (-1);218return (((zfs_ace_t *)acep)->z_fuid);219}220221static void222zfs_ace_fuid_set_type(void *acep, uint16_t type)223{224((zfs_ace_hdr_t *)acep)->z_type = type;225}226227static void228zfs_ace_fuid_set_flags(void *acep, uint16_t flags)229{230((zfs_ace_hdr_t *)acep)->z_flags = flags;231}232233static void234zfs_ace_fuid_set_mask(void *acep, uint32_t mask)235{236((zfs_ace_hdr_t *)acep)->z_access_mask = mask;237}238239static void240zfs_ace_fuid_set_who(void *arg, uint64_t who)241{242zfs_ace_t *acep = arg;243244uint16_t entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS;245246if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP ||247entry_type == ACE_EVERYONE)248return;249acep->z_fuid = who;250}251252static size_t253zfs_ace_fuid_size(void *acep)254{255zfs_ace_hdr_t *zacep = acep;256uint16_t entry_type;257258switch (zacep->z_type) {259case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:260case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:261case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:262case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:263return (sizeof (zfs_object_ace_t));264case ALLOW:265case DENY:266entry_type =267(((zfs_ace_hdr_t *)acep)->z_flags & ACE_TYPE_FLAGS);268if (entry_type == ACE_OWNER ||269entry_type == OWNING_GROUP ||270entry_type == ACE_EVERYONE)271return (sizeof (zfs_ace_hdr_t));272zfs_fallthrough;273default:274return (sizeof (zfs_ace_t));275}276}277278static size_t279zfs_ace_fuid_abstract_size(void)280{281return (sizeof (zfs_ace_hdr_t));282}283284static int285zfs_ace_fuid_mask_off(void)286{287return (offsetof(zfs_ace_hdr_t, z_access_mask));288}289290static int291zfs_ace_fuid_data(void *acep, void **datap)292{293zfs_ace_t *zacep = acep;294zfs_object_ace_t *zobjp;295296switch (zacep->z_hdr.z_type) {297case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:298case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:299case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:300case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:301zobjp = acep;302*datap = (caddr_t)zobjp + sizeof (zfs_ace_t);303return (sizeof (zfs_object_ace_t) - sizeof (zfs_ace_t));304default:305*datap = NULL;306return (0);307}308}309310static const acl_ops_t zfs_acl_fuid_ops = {311.ace_mask_get = zfs_ace_fuid_get_mask,312.ace_mask_set = zfs_ace_fuid_set_mask,313.ace_flags_get = zfs_ace_fuid_get_flags,314.ace_flags_set = zfs_ace_fuid_set_flags,315.ace_type_get = zfs_ace_fuid_get_type,316.ace_type_set = zfs_ace_fuid_set_type,317.ace_who_get = zfs_ace_fuid_get_who,318.ace_who_set = zfs_ace_fuid_set_who,319.ace_size = zfs_ace_fuid_size,320.ace_abstract_size = zfs_ace_fuid_abstract_size,321.ace_mask_off = zfs_ace_fuid_mask_off,322.ace_data = zfs_ace_fuid_data323};324325/*326* The following three functions are provided for compatibility with327* older ZPL version in order to determine if the file use to have328* an external ACL and what version of ACL previously existed on the329* file. Would really be nice to not need this, sigh.330*/331uint64_t332zfs_external_acl(znode_t *zp)333{334zfs_acl_phys_t acl_phys;335int error;336337if (zp->z_is_sa)338return (0);339340/*341* Need to deal with a potential342* race where zfs_sa_upgrade could cause343* z_isa_sa to change.344*345* If the lookup fails then the state of z_is_sa should have346* changed.347*/348349if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(ZTOZSB(zp)),350&acl_phys, sizeof (acl_phys))) == 0)351return (acl_phys.z_acl_extern_obj);352else {353/*354* after upgrade the SA_ZPL_ZNODE_ACL should have been355* removed356*/357VERIFY(zp->z_is_sa && error == ENOENT);358return (0);359}360}361362/*363* Determine size of ACL in bytes364*365* This is more complicated than it should be since we have to deal366* with old external ACLs.367*/368static int369zfs_acl_znode_info(znode_t *zp, int *aclsize, int *aclcount,370zfs_acl_phys_t *aclphys)371{372zfsvfs_t *zfsvfs = ZTOZSB(zp);373uint64_t acl_count;374int size;375int error;376377ASSERT(MUTEX_HELD(&zp->z_acl_lock));378if (zp->z_is_sa) {379if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zfsvfs),380&size)) != 0)381return (error);382*aclsize = size;383if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_COUNT(zfsvfs),384&acl_count, sizeof (acl_count))) != 0)385return (error);386*aclcount = acl_count;387} else {388if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs),389aclphys, sizeof (*aclphys))) != 0)390return (error);391392if (aclphys->z_acl_version == ZFS_ACL_VERSION_INITIAL) {393*aclsize = ZFS_ACL_SIZE(aclphys->z_acl_size);394*aclcount = aclphys->z_acl_size;395} else {396*aclsize = aclphys->z_acl_size;397*aclcount = aclphys->z_acl_count;398}399}400return (0);401}402403int404zfs_znode_acl_version(znode_t *zp)405{406zfs_acl_phys_t acl_phys;407408if (zp->z_is_sa)409return (ZFS_ACL_VERSION_FUID);410else {411int error;412413/*414* Need to deal with a potential415* race where zfs_sa_upgrade could cause416* z_isa_sa to change.417*418* If the lookup fails then the state of z_is_sa should have419* changed.420*/421if ((error = sa_lookup(zp->z_sa_hdl,422SA_ZPL_ZNODE_ACL(ZTOZSB(zp)),423&acl_phys, sizeof (acl_phys))) == 0)424return (acl_phys.z_acl_version);425else {426/*427* After upgrade SA_ZPL_ZNODE_ACL should have428* been removed.429*/430VERIFY(zp->z_is_sa && error == ENOENT);431return (ZFS_ACL_VERSION_FUID);432}433}434}435436static int437zfs_acl_version(int version)438{439if (version < ZPL_VERSION_FUID)440return (ZFS_ACL_VERSION_INITIAL);441else442return (ZFS_ACL_VERSION_FUID);443}444445static int446zfs_acl_version_zp(znode_t *zp)447{448return (zfs_acl_version(ZTOZSB(zp)->z_version));449}450451zfs_acl_t *452zfs_acl_alloc(int vers)453{454zfs_acl_t *aclp;455456aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP);457list_create(&aclp->z_acl, sizeof (zfs_acl_node_t),458offsetof(zfs_acl_node_t, z_next));459aclp->z_version = vers;460if (vers == ZFS_ACL_VERSION_FUID)461aclp->z_ops = &zfs_acl_fuid_ops;462else463aclp->z_ops = &zfs_acl_v0_ops;464return (aclp);465}466467zfs_acl_node_t *468zfs_acl_node_alloc(size_t bytes)469{470zfs_acl_node_t *aclnode;471472aclnode = kmem_zalloc(sizeof (zfs_acl_node_t), KM_SLEEP);473if (bytes) {474aclnode->z_acldata = kmem_zalloc(bytes, KM_SLEEP);475aclnode->z_allocdata = aclnode->z_acldata;476aclnode->z_allocsize = bytes;477aclnode->z_size = bytes;478}479480return (aclnode);481}482483static void484zfs_acl_node_free(zfs_acl_node_t *aclnode)485{486if (aclnode->z_allocsize)487kmem_free(aclnode->z_allocdata, aclnode->z_allocsize);488kmem_free(aclnode, sizeof (zfs_acl_node_t));489}490491static void492zfs_acl_release_nodes(zfs_acl_t *aclp)493{494zfs_acl_node_t *aclnode;495496while ((aclnode = list_remove_head(&aclp->z_acl)))497zfs_acl_node_free(aclnode);498aclp->z_acl_count = 0;499aclp->z_acl_bytes = 0;500}501502void503zfs_acl_free(zfs_acl_t *aclp)504{505zfs_acl_release_nodes(aclp);506list_destroy(&aclp->z_acl);507kmem_free(aclp, sizeof (zfs_acl_t));508}509510static boolean_t511zfs_acl_valid_ace_type(uint_t type, uint_t flags)512{513uint16_t entry_type;514515switch (type) {516case ALLOW:517case DENY:518case ACE_SYSTEM_AUDIT_ACE_TYPE:519case ACE_SYSTEM_ALARM_ACE_TYPE:520entry_type = flags & ACE_TYPE_FLAGS;521return (entry_type == ACE_OWNER ||522entry_type == OWNING_GROUP ||523entry_type == ACE_EVERYONE || entry_type == 0 ||524entry_type == ACE_IDENTIFIER_GROUP);525default:526if (type <= MAX_ACE_TYPE)527return (B_TRUE);528}529return (B_FALSE);530}531532static boolean_t533zfs_ace_valid(umode_t obj_mode, zfs_acl_t *aclp, uint16_t type, uint16_t iflags)534{535/*536* first check type of entry537*/538539if (!zfs_acl_valid_ace_type(type, iflags))540return (B_FALSE);541542switch (type) {543case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:544case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:545case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:546case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:547if (aclp->z_version < ZFS_ACL_VERSION_FUID)548return (B_FALSE);549aclp->z_hints |= ZFS_ACL_OBJ_ACE;550}551552/*553* next check inheritance level flags554*/555556if (S_ISDIR(obj_mode) &&557(iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)))558aclp->z_hints |= ZFS_INHERIT_ACE;559560if (iflags & (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) {561if ((iflags & (ACE_FILE_INHERIT_ACE|562ACE_DIRECTORY_INHERIT_ACE)) == 0) {563return (B_FALSE);564}565}566567return (B_TRUE);568}569570static void *571zfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who,572uint32_t *access_mask, uint16_t *iflags, uint16_t *type)573{574zfs_acl_node_t *aclnode;575576ASSERT(aclp);577578if (start == NULL) {579aclnode = list_head(&aclp->z_acl);580if (aclnode == NULL)581return (NULL);582583aclp->z_next_ace = aclnode->z_acldata;584aclp->z_curr_node = aclnode;585aclnode->z_ace_idx = 0;586}587588aclnode = aclp->z_curr_node;589590if (aclnode == NULL)591return (NULL);592593if (aclnode->z_ace_idx >= aclnode->z_ace_count) {594aclnode = list_next(&aclp->z_acl, aclnode);595if (aclnode == NULL)596return (NULL);597else {598aclp->z_curr_node = aclnode;599aclnode->z_ace_idx = 0;600aclp->z_next_ace = aclnode->z_acldata;601}602}603604if (aclnode->z_ace_idx < aclnode->z_ace_count) {605void *acep = aclp->z_next_ace;606size_t ace_size;607608/*609* Make sure we don't overstep our bounds610*/611ace_size = aclp->z_ops->ace_size(acep);612613if (((caddr_t)acep + ace_size) >614((caddr_t)aclnode->z_acldata + aclnode->z_size)) {615return (NULL);616}617618*iflags = aclp->z_ops->ace_flags_get(acep);619*type = aclp->z_ops->ace_type_get(acep);620*access_mask = aclp->z_ops->ace_mask_get(acep);621*who = aclp->z_ops->ace_who_get(acep);622aclp->z_next_ace = (caddr_t)aclp->z_next_ace + ace_size;623aclnode->z_ace_idx++;624625return ((void *)acep);626}627return (NULL);628}629630static uintptr_t631zfs_ace_walk(void *datap, uintptr_t cookie, int aclcnt,632uint16_t *flags, uint16_t *type, uint32_t *mask)633{634(void) aclcnt;635zfs_acl_t *aclp = datap;636zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)cookie;637uint64_t who;638639acep = zfs_acl_next_ace(aclp, acep, &who, mask,640flags, type);641return ((uintptr_t)acep);642}643644/*645* Copy ACE to internal ZFS format.646* While processing the ACL each ACE will be validated for correctness.647* ACE FUIDs will be created later.648*/649static int650zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, umode_t obj_mode, zfs_acl_t *aclp,651void *datap, zfs_ace_t *z_acl, uint64_t aclcnt, size_t *size,652zfs_fuid_info_t **fuidp, cred_t *cr)653{654int i;655uint16_t entry_type;656zfs_ace_t *aceptr = z_acl;657ace_t *acep = datap;658zfs_object_ace_t *zobjacep;659ace_object_t *aceobjp;660661for (i = 0; i != aclcnt; i++) {662aceptr->z_hdr.z_access_mask = acep->a_access_mask;663aceptr->z_hdr.z_flags = acep->a_flags;664aceptr->z_hdr.z_type = acep->a_type;665entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS;666if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP &&667entry_type != ACE_EVERYONE) {668aceptr->z_fuid = zfs_fuid_create(zfsvfs, acep->a_who,669cr, (entry_type == 0) ?670ZFS_ACE_USER : ZFS_ACE_GROUP, fuidp);671}672673/*674* Make sure ACE is valid675*/676if (zfs_ace_valid(obj_mode, aclp, aceptr->z_hdr.z_type,677aceptr->z_hdr.z_flags) != B_TRUE)678return (SET_ERROR(EINVAL));679680switch (acep->a_type) {681case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:682case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:683case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:684case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:685zobjacep = (zfs_object_ace_t *)aceptr;686aceobjp = (ace_object_t *)acep;687688memcpy(zobjacep->z_object_type, aceobjp->a_obj_type,689sizeof (aceobjp->a_obj_type));690memcpy(zobjacep->z_inherit_type,691aceobjp->a_inherit_obj_type,692sizeof (aceobjp->a_inherit_obj_type));693acep = (ace_t *)((caddr_t)acep + sizeof (ace_object_t));694break;695default:696acep = (ace_t *)((caddr_t)acep + sizeof (ace_t));697}698699aceptr = (zfs_ace_t *)((caddr_t)aceptr +700aclp->z_ops->ace_size(aceptr));701}702703*size = (caddr_t)aceptr - (caddr_t)z_acl;704705return (0);706}707708/*709* Copy ZFS ACEs to fixed size ace_t layout710*/711static void712zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr,713void *datap, int filter)714{715uint64_t who;716uint32_t access_mask;717uint16_t iflags, type;718zfs_ace_hdr_t *zacep = NULL;719ace_t *acep = datap;720ace_object_t *objacep;721zfs_object_ace_t *zobjacep;722size_t ace_size;723uint16_t entry_type;724725while ((zacep = zfs_acl_next_ace(aclp, zacep,726&who, &access_mask, &iflags, &type))) {727728switch (type) {729case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:730case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:731case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:732case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:733if (filter) {734continue;735}736zobjacep = (zfs_object_ace_t *)zacep;737objacep = (ace_object_t *)acep;738memcpy(objacep->a_obj_type,739zobjacep->z_object_type,740sizeof (zobjacep->z_object_type));741memcpy(objacep->a_inherit_obj_type,742zobjacep->z_inherit_type,743sizeof (zobjacep->z_inherit_type));744ace_size = sizeof (ace_object_t);745break;746default:747ace_size = sizeof (ace_t);748break;749}750751entry_type = (iflags & ACE_TYPE_FLAGS);752if ((entry_type != ACE_OWNER &&753entry_type != OWNING_GROUP &&754entry_type != ACE_EVERYONE)) {755acep->a_who = zfs_fuid_map_id(zfsvfs, who,756cr, (entry_type & ACE_IDENTIFIER_GROUP) ?757ZFS_ACE_GROUP : ZFS_ACE_USER);758} else {759acep->a_who = (uid_t)(int64_t)who;760}761acep->a_access_mask = access_mask;762acep->a_flags = iflags;763acep->a_type = type;764acep = (ace_t *)((caddr_t)acep + ace_size);765}766}767768static int769zfs_copy_ace_2_oldace(umode_t obj_mode, zfs_acl_t *aclp, ace_t *acep,770zfs_oldace_t *z_acl, int aclcnt, size_t *size)771{772int i;773zfs_oldace_t *aceptr = z_acl;774775for (i = 0; i != aclcnt; i++, aceptr++) {776aceptr->z_access_mask = acep[i].a_access_mask;777aceptr->z_type = acep[i].a_type;778aceptr->z_flags = acep[i].a_flags;779aceptr->z_fuid = acep[i].a_who;780/*781* Make sure ACE is valid782*/783if (zfs_ace_valid(obj_mode, aclp, aceptr->z_type,784aceptr->z_flags) != B_TRUE)785return (SET_ERROR(EINVAL));786}787*size = (caddr_t)aceptr - (caddr_t)z_acl;788return (0);789}790791/*792* convert old ACL format to new793*/794void795zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr)796{797zfs_oldace_t *oldaclp;798int i;799uint16_t type, iflags;800uint32_t access_mask;801uint64_t who;802void *cookie = NULL;803zfs_acl_node_t *newaclnode;804805ASSERT(aclp->z_version == ZFS_ACL_VERSION_INITIAL);806/*807* First create the ACE in a contiguous piece of memory808* for zfs_copy_ace_2_fuid().809*810* We only convert an ACL once, so this won't happen811* every time.812*/813oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count,814KM_SLEEP);815i = 0;816while ((cookie = zfs_acl_next_ace(aclp, cookie, &who,817&access_mask, &iflags, &type))) {818oldaclp[i].z_flags = iflags;819oldaclp[i].z_type = type;820oldaclp[i].z_fuid = who;821oldaclp[i++].z_access_mask = access_mask;822}823824newaclnode = zfs_acl_node_alloc(aclp->z_acl_count *825sizeof (zfs_object_ace_t));826aclp->z_ops = &zfs_acl_fuid_ops;827VERIFY(zfs_copy_ace_2_fuid(ZTOZSB(zp), ZTOI(zp)->i_mode,828aclp, oldaclp, newaclnode->z_acldata, aclp->z_acl_count,829&newaclnode->z_size, NULL, cr) == 0);830newaclnode->z_ace_count = aclp->z_acl_count;831aclp->z_version = ZFS_ACL_VERSION;832kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t));833834/*835* Release all previous ACL nodes836*/837838zfs_acl_release_nodes(aclp);839840list_insert_head(&aclp->z_acl, newaclnode);841842aclp->z_acl_bytes = newaclnode->z_size;843aclp->z_acl_count = newaclnode->z_ace_count;844845}846847/*848* Convert unix access mask to v4 access mask849*/850static uint32_t851zfs_unix_to_v4(uint32_t access_mask)852{853uint32_t new_mask = 0;854855if (access_mask & S_IXOTH)856new_mask |= ACE_EXECUTE;857if (access_mask & S_IWOTH)858new_mask |= ACE_WRITE_DATA;859if (access_mask & S_IROTH)860new_mask |= ACE_READ_DATA;861return (new_mask);862}863864865static int866zfs_v4_to_unix(uint32_t access_mask, int *unmapped)867{868int new_mask = 0;869870*unmapped = access_mask &871(ACE_WRITE_OWNER | ACE_WRITE_ACL | ACE_DELETE);872873if (access_mask & WRITE_MASK)874new_mask |= S_IWOTH;875if (access_mask & ACE_READ_DATA)876new_mask |= S_IROTH;877if (access_mask & ACE_EXECUTE)878new_mask |= S_IXOTH;879880return (new_mask);881}882883884static void885zfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask,886uint16_t access_type, uint64_t fuid, uint16_t entry_type)887{888uint16_t type = entry_type & ACE_TYPE_FLAGS;889890aclp->z_ops->ace_mask_set(acep, access_mask);891aclp->z_ops->ace_type_set(acep, access_type);892aclp->z_ops->ace_flags_set(acep, entry_type);893if ((type != ACE_OWNER && type != OWNING_GROUP &&894type != ACE_EVERYONE))895aclp->z_ops->ace_who_set(acep, fuid);896}897898/*899* Determine mode of file based on ACL.900*/901uint64_t902zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp,903uint64_t *pflags, uint64_t fuid, uint64_t fgid)904{905int entry_type;906mode_t mode;907mode_t seen = 0;908zfs_ace_hdr_t *acep = NULL;909uint64_t who;910uint16_t iflags, type;911uint32_t access_mask;912boolean_t an_exec_denied = B_FALSE;913914mode = (fmode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX));915916while ((acep = zfs_acl_next_ace(aclp, acep, &who,917&access_mask, &iflags, &type))) {918919if (!zfs_acl_valid_ace_type(type, iflags))920continue;921922entry_type = (iflags & ACE_TYPE_FLAGS);923924/*925* Skip over any inherit_only ACEs926*/927if (iflags & ACE_INHERIT_ONLY_ACE)928continue;929930if (entry_type == ACE_OWNER || (entry_type == 0 &&931who == fuid)) {932if ((access_mask & ACE_READ_DATA) &&933(!(seen & S_IRUSR))) {934seen |= S_IRUSR;935if (type == ALLOW) {936mode |= S_IRUSR;937}938}939if ((access_mask & ACE_WRITE_DATA) &&940(!(seen & S_IWUSR))) {941seen |= S_IWUSR;942if (type == ALLOW) {943mode |= S_IWUSR;944}945}946if ((access_mask & ACE_EXECUTE) &&947(!(seen & S_IXUSR))) {948seen |= S_IXUSR;949if (type == ALLOW) {950mode |= S_IXUSR;951}952}953} else if (entry_type == OWNING_GROUP ||954(entry_type == ACE_IDENTIFIER_GROUP && who == fgid)) {955if ((access_mask & ACE_READ_DATA) &&956(!(seen & S_IRGRP))) {957seen |= S_IRGRP;958if (type == ALLOW) {959mode |= S_IRGRP;960}961}962if ((access_mask & ACE_WRITE_DATA) &&963(!(seen & S_IWGRP))) {964seen |= S_IWGRP;965if (type == ALLOW) {966mode |= S_IWGRP;967}968}969if ((access_mask & ACE_EXECUTE) &&970(!(seen & S_IXGRP))) {971seen |= S_IXGRP;972if (type == ALLOW) {973mode |= S_IXGRP;974}975}976} else if (entry_type == ACE_EVERYONE) {977if ((access_mask & ACE_READ_DATA)) {978if (!(seen & S_IRUSR)) {979seen |= S_IRUSR;980if (type == ALLOW) {981mode |= S_IRUSR;982}983}984if (!(seen & S_IRGRP)) {985seen |= S_IRGRP;986if (type == ALLOW) {987mode |= S_IRGRP;988}989}990if (!(seen & S_IROTH)) {991seen |= S_IROTH;992if (type == ALLOW) {993mode |= S_IROTH;994}995}996}997if ((access_mask & ACE_WRITE_DATA)) {998if (!(seen & S_IWUSR)) {999seen |= S_IWUSR;1000if (type == ALLOW) {1001mode |= S_IWUSR;1002}1003}1004if (!(seen & S_IWGRP)) {1005seen |= S_IWGRP;1006if (type == ALLOW) {1007mode |= S_IWGRP;1008}1009}1010if (!(seen & S_IWOTH)) {1011seen |= S_IWOTH;1012if (type == ALLOW) {1013mode |= S_IWOTH;1014}1015}1016}1017if ((access_mask & ACE_EXECUTE)) {1018if (!(seen & S_IXUSR)) {1019seen |= S_IXUSR;1020if (type == ALLOW) {1021mode |= S_IXUSR;1022}1023}1024if (!(seen & S_IXGRP)) {1025seen |= S_IXGRP;1026if (type == ALLOW) {1027mode |= S_IXGRP;1028}1029}1030if (!(seen & S_IXOTH)) {1031seen |= S_IXOTH;1032if (type == ALLOW) {1033mode |= S_IXOTH;1034}1035}1036}1037} else {1038/*1039* Only care if this IDENTIFIER_GROUP or1040* USER ACE denies execute access to someone,1041* mode is not affected1042*/1043if ((access_mask & ACE_EXECUTE) && type == DENY)1044an_exec_denied = B_TRUE;1045}1046}10471048/*1049* Failure to allow is effectively a deny, so execute permission1050* is denied if it was never mentioned or if we explicitly1051* weren't allowed it.1052*/1053if (!an_exec_denied &&1054((seen & ALL_MODE_EXECS) != ALL_MODE_EXECS ||1055(mode & ALL_MODE_EXECS) != ALL_MODE_EXECS))1056an_exec_denied = B_TRUE;10571058if (an_exec_denied)1059*pflags &= ~ZFS_NO_EXECS_DENIED;1060else1061*pflags |= ZFS_NO_EXECS_DENIED;10621063return (mode);1064}10651066/*1067* Read an external acl object. If the intent is to modify, always1068* create a new acl and leave any cached acl in place.1069*/1070int1071zfs_acl_node_read(struct znode *zp, boolean_t have_lock, zfs_acl_t **aclpp,1072boolean_t will_modify)1073{1074zfs_acl_t *aclp;1075int aclsize = 0;1076int acl_count = 0;1077zfs_acl_node_t *aclnode;1078zfs_acl_phys_t znode_acl;1079int version;1080int error;1081boolean_t drop_lock = B_FALSE;10821083ASSERT(MUTEX_HELD(&zp->z_acl_lock));10841085if (zp->z_acl_cached && !will_modify) {1086*aclpp = zp->z_acl_cached;1087return (0);1088}10891090/*1091* close race where znode could be upgrade while trying to1092* read the znode attributes.1093*1094* But this could only happen if the file isn't already an SA1095* znode1096*/1097if (!zp->z_is_sa && !have_lock) {1098mutex_enter(&zp->z_lock);1099drop_lock = B_TRUE;1100}1101version = zfs_znode_acl_version(zp);11021103if ((error = zfs_acl_znode_info(zp, &aclsize,1104&acl_count, &znode_acl)) != 0) {1105goto done;1106}11071108aclp = zfs_acl_alloc(version);11091110aclp->z_acl_count = acl_count;1111aclp->z_acl_bytes = aclsize;11121113aclnode = zfs_acl_node_alloc(aclsize);1114aclnode->z_ace_count = aclp->z_acl_count;1115aclnode->z_size = aclsize;11161117if (!zp->z_is_sa) {1118if (znode_acl.z_acl_extern_obj) {1119error = dmu_read(ZTOZSB(zp)->z_os,1120znode_acl.z_acl_extern_obj, 0, aclnode->z_size,1121aclnode->z_acldata, DMU_READ_PREFETCH);1122} else {1123memcpy(aclnode->z_acldata, znode_acl.z_ace_data,1124aclnode->z_size);1125}1126} else {1127error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_ACES(ZTOZSB(zp)),1128aclnode->z_acldata, aclnode->z_size);1129}11301131if (error != 0) {1132zfs_acl_free(aclp);1133zfs_acl_node_free(aclnode);1134/* convert checksum errors into IO errors */1135if (error == ECKSUM)1136error = SET_ERROR(EIO);1137goto done;1138}11391140list_insert_head(&aclp->z_acl, aclnode);11411142*aclpp = aclp;1143if (!will_modify)1144zp->z_acl_cached = aclp;1145done:1146if (drop_lock)1147mutex_exit(&zp->z_lock);1148return (error);1149}11501151void1152zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen,1153boolean_t start, void *userdata)1154{1155(void) buflen;1156zfs_acl_locator_cb_t *cb = (zfs_acl_locator_cb_t *)userdata;11571158if (start) {1159cb->cb_acl_node = list_head(&cb->cb_aclp->z_acl);1160} else {1161cb->cb_acl_node = list_next(&cb->cb_aclp->z_acl,1162cb->cb_acl_node);1163}1164ASSERT3P(cb->cb_acl_node, !=, NULL);1165*dataptr = cb->cb_acl_node->z_acldata;1166*length = cb->cb_acl_node->z_size;1167}11681169int1170zfs_acl_chown_setattr(znode_t *zp)1171{1172int error;1173zfs_acl_t *aclp;11741175if (ZTOZSB(zp)->z_acl_type == ZFS_ACLTYPE_POSIX)1176return (0);11771178ASSERT(MUTEX_HELD(&zp->z_lock));1179ASSERT(MUTEX_HELD(&zp->z_acl_lock));11801181error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE);1182if (error == 0 && aclp->z_acl_count > 0)1183zp->z_mode = ZTOI(zp)->i_mode =1184zfs_mode_compute(zp->z_mode, aclp,1185&zp->z_pflags, KUID_TO_SUID(ZTOI(zp)->i_uid),1186KGID_TO_SGID(ZTOI(zp)->i_gid));11871188/*1189* Some ZFS implementations (ZEVO) create neither a ZNODE_ACL1190* nor a DACL_ACES SA in which case ENOENT is returned from1191* zfs_acl_node_read() when the SA can't be located.1192* Allow chown/chgrp to succeed in these cases rather than1193* returning an error that makes no sense in the context of1194* the caller.1195*/1196if (error == ENOENT)1197return (0);11981199return (error);1200}12011202typedef struct trivial_acl {1203uint32_t allow0; /* allow mask for bits only in owner */1204uint32_t deny1; /* deny mask for bits not in owner */1205uint32_t deny2; /* deny mask for bits not in group */1206uint32_t owner; /* allow mask matching mode */1207uint32_t group; /* allow mask matching mode */1208uint32_t everyone; /* allow mask matching mode */1209} trivial_acl_t;12101211static void1212acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks)1213{1214uint32_t read_mask = ACE_READ_DATA;1215uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA;1216uint32_t execute_mask = ACE_EXECUTE;12171218if (isdir)1219write_mask |= ACE_DELETE_CHILD;12201221masks->deny1 = 0;12221223if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))1224masks->deny1 |= read_mask;1225if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))1226masks->deny1 |= write_mask;1227if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))1228masks->deny1 |= execute_mask;12291230masks->deny2 = 0;1231if (!(mode & S_IRGRP) && (mode & S_IROTH))1232masks->deny2 |= read_mask;1233if (!(mode & S_IWGRP) && (mode & S_IWOTH))1234masks->deny2 |= write_mask;1235if (!(mode & S_IXGRP) && (mode & S_IXOTH))1236masks->deny2 |= execute_mask;12371238masks->allow0 = 0;1239if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))1240masks->allow0 |= read_mask;1241if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))1242masks->allow0 |= write_mask;1243if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))1244masks->allow0 |= execute_mask;12451246masks->owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|1247ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES|1248ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE;1249if (mode & S_IRUSR)1250masks->owner |= read_mask;1251if (mode & S_IWUSR)1252masks->owner |= write_mask;1253if (mode & S_IXUSR)1254masks->owner |= execute_mask;12551256masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|1257ACE_SYNCHRONIZE;1258if (mode & S_IRGRP)1259masks->group |= read_mask;1260if (mode & S_IWGRP)1261masks->group |= write_mask;1262if (mode & S_IXGRP)1263masks->group |= execute_mask;12641265masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|1266ACE_SYNCHRONIZE;1267if (mode & S_IROTH)1268masks->everyone |= read_mask;1269if (mode & S_IWOTH)1270masks->everyone |= write_mask;1271if (mode & S_IXOTH)1272masks->everyone |= execute_mask;1273}12741275/*1276* ace_trivial:1277* determine whether an ace_t acl is trivial1278*1279* Trivialness implies that the acl is composed of only1280* owner, group, everyone entries. ACL can't1281* have read_acl denied, and write_owner/write_acl/write_attributes1282* can only be owner@ entry.1283*/1284static int1285ace_trivial_common(void *acep, int aclcnt,1286uintptr_t (*walk)(void *, uintptr_t, int,1287uint16_t *, uint16_t *, uint32_t *))1288{1289uint16_t flags;1290uint32_t mask;1291uint16_t type;1292uint64_t cookie = 0;12931294while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) {1295switch (flags & ACE_TYPE_FLAGS) {1296case ACE_OWNER:1297case ACE_GROUP|ACE_IDENTIFIER_GROUP:1298case ACE_EVERYONE:1299break;1300default:1301return (1);1302}13031304if (flags & (ACE_FILE_INHERIT_ACE|1305ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|1306ACE_INHERIT_ONLY_ACE))1307return (1);13081309/*1310* Special check for some special bits1311*1312* Don't allow anybody to deny reading basic1313* attributes or a files ACL.1314*/1315if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&1316(type == ACE_ACCESS_DENIED_ACE_TYPE))1317return (1);13181319/*1320* Delete permission is never set by default1321*/1322if (mask & ACE_DELETE)1323return (1);13241325/*1326* Child delete permission should be accompanied by write1327*/1328if ((mask & ACE_DELETE_CHILD) && !(mask & ACE_WRITE_DATA))1329return (1);13301331/*1332* only allow owner@ to have1333* write_acl/write_owner/write_attributes/write_xattr/1334*/1335if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&1336(!(flags & ACE_OWNER) && (mask &1337(ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|1338ACE_WRITE_NAMED_ATTRS))))1339return (1);13401341}13421343return (0);1344}13451346/*1347* common code for setting ACLs.1348*1349* This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl.1350* zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's1351* already checked the acl and knows whether to inherit.1352*/1353int1354zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)1355{1356int error;1357zfsvfs_t *zfsvfs = ZTOZSB(zp);1358dmu_object_type_t otype;1359zfs_acl_locator_cb_t locate = { 0 };1360uint64_t mode;1361sa_bulk_attr_t bulk[5];1362uint64_t ctime[2];1363int count = 0;1364zfs_acl_phys_t acl_phys;13651366mode = zp->z_mode;13671368mode = zfs_mode_compute(mode, aclp, &zp->z_pflags,1369KUID_TO_SUID(ZTOI(zp)->i_uid), KGID_TO_SGID(ZTOI(zp)->i_gid));13701371zp->z_mode = ZTOI(zp)->i_mode = mode;1372SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,1373&mode, sizeof (mode));1374SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,1375&zp->z_pflags, sizeof (zp->z_pflags));1376SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,1377&ctime, sizeof (ctime));13781379if (zp->z_acl_cached) {1380zfs_acl_free(zp->z_acl_cached);1381zp->z_acl_cached = NULL;1382}13831384/*1385* Upgrade needed?1386*/1387if (!zfsvfs->z_use_fuids) {1388otype = DMU_OT_OLDACL;1389} else {1390if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) &&1391(zfsvfs->z_version >= ZPL_VERSION_FUID))1392zfs_acl_xform(zp, aclp, cr);1393ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID);1394otype = DMU_OT_ACL;1395}13961397/*1398* Arrgh, we have to handle old on disk format1399* as well as newer (preferred) SA format.1400*/14011402if (zp->z_is_sa) { /* the easy case, just update the ACL attribute */1403locate.cb_aclp = aclp;1404SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_ACES(zfsvfs),1405zfs_acl_data_locator, &locate, aclp->z_acl_bytes);1406SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_COUNT(zfsvfs),1407NULL, &aclp->z_acl_count, sizeof (uint64_t));1408} else { /* Painful legacy way */1409zfs_acl_node_t *aclnode;1410uint64_t off = 0;1411uint64_t aoid;14121413if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs),1414&acl_phys, sizeof (acl_phys))) != 0)1415return (error);14161417aoid = acl_phys.z_acl_extern_obj;14181419if (aclp->z_acl_bytes > ZFS_ACE_SPACE) {1420/*1421* If ACL was previously external and we are now1422* converting to new ACL format then release old1423* ACL object and create a new one.1424*/1425if (aoid &&1426aclp->z_version != acl_phys.z_acl_version) {1427error = dmu_object_free(zfsvfs->z_os, aoid, tx);1428if (error)1429return (error);1430aoid = 0;1431}1432if (aoid == 0) {1433aoid = dmu_object_alloc(zfsvfs->z_os,1434otype, aclp->z_acl_bytes,1435otype == DMU_OT_ACL ?1436DMU_OT_SYSACL : DMU_OT_NONE,1437otype == DMU_OT_ACL ?1438DN_OLD_MAX_BONUSLEN : 0, tx);1439} else {1440(void) dmu_object_set_blocksize(zfsvfs->z_os,1441aoid, aclp->z_acl_bytes, 0, tx);1442}1443acl_phys.z_acl_extern_obj = aoid;1444for (aclnode = list_head(&aclp->z_acl); aclnode;1445aclnode = list_next(&aclp->z_acl, aclnode)) {1446if (aclnode->z_ace_count == 0)1447continue;1448dmu_write(zfsvfs->z_os, aoid, off,1449aclnode->z_size, aclnode->z_acldata, tx);1450off += aclnode->z_size;1451}1452} else {1453void *start = acl_phys.z_ace_data;1454/*1455* Migrating back embedded?1456*/1457if (acl_phys.z_acl_extern_obj) {1458error = dmu_object_free(zfsvfs->z_os,1459acl_phys.z_acl_extern_obj, tx);1460if (error)1461return (error);1462acl_phys.z_acl_extern_obj = 0;1463}14641465for (aclnode = list_head(&aclp->z_acl); aclnode;1466aclnode = list_next(&aclp->z_acl, aclnode)) {1467if (aclnode->z_ace_count == 0)1468continue;1469memcpy(start, aclnode->z_acldata,1470aclnode->z_size);1471start = (caddr_t)start + aclnode->z_size;1472}1473}1474/*1475* If Old version then swap count/bytes to match old1476* layout of znode_acl_phys_t.1477*/1478if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) {1479acl_phys.z_acl_size = aclp->z_acl_count;1480acl_phys.z_acl_count = aclp->z_acl_bytes;1481} else {1482acl_phys.z_acl_size = aclp->z_acl_bytes;1483acl_phys.z_acl_count = aclp->z_acl_count;1484}1485acl_phys.z_acl_version = aclp->z_version;14861487SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,1488&acl_phys, sizeof (acl_phys));1489}14901491/*1492* Replace ACL wide bits, but first clear them.1493*/1494zp->z_pflags &= ~ZFS_ACL_WIDE_FLAGS;14951496zp->z_pflags |= aclp->z_hints;14971498if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0)1499zp->z_pflags |= ZFS_ACL_TRIVIAL;15001501zfs_tstamp_update_setup(zp, STATE_CHANGED, NULL, ctime);1502return (sa_bulk_update(zp->z_sa_hdl, bulk, count, tx));1503}15041505static void1506zfs_acl_chmod(boolean_t isdir, uint64_t mode, boolean_t split, boolean_t trim,1507zfs_acl_t *aclp)1508{1509void *acep = NULL;1510uint64_t who;1511int new_count, new_bytes;1512int ace_size;1513int entry_type;1514uint16_t iflags, type;1515uint32_t access_mask;1516zfs_acl_node_t *newnode;1517size_t abstract_size = aclp->z_ops->ace_abstract_size();1518void *zacep;1519trivial_acl_t masks;15201521new_count = new_bytes = 0;15221523acl_trivial_access_masks((mode_t)mode, isdir, &masks);15241525newnode = zfs_acl_node_alloc((abstract_size * 6) + aclp->z_acl_bytes);15261527zacep = newnode->z_acldata;1528if (masks.allow0) {1529zfs_set_ace(aclp, zacep, masks.allow0, ALLOW, -1, ACE_OWNER);1530zacep = (void *)((uintptr_t)zacep + abstract_size);1531new_count++;1532new_bytes += abstract_size;1533}1534if (masks.deny1) {1535zfs_set_ace(aclp, zacep, masks.deny1, DENY, -1, ACE_OWNER);1536zacep = (void *)((uintptr_t)zacep + abstract_size);1537new_count++;1538new_bytes += abstract_size;1539}1540if (masks.deny2) {1541zfs_set_ace(aclp, zacep, masks.deny2, DENY, -1, OWNING_GROUP);1542zacep = (void *)((uintptr_t)zacep + abstract_size);1543new_count++;1544new_bytes += abstract_size;1545}15461547while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,1548&iflags, &type))) {1549entry_type = (iflags & ACE_TYPE_FLAGS);1550/*1551* ACEs used to represent the file mode may be divided1552* into an equivalent pair of inherit-only and regular1553* ACEs, if they are inheritable.1554* Skip regular ACEs, which are replaced by the new mode.1555*/1556if (split && (entry_type == ACE_OWNER ||1557entry_type == OWNING_GROUP ||1558entry_type == ACE_EVERYONE)) {1559if (!isdir || !(iflags &1560(ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)))1561continue;1562/*1563* We preserve owner@, group@, or @everyone1564* permissions, if they are inheritable, by1565* copying them to inherit_only ACEs. This1566* prevents inheritable permissions from being1567* altered along with the file mode.1568*/1569iflags |= ACE_INHERIT_ONLY_ACE;1570}15711572/*1573* If this ACL has any inheritable ACEs, mark that in1574* the hints (which are later masked into the pflags)1575* so create knows to do inheritance.1576*/1577if (isdir && (iflags &1578(ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)))1579aclp->z_hints |= ZFS_INHERIT_ACE;15801581if ((type != ALLOW && type != DENY) ||1582(iflags & ACE_INHERIT_ONLY_ACE)) {1583switch (type) {1584case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:1585case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:1586case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:1587case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:1588aclp->z_hints |= ZFS_ACL_OBJ_ACE;1589break;1590}1591} else {1592/*1593* Limit permissions to be no greater than1594* group permissions.1595* The "aclinherit" and "aclmode" properties1596* affect policy for create and chmod(2),1597* respectively.1598*/1599if ((type == ALLOW) && trim)1600access_mask &= masks.group;1601}1602zfs_set_ace(aclp, zacep, access_mask, type, who, iflags);1603ace_size = aclp->z_ops->ace_size(acep);1604zacep = (void *)((uintptr_t)zacep + ace_size);1605new_count++;1606new_bytes += ace_size;1607}1608zfs_set_ace(aclp, zacep, masks.owner, ALLOW, -1, ACE_OWNER);1609zacep = (void *)((uintptr_t)zacep + abstract_size);1610zfs_set_ace(aclp, zacep, masks.group, ALLOW, -1, OWNING_GROUP);1611zacep = (void *)((uintptr_t)zacep + abstract_size);1612zfs_set_ace(aclp, zacep, masks.everyone, ALLOW, -1, ACE_EVERYONE);16131614new_count += 3;1615new_bytes += abstract_size * 3;1616zfs_acl_release_nodes(aclp);1617aclp->z_acl_count = new_count;1618aclp->z_acl_bytes = new_bytes;1619newnode->z_ace_count = new_count;1620newnode->z_size = new_bytes;1621list_insert_tail(&aclp->z_acl, newnode);1622}16231624int1625zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode)1626{1627int error = 0;16281629mutex_enter(&zp->z_acl_lock);1630mutex_enter(&zp->z_lock);1631if (ZTOZSB(zp)->z_acl_mode == ZFS_ACL_DISCARD)1632*aclp = zfs_acl_alloc(zfs_acl_version_zp(zp));1633else1634error = zfs_acl_node_read(zp, B_TRUE, aclp, B_TRUE);16351636if (error == 0) {1637(*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS;1638zfs_acl_chmod(S_ISDIR(ZTOI(zp)->i_mode), mode, B_TRUE,1639(ZTOZSB(zp)->z_acl_mode == ZFS_ACL_GROUPMASK), *aclp);1640}1641mutex_exit(&zp->z_lock);1642mutex_exit(&zp->z_acl_lock);16431644return (error);1645}16461647/*1648* Should ACE be inherited?1649*/1650static int1651zfs_ace_can_use(umode_t obj_mode, uint16_t acep_flags)1652{1653int iflags = (acep_flags & 0xf);16541655if (S_ISDIR(obj_mode) && (iflags & ACE_DIRECTORY_INHERIT_ACE))1656return (1);1657else if (iflags & ACE_FILE_INHERIT_ACE)1658return (!(S_ISDIR(obj_mode) &&1659(iflags & ACE_NO_PROPAGATE_INHERIT_ACE)));1660return (0);1661}16621663/*1664* inherit inheritable ACEs from parent1665*/1666static zfs_acl_t *1667zfs_acl_inherit(zfsvfs_t *zfsvfs, umode_t va_mode, zfs_acl_t *paclp,1668uint64_t mode, boolean_t *need_chmod)1669{1670void *pacep = NULL;1671void *acep;1672zfs_acl_node_t *aclnode;1673zfs_acl_t *aclp = NULL;1674uint64_t who;1675uint32_t access_mask;1676uint16_t iflags, newflags, type;1677size_t ace_size;1678void *data1, *data2;1679size_t data1sz, data2sz;1680uint_t aclinherit;1681boolean_t isdir = S_ISDIR(va_mode);1682boolean_t isreg = S_ISREG(va_mode);16831684*need_chmod = B_TRUE;16851686aclp = zfs_acl_alloc(paclp->z_version);1687aclinherit = zfsvfs->z_acl_inherit;1688if (aclinherit == ZFS_ACL_DISCARD || S_ISLNK(va_mode))1689return (aclp);16901691while ((pacep = zfs_acl_next_ace(paclp, pacep, &who,1692&access_mask, &iflags, &type))) {16931694/*1695* don't inherit bogus ACEs1696*/1697if (!zfs_acl_valid_ace_type(type, iflags))1698continue;16991700/*1701* Check if ACE is inheritable by this vnode1702*/1703if ((aclinherit == ZFS_ACL_NOALLOW && type == ALLOW) ||1704!zfs_ace_can_use(va_mode, iflags))1705continue;17061707/*1708* If owner@, group@, or everyone@ inheritable1709* then zfs_acl_chmod() isn't needed.1710*/1711if ((aclinherit == ZFS_ACL_PASSTHROUGH ||1712aclinherit == ZFS_ACL_PASSTHROUGH_X) &&1713((iflags & (ACE_OWNER|ACE_EVERYONE)) ||1714((iflags & OWNING_GROUP) == OWNING_GROUP)) &&1715(isreg || (isdir && (iflags & ACE_DIRECTORY_INHERIT_ACE))))1716*need_chmod = B_FALSE;17171718/*1719* Strip inherited execute permission from file if1720* not in mode1721*/1722if (aclinherit == ZFS_ACL_PASSTHROUGH_X && type == ALLOW &&1723!isdir && ((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)) {1724access_mask &= ~ACE_EXECUTE;1725}17261727/*1728* Strip write_acl and write_owner from permissions1729* when inheriting an ACE1730*/1731if (aclinherit == ZFS_ACL_RESTRICTED && type == ALLOW) {1732access_mask &= ~RESTRICTED_CLEAR;1733}17341735ace_size = aclp->z_ops->ace_size(pacep);1736aclnode = zfs_acl_node_alloc(ace_size);1737list_insert_tail(&aclp->z_acl, aclnode);1738acep = aclnode->z_acldata;17391740zfs_set_ace(aclp, acep, access_mask, type,1741who, iflags|ACE_INHERITED_ACE);17421743/*1744* Copy special opaque data if any1745*/1746if ((data1sz = paclp->z_ops->ace_data(pacep, &data1)) != 0) {1747VERIFY((data2sz = aclp->z_ops->ace_data(acep,1748&data2)) == data1sz);1749memcpy(data2, data1, data2sz);1750}17511752aclp->z_acl_count++;1753aclnode->z_ace_count++;1754aclp->z_acl_bytes += aclnode->z_size;1755newflags = aclp->z_ops->ace_flags_get(acep);17561757/*1758* If ACE is not to be inherited further, or if the vnode is1759* not a directory, remove all inheritance flags1760*/1761if (!isdir || (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) {1762newflags &= ~ALL_INHERIT;1763aclp->z_ops->ace_flags_set(acep,1764newflags|ACE_INHERITED_ACE);1765continue;1766}17671768/*1769* This directory has an inheritable ACE1770*/1771aclp->z_hints |= ZFS_INHERIT_ACE;17721773/*1774* If only FILE_INHERIT is set then turn on1775* inherit_only1776*/1777if ((iflags & (ACE_FILE_INHERIT_ACE |1778ACE_DIRECTORY_INHERIT_ACE)) == ACE_FILE_INHERIT_ACE) {1779newflags |= ACE_INHERIT_ONLY_ACE;1780aclp->z_ops->ace_flags_set(acep,1781newflags|ACE_INHERITED_ACE);1782} else {1783newflags &= ~ACE_INHERIT_ONLY_ACE;1784aclp->z_ops->ace_flags_set(acep,1785newflags|ACE_INHERITED_ACE);1786}1787}1788if (zfsvfs->z_acl_mode == ZFS_ACL_RESTRICTED &&1789aclp->z_acl_count != 0) {1790*need_chmod = B_FALSE;1791}17921793return (aclp);1794}17951796/*1797* Create file system object initial permissions1798* including inheritable ACEs.1799* Also, create FUIDs for owner and group.1800*/1801int1802zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,1803vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns)1804{1805int error;1806zfsvfs_t *zfsvfs = ZTOZSB(dzp);1807zfs_acl_t *paclp;1808gid_t gid = vap->va_gid;1809boolean_t need_chmod = B_TRUE;1810boolean_t trim = B_FALSE;1811boolean_t inherited = B_FALSE;18121813memset(acl_ids, 0, sizeof (zfs_acl_ids_t));1814acl_ids->z_mode = vap->va_mode;18151816if (vsecp)1817if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_mode, vsecp,1818cr, &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0)1819return (error);18201821acl_ids->z_fuid = vap->va_uid;1822acl_ids->z_fgid = vap->va_gid;1823#ifdef HAVE_KSID1824/*1825* Determine uid and gid.1826*/1827if ((flag & IS_ROOT_NODE) || zfsvfs->z_replay ||1828((flag & IS_XATTR) && (S_ISDIR(vap->va_mode)))) {1829acl_ids->z_fuid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_uid,1830cr, ZFS_OWNER, &acl_ids->z_fuidp);1831acl_ids->z_fgid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_gid,1832cr, ZFS_GROUP, &acl_ids->z_fuidp);1833gid = vap->va_gid;1834} else {1835acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER,1836cr, &acl_ids->z_fuidp);1837acl_ids->z_fgid = 0;1838if (vap->va_mask & AT_GID) {1839acl_ids->z_fgid = zfs_fuid_create(zfsvfs,1840(uint64_t)vap->va_gid,1841cr, ZFS_GROUP, &acl_ids->z_fuidp);1842gid = vap->va_gid;1843if (acl_ids->z_fgid != KGID_TO_SGID(ZTOI(dzp)->i_gid) &&1844!groupmember(vap->va_gid, cr) &&1845secpolicy_vnode_create_gid(cr) != 0)1846acl_ids->z_fgid = 0;1847}1848if (acl_ids->z_fgid == 0) {1849if (dzp->z_mode & S_ISGID) {1850char *domain;1851uint32_t rid;18521853acl_ids->z_fgid = KGID_TO_SGID(1854ZTOI(dzp)->i_gid);1855gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid,1856cr, ZFS_GROUP);18571858if (zfsvfs->z_use_fuids &&1859IS_EPHEMERAL(acl_ids->z_fgid)) {1860domain = zfs_fuid_idx_domain(1861&zfsvfs->z_fuid_idx,1862FUID_INDEX(acl_ids->z_fgid));1863rid = FUID_RID(acl_ids->z_fgid);1864zfs_fuid_node_add(&acl_ids->z_fuidp,1865domain, rid,1866FUID_INDEX(acl_ids->z_fgid),1867acl_ids->z_fgid, ZFS_GROUP);1868}1869} else {1870acl_ids->z_fgid = zfs_fuid_create_cred(zfsvfs,1871ZFS_GROUP, cr, &acl_ids->z_fuidp);1872gid = crgetgid(cr);1873}1874}1875}1876#endif /* HAVE_KSID */18771878/*1879* If we're creating a directory, and the parent directory has the1880* set-GID bit set, set in on the new directory.1881* Otherwise, if the user is neither privileged nor a member of the1882* file's new group, clear the file's set-GID bit.1883*/18841885if (!(flag & IS_ROOT_NODE) && (dzp->z_mode & S_ISGID) &&1886(S_ISDIR(vap->va_mode))) {1887acl_ids->z_mode |= S_ISGID;1888} else {1889if ((acl_ids->z_mode & S_ISGID) &&1890secpolicy_vnode_setids_setgids(cr, gid, mnt_ns,1891zfs_i_user_ns(ZTOI(dzp))) != 0) {1892acl_ids->z_mode &= ~S_ISGID;1893}1894}18951896if (acl_ids->z_aclp == NULL) {1897mutex_enter(&dzp->z_acl_lock);1898mutex_enter(&dzp->z_lock);1899if (!(flag & IS_ROOT_NODE) &&1900(dzp->z_pflags & ZFS_INHERIT_ACE) &&1901!(dzp->z_pflags & ZFS_XATTR)) {1902VERIFY0(zfs_acl_node_read(dzp, B_TRUE,1903&paclp, B_FALSE));1904acl_ids->z_aclp = zfs_acl_inherit(zfsvfs,1905vap->va_mode, paclp, acl_ids->z_mode, &need_chmod);1906inherited = B_TRUE;1907} else {1908acl_ids->z_aclp =1909zfs_acl_alloc(zfs_acl_version_zp(dzp));1910acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL;1911}1912mutex_exit(&dzp->z_lock);1913mutex_exit(&dzp->z_acl_lock);19141915if (need_chmod) {1916if (S_ISDIR(vap->va_mode))1917acl_ids->z_aclp->z_hints |=1918ZFS_ACL_AUTO_INHERIT;19191920if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK &&1921zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH &&1922zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X)1923trim = B_TRUE;1924zfs_acl_chmod(S_ISDIR(vap->va_mode), acl_ids->z_mode,1925B_FALSE, trim, acl_ids->z_aclp);1926}1927}19281929if (inherited || vsecp) {1930acl_ids->z_mode = zfs_mode_compute(acl_ids->z_mode,1931acl_ids->z_aclp, &acl_ids->z_aclp->z_hints,1932acl_ids->z_fuid, acl_ids->z_fgid);1933if (ace_trivial_common(acl_ids->z_aclp, 0, zfs_ace_walk) == 0)1934acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL;1935}19361937return (0);1938}19391940/*1941* Free ACL and fuid_infop, but not the acl_ids structure1942*/1943void1944zfs_acl_ids_free(zfs_acl_ids_t *acl_ids)1945{1946if (acl_ids->z_aclp)1947zfs_acl_free(acl_ids->z_aclp);1948if (acl_ids->z_fuidp)1949zfs_fuid_info_free(acl_ids->z_fuidp);1950acl_ids->z_aclp = NULL;1951acl_ids->z_fuidp = NULL;1952}19531954boolean_t1955zfs_acl_ids_overquota(zfsvfs_t *zv, zfs_acl_ids_t *acl_ids, uint64_t projid)1956{1957return (zfs_id_overquota(zv, DMU_USERUSED_OBJECT, acl_ids->z_fuid) ||1958zfs_id_overquota(zv, DMU_GROUPUSED_OBJECT, acl_ids->z_fgid) ||1959(projid != ZFS_DEFAULT_PROJID && projid != ZFS_INVALID_PROJID &&1960zfs_id_overquota(zv, DMU_PROJECTUSED_OBJECT, projid)));1961}19621963/*1964* Retrieve a file's ACL1965*/1966int1967zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)1968{1969zfs_acl_t *aclp;1970ulong_t mask;1971int error;1972int count = 0;1973int largeace = 0;19741975mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT |1976VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES);19771978if (mask == 0)1979return (SET_ERROR(ENOSYS));19801981if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr,1982zfs_init_idmap)))1983return (error);19841985mutex_enter(&zp->z_acl_lock);19861987error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE);1988if (error != 0) {1989mutex_exit(&zp->z_acl_lock);1990return (error);1991}19921993/*1994* Scan ACL to determine number of ACEs1995*/1996if ((zp->z_pflags & ZFS_ACL_OBJ_ACE) && !(mask & VSA_ACE_ALLTYPES)) {1997void *zacep = NULL;1998uint64_t who;1999uint32_t access_mask;2000uint16_t type, iflags;20012002while ((zacep = zfs_acl_next_ace(aclp, zacep,2003&who, &access_mask, &iflags, &type))) {2004switch (type) {2005case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:2006case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:2007case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE:2008case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE:2009largeace++;2010continue;2011default:2012count++;2013}2014}2015vsecp->vsa_aclcnt = count;2016} else2017count = (int)aclp->z_acl_count;20182019if (mask & VSA_ACECNT) {2020vsecp->vsa_aclcnt = count;2021}20222023if (mask & VSA_ACE) {2024size_t aclsz;20252026aclsz = count * sizeof (ace_t) +2027sizeof (ace_object_t) * largeace;20282029vsecp->vsa_aclentp = kmem_alloc(aclsz, KM_SLEEP);2030vsecp->vsa_aclentsz = aclsz;20312032if (aclp->z_version == ZFS_ACL_VERSION_FUID)2033zfs_copy_fuid_2_ace(ZTOZSB(zp), aclp, cr,2034vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES));2035else {2036zfs_acl_node_t *aclnode;2037void *start = vsecp->vsa_aclentp;20382039for (aclnode = list_head(&aclp->z_acl); aclnode;2040aclnode = list_next(&aclp->z_acl, aclnode)) {2041memcpy(start, aclnode->z_acldata,2042aclnode->z_size);2043start = (caddr_t)start + aclnode->z_size;2044}2045ASSERT((caddr_t)start - (caddr_t)vsecp->vsa_aclentp ==2046aclp->z_acl_bytes);2047}2048}2049if (mask & VSA_ACE_ACLFLAGS) {2050vsecp->vsa_aclflags = 0;2051if (zp->z_pflags & ZFS_ACL_DEFAULTED)2052vsecp->vsa_aclflags |= ACL_DEFAULTED;2053if (zp->z_pflags & ZFS_ACL_PROTECTED)2054vsecp->vsa_aclflags |= ACL_PROTECTED;2055if (zp->z_pflags & ZFS_ACL_AUTO_INHERIT)2056vsecp->vsa_aclflags |= ACL_AUTO_INHERIT;2057}20582059mutex_exit(&zp->z_acl_lock);20602061return (0);2062}20632064int2065zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, umode_t obj_mode,2066vsecattr_t *vsecp, cred_t *cr, zfs_fuid_info_t **fuidp, zfs_acl_t **zaclp)2067{2068zfs_acl_t *aclp;2069zfs_acl_node_t *aclnode;2070int aclcnt = vsecp->vsa_aclcnt;2071int error;20722073if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0)2074return (SET_ERROR(EINVAL));20752076aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version));20772078aclp->z_hints = 0;2079aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t));2080if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) {2081if ((error = zfs_copy_ace_2_oldace(obj_mode, aclp,2082(ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata,2083aclcnt, &aclnode->z_size)) != 0) {2084zfs_acl_free(aclp);2085zfs_acl_node_free(aclnode);2086return (error);2087}2088} else {2089if ((error = zfs_copy_ace_2_fuid(zfsvfs, obj_mode, aclp,2090vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt,2091&aclnode->z_size, fuidp, cr)) != 0) {2092zfs_acl_free(aclp);2093zfs_acl_node_free(aclnode);2094return (error);2095}2096}2097aclp->z_acl_bytes = aclnode->z_size;2098aclnode->z_ace_count = aclcnt;2099aclp->z_acl_count = aclcnt;2100list_insert_head(&aclp->z_acl, aclnode);21012102/*2103* If flags are being set then add them to z_hints2104*/2105if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) {2106if (vsecp->vsa_aclflags & ACL_PROTECTED)2107aclp->z_hints |= ZFS_ACL_PROTECTED;2108if (vsecp->vsa_aclflags & ACL_DEFAULTED)2109aclp->z_hints |= ZFS_ACL_DEFAULTED;2110if (vsecp->vsa_aclflags & ACL_AUTO_INHERIT)2111aclp->z_hints |= ZFS_ACL_AUTO_INHERIT;2112}21132114*zaclp = aclp;21152116return (0);2117}21182119/*2120* Set a file's ACL2121*/2122int2123zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)2124{2125zfsvfs_t *zfsvfs = ZTOZSB(zp);2126zilog_t *zilog = zfsvfs->z_log;2127ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT);2128dmu_tx_t *tx;2129int error;2130zfs_acl_t *aclp;2131zfs_fuid_info_t *fuidp = NULL;2132boolean_t fuid_dirtied;2133uint64_t acl_obj;21342135if (mask == 0)2136return (SET_ERROR(ENOSYS));21372138if (zp->z_pflags & ZFS_IMMUTABLE)2139return (SET_ERROR(EPERM));21402141if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr,2142zfs_init_idmap)))2143return (error);21442145error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp,2146&aclp);2147if (error)2148return (error);21492150/*2151* If ACL wide flags aren't being set then preserve any2152* existing flags.2153*/2154if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) {2155aclp->z_hints |=2156(zp->z_pflags & V4_ACL_WIDE_FLAGS);2157}2158top:2159mutex_enter(&zp->z_acl_lock);2160mutex_enter(&zp->z_lock);21612162tx = dmu_tx_create(zfsvfs->z_os);21632164dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);21652166fuid_dirtied = zfsvfs->z_fuid_dirty;2167if (fuid_dirtied)2168zfs_fuid_txhold(zfsvfs, tx);21692170/*2171* If old version and ACL won't fit in bonus and we aren't2172* upgrading then take out necessary DMU holds2173*/21742175if ((acl_obj = zfs_external_acl(zp)) != 0) {2176if (zfsvfs->z_version >= ZPL_VERSION_FUID &&2177zfs_znode_acl_version(zp) <= ZFS_ACL_VERSION_INITIAL) {2178dmu_tx_hold_free(tx, acl_obj, 0,2179DMU_OBJECT_END);2180dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,2181aclp->z_acl_bytes);2182} else {2183dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes);2184}2185} else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) {2186dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes);2187}21882189zfs_sa_upgrade_txholds(tx, zp);2190error = dmu_tx_assign(tx, DMU_TX_NOWAIT);2191if (error) {2192mutex_exit(&zp->z_acl_lock);2193mutex_exit(&zp->z_lock);21942195if (error == ERESTART) {2196dmu_tx_wait(tx);2197dmu_tx_abort(tx);2198goto top;2199}2200dmu_tx_abort(tx);2201zfs_acl_free(aclp);2202return (error);2203}22042205error = zfs_aclset_common(zp, aclp, cr, tx);2206ASSERT0(error);2207ASSERT0P(zp->z_acl_cached);2208zp->z_acl_cached = aclp;22092210if (fuid_dirtied)2211zfs_fuid_sync(zfsvfs, tx);22122213zfs_log_acl(zilog, tx, zp, vsecp, fuidp);22142215if (fuidp)2216zfs_fuid_info_free(fuidp);2217dmu_tx_commit(tx);22182219mutex_exit(&zp->z_lock);2220mutex_exit(&zp->z_acl_lock);22212222return (error);2223}22242225/*2226* Check accesses of interest (AoI) against attributes of the dataset2227* such as read-only. Returns zero if no AoI conflict with dataset2228* attributes, otherwise an appropriate errno is returned.2229*/2230static int2231zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)2232{2233if ((v4_mode & WRITE_MASK) && (zfs_is_readonly(ZTOZSB(zp))) &&2234(!Z_ISDEV(ZTOI(zp)->i_mode) || (v4_mode & WRITE_MASK_ATTRS))) {2235return (SET_ERROR(EROFS));2236}22372238/*2239* Intentionally allow ZFS_READONLY through here.2240* See zfs_zaccess_common().2241*/2242if ((v4_mode & WRITE_MASK_DATA) &&2243(zp->z_pflags & ZFS_IMMUTABLE)) {2244return (SET_ERROR(EPERM));2245}22462247if ((v4_mode & (ACE_DELETE | ACE_DELETE_CHILD)) &&2248(zp->z_pflags & ZFS_NOUNLINK)) {2249return (SET_ERROR(EPERM));2250}22512252if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) &&2253(zp->z_pflags & ZFS_AV_QUARANTINED))) {2254return (SET_ERROR(EACCES));2255}22562257return (0);2258}22592260/*2261* The primary usage of this function is to loop through all of the2262* ACEs in the znode, determining what accesses of interest (AoI) to2263* the caller are allowed or denied. The AoI are expressed as bits in2264* the working_mode parameter. As each ACE is processed, bits covered2265* by that ACE are removed from the working_mode. This removal2266* facilitates two things. The first is that when the working mode is2267* empty (= 0), we know we've looked at all the AoI. The second is2268* that the ACE interpretation rules don't allow a later ACE to undo2269* something granted or denied by an earlier ACE. Removing the2270* discovered access or denial enforces this rule. At the end of2271* processing the ACEs, all AoI that were found to be denied are2272* placed into the working_mode, giving the caller a mask of denied2273* accesses. Returns:2274* 0 if all AoI granted2275* EACCES if the denied mask is non-zero2276* other error if abnormal failure (e.g., IO error)2277*2278* A secondary usage of the function is to determine if any of the2279* AoI are granted. If an ACE grants any access in2280* the working_mode, we immediately short circuit out of the function.2281* This mode is chosen by setting anyaccess to B_TRUE. The2282* working_mode is not a denied access mask upon exit if the function2283* is used in this manner.2284*/2285static int2286zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,2287boolean_t anyaccess, cred_t *cr, zidmap_t *mnt_ns)2288{2289zfsvfs_t *zfsvfs = ZTOZSB(zp);2290zfs_acl_t *aclp;2291int error;2292uid_t uid = crgetuid(cr);2293uint64_t who;2294uint16_t type, iflags;2295uint16_t entry_type;2296uint32_t access_mask;2297uint32_t deny_mask = 0;2298zfs_ace_hdr_t *acep = NULL;2299boolean_t checkit;2300uid_t gowner;2301uid_t fowner;23022303if (mnt_ns) {2304fowner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),2305KUID_TO_SUID(ZTOI(zp)->i_uid));2306gowner = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),2307KGID_TO_SGID(ZTOI(zp)->i_gid));2308} else2309zfs_fuid_map_ids(zp, cr, &fowner, &gowner);23102311mutex_enter(&zp->z_acl_lock);23122313error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE);2314if (error != 0) {2315mutex_exit(&zp->z_acl_lock);2316return (error);2317}23182319ASSERT(zp->z_acl_cached);23202321while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,2322&iflags, &type))) {2323uint32_t mask_matched;23242325if (!zfs_acl_valid_ace_type(type, iflags))2326continue;23272328if (S_ISDIR(ZTOI(zp)->i_mode) &&2329(iflags & ACE_INHERIT_ONLY_ACE))2330continue;23312332/* Skip ACE if it does not affect any AoI */2333mask_matched = (access_mask & *working_mode);2334if (!mask_matched)2335continue;23362337entry_type = (iflags & ACE_TYPE_FLAGS);23382339checkit = B_FALSE;23402341switch (entry_type) {2342case ACE_OWNER:2343if (uid == fowner)2344checkit = B_TRUE;2345break;2346case OWNING_GROUP:2347who = gowner;2348zfs_fallthrough;2349case ACE_IDENTIFIER_GROUP:2350checkit = zfs_groupmember(zfsvfs, who, cr);2351break;2352case ACE_EVERYONE:2353checkit = B_TRUE;2354break;23552356/* USER Entry */2357default:2358if (entry_type == 0) {2359uid_t newid;23602361newid = zfs_fuid_map_id(zfsvfs, who, cr,2362ZFS_ACE_USER);2363if (newid != IDMAP_WK_CREATOR_OWNER_UID &&2364uid == newid)2365checkit = B_TRUE;2366break;2367} else {2368mutex_exit(&zp->z_acl_lock);2369return (SET_ERROR(EIO));2370}2371}23722373if (checkit) {2374if (type == DENY) {2375DTRACE_PROBE3(zfs__ace__denies,2376znode_t *, zp,2377zfs_ace_hdr_t *, acep,2378uint32_t, mask_matched);2379deny_mask |= mask_matched;2380} else {2381DTRACE_PROBE3(zfs__ace__allows,2382znode_t *, zp,2383zfs_ace_hdr_t *, acep,2384uint32_t, mask_matched);2385if (anyaccess) {2386mutex_exit(&zp->z_acl_lock);2387return (0);2388}2389}2390*working_mode &= ~mask_matched;2391}23922393/* Are we done? */2394if (*working_mode == 0)2395break;2396}23972398mutex_exit(&zp->z_acl_lock);23992400/* Put the found 'denies' back on the working mode */2401if (deny_mask) {2402*working_mode |= deny_mask;2403return (SET_ERROR(EACCES));2404} else if (*working_mode) {2405return (-1);2406}24072408return (0);2409}24102411/*2412* Return true if any access whatsoever granted, we don't actually2413* care what access is granted.2414*/2415boolean_t2416zfs_has_access(znode_t *zp, cred_t *cr)2417{2418uint32_t have = ACE_ALL_PERMS;24192420if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr,2421zfs_init_idmap) != 0) {2422uid_t owner;24232424owner = zfs_fuid_map_id(ZTOZSB(zp),2425KUID_TO_SUID(ZTOI(zp)->i_uid), cr, ZFS_OWNER);2426return (secpolicy_vnode_any_access(cr, ZTOI(zp), owner) == 0);2427}2428return (B_TRUE);2429}24302431/*2432* Simplified access check for case where ACL is known to not contain2433* information beyond what is defined in the mode. In this case, we2434* can pass along to the kernel / vfs generic_permission() check, which2435* evaluates the mode and POSIX ACL.2436*2437* NFSv4 ACLs allow granting permissions that are usually relegated only2438* to the file owner or superuser. Examples are ACE_WRITE_OWNER (chown),2439* ACE_WRITE_ACL(chmod), and ACE_DELETE. ACE_DELETE requests must fail2440* because with conventional posix permissions, right to delete file2441* is determined by write bit on the parent dir.2442*2443* If unmappable perms are requested, then we must return EPERM2444* and include those bits in the working_mode so that the caller of2445* zfs_zaccess_common() can decide whether to perform additional2446* policy / capability checks. EACCES is used in zfs_zaccess_aces_check()2447* to indicate access check failed due to explicit DENY entry, and so2448* we want to avoid that here.2449*/2450static int2451zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr,2452zidmap_t *mnt_ns)2453{2454int err, mask;2455int unmapped = 0;24562457ASSERT(zp->z_pflags & ZFS_ACL_TRIVIAL);24582459mask = zfs_v4_to_unix(*working_mode, &unmapped);2460if (mask == 0 || unmapped) {2461*working_mode = unmapped;2462return (unmapped ? SET_ERROR(EPERM) : 0);2463}24642465#if (defined(HAVE_IOPS_PERMISSION_USERNS) || \2466defined(HAVE_IOPS_PERMISSION_IDMAP))2467err = generic_permission(mnt_ns, ZTOI(zp), mask);2468#else2469err = generic_permission(ZTOI(zp), mask);2470#endif2471if (err != 0) {2472return (SET_ERROR(EPERM));2473}24742475*working_mode = unmapped;24762477return (0);2478}24792480static int2481zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,2482boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zidmap_t *mnt_ns)2483{2484zfsvfs_t *zfsvfs = ZTOZSB(zp);2485int err;24862487*working_mode = v4_mode;2488*check_privs = B_TRUE;24892490/*2491* Short circuit empty requests2492*/2493if (v4_mode == 0 || zfsvfs->z_replay) {2494*working_mode = 0;2495return (0);2496}24972498if ((err = zfs_zaccess_dataset_check(zp, v4_mode)) != 0) {2499*check_privs = B_FALSE;2500return (err);2501}25022503/*2504* The caller requested that the ACL check be skipped. This2505* would only happen if the caller checked VOP_ACCESS() with a2506* 32 bit ACE mask and already had the appropriate permissions.2507*/2508if (skipaclchk) {2509*working_mode = 0;2510return (0);2511}25122513/*2514* Note: ZFS_READONLY represents the "DOS R/O" attribute.2515* When that flag is set, we should behave as if write access2516* were not granted by anything in the ACL. In particular:2517* We _must_ allow writes after opening the file r/w, then2518* setting the DOS R/O attribute, and writing some more.2519* (Similar to how you can write after fchmod(fd, 0444).)2520*2521* Therefore ZFS_READONLY is ignored in the dataset check2522* above, and checked here as if part of the ACL check.2523* Also note: DOS R/O is ignored for directories.2524*/2525if ((v4_mode & WRITE_MASK_DATA) &&2526!S_ISDIR(ZTOI(zp)->i_mode) &&2527(zp->z_pflags & ZFS_READONLY)) {2528return (SET_ERROR(EPERM));2529}25302531if (zp->z_pflags & ZFS_ACL_TRIVIAL)2532return (zfs_zaccess_trivial(zp, working_mode, cr, mnt_ns));25332534return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr, mnt_ns));2535}25362537static int2538zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs,2539cred_t *cr, zidmap_t *mnt_ns)2540{2541if (*working_mode != ACE_WRITE_DATA)2542return (SET_ERROR(EACCES));25432544return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode,2545check_privs, B_FALSE, cr, mnt_ns));2546}25472548int2549zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)2550{2551boolean_t owner = B_FALSE;2552boolean_t groupmbr = B_FALSE;2553boolean_t is_attr;2554uid_t uid = crgetuid(cr);2555int error;25562557if (zdp->z_pflags & ZFS_AV_QUARANTINED)2558return (SET_ERROR(EACCES));25592560is_attr = ((zdp->z_pflags & ZFS_XATTR) &&2561(S_ISDIR(ZTOI(zdp)->i_mode)));2562if (is_attr)2563goto slow;256425652566mutex_enter(&zdp->z_acl_lock);25672568if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) {2569mutex_exit(&zdp->z_acl_lock);2570return (0);2571}25722573if (KUID_TO_SUID(ZTOI(zdp)->i_uid) != 0 ||2574KGID_TO_SGID(ZTOI(zdp)->i_gid) != 0) {2575mutex_exit(&zdp->z_acl_lock);2576goto slow;2577}25782579if (uid == KUID_TO_SUID(ZTOI(zdp)->i_uid)) {2580if (zdp->z_mode & S_IXUSR) {2581mutex_exit(&zdp->z_acl_lock);2582return (0);2583} else {2584mutex_exit(&zdp->z_acl_lock);2585goto slow;2586}2587}2588if (groupmember(KGID_TO_SGID(ZTOI(zdp)->i_gid), cr)) {2589if (zdp->z_mode & S_IXGRP) {2590mutex_exit(&zdp->z_acl_lock);2591return (0);2592} else {2593mutex_exit(&zdp->z_acl_lock);2594goto slow;2595}2596}2597if (!owner && !groupmbr) {2598if (zdp->z_mode & S_IXOTH) {2599mutex_exit(&zdp->z_acl_lock);2600return (0);2601}2602}26032604mutex_exit(&zdp->z_acl_lock);26052606slow:2607DTRACE_PROBE(zfs__fastpath__execute__access__miss);2608if ((error = zfs_enter(ZTOZSB(zdp), FTAG)) != 0)2609return (error);2610error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr,2611zfs_init_idmap);2612zfs_exit(ZTOZSB(zdp), FTAG);2613return (error);2614}26152616/*2617* Determine whether Access should be granted/denied.2618*2619* The least priv subsystem is always consulted as a basic privilege2620* can define any form of access.2621*/2622int2623zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr,2624zidmap_t *mnt_ns)2625{2626uint32_t working_mode;2627int error;2628int is_attr;2629boolean_t check_privs;2630znode_t *xzp;2631znode_t *check_zp = zp;2632mode_t needed_bits;2633uid_t owner;26342635is_attr = ((zp->z_pflags & ZFS_XATTR) && S_ISDIR(ZTOI(zp)->i_mode));26362637/*2638* If attribute then validate against base file2639*/2640if (is_attr) {2641if ((error = zfs_zget(ZTOZSB(zp),2642zp->z_xattr_parent, &xzp)) != 0) {2643return (error);2644}26452646check_zp = xzp;26472648/*2649* fixup mode to map to xattr perms2650*/26512652if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {2653mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);2654mode |= ACE_WRITE_NAMED_ATTRS;2655}26562657if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {2658mode &= ~(ACE_READ_DATA|ACE_EXECUTE);2659mode |= ACE_READ_NAMED_ATTRS;2660}2661}26622663owner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)),2664KUID_TO_SUID(ZTOI(zp)->i_uid));2665owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER);26662667/*2668* Map the bits required to the standard inode flags2669* S_IRUSR|S_IWUSR|S_IXUSR in the needed_bits. Map the bits2670* mapped by working_mode (currently missing) in missing_bits.2671* Call secpolicy_vnode_access2() with (needed_bits & ~checkmode),2672* needed_bits.2673*/2674needed_bits = 0;26752676working_mode = mode;2677if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&2678owner == crgetuid(cr))2679working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES);26802681if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS|2682ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE))2683needed_bits |= S_IRUSR;2684if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS|2685ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE))2686needed_bits |= S_IWUSR;2687if (working_mode & ACE_EXECUTE)2688needed_bits |= S_IXUSR;26892690if ((error = zfs_zaccess_common(check_zp, mode, &working_mode,2691&check_privs, skipaclchk, cr, mnt_ns)) == 0) {2692if (is_attr)2693zrele(xzp);2694return (secpolicy_vnode_access2(cr, ZTOI(zp), owner,2695needed_bits, needed_bits));2696}26972698if (error && !check_privs) {2699if (is_attr)2700zrele(xzp);2701return (error);2702}27032704if (error && (flags & V_APPEND)) {2705error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr,2706mnt_ns);2707}27082709if (error && check_privs) {2710mode_t checkmode = 0;27112712/*2713* First check for implicit owner permission on2714* read_acl/read_attributes2715*/27162717ASSERT(working_mode != 0);27182719if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) &&2720owner == crgetuid(cr)))2721working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES);27222723if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS|2724ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE))2725checkmode |= S_IRUSR;2726if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS|2727ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE))2728checkmode |= S_IWUSR;2729if (working_mode & ACE_EXECUTE)2730checkmode |= S_IXUSR;27312732error = secpolicy_vnode_access2(cr, ZTOI(check_zp), owner,2733needed_bits & ~checkmode, needed_bits);27342735if (error == 0 && (working_mode & ACE_WRITE_OWNER))2736error = secpolicy_vnode_chown(cr, owner);2737if (error == 0 && (working_mode & ACE_WRITE_ACL))2738error = secpolicy_vnode_setdac(cr, owner);27392740if (error == 0 && (working_mode &2741(ACE_DELETE|ACE_DELETE_CHILD)))2742error = secpolicy_vnode_remove(cr);27432744if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) {2745error = secpolicy_vnode_chown(cr, owner);2746}2747if (error == 0) {2748/*2749* See if any bits other than those already checked2750* for are still present. If so then return EACCES2751*/2752if (working_mode & ~(ZFS_CHECKED_MASKS)) {2753error = SET_ERROR(EACCES);2754}2755}2756} else if (error == 0) {2757error = secpolicy_vnode_access2(cr, ZTOI(zp), owner,2758needed_bits, needed_bits);2759}27602761if (is_attr)2762zrele(xzp);27632764return (error);2765}27662767/*2768* Translate traditional unix S_IRUSR/S_IWUSR/S_IXUSR mode into2769* NFSv4-style ZFS ACL format and call zfs_zaccess()2770*/2771int2772zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr,2773zidmap_t *mnt_ns)2774{2775return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr,2776mnt_ns));2777}27782779/*2780* Access function for secpolicy_vnode_setattr2781*/2782int2783zfs_zaccess_unix(void *zp, int mode, cred_t *cr)2784{2785int v4_mode = zfs_unix_to_v4(mode >> 6);27862787return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, zfs_init_idmap));2788}27892790/* See zfs_zaccess_delete() */2791static const boolean_t zfs_write_implies_delete_child = B_TRUE;27922793/*2794* Determine whether delete access should be granted.2795*2796* The following chart outlines how we handle delete permissions which is2797* how recent versions of windows (Windows 2008) handles it. The efficiency2798* comes from not having to check the parent ACL where the object itself grants2799* delete:2800*2801* -------------------------------------------------------2802* | Parent Dir | Target Object Permissions |2803* | permissions | |2804* -------------------------------------------------------2805* | | ACL Allows | ACL Denies| Delete |2806* | | Delete | Delete | unspecified|2807* -------------------------------------------------------2808* | ACL Allows | Permit | Deny * | Permit |2809* | DELETE_CHILD | | | |2810* -------------------------------------------------------2811* | ACL Denies | Permit | Deny | Deny |2812* | DELETE_CHILD | | | |2813* -------------------------------------------------------2814* | ACL specifies | | | |2815* | only allow | Permit | Deny * | Permit |2816* | write and | | | |2817* | execute | | | |2818* -------------------------------------------------------2819* | ACL denies | | | |2820* | write and | Permit | Deny | Deny |2821* | execute | | | |2822* -------------------------------------------------------2823* ^2824* |2825* Re. execute permission on the directory: if that's missing,2826* the vnode lookup of the target will fail before we get here.2827*2828* Re [*] in the table above: NFSv4 would normally Permit delete for2829* these two cells of the matrix.2830* See acl.h for notes on which ACE_... flags should be checked for which2831* operations. Specifically, the NFSv4 committee recommendation is in2832* conflict with the Windows interpretation of DENY ACEs, where DENY ACEs2833* should take precedence ahead of ALLOW ACEs.2834*2835* This implementation always consults the target object's ACL first.2836* If a DENY ACE is present on the target object that specifies ACE_DELETE,2837* delete access is denied. If an ALLOW ACE with ACE_DELETE is present on2838* the target object, access is allowed. If and only if no entries with2839* ACE_DELETE are present in the object's ACL, check the container's ACL2840* for entries with ACE_DELETE_CHILD.2841*2842* A summary of the logic implemented from the table above is as follows:2843*2844* First check for DENY ACEs that apply.2845* If either target or container has a deny, EACCES.2846*2847* Delete access can then be summarized as follows:2848* 1: The object to be deleted grants ACE_DELETE, or2849* 2: The containing directory grants ACE_DELETE_CHILD.2850* In a Windows system, that would be the end of the story.2851* In this system, (2) has some complications...2852* 2a: "sticky" bit on a directory adds restrictions, and2853* 2b: existing ACEs from previous versions of ZFS may2854* not carry ACE_DELETE_CHILD where they should, so we2855* also allow delete when ACE_WRITE_DATA is granted.2856*2857* Note: 2b is technically a work-around for a prior bug,2858* which hopefully can go away some day. For those who2859* no longer need the work around, and for testing, this2860* work-around is made conditional via the tunable:2861* zfs_write_implies_delete_child2862*/2863int2864zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns)2865{2866uint32_t wanted_dirperms;2867uint32_t dzp_working_mode = 0;2868uint32_t zp_working_mode = 0;2869int dzp_error, zp_error;2870boolean_t dzpcheck_privs;2871boolean_t zpcheck_privs;28722873if (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_NOUNLINK))2874return (SET_ERROR(EPERM));28752876/*2877* Case 1:2878* If target object grants ACE_DELETE then we are done. This is2879* indicated by a return value of 0. For this case we don't worry2880* about the sticky bit because sticky only applies to the parent2881* directory and this is the child access result.2882*2883* If we encounter a DENY ACE here, we're also done (EACCES).2884* Note that if we hit a DENY ACE here (on the target) it should2885* take precedence over a DENY ACE on the container, so that when2886* we have more complete auditing support we will be able to2887* report an access failure against the specific target.2888* (This is part of why we're checking the target first.)2889*/2890zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode,2891&zpcheck_privs, B_FALSE, cr, mnt_ns);2892if (zp_error == EACCES) {2893/* We hit a DENY ACE. */2894if (!zpcheck_privs)2895return (SET_ERROR(zp_error));2896return (secpolicy_vnode_remove(cr));28972898}2899if (zp_error == 0)2900return (0);29012902/*2903* Case 2:2904* If the containing directory grants ACE_DELETE_CHILD,2905* or we're in backward compatibility mode and the2906* containing directory has ACE_WRITE_DATA, allow.2907* Case 2b is handled with wanted_dirperms.2908*/2909wanted_dirperms = ACE_DELETE_CHILD;2910if (zfs_write_implies_delete_child)2911wanted_dirperms |= ACE_WRITE_DATA;2912dzp_error = zfs_zaccess_common(dzp, wanted_dirperms,2913&dzp_working_mode, &dzpcheck_privs, B_FALSE, cr, mnt_ns);2914if (dzp_error == EACCES) {2915/* We hit a DENY ACE. */2916if (!dzpcheck_privs)2917return (SET_ERROR(dzp_error));2918return (secpolicy_vnode_remove(cr));2919}29202921/*2922* Cases 2a, 2b (continued)2923*2924* Note: dzp_working_mode now contains any permissions2925* that were NOT granted. Therefore, if any of the2926* wanted_dirperms WERE granted, we will have:2927* dzp_working_mode != wanted_dirperms2928* We're really asking if ANY of those permissions2929* were granted, and if so, grant delete access.2930*/2931if (dzp_working_mode != wanted_dirperms)2932dzp_error = 0;29332934/*2935* dzp_error is 0 if the container granted us permissions to "modify".2936* If we do not have permission via one or more ACEs, our current2937* privileges may still permit us to modify the container.2938*2939* dzpcheck_privs is false when i.e. the FS is read-only.2940* Otherwise, do privilege checks for the container.2941*/2942if (dzp_error != 0 && dzpcheck_privs) {2943uid_t owner;29442945/*2946* The secpolicy call needs the requested access and2947* the current access mode of the container, but it2948* only knows about Unix-style modes (VEXEC, VWRITE),2949* so this must condense the fine-grained ACE bits into2950* Unix modes.2951*2952* The VEXEC flag is easy, because we know that has2953* always been checked before we get here (during the2954* lookup of the target vnode). The container has not2955* granted us permissions to "modify", so we do not set2956* the VWRITE flag in the current access mode.2957*/2958owner = zfs_fuid_map_id(ZTOZSB(dzp),2959KUID_TO_SUID(ZTOI(dzp)->i_uid), cr, ZFS_OWNER);2960dzp_error = secpolicy_vnode_access2(cr, ZTOI(dzp),2961owner, S_IXUSR, S_IWUSR|S_IXUSR);2962}2963if (dzp_error != 0) {2964/*2965* Note: We may have dzp_error = -1 here (from2966* zfs_zacess_common). Don't return that.2967*/2968return (SET_ERROR(EACCES));2969}297029712972/*2973* At this point, we know that the directory permissions allow2974* us to modify, but we still need to check for the additional2975* restrictions that apply when the "sticky bit" is set.2976*2977* Yes, zfs_sticky_remove_access() also checks this bit, but2978* checking it here and skipping the call below is nice when2979* you're watching all of this with dtrace.2980*/2981if ((dzp->z_mode & S_ISVTX) == 0)2982return (0);29832984/*2985* zfs_sticky_remove_access will succeed if:2986* 1. The sticky bit is absent.2987* 2. We pass the sticky bit restrictions.2988* 3. We have privileges that always allow file removal.2989*/2990return (zfs_sticky_remove_access(dzp, zp, cr));2991}29922993int2994zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,2995znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns)2996{2997int add_perm;2998int error;29993000if (szp->z_pflags & ZFS_AV_QUARANTINED)3001return (SET_ERROR(EACCES));30023003add_perm = S_ISDIR(ZTOI(szp)->i_mode) ?3004ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE;30053006/*3007* Rename permissions are combination of delete permission +3008* add file/subdir permission.3009*/30103011/*3012* first make sure we do the delete portion.3013*3014* If that succeeds then check for add_file/add_subdir permissions3015*/30163017if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns)))3018return (error);30193020/*3021* If we have a tzp, see if we can delete it?3022*/3023if (tzp) {3024if ((error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns)))3025return (error);3026}30273028/*3029* Now check for add permissions3030*/3031error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns);30323033return (error);3034}303530363037