zfs_acl.c revision 201143
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22185029Spjd * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26168404Spjd#include <sys/types.h> 27168404Spjd#include <sys/param.h> 28168404Spjd#include <sys/time.h> 29168404Spjd#include <sys/systm.h> 30168404Spjd#include <sys/sysmacros.h> 31168404Spjd#include <sys/resource.h> 32168404Spjd#include <sys/vfs.h> 33168404Spjd#include <sys/vnode.h> 34168404Spjd#include <sys/file.h> 35168404Spjd#include <sys/stat.h> 36168404Spjd#include <sys/kmem.h> 37168404Spjd#include <sys/cmn_err.h> 38168404Spjd#include <sys/errno.h> 39168404Spjd#include <sys/unistd.h> 40168404Spjd#include <sys/sdt.h> 41168404Spjd#include <sys/fs/zfs.h> 42169023Spjd#include <sys/policy.h> 43168404Spjd#include <sys/zfs_znode.h> 44185029Spjd#include <sys/zfs_fuid.h> 45168404Spjd#include <sys/zfs_acl.h> 46168404Spjd#include <sys/zfs_dir.h> 47168404Spjd#include <sys/zfs_vfsops.h> 48168404Spjd#include <sys/dmu.h> 49185029Spjd#include <sys/dnode.h> 50168404Spjd#include <sys/zap.h> 51168404Spjd#include <acl/acl_common.h> 52168404Spjd 53168404Spjd#define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE 54168404Spjd#define DENY ACE_ACCESS_DENIED_ACE_TYPE 55185029Spjd#define MAX_ACE_TYPE ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 56185029Spjd#define MIN_ACE_TYPE ALLOW 57168404Spjd 58168404Spjd#define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 59168404Spjd#define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 60168404Spjd ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 61168404Spjd#define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 62168404Spjd ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 63168404Spjd#define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 64168404Spjd ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 65185029Spjd#define WRITE_MASK_DATA (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS) 66168404Spjd 67185029Spjd#define ZFS_CHECKED_MASKS (ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_DATA| \ 68185029Spjd ACE_READ_NAMED_ATTRS|ACE_WRITE_DATA|ACE_WRITE_ATTRIBUTES| \ 69185029Spjd ACE_WRITE_NAMED_ATTRS|ACE_APPEND_DATA|ACE_EXECUTE|ACE_WRITE_OWNER| \ 70185029Spjd ACE_WRITE_ACL|ACE_DELETE|ACE_DELETE_CHILD|ACE_SYNCHRONIZE) 71185029Spjd 72185029Spjd#define WRITE_MASK (WRITE_MASK_DATA|ACE_WRITE_ATTRIBUTES|ACE_WRITE_ACL|\ 73185029Spjd ACE_WRITE_OWNER|ACE_DELETE|ACE_DELETE_CHILD) 74185029Spjd 75168404Spjd#define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 76168404Spjd ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 77168404Spjd 78168404Spjd#define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 79168404Spjd ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 80168404Spjd 81168404Spjd#define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 82185029Spjd ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE) 83168404Spjd 84185029Spjd#define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) 85168404Spjd 86185029Spjd#define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\ 87185029Spjd ZFS_ACL_PROTECTED) 88168404Spjd 89185029Spjd#define ZFS_ACL_WIDE_FLAGS (V4_ACL_WIDE_FLAGS|ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|\ 90185029Spjd ZFS_ACL_OBJ_ACE) 91168404Spjd 92185029Spjdstatic uint16_t 93185029Spjdzfs_ace_v0_get_type(void *acep) 94185029Spjd{ 95185029Spjd return (((zfs_oldace_t *)acep)->z_type); 96185029Spjd} 97185029Spjd 98185029Spjdstatic uint16_t 99185029Spjdzfs_ace_v0_get_flags(void *acep) 100185029Spjd{ 101185029Spjd return (((zfs_oldace_t *)acep)->z_flags); 102185029Spjd} 103185029Spjd 104185029Spjdstatic uint32_t 105185029Spjdzfs_ace_v0_get_mask(void *acep) 106185029Spjd{ 107185029Spjd return (((zfs_oldace_t *)acep)->z_access_mask); 108185029Spjd} 109185029Spjd 110185029Spjdstatic uint64_t 111185029Spjdzfs_ace_v0_get_who(void *acep) 112185029Spjd{ 113185029Spjd return (((zfs_oldace_t *)acep)->z_fuid); 114185029Spjd} 115185029Spjd 116185029Spjdstatic void 117185029Spjdzfs_ace_v0_set_type(void *acep, uint16_t type) 118185029Spjd{ 119185029Spjd ((zfs_oldace_t *)acep)->z_type = type; 120185029Spjd} 121185029Spjd 122185029Spjdstatic void 123185029Spjdzfs_ace_v0_set_flags(void *acep, uint16_t flags) 124185029Spjd{ 125185029Spjd ((zfs_oldace_t *)acep)->z_flags = flags; 126185029Spjd} 127185029Spjd 128185029Spjdstatic void 129185029Spjdzfs_ace_v0_set_mask(void *acep, uint32_t mask) 130185029Spjd{ 131185029Spjd ((zfs_oldace_t *)acep)->z_access_mask = mask; 132185029Spjd} 133185029Spjd 134185029Spjdstatic void 135185029Spjdzfs_ace_v0_set_who(void *acep, uint64_t who) 136185029Spjd{ 137185029Spjd ((zfs_oldace_t *)acep)->z_fuid = who; 138185029Spjd} 139185029Spjd 140185029Spjd/*ARGSUSED*/ 141185029Spjdstatic size_t 142185029Spjdzfs_ace_v0_size(void *acep) 143185029Spjd{ 144185029Spjd return (sizeof (zfs_oldace_t)); 145185029Spjd} 146185029Spjd 147185029Spjdstatic size_t 148185029Spjdzfs_ace_v0_abstract_size(void) 149185029Spjd{ 150185029Spjd return (sizeof (zfs_oldace_t)); 151185029Spjd} 152185029Spjd 153185029Spjdstatic int 154185029Spjdzfs_ace_v0_mask_off(void) 155185029Spjd{ 156185029Spjd return (offsetof(zfs_oldace_t, z_access_mask)); 157185029Spjd} 158185029Spjd 159185029Spjd/*ARGSUSED*/ 160185029Spjdstatic int 161185029Spjdzfs_ace_v0_data(void *acep, void **datap) 162185029Spjd{ 163185029Spjd *datap = NULL; 164185029Spjd return (0); 165185029Spjd} 166185029Spjd 167185029Spjdstatic acl_ops_t zfs_acl_v0_ops = { 168185029Spjd zfs_ace_v0_get_mask, 169185029Spjd zfs_ace_v0_set_mask, 170185029Spjd zfs_ace_v0_get_flags, 171185029Spjd zfs_ace_v0_set_flags, 172185029Spjd zfs_ace_v0_get_type, 173185029Spjd zfs_ace_v0_set_type, 174185029Spjd zfs_ace_v0_get_who, 175185029Spjd zfs_ace_v0_set_who, 176185029Spjd zfs_ace_v0_size, 177185029Spjd zfs_ace_v0_abstract_size, 178185029Spjd zfs_ace_v0_mask_off, 179185029Spjd zfs_ace_v0_data 180185029Spjd}; 181185029Spjd 182185029Spjdstatic uint16_t 183185029Spjdzfs_ace_fuid_get_type(void *acep) 184185029Spjd{ 185185029Spjd return (((zfs_ace_hdr_t *)acep)->z_type); 186185029Spjd} 187185029Spjd 188185029Spjdstatic uint16_t 189185029Spjdzfs_ace_fuid_get_flags(void *acep) 190185029Spjd{ 191185029Spjd return (((zfs_ace_hdr_t *)acep)->z_flags); 192185029Spjd} 193185029Spjd 194185029Spjdstatic uint32_t 195185029Spjdzfs_ace_fuid_get_mask(void *acep) 196185029Spjd{ 197185029Spjd return (((zfs_ace_hdr_t *)acep)->z_access_mask); 198185029Spjd} 199185029Spjd 200185029Spjdstatic uint64_t 201185029Spjdzfs_ace_fuid_get_who(void *args) 202185029Spjd{ 203185029Spjd uint16_t entry_type; 204185029Spjd zfs_ace_t *acep = args; 205185029Spjd 206185029Spjd entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 207185029Spjd 208185029Spjd if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 209185029Spjd entry_type == ACE_EVERYONE) 210185029Spjd return (-1); 211185029Spjd return (((zfs_ace_t *)acep)->z_fuid); 212185029Spjd} 213185029Spjd 214185029Spjdstatic void 215185029Spjdzfs_ace_fuid_set_type(void *acep, uint16_t type) 216185029Spjd{ 217185029Spjd ((zfs_ace_hdr_t *)acep)->z_type = type; 218185029Spjd} 219185029Spjd 220185029Spjdstatic void 221185029Spjdzfs_ace_fuid_set_flags(void *acep, uint16_t flags) 222185029Spjd{ 223185029Spjd ((zfs_ace_hdr_t *)acep)->z_flags = flags; 224185029Spjd} 225185029Spjd 226185029Spjdstatic void 227185029Spjdzfs_ace_fuid_set_mask(void *acep, uint32_t mask) 228185029Spjd{ 229185029Spjd ((zfs_ace_hdr_t *)acep)->z_access_mask = mask; 230185029Spjd} 231185029Spjd 232185029Spjdstatic void 233185029Spjdzfs_ace_fuid_set_who(void *arg, uint64_t who) 234185029Spjd{ 235185029Spjd zfs_ace_t *acep = arg; 236185029Spjd 237185029Spjd uint16_t entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 238185029Spjd 239185029Spjd if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 240185029Spjd entry_type == ACE_EVERYONE) 241185029Spjd return; 242185029Spjd acep->z_fuid = who; 243185029Spjd} 244185029Spjd 245185029Spjdstatic size_t 246185029Spjdzfs_ace_fuid_size(void *acep) 247185029Spjd{ 248185029Spjd zfs_ace_hdr_t *zacep = acep; 249185029Spjd uint16_t entry_type; 250185029Spjd 251185029Spjd switch (zacep->z_type) { 252185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 253185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 254185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 255185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 256185029Spjd return (sizeof (zfs_object_ace_t)); 257185029Spjd case ALLOW: 258185029Spjd case DENY: 259185029Spjd entry_type = 260185029Spjd (((zfs_ace_hdr_t *)acep)->z_flags & ACE_TYPE_FLAGS); 261185029Spjd if (entry_type == ACE_OWNER || 262185029Spjd entry_type == OWNING_GROUP || 263185029Spjd entry_type == ACE_EVERYONE) 264185029Spjd return (sizeof (zfs_ace_hdr_t)); 265185029Spjd /*FALLTHROUGH*/ 266185029Spjd default: 267185029Spjd return (sizeof (zfs_ace_t)); 268185029Spjd } 269185029Spjd} 270185029Spjd 271185029Spjdstatic size_t 272185029Spjdzfs_ace_fuid_abstract_size(void) 273185029Spjd{ 274185029Spjd return (sizeof (zfs_ace_hdr_t)); 275185029Spjd} 276185029Spjd 277185029Spjdstatic int 278185029Spjdzfs_ace_fuid_mask_off(void) 279185029Spjd{ 280185029Spjd return (offsetof(zfs_ace_hdr_t, z_access_mask)); 281185029Spjd} 282185029Spjd 283185029Spjdstatic int 284185029Spjdzfs_ace_fuid_data(void *acep, void **datap) 285185029Spjd{ 286185029Spjd zfs_ace_t *zacep = acep; 287185029Spjd zfs_object_ace_t *zobjp; 288185029Spjd 289185029Spjd switch (zacep->z_hdr.z_type) { 290185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 291185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 292185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 293185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 294185029Spjd zobjp = acep; 295185029Spjd *datap = (caddr_t)zobjp + sizeof (zfs_ace_t); 296185029Spjd return (sizeof (zfs_object_ace_t) - sizeof (zfs_ace_t)); 297185029Spjd default: 298185029Spjd *datap = NULL; 299185029Spjd return (0); 300185029Spjd } 301185029Spjd} 302185029Spjd 303185029Spjdstatic acl_ops_t zfs_acl_fuid_ops = { 304185029Spjd zfs_ace_fuid_get_mask, 305185029Spjd zfs_ace_fuid_set_mask, 306185029Spjd zfs_ace_fuid_get_flags, 307185029Spjd zfs_ace_fuid_set_flags, 308185029Spjd zfs_ace_fuid_get_type, 309185029Spjd zfs_ace_fuid_set_type, 310185029Spjd zfs_ace_fuid_get_who, 311185029Spjd zfs_ace_fuid_set_who, 312185029Spjd zfs_ace_fuid_size, 313185029Spjd zfs_ace_fuid_abstract_size, 314185029Spjd zfs_ace_fuid_mask_off, 315185029Spjd zfs_ace_fuid_data 316185029Spjd}; 317185029Spjd 318185029Spjdstatic int 319185029Spjdzfs_acl_version(int version) 320185029Spjd{ 321185029Spjd if (version < ZPL_VERSION_FUID) 322185029Spjd return (ZFS_ACL_VERSION_INITIAL); 323185029Spjd else 324185029Spjd return (ZFS_ACL_VERSION_FUID); 325185029Spjd} 326185029Spjd 327185029Spjdstatic int 328185029Spjdzfs_acl_version_zp(znode_t *zp) 329185029Spjd{ 330185029Spjd return (zfs_acl_version(zp->z_zfsvfs->z_version)); 331185029Spjd} 332185029Spjd 333168404Spjdstatic zfs_acl_t * 334185029Spjdzfs_acl_alloc(int vers) 335168404Spjd{ 336168404Spjd zfs_acl_t *aclp; 337168404Spjd 338168404Spjd aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 339185029Spjd list_create(&aclp->z_acl, sizeof (zfs_acl_node_t), 340185029Spjd offsetof(zfs_acl_node_t, z_next)); 341185029Spjd aclp->z_version = vers; 342185029Spjd if (vers == ZFS_ACL_VERSION_FUID) 343185029Spjd aclp->z_ops = zfs_acl_fuid_ops; 344185029Spjd else 345185029Spjd aclp->z_ops = zfs_acl_v0_ops; 346168404Spjd return (aclp); 347168404Spjd} 348168404Spjd 349185029Spjdstatic zfs_acl_node_t * 350185029Spjdzfs_acl_node_alloc(size_t bytes) 351185029Spjd{ 352185029Spjd zfs_acl_node_t *aclnode; 353185029Spjd 354185029Spjd aclnode = kmem_zalloc(sizeof (zfs_acl_node_t), KM_SLEEP); 355185029Spjd if (bytes) { 356185029Spjd aclnode->z_acldata = kmem_alloc(bytes, KM_SLEEP); 357185029Spjd aclnode->z_allocdata = aclnode->z_acldata; 358185029Spjd aclnode->z_allocsize = bytes; 359185029Spjd aclnode->z_size = bytes; 360185029Spjd } 361185029Spjd 362185029Spjd return (aclnode); 363185029Spjd} 364185029Spjd 365185029Spjdstatic void 366185029Spjdzfs_acl_node_free(zfs_acl_node_t *aclnode) 367185029Spjd{ 368185029Spjd if (aclnode->z_allocsize) 369185029Spjd kmem_free(aclnode->z_allocdata, aclnode->z_allocsize); 370185029Spjd kmem_free(aclnode, sizeof (zfs_acl_node_t)); 371185029Spjd} 372185029Spjd 373185029Spjdstatic void 374185029Spjdzfs_acl_release_nodes(zfs_acl_t *aclp) 375185029Spjd{ 376185029Spjd zfs_acl_node_t *aclnode; 377185029Spjd 378185029Spjd while (aclnode = list_head(&aclp->z_acl)) { 379185029Spjd list_remove(&aclp->z_acl, aclnode); 380185029Spjd zfs_acl_node_free(aclnode); 381185029Spjd } 382185029Spjd aclp->z_acl_count = 0; 383185029Spjd aclp->z_acl_bytes = 0; 384185029Spjd} 385185029Spjd 386168404Spjdvoid 387168404Spjdzfs_acl_free(zfs_acl_t *aclp) 388168404Spjd{ 389185029Spjd zfs_acl_release_nodes(aclp); 390185029Spjd list_destroy(&aclp->z_acl); 391168404Spjd kmem_free(aclp, sizeof (zfs_acl_t)); 392168404Spjd} 393168404Spjd 394185029Spjdstatic boolean_t 395185029Spjdzfs_acl_valid_ace_type(uint_t type, uint_t flags) 396168404Spjd{ 397185029Spjd uint16_t entry_type; 398168404Spjd 399185029Spjd switch (type) { 400185029Spjd case ALLOW: 401185029Spjd case DENY: 402185029Spjd case ACE_SYSTEM_AUDIT_ACE_TYPE: 403185029Spjd case ACE_SYSTEM_ALARM_ACE_TYPE: 404185029Spjd entry_type = flags & ACE_TYPE_FLAGS; 405185029Spjd return (entry_type == ACE_OWNER || 406185029Spjd entry_type == OWNING_GROUP || 407185029Spjd entry_type == ACE_EVERYONE || entry_type == 0 || 408185029Spjd entry_type == ACE_IDENTIFIER_GROUP); 409185029Spjd default: 410185029Spjd if (type >= MIN_ACE_TYPE && type <= MAX_ACE_TYPE) 411185029Spjd return (B_TRUE); 412185029Spjd } 413185029Spjd return (B_FALSE); 414185029Spjd} 415185029Spjd 416185029Spjdstatic boolean_t 417185029Spjdzfs_ace_valid(vtype_t obj_type, zfs_acl_t *aclp, uint16_t type, uint16_t iflags) 418185029Spjd{ 419168404Spjd /* 420185029Spjd * first check type of entry 421168404Spjd */ 422168404Spjd 423185029Spjd if (!zfs_acl_valid_ace_type(type, iflags)) 424185029Spjd return (B_FALSE); 425185029Spjd 426185029Spjd switch (type) { 427185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 428185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 429185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 430185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 431185029Spjd if (aclp->z_version < ZFS_ACL_VERSION_FUID) 432185029Spjd return (B_FALSE); 433185029Spjd aclp->z_hints |= ZFS_ACL_OBJ_ACE; 434185029Spjd } 435185029Spjd 436185029Spjd /* 437185029Spjd * next check inheritance level flags 438185029Spjd */ 439185029Spjd 440185029Spjd if (obj_type == VDIR && 441185029Spjd (iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 442185029Spjd aclp->z_hints |= ZFS_INHERIT_ACE; 443185029Spjd 444185029Spjd if (iflags & (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 445185029Spjd if ((iflags & (ACE_FILE_INHERIT_ACE| 446185029Spjd ACE_DIRECTORY_INHERIT_ACE)) == 0) { 447185029Spjd return (B_FALSE); 448185029Spjd } 449185029Spjd } 450185029Spjd 451185029Spjd return (B_TRUE); 452168404Spjd} 453168404Spjd 454185029Spjdstatic void * 455185029Spjdzfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who, 456185029Spjd uint32_t *access_mask, uint16_t *iflags, uint16_t *type) 457185029Spjd{ 458185029Spjd zfs_acl_node_t *aclnode; 459185029Spjd 460185029Spjd if (start == NULL) { 461185029Spjd aclnode = list_head(&aclp->z_acl); 462185029Spjd if (aclnode == NULL) 463185029Spjd return (NULL); 464185029Spjd 465185029Spjd aclp->z_next_ace = aclnode->z_acldata; 466185029Spjd aclp->z_curr_node = aclnode; 467185029Spjd aclnode->z_ace_idx = 0; 468185029Spjd } 469185029Spjd 470185029Spjd aclnode = aclp->z_curr_node; 471185029Spjd 472185029Spjd if (aclnode == NULL) 473185029Spjd return (NULL); 474185029Spjd 475185029Spjd if (aclnode->z_ace_idx >= aclnode->z_ace_count) { 476185029Spjd aclnode = list_next(&aclp->z_acl, aclnode); 477185029Spjd if (aclnode == NULL) 478185029Spjd return (NULL); 479185029Spjd else { 480185029Spjd aclp->z_curr_node = aclnode; 481185029Spjd aclnode->z_ace_idx = 0; 482185029Spjd aclp->z_next_ace = aclnode->z_acldata; 483185029Spjd } 484185029Spjd } 485185029Spjd 486185029Spjd if (aclnode->z_ace_idx < aclnode->z_ace_count) { 487185029Spjd void *acep = aclp->z_next_ace; 488185029Spjd size_t ace_size; 489185029Spjd 490185029Spjd /* 491185029Spjd * Make sure we don't overstep our bounds 492185029Spjd */ 493185029Spjd ace_size = aclp->z_ops.ace_size(acep); 494185029Spjd 495185029Spjd if (((caddr_t)acep + ace_size) > 496185029Spjd ((caddr_t)aclnode->z_acldata + aclnode->z_size)) { 497185029Spjd return (NULL); 498185029Spjd } 499185029Spjd 500185029Spjd *iflags = aclp->z_ops.ace_flags_get(acep); 501185029Spjd *type = aclp->z_ops.ace_type_get(acep); 502185029Spjd *access_mask = aclp->z_ops.ace_mask_get(acep); 503185029Spjd *who = aclp->z_ops.ace_who_get(acep); 504185029Spjd aclp->z_next_ace = (caddr_t)aclp->z_next_ace + ace_size; 505185029Spjd aclnode->z_ace_idx++; 506185029Spjd return ((void *)acep); 507185029Spjd } 508185029Spjd return (NULL); 509185029Spjd} 510185029Spjd 511185029Spjd/*ARGSUSED*/ 512185029Spjdstatic uint64_t 513185029Spjdzfs_ace_walk(void *datap, uint64_t cookie, int aclcnt, 514185029Spjd uint16_t *flags, uint16_t *type, uint32_t *mask) 515185029Spjd{ 516185029Spjd zfs_acl_t *aclp = datap; 517185029Spjd zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)(uintptr_t)cookie; 518185029Spjd uint64_t who; 519185029Spjd 520185029Spjd acep = zfs_acl_next_ace(aclp, acep, &who, mask, 521185029Spjd flags, type); 522185029Spjd return ((uint64_t)(uintptr_t)acep); 523185029Spjd} 524185029Spjd 525185029Spjdstatic zfs_acl_node_t * 526185029Spjdzfs_acl_curr_node(zfs_acl_t *aclp) 527185029Spjd{ 528185029Spjd ASSERT(aclp->z_curr_node); 529185029Spjd return (aclp->z_curr_node); 530185029Spjd} 531185029Spjd 532168404Spjd/* 533185029Spjd * Copy ACE to internal ZFS format. 534185029Spjd * While processing the ACL each ACE will be validated for correctness. 535185029Spjd * ACE FUIDs will be created later. 536185029Spjd */ 537185029Spjdint 538185029Spjdzfs_copy_ace_2_fuid(vtype_t obj_type, zfs_acl_t *aclp, void *datap, 539185029Spjd zfs_ace_t *z_acl, int aclcnt, size_t *size) 540185029Spjd{ 541185029Spjd int i; 542185029Spjd uint16_t entry_type; 543185029Spjd zfs_ace_t *aceptr = z_acl; 544185029Spjd ace_t *acep = datap; 545185029Spjd zfs_object_ace_t *zobjacep; 546185029Spjd ace_object_t *aceobjp; 547185029Spjd 548185029Spjd for (i = 0; i != aclcnt; i++) { 549185029Spjd aceptr->z_hdr.z_access_mask = acep->a_access_mask; 550185029Spjd aceptr->z_hdr.z_flags = acep->a_flags; 551185029Spjd aceptr->z_hdr.z_type = acep->a_type; 552185029Spjd entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS; 553185029Spjd if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP && 554185029Spjd entry_type != ACE_EVERYONE) { 555185029Spjd if (!aclp->z_has_fuids) 556185029Spjd aclp->z_has_fuids = IS_EPHEMERAL(acep->a_who); 557185029Spjd aceptr->z_fuid = (uint64_t)acep->a_who; 558185029Spjd } 559185029Spjd 560185029Spjd /* 561185029Spjd * Make sure ACE is valid 562185029Spjd */ 563185029Spjd if (zfs_ace_valid(obj_type, aclp, aceptr->z_hdr.z_type, 564185029Spjd aceptr->z_hdr.z_flags) != B_TRUE) 565185029Spjd return (EINVAL); 566185029Spjd 567185029Spjd switch (acep->a_type) { 568185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 569185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 570185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 571185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 572185029Spjd zobjacep = (zfs_object_ace_t *)aceptr; 573185029Spjd aceobjp = (ace_object_t *)acep; 574185029Spjd 575185029Spjd bcopy(aceobjp->a_obj_type, zobjacep->z_object_type, 576185029Spjd sizeof (aceobjp->a_obj_type)); 577185029Spjd bcopy(aceobjp->a_inherit_obj_type, 578185029Spjd zobjacep->z_inherit_type, 579185029Spjd sizeof (aceobjp->a_inherit_obj_type)); 580185029Spjd acep = (ace_t *)((caddr_t)acep + sizeof (ace_object_t)); 581185029Spjd break; 582185029Spjd default: 583185029Spjd acep = (ace_t *)((caddr_t)acep + sizeof (ace_t)); 584185029Spjd } 585185029Spjd 586185029Spjd aceptr = (zfs_ace_t *)((caddr_t)aceptr + 587185029Spjd aclp->z_ops.ace_size(aceptr)); 588185029Spjd } 589185029Spjd 590185029Spjd *size = (caddr_t)aceptr - (caddr_t)z_acl; 591185029Spjd 592185029Spjd return (0); 593185029Spjd} 594185029Spjd 595185029Spjd/* 596185029Spjd * Copy ZFS ACEs to fixed size ace_t layout 597185029Spjd */ 598185029Spjdstatic void 599185029Spjdzfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr, 600185029Spjd void *datap, int filter) 601185029Spjd{ 602185029Spjd uint64_t who; 603185029Spjd uint32_t access_mask; 604185029Spjd uint16_t iflags, type; 605185029Spjd zfs_ace_hdr_t *zacep = NULL; 606185029Spjd ace_t *acep = datap; 607185029Spjd ace_object_t *objacep; 608185029Spjd zfs_object_ace_t *zobjacep; 609185029Spjd size_t ace_size; 610185029Spjd uint16_t entry_type; 611185029Spjd 612185029Spjd while (zacep = zfs_acl_next_ace(aclp, zacep, 613185029Spjd &who, &access_mask, &iflags, &type)) { 614185029Spjd 615185029Spjd switch (type) { 616185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 617185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 618185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 619185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 620185029Spjd if (filter) { 621185029Spjd continue; 622185029Spjd } 623185029Spjd zobjacep = (zfs_object_ace_t *)zacep; 624185029Spjd objacep = (ace_object_t *)acep; 625185029Spjd bcopy(zobjacep->z_object_type, 626185029Spjd objacep->a_obj_type, 627185029Spjd sizeof (zobjacep->z_object_type)); 628185029Spjd bcopy(zobjacep->z_inherit_type, 629185029Spjd objacep->a_inherit_obj_type, 630185029Spjd sizeof (zobjacep->z_inherit_type)); 631185029Spjd ace_size = sizeof (ace_object_t); 632185029Spjd break; 633185029Spjd default: 634185029Spjd ace_size = sizeof (ace_t); 635185029Spjd break; 636185029Spjd } 637185029Spjd 638185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 639185029Spjd if ((entry_type != ACE_OWNER && 640185029Spjd entry_type != OWNING_GROUP && 641185029Spjd entry_type != ACE_EVERYONE)) { 642185029Spjd acep->a_who = zfs_fuid_map_id(zfsvfs, who, 643185029Spjd cr, (entry_type & ACE_IDENTIFIER_GROUP) ? 644185029Spjd ZFS_ACE_GROUP : ZFS_ACE_USER); 645185029Spjd } else { 646185029Spjd acep->a_who = (uid_t)(int64_t)who; 647185029Spjd } 648185029Spjd acep->a_access_mask = access_mask; 649185029Spjd acep->a_flags = iflags; 650185029Spjd acep->a_type = type; 651185029Spjd acep = (ace_t *)((caddr_t)acep + ace_size); 652185029Spjd } 653185029Spjd} 654185029Spjd 655185029Spjdstatic int 656185029Spjdzfs_copy_ace_2_oldace(vtype_t obj_type, zfs_acl_t *aclp, ace_t *acep, 657185029Spjd zfs_oldace_t *z_acl, int aclcnt, size_t *size) 658185029Spjd{ 659185029Spjd int i; 660185029Spjd zfs_oldace_t *aceptr = z_acl; 661185029Spjd 662185029Spjd for (i = 0; i != aclcnt; i++, aceptr++) { 663185029Spjd aceptr->z_access_mask = acep[i].a_access_mask; 664185029Spjd aceptr->z_type = acep[i].a_type; 665185029Spjd aceptr->z_flags = acep[i].a_flags; 666185029Spjd aceptr->z_fuid = acep[i].a_who; 667185029Spjd /* 668185029Spjd * Make sure ACE is valid 669185029Spjd */ 670185029Spjd if (zfs_ace_valid(obj_type, aclp, aceptr->z_type, 671185029Spjd aceptr->z_flags) != B_TRUE) 672185029Spjd return (EINVAL); 673185029Spjd } 674185029Spjd *size = (caddr_t)aceptr - (caddr_t)z_acl; 675185029Spjd return (0); 676185029Spjd} 677185029Spjd 678185029Spjd/* 679185029Spjd * convert old ACL format to new 680185029Spjd */ 681185029Spjdvoid 682185029Spjdzfs_acl_xform(znode_t *zp, zfs_acl_t *aclp) 683185029Spjd{ 684185029Spjd zfs_oldace_t *oldaclp; 685185029Spjd int i; 686185029Spjd uint16_t type, iflags; 687185029Spjd uint32_t access_mask; 688185029Spjd uint64_t who; 689185029Spjd void *cookie = NULL; 690185029Spjd zfs_acl_node_t *newaclnode; 691185029Spjd 692185029Spjd ASSERT(aclp->z_version == ZFS_ACL_VERSION_INITIAL); 693185029Spjd /* 694185029Spjd * First create the ACE in a contiguous piece of memory 695185029Spjd * for zfs_copy_ace_2_fuid(). 696185029Spjd * 697185029Spjd * We only convert an ACL once, so this won't happen 698185029Spjd * everytime. 699185029Spjd */ 700185029Spjd oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count, 701185029Spjd KM_SLEEP); 702185029Spjd i = 0; 703185029Spjd while (cookie = zfs_acl_next_ace(aclp, cookie, &who, 704185029Spjd &access_mask, &iflags, &type)) { 705185029Spjd oldaclp[i].z_flags = iflags; 706185029Spjd oldaclp[i].z_type = type; 707185029Spjd oldaclp[i].z_fuid = who; 708185029Spjd oldaclp[i++].z_access_mask = access_mask; 709185029Spjd } 710185029Spjd 711185029Spjd newaclnode = zfs_acl_node_alloc(aclp->z_acl_count * 712185029Spjd sizeof (zfs_object_ace_t)); 713185029Spjd aclp->z_ops = zfs_acl_fuid_ops; 714185029Spjd VERIFY(zfs_copy_ace_2_fuid(ZTOV(zp)->v_type, aclp, oldaclp, 715185029Spjd newaclnode->z_acldata, aclp->z_acl_count, 716185029Spjd &newaclnode->z_size) == 0); 717185029Spjd newaclnode->z_ace_count = aclp->z_acl_count; 718185029Spjd aclp->z_version = ZFS_ACL_VERSION; 719185029Spjd kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t)); 720185029Spjd 721185029Spjd /* 722185029Spjd * Release all previous ACL nodes 723185029Spjd */ 724185029Spjd 725185029Spjd zfs_acl_release_nodes(aclp); 726185029Spjd 727185029Spjd list_insert_head(&aclp->z_acl, newaclnode); 728185029Spjd 729185029Spjd aclp->z_acl_bytes = newaclnode->z_size; 730185029Spjd aclp->z_acl_count = newaclnode->z_ace_count; 731185029Spjd 732185029Spjd} 733185029Spjd 734185029Spjd/* 735168404Spjd * Convert unix access mask to v4 access mask 736168404Spjd */ 737168404Spjdstatic uint32_t 738168404Spjdzfs_unix_to_v4(uint32_t access_mask) 739168404Spjd{ 740168404Spjd uint32_t new_mask = 0; 741168404Spjd 742185029Spjd if (access_mask & S_IXOTH) 743185029Spjd new_mask |= ACE_EXECUTE; 744185029Spjd if (access_mask & S_IWOTH) 745185029Spjd new_mask |= ACE_WRITE_DATA; 746185029Spjd if (access_mask & S_IROTH) 747168404Spjd new_mask |= ACE_READ_DATA; 748168404Spjd return (new_mask); 749168404Spjd} 750168404Spjd 751168404Spjdstatic void 752185029Spjdzfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask, 753185029Spjd uint16_t access_type, uint64_t fuid, uint16_t entry_type) 754168404Spjd{ 755185029Spjd uint16_t type = entry_type & ACE_TYPE_FLAGS; 756185029Spjd 757185029Spjd aclp->z_ops.ace_mask_set(acep, access_mask); 758185029Spjd aclp->z_ops.ace_type_set(acep, access_type); 759185029Spjd aclp->z_ops.ace_flags_set(acep, entry_type); 760185029Spjd if ((type != ACE_OWNER && type != OWNING_GROUP && 761185029Spjd type != ACE_EVERYONE)) 762185029Spjd aclp->z_ops.ace_who_set(acep, fuid); 763168404Spjd} 764168404Spjd 765185029Spjd/* 766185029Spjd * Determine mode of file based on ACL. 767185029Spjd * Also, create FUIDs for any User/Group ACEs 768185029Spjd */ 769168404Spjdstatic uint64_t 770185029Spjdzfs_mode_fuid_compute(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, 771185029Spjd zfs_fuid_info_t **fuidp, dmu_tx_t *tx) 772168404Spjd{ 773185029Spjd int entry_type; 774185029Spjd mode_t mode; 775185029Spjd mode_t seen = 0; 776185029Spjd zfs_ace_hdr_t *acep = NULL; 777185029Spjd uint64_t who; 778185029Spjd uint16_t iflags, type; 779185029Spjd uint32_t access_mask; 780168404Spjd 781185029Spjd mode = (zp->z_phys->zp_mode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 782185029Spjd 783185029Spjd while (acep = zfs_acl_next_ace(aclp, acep, &who, 784185029Spjd &access_mask, &iflags, &type)) { 785185029Spjd 786185029Spjd if (!zfs_acl_valid_ace_type(type, iflags)) 787185029Spjd continue; 788185029Spjd 789185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 790185029Spjd 791185029Spjd /* 792185029Spjd * Skip over owner@, group@ or everyone@ inherit only ACEs 793185029Spjd */ 794185029Spjd if ((iflags & ACE_INHERIT_ONLY_ACE) && 795185029Spjd (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 796185029Spjd entry_type == OWNING_GROUP)) 797185029Spjd continue; 798185029Spjd 799168404Spjd if (entry_type == ACE_OWNER) { 800185029Spjd if ((access_mask & ACE_READ_DATA) && 801168404Spjd (!(seen & S_IRUSR))) { 802168404Spjd seen |= S_IRUSR; 803185029Spjd if (type == ALLOW) { 804168404Spjd mode |= S_IRUSR; 805168404Spjd } 806168404Spjd } 807185029Spjd if ((access_mask & ACE_WRITE_DATA) && 808168404Spjd (!(seen & S_IWUSR))) { 809168404Spjd seen |= S_IWUSR; 810185029Spjd if (type == ALLOW) { 811168404Spjd mode |= S_IWUSR; 812168404Spjd } 813168404Spjd } 814185029Spjd if ((access_mask & ACE_EXECUTE) && 815168404Spjd (!(seen & S_IXUSR))) { 816168404Spjd seen |= S_IXUSR; 817185029Spjd if (type == ALLOW) { 818168404Spjd mode |= S_IXUSR; 819168404Spjd } 820168404Spjd } 821168404Spjd } else if (entry_type == OWNING_GROUP) { 822185029Spjd if ((access_mask & ACE_READ_DATA) && 823168404Spjd (!(seen & S_IRGRP))) { 824168404Spjd seen |= S_IRGRP; 825185029Spjd if (type == ALLOW) { 826168404Spjd mode |= S_IRGRP; 827168404Spjd } 828168404Spjd } 829185029Spjd if ((access_mask & ACE_WRITE_DATA) && 830168404Spjd (!(seen & S_IWGRP))) { 831168404Spjd seen |= S_IWGRP; 832185029Spjd if (type == ALLOW) { 833168404Spjd mode |= S_IWGRP; 834168404Spjd } 835168404Spjd } 836185029Spjd if ((access_mask & ACE_EXECUTE) && 837168404Spjd (!(seen & S_IXGRP))) { 838168404Spjd seen |= S_IXGRP; 839185029Spjd if (type == ALLOW) { 840168404Spjd mode |= S_IXGRP; 841168404Spjd } 842168404Spjd } 843168404Spjd } else if (entry_type == ACE_EVERYONE) { 844185029Spjd if ((access_mask & ACE_READ_DATA)) { 845168404Spjd if (!(seen & S_IRUSR)) { 846168404Spjd seen |= S_IRUSR; 847185029Spjd if (type == ALLOW) { 848168404Spjd mode |= S_IRUSR; 849168404Spjd } 850168404Spjd } 851168404Spjd if (!(seen & S_IRGRP)) { 852168404Spjd seen |= S_IRGRP; 853185029Spjd if (type == ALLOW) { 854168404Spjd mode |= S_IRGRP; 855168404Spjd } 856168404Spjd } 857168404Spjd if (!(seen & S_IROTH)) { 858168404Spjd seen |= S_IROTH; 859185029Spjd if (type == ALLOW) { 860168404Spjd mode |= S_IROTH; 861168404Spjd } 862168404Spjd } 863168404Spjd } 864185029Spjd if ((access_mask & ACE_WRITE_DATA)) { 865168404Spjd if (!(seen & S_IWUSR)) { 866168404Spjd seen |= S_IWUSR; 867185029Spjd if (type == ALLOW) { 868168404Spjd mode |= S_IWUSR; 869168404Spjd } 870168404Spjd } 871168404Spjd if (!(seen & S_IWGRP)) { 872168404Spjd seen |= S_IWGRP; 873185029Spjd if (type == ALLOW) { 874168404Spjd mode |= S_IWGRP; 875168404Spjd } 876168404Spjd } 877168404Spjd if (!(seen & S_IWOTH)) { 878168404Spjd seen |= S_IWOTH; 879185029Spjd if (type == ALLOW) { 880168404Spjd mode |= S_IWOTH; 881168404Spjd } 882168404Spjd } 883168404Spjd } 884185029Spjd if ((access_mask & ACE_EXECUTE)) { 885168404Spjd if (!(seen & S_IXUSR)) { 886168404Spjd seen |= S_IXUSR; 887185029Spjd if (type == ALLOW) { 888168404Spjd mode |= S_IXUSR; 889168404Spjd } 890168404Spjd } 891168404Spjd if (!(seen & S_IXGRP)) { 892168404Spjd seen |= S_IXGRP; 893185029Spjd if (type == ALLOW) { 894168404Spjd mode |= S_IXGRP; 895168404Spjd } 896168404Spjd } 897168404Spjd if (!(seen & S_IXOTH)) { 898168404Spjd seen |= S_IXOTH; 899185029Spjd if (type == ALLOW) { 900168404Spjd mode |= S_IXOTH; 901168404Spjd } 902168404Spjd } 903168404Spjd } 904168404Spjd } 905185029Spjd /* 906185029Spjd * Now handle FUID create for user/group ACEs 907185029Spjd */ 908185029Spjd if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) { 909185029Spjd aclp->z_ops.ace_who_set(acep, 910185029Spjd zfs_fuid_create(zp->z_zfsvfs, who, cr, 911185029Spjd (entry_type == 0) ? ZFS_ACE_USER : ZFS_ACE_GROUP, 912185029Spjd tx, fuidp)); 913185029Spjd } 914168404Spjd } 915168404Spjd return (mode); 916168404Spjd} 917168404Spjd 918168404Spjdstatic zfs_acl_t * 919185029Spjdzfs_acl_node_read_internal(znode_t *zp, boolean_t will_modify) 920168404Spjd{ 921168404Spjd zfs_acl_t *aclp; 922185029Spjd zfs_acl_node_t *aclnode; 923168404Spjd 924185029Spjd aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_version); 925168404Spjd 926185029Spjd /* 927185029Spjd * Version 0 to 1 znode_acl_phys has the size/count fields swapped. 928185029Spjd * Version 0 didn't have a size field, only a count. 929185029Spjd */ 930185029Spjd if (zp->z_phys->zp_acl.z_acl_version == ZFS_ACL_VERSION_INITIAL) { 931185029Spjd aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_size; 932185029Spjd aclp->z_acl_bytes = ZFS_ACL_SIZE(aclp->z_acl_count); 933185029Spjd } else { 934185029Spjd aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count; 935185029Spjd aclp->z_acl_bytes = zp->z_phys->zp_acl.z_acl_size; 936185029Spjd } 937185029Spjd 938185029Spjd aclnode = zfs_acl_node_alloc(will_modify ? aclp->z_acl_bytes : 0); 939185029Spjd aclnode->z_ace_count = aclp->z_acl_count; 940185029Spjd if (will_modify) { 941185029Spjd bcopy(zp->z_phys->zp_acl.z_ace_data, aclnode->z_acldata, 942185029Spjd aclp->z_acl_bytes); 943185029Spjd } else { 944185029Spjd aclnode->z_size = aclp->z_acl_bytes; 945185029Spjd aclnode->z_acldata = &zp->z_phys->zp_acl.z_ace_data[0]; 946185029Spjd } 947185029Spjd 948185029Spjd list_insert_head(&aclp->z_acl, aclnode); 949185029Spjd 950168404Spjd return (aclp); 951168404Spjd} 952168404Spjd 953168404Spjd/* 954168404Spjd * Read an external acl object. 955168404Spjd */ 956168404Spjdstatic int 957185029Spjdzfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp, boolean_t will_modify) 958168404Spjd{ 959168404Spjd uint64_t extacl = zp->z_phys->zp_acl.z_acl_extern_obj; 960168404Spjd zfs_acl_t *aclp; 961185029Spjd size_t aclsize; 962185029Spjd size_t acl_count; 963185029Spjd zfs_acl_node_t *aclnode; 964168404Spjd int error; 965168404Spjd 966168404Spjd ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 967168404Spjd 968168404Spjd if (zp->z_phys->zp_acl.z_acl_extern_obj == 0) { 969185029Spjd *aclpp = zfs_acl_node_read_internal(zp, will_modify); 970168404Spjd return (0); 971168404Spjd } 972168404Spjd 973185029Spjd aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_version); 974185029Spjd if (zp->z_phys->zp_acl.z_acl_version == ZFS_ACL_VERSION_INITIAL) { 975185029Spjd zfs_acl_phys_v0_t *zacl0 = 976185029Spjd (zfs_acl_phys_v0_t *)&zp->z_phys->zp_acl; 977168404Spjd 978185029Spjd aclsize = ZFS_ACL_SIZE(zacl0->z_acl_count); 979185029Spjd acl_count = zacl0->z_acl_count; 980185029Spjd } else { 981185029Spjd aclsize = zp->z_phys->zp_acl.z_acl_size; 982185029Spjd acl_count = zp->z_phys->zp_acl.z_acl_count; 983185029Spjd if (aclsize == 0) 984185029Spjd aclsize = acl_count * sizeof (zfs_ace_t); 985185029Spjd } 986185029Spjd aclnode = zfs_acl_node_alloc(aclsize); 987185029Spjd list_insert_head(&aclp->z_acl, aclnode); 988168404Spjd error = dmu_read(zp->z_zfsvfs->z_os, extacl, 0, 989185029Spjd aclsize, aclnode->z_acldata); 990185029Spjd aclnode->z_ace_count = acl_count; 991185029Spjd aclp->z_acl_count = acl_count; 992185029Spjd aclp->z_acl_bytes = aclsize; 993185029Spjd 994168404Spjd if (error != 0) { 995168404Spjd zfs_acl_free(aclp); 996185029Spjd /* convert checksum errors into IO errors */ 997185029Spjd if (error == ECKSUM) 998185029Spjd error = EIO; 999168404Spjd return (error); 1000168404Spjd } 1001168404Spjd 1002168404Spjd *aclpp = aclp; 1003168404Spjd return (0); 1004168404Spjd} 1005168404Spjd 1006168404Spjd/* 1007185029Spjd * common code for setting ACLs. 1008168404Spjd * 1009168404Spjd * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 1010168404Spjd * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 1011168404Spjd * already checked the acl and knows whether to inherit. 1012168404Spjd */ 1013168404Spjdint 1014185029Spjdzfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, 1015185029Spjd zfs_fuid_info_t **fuidp, dmu_tx_t *tx) 1016168404Spjd{ 1017168404Spjd int error; 1018168404Spjd znode_phys_t *zphys = zp->z_phys; 1019185029Spjd zfs_acl_phys_t *zacl = &zphys->zp_acl; 1020168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1021168404Spjd uint64_t aoid = zphys->zp_acl.z_acl_extern_obj; 1022185029Spjd uint64_t off = 0; 1023185029Spjd dmu_object_type_t otype; 1024185029Spjd zfs_acl_node_t *aclnode; 1025168404Spjd 1026168404Spjd ASSERT(MUTEX_HELD(&zp->z_lock)); 1027168404Spjd ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1028168404Spjd 1029168404Spjd dmu_buf_will_dirty(zp->z_dbuf, tx); 1030168404Spjd 1031185029Spjd zphys->zp_mode = zfs_mode_fuid_compute(zp, aclp, cr, fuidp, tx); 1032185029Spjd 1033168404Spjd /* 1034185029Spjd * Decide which opbject type to use. If we are forced to 1035185029Spjd * use old ACL format than transform ACL into zfs_oldace_t 1036185029Spjd * layout. 1037168404Spjd */ 1038185029Spjd if (!zfsvfs->z_use_fuids) { 1039185029Spjd otype = DMU_OT_OLDACL; 1040185029Spjd } else { 1041185029Spjd if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) && 1042185029Spjd (zfsvfs->z_version >= ZPL_VERSION_FUID)) 1043185029Spjd zfs_acl_xform(zp, aclp); 1044185029Spjd ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID); 1045185029Spjd otype = DMU_OT_ACL; 1046185029Spjd } 1047185029Spjd 1048185029Spjd if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 1049185029Spjd /* 1050185029Spjd * If ACL was previously external and we are now 1051185029Spjd * converting to new ACL format then release old 1052185029Spjd * ACL object and create a new one. 1053185029Spjd */ 1054185029Spjd if (aoid && aclp->z_version != zacl->z_acl_version) { 1055185029Spjd error = dmu_object_free(zfsvfs->z_os, 1056185029Spjd zp->z_phys->zp_acl.z_acl_extern_obj, tx); 1057185029Spjd if (error) 1058185029Spjd return (error); 1059185029Spjd aoid = 0; 1060185029Spjd } 1061168404Spjd if (aoid == 0) { 1062168404Spjd aoid = dmu_object_alloc(zfsvfs->z_os, 1063185029Spjd otype, aclp->z_acl_bytes, 1064185029Spjd otype == DMU_OT_ACL ? DMU_OT_SYSACL : DMU_OT_NONE, 1065185029Spjd otype == DMU_OT_ACL ? DN_MAX_BONUSLEN : 0, tx); 1066168404Spjd } else { 1067168404Spjd (void) dmu_object_set_blocksize(zfsvfs->z_os, aoid, 1068185029Spjd aclp->z_acl_bytes, 0, tx); 1069168404Spjd } 1070168404Spjd zphys->zp_acl.z_acl_extern_obj = aoid; 1071185029Spjd for (aclnode = list_head(&aclp->z_acl); aclnode; 1072185029Spjd aclnode = list_next(&aclp->z_acl, aclnode)) { 1073185029Spjd if (aclnode->z_ace_count == 0) 1074185029Spjd continue; 1075185029Spjd dmu_write(zfsvfs->z_os, aoid, off, 1076185029Spjd aclnode->z_size, aclnode->z_acldata, tx); 1077185029Spjd off += aclnode->z_size; 1078185029Spjd } 1079168404Spjd } else { 1080185029Spjd void *start = zacl->z_ace_data; 1081168404Spjd /* 1082168404Spjd * Migrating back embedded? 1083168404Spjd */ 1084168404Spjd if (zphys->zp_acl.z_acl_extern_obj) { 1085168404Spjd error = dmu_object_free(zfsvfs->z_os, 1086185029Spjd zp->z_phys->zp_acl.z_acl_extern_obj, tx); 1087168404Spjd if (error) 1088168404Spjd return (error); 1089168404Spjd zphys->zp_acl.z_acl_extern_obj = 0; 1090168404Spjd } 1091185029Spjd 1092185029Spjd for (aclnode = list_head(&aclp->z_acl); aclnode; 1093185029Spjd aclnode = list_next(&aclp->z_acl, aclnode)) { 1094185029Spjd if (aclnode->z_ace_count == 0) 1095185029Spjd continue; 1096185029Spjd bcopy(aclnode->z_acldata, start, aclnode->z_size); 1097185029Spjd start = (caddr_t)start + aclnode->z_size; 1098185029Spjd } 1099168404Spjd } 1100168404Spjd 1101185029Spjd /* 1102185029Spjd * If Old version then swap count/bytes to match old 1103185029Spjd * layout of znode_acl_phys_t. 1104185029Spjd */ 1105185029Spjd if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 1106185029Spjd zphys->zp_acl.z_acl_size = aclp->z_acl_count; 1107185029Spjd zphys->zp_acl.z_acl_count = aclp->z_acl_bytes; 1108185029Spjd } else { 1109185029Spjd zphys->zp_acl.z_acl_size = aclp->z_acl_bytes; 1110185029Spjd zphys->zp_acl.z_acl_count = aclp->z_acl_count; 1111168404Spjd } 1112168404Spjd 1113185029Spjd zphys->zp_acl.z_acl_version = aclp->z_version; 1114168404Spjd 1115185029Spjd /* 1116185029Spjd * Replace ACL wide bits, but first clear them. 1117185029Spjd */ 1118185029Spjd zp->z_phys->zp_flags &= ~ZFS_ACL_WIDE_FLAGS; 1119168404Spjd 1120185029Spjd zp->z_phys->zp_flags |= aclp->z_hints; 1121168404Spjd 1122185029Spjd if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0) 1123185029Spjd zp->z_phys->zp_flags |= ZFS_ACL_TRIVIAL; 1124168404Spjd 1125185029Spjd zfs_time_stamper_locked(zp, STATE_CHANGED, tx); 1126185029Spjd return (0); 1127168404Spjd} 1128168404Spjd 1129168404Spjd/* 1130168404Spjd * Update access mask for prepended ACE 1131168404Spjd * 1132168404Spjd * This applies the "groupmask" value for aclmode property. 1133168404Spjd */ 1134168404Spjdstatic void 1135185029Spjdzfs_acl_prepend_fixup(zfs_acl_t *aclp, void *acep, void *origacep, 1136185029Spjd mode_t mode, uint64_t owner) 1137168404Spjd{ 1138168404Spjd int rmask, wmask, xmask; 1139168404Spjd int user_ace; 1140185029Spjd uint16_t aceflags; 1141185029Spjd uint32_t origmask, acepmask; 1142185029Spjd uint64_t fuid; 1143168404Spjd 1144185029Spjd aceflags = aclp->z_ops.ace_flags_get(acep); 1145185029Spjd fuid = aclp->z_ops.ace_who_get(acep); 1146185029Spjd origmask = aclp->z_ops.ace_mask_get(origacep); 1147185029Spjd acepmask = aclp->z_ops.ace_mask_get(acep); 1148185029Spjd 1149185029Spjd user_ace = (!(aceflags & 1150168404Spjd (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP))); 1151168404Spjd 1152185029Spjd if (user_ace && (fuid == owner)) { 1153168404Spjd rmask = S_IRUSR; 1154168404Spjd wmask = S_IWUSR; 1155168404Spjd xmask = S_IXUSR; 1156168404Spjd } else { 1157168404Spjd rmask = S_IRGRP; 1158168404Spjd wmask = S_IWGRP; 1159168404Spjd xmask = S_IXGRP; 1160168404Spjd } 1161168404Spjd 1162185029Spjd if (origmask & ACE_READ_DATA) { 1163185029Spjd if (mode & rmask) { 1164185029Spjd acepmask &= ~ACE_READ_DATA; 1165185029Spjd } else { 1166185029Spjd acepmask |= ACE_READ_DATA; 1167185029Spjd } 1168168404Spjd } 1169168404Spjd 1170185029Spjd if (origmask & ACE_WRITE_DATA) { 1171185029Spjd if (mode & wmask) { 1172185029Spjd acepmask &= ~ACE_WRITE_DATA; 1173185029Spjd } else { 1174185029Spjd acepmask |= ACE_WRITE_DATA; 1175185029Spjd } 1176168404Spjd } 1177168404Spjd 1178185029Spjd if (origmask & ACE_APPEND_DATA) { 1179185029Spjd if (mode & wmask) { 1180185029Spjd acepmask &= ~ACE_APPEND_DATA; 1181185029Spjd } else { 1182185029Spjd acepmask |= ACE_APPEND_DATA; 1183185029Spjd } 1184168404Spjd } 1185168404Spjd 1186185029Spjd if (origmask & ACE_EXECUTE) { 1187185029Spjd if (mode & xmask) { 1188185029Spjd acepmask &= ~ACE_EXECUTE; 1189185029Spjd } else { 1190185029Spjd acepmask |= ACE_EXECUTE; 1191185029Spjd } 1192168404Spjd } 1193185029Spjd aclp->z_ops.ace_mask_set(acep, acepmask); 1194168404Spjd} 1195168404Spjd 1196168404Spjd/* 1197168404Spjd * Apply mode to canonical six ACEs. 1198168404Spjd */ 1199168404Spjdstatic void 1200168404Spjdzfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode) 1201168404Spjd{ 1202185029Spjd zfs_acl_node_t *aclnode = list_tail(&aclp->z_acl); 1203185029Spjd void *acep; 1204185029Spjd int maskoff = aclp->z_ops.ace_mask_off(); 1205185029Spjd size_t abstract_size = aclp->z_ops.ace_abstract_size(); 1206168404Spjd 1207185029Spjd ASSERT(aclnode != NULL); 1208168404Spjd 1209185029Spjd acep = (void *)((caddr_t)aclnode->z_acldata + 1210185029Spjd aclnode->z_size - (abstract_size * 6)); 1211185029Spjd 1212168404Spjd /* 1213168404Spjd * Fixup final ACEs to match the mode 1214168404Spjd */ 1215168404Spjd 1216185029Spjd adjust_ace_pair_common(acep, maskoff, abstract_size, 1217185029Spjd (mode & 0700) >> 6); /* owner@ */ 1218185029Spjd 1219185029Spjd acep = (caddr_t)acep + (abstract_size * 2); 1220185029Spjd 1221185029Spjd adjust_ace_pair_common(acep, maskoff, abstract_size, 1222185029Spjd (mode & 0070) >> 3); /* group@ */ 1223185029Spjd 1224185029Spjd acep = (caddr_t)acep + (abstract_size * 2); 1225185029Spjd adjust_ace_pair_common(acep, maskoff, 1226185029Spjd abstract_size, mode); /* everyone@ */ 1227168404Spjd} 1228168404Spjd 1229168404Spjd 1230168404Spjdstatic int 1231185029Spjdzfs_acl_ace_match(zfs_acl_t *aclp, void *acep, int allow_deny, 1232185029Spjd int entry_type, int accessmask) 1233168404Spjd{ 1234185029Spjd uint32_t mask = aclp->z_ops.ace_mask_get(acep); 1235185029Spjd uint16_t type = aclp->z_ops.ace_type_get(acep); 1236185029Spjd uint16_t flags = aclp->z_ops.ace_flags_get(acep); 1237185029Spjd 1238185029Spjd return (mask == accessmask && type == allow_deny && 1239185029Spjd ((flags & ACE_TYPE_FLAGS) == entry_type)); 1240168404Spjd} 1241168404Spjd 1242168404Spjd/* 1243168404Spjd * Can prepended ACE be reused? 1244168404Spjd */ 1245168404Spjdstatic int 1246185029Spjdzfs_reuse_deny(zfs_acl_t *aclp, void *acep, void *prevacep) 1247168404Spjd{ 1248168404Spjd int okay_masks; 1249185029Spjd uint16_t prevtype; 1250185029Spjd uint16_t prevflags; 1251185029Spjd uint16_t flags; 1252185029Spjd uint32_t mask, prevmask; 1253168404Spjd 1254185029Spjd if (prevacep == NULL) 1255168404Spjd return (B_FALSE); 1256168404Spjd 1257185029Spjd prevtype = aclp->z_ops.ace_type_get(prevacep); 1258185029Spjd prevflags = aclp->z_ops.ace_flags_get(prevacep); 1259185029Spjd flags = aclp->z_ops.ace_flags_get(acep); 1260185029Spjd mask = aclp->z_ops.ace_mask_get(acep); 1261185029Spjd prevmask = aclp->z_ops.ace_mask_get(prevacep); 1262185029Spjd 1263185029Spjd if (prevtype != DENY) 1264168404Spjd return (B_FALSE); 1265168404Spjd 1266185029Spjd if (prevflags != (flags & ACE_IDENTIFIER_GROUP)) 1267168404Spjd return (B_FALSE); 1268168404Spjd 1269185029Spjd okay_masks = (mask & OKAY_MASK_BITS); 1270168404Spjd 1271185029Spjd if (prevmask & ~okay_masks) 1272168404Spjd return (B_FALSE); 1273168404Spjd 1274168404Spjd return (B_TRUE); 1275168404Spjd} 1276168404Spjd 1277185029Spjd 1278168404Spjd/* 1279185029Spjd * Insert new ACL node into chain of zfs_acl_node_t's 1280185029Spjd * 1281185029Spjd * This will result in two possible results. 1282185029Spjd * 1. If the ACL is currently just a single zfs_acl_node and 1283185029Spjd * we are prepending the entry then current acl node will have 1284185029Spjd * a new node inserted above it. 1285185029Spjd * 1286185029Spjd * 2. If we are inserting in the middle of current acl node then 1287185029Spjd * the current node will be split in two and new node will be inserted 1288185029Spjd * in between the two split nodes. 1289168404Spjd */ 1290185029Spjdstatic zfs_acl_node_t * 1291185029Spjdzfs_acl_ace_insert(zfs_acl_t *aclp, void *acep) 1292168404Spjd{ 1293185029Spjd zfs_acl_node_t *newnode; 1294185029Spjd zfs_acl_node_t *trailernode = NULL; 1295185029Spjd zfs_acl_node_t *currnode = zfs_acl_curr_node(aclp); 1296185029Spjd int curr_idx = aclp->z_curr_node->z_ace_idx; 1297185029Spjd int trailer_count; 1298185029Spjd size_t oldsize; 1299168404Spjd 1300185029Spjd newnode = zfs_acl_node_alloc(aclp->z_ops.ace_size(acep)); 1301185029Spjd newnode->z_ace_count = 1; 1302168404Spjd 1303185029Spjd oldsize = currnode->z_size; 1304168404Spjd 1305185029Spjd if (curr_idx != 1) { 1306185029Spjd trailernode = zfs_acl_node_alloc(0); 1307185029Spjd trailernode->z_acldata = acep; 1308185029Spjd 1309185029Spjd trailer_count = currnode->z_ace_count - curr_idx + 1; 1310185029Spjd currnode->z_ace_count = curr_idx - 1; 1311185029Spjd currnode->z_size = (caddr_t)acep - (caddr_t)currnode->z_acldata; 1312185029Spjd trailernode->z_size = oldsize - currnode->z_size; 1313185029Spjd trailernode->z_ace_count = trailer_count; 1314168404Spjd } 1315168404Spjd 1316185029Spjd aclp->z_acl_count += 1; 1317185029Spjd aclp->z_acl_bytes += aclp->z_ops.ace_size(acep); 1318168404Spjd 1319185029Spjd if (curr_idx == 1) 1320185029Spjd list_insert_before(&aclp->z_acl, currnode, newnode); 1321185029Spjd else 1322185029Spjd list_insert_after(&aclp->z_acl, currnode, newnode); 1323185029Spjd if (trailernode) { 1324185029Spjd list_insert_after(&aclp->z_acl, newnode, trailernode); 1325185029Spjd aclp->z_curr_node = trailernode; 1326185029Spjd trailernode->z_ace_idx = 1; 1327168404Spjd } 1328168404Spjd 1329185029Spjd return (newnode); 1330168404Spjd} 1331168404Spjd 1332168404Spjd/* 1333168404Spjd * Prepend deny ACE 1334168404Spjd */ 1335185029Spjdstatic void * 1336185029Spjdzfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, void *acep, 1337168404Spjd mode_t mode) 1338168404Spjd{ 1339185029Spjd zfs_acl_node_t *aclnode; 1340185029Spjd void *newacep; 1341185029Spjd uint64_t fuid; 1342185029Spjd uint16_t flags; 1343168404Spjd 1344185029Spjd aclnode = zfs_acl_ace_insert(aclp, acep); 1345185029Spjd newacep = aclnode->z_acldata; 1346185029Spjd fuid = aclp->z_ops.ace_who_get(acep); 1347185029Spjd flags = aclp->z_ops.ace_flags_get(acep); 1348185029Spjd zfs_set_ace(aclp, newacep, 0, DENY, fuid, (flags & ACE_TYPE_FLAGS)); 1349185029Spjd zfs_acl_prepend_fixup(aclp, newacep, acep, mode, zp->z_phys->zp_uid); 1350168404Spjd 1351185029Spjd return (newacep); 1352168404Spjd} 1353168404Spjd 1354168404Spjd/* 1355168404Spjd * Split an inherited ACE into inherit_only ACE 1356168404Spjd * and original ACE with inheritance flags stripped off. 1357168404Spjd */ 1358168404Spjdstatic void 1359185029Spjdzfs_acl_split_ace(zfs_acl_t *aclp, zfs_ace_hdr_t *acep) 1360168404Spjd{ 1361185029Spjd zfs_acl_node_t *aclnode; 1362185029Spjd zfs_acl_node_t *currnode; 1363185029Spjd void *newacep; 1364185029Spjd uint16_t type, flags; 1365185029Spjd uint32_t mask; 1366185029Spjd uint64_t fuid; 1367168404Spjd 1368185029Spjd type = aclp->z_ops.ace_type_get(acep); 1369185029Spjd flags = aclp->z_ops.ace_flags_get(acep); 1370185029Spjd mask = aclp->z_ops.ace_mask_get(acep); 1371185029Spjd fuid = aclp->z_ops.ace_who_get(acep); 1372185029Spjd 1373185029Spjd aclnode = zfs_acl_ace_insert(aclp, acep); 1374185029Spjd newacep = aclnode->z_acldata; 1375185029Spjd 1376185029Spjd aclp->z_ops.ace_type_set(newacep, type); 1377185029Spjd aclp->z_ops.ace_flags_set(newacep, flags | ACE_INHERIT_ONLY_ACE); 1378185029Spjd aclp->z_ops.ace_mask_set(newacep, mask); 1379185029Spjd aclp->z_ops.ace_type_set(newacep, type); 1380185029Spjd aclp->z_ops.ace_who_set(newacep, fuid); 1381185029Spjd aclp->z_next_ace = acep; 1382185029Spjd flags &= ~ALL_INHERIT; 1383185029Spjd aclp->z_ops.ace_flags_set(acep, flags); 1384185029Spjd currnode = zfs_acl_curr_node(aclp); 1385185029Spjd ASSERT(currnode->z_ace_idx >= 1); 1386185029Spjd currnode->z_ace_idx -= 1; 1387168404Spjd} 1388168404Spjd 1389168404Spjd/* 1390168404Spjd * Are ACES started at index i, the canonical six ACES? 1391168404Spjd */ 1392168404Spjdstatic int 1393185029Spjdzfs_have_canonical_six(zfs_acl_t *aclp) 1394168404Spjd{ 1395185029Spjd void *acep; 1396185029Spjd zfs_acl_node_t *aclnode = list_tail(&aclp->z_acl); 1397185029Spjd int i = 0; 1398185029Spjd size_t abstract_size = aclp->z_ops.ace_abstract_size(); 1399168404Spjd 1400185029Spjd ASSERT(aclnode != NULL); 1401185029Spjd 1402185029Spjd if (aclnode->z_ace_count < 6) 1403185029Spjd return (0); 1404185029Spjd 1405185029Spjd acep = (void *)((caddr_t)aclnode->z_acldata + 1406185029Spjd aclnode->z_size - (aclp->z_ops.ace_abstract_size() * 6)); 1407185029Spjd 1408185029Spjd if ((zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 1409168404Spjd DENY, ACE_OWNER, 0) && 1410185029Spjd zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 1411185029Spjd ALLOW, ACE_OWNER, OWNER_ALLOW_MASK) && 1412185029Spjd zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), DENY, 1413185029Spjd OWNING_GROUP, 0) && zfs_acl_ace_match(aclp, (caddr_t)acep + 1414185029Spjd (abstract_size * i++), 1415185029Spjd ALLOW, OWNING_GROUP, 0) && 1416185029Spjd zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 1417168404Spjd DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) && 1418185029Spjd zfs_acl_ace_match(aclp, (caddr_t)acep + (abstract_size * i++), 1419185029Spjd ALLOW, ACE_EVERYONE, EVERYONE_ALLOW_MASK))) { 1420168404Spjd return (1); 1421168404Spjd } else { 1422168404Spjd return (0); 1423168404Spjd } 1424168404Spjd} 1425168404Spjd 1426185029Spjd 1427168404Spjd/* 1428168404Spjd * Apply step 1g, to group entries 1429168404Spjd * 1430168404Spjd * Need to deal with corner case where group may have 1431168404Spjd * greater permissions than owner. If so then limit 1432168404Spjd * group permissions, based on what extra permissions 1433168404Spjd * group has. 1434168404Spjd */ 1435168404Spjdstatic void 1436185029Spjdzfs_fixup_group_entries(zfs_acl_t *aclp, void *acep, void *prevacep, 1437185029Spjd mode_t mode) 1438168404Spjd{ 1439185029Spjd uint32_t prevmask = aclp->z_ops.ace_mask_get(prevacep); 1440185029Spjd uint32_t mask = aclp->z_ops.ace_mask_get(acep); 1441185029Spjd uint16_t prevflags = aclp->z_ops.ace_flags_get(prevacep); 1442168404Spjd mode_t extramode = (mode >> 3) & 07; 1443168404Spjd mode_t ownermode = (mode >> 6); 1444168404Spjd 1445185029Spjd if (prevflags & ACE_IDENTIFIER_GROUP) { 1446168404Spjd 1447168404Spjd extramode &= ~ownermode; 1448168404Spjd 1449168404Spjd if (extramode) { 1450185029Spjd if (extramode & S_IROTH) { 1451185029Spjd prevmask &= ~ACE_READ_DATA; 1452185029Spjd mask &= ~ACE_READ_DATA; 1453168404Spjd } 1454185029Spjd if (extramode & S_IWOTH) { 1455185029Spjd prevmask &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 1456185029Spjd mask &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 1457168404Spjd } 1458185029Spjd if (extramode & S_IXOTH) { 1459185029Spjd prevmask &= ~ACE_EXECUTE; 1460185029Spjd mask &= ~ACE_EXECUTE; 1461168404Spjd } 1462168404Spjd } 1463168404Spjd } 1464185029Spjd aclp->z_ops.ace_mask_set(acep, mask); 1465185029Spjd aclp->z_ops.ace_mask_set(prevacep, prevmask); 1466168404Spjd} 1467168404Spjd 1468168404Spjd/* 1469168404Spjd * Apply the chmod algorithm as described 1470168404Spjd * in PSARC/2002/240 1471168404Spjd */ 1472185029Spjdstatic void 1473185029Spjdzfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp) 1474168404Spjd{ 1475168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1476185029Spjd void *acep = NULL, *prevacep = NULL; 1477185029Spjd uint64_t who; 1478168404Spjd int i; 1479168404Spjd int entry_type; 1480168404Spjd int reuse_deny; 1481168404Spjd int need_canonical_six = 1; 1482185029Spjd uint16_t iflags, type; 1483185029Spjd uint32_t access_mask; 1484168404Spjd 1485168404Spjd ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1486168404Spjd ASSERT(MUTEX_HELD(&zp->z_lock)); 1487168404Spjd 1488185029Spjd aclp->z_hints = (zp->z_phys->zp_flags & V4_ACL_WIDE_FLAGS); 1489168404Spjd 1490185029Spjd /* 1491185029Spjd * If discard then just discard all ACL nodes which 1492185029Spjd * represent the ACEs. 1493185029Spjd * 1494185029Spjd * New owner@/group@/everone@ ACEs will be added 1495185029Spjd * later. 1496185029Spjd */ 1497185029Spjd if (zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) 1498185029Spjd zfs_acl_release_nodes(aclp); 1499185029Spjd 1500185029Spjd while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 1501185029Spjd &iflags, &type)) { 1502185029Spjd 1503185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 1504185029Spjd iflags = (iflags & ALL_INHERIT); 1505185029Spjd 1506185029Spjd if ((type != ALLOW && type != DENY) || 1507168404Spjd (iflags & ACE_INHERIT_ONLY_ACE)) { 1508168404Spjd if (iflags) 1509185029Spjd aclp->z_hints |= ZFS_INHERIT_ACE; 1510185029Spjd switch (type) { 1511185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1512185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1513185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1514185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1515185029Spjd aclp->z_hints |= ZFS_ACL_OBJ_ACE; 1516185029Spjd break; 1517185029Spjd } 1518185029Spjd goto nextace; 1519168404Spjd } 1520168404Spjd 1521168404Spjd /* 1522168404Spjd * Need to split ace into two? 1523168404Spjd */ 1524168404Spjd if ((iflags & (ACE_FILE_INHERIT_ACE| 1525168404Spjd ACE_DIRECTORY_INHERIT_ACE)) && 1526168404Spjd (!(iflags & ACE_INHERIT_ONLY_ACE))) { 1527185029Spjd zfs_acl_split_ace(aclp, acep); 1528185029Spjd aclp->z_hints |= ZFS_INHERIT_ACE; 1529185029Spjd goto nextace; 1530168404Spjd } 1531168404Spjd 1532168404Spjd if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 1533168404Spjd (entry_type == OWNING_GROUP)) { 1534185029Spjd access_mask &= ~OGE_CLEAR; 1535185029Spjd aclp->z_ops.ace_mask_set(acep, access_mask); 1536185029Spjd goto nextace; 1537168404Spjd } else { 1538185029Spjd reuse_deny = B_TRUE; 1539185029Spjd if (type == ALLOW) { 1540168404Spjd 1541168404Spjd /* 1542168404Spjd * Check preceding ACE if any, to see 1543168404Spjd * if we need to prepend a DENY ACE. 1544168404Spjd * This is only applicable when the acl_mode 1545168404Spjd * property == groupmask. 1546168404Spjd */ 1547168404Spjd if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK) { 1548168404Spjd 1549185029Spjd reuse_deny = zfs_reuse_deny(aclp, acep, 1550185029Spjd prevacep); 1551168404Spjd 1552185029Spjd if (!reuse_deny) { 1553185029Spjd prevacep = 1554185029Spjd zfs_acl_prepend_deny(zp, 1555185029Spjd aclp, acep, mode); 1556168404Spjd } else { 1557168404Spjd zfs_acl_prepend_fixup( 1558185029Spjd aclp, prevacep, 1559185029Spjd acep, mode, 1560168404Spjd zp->z_phys->zp_uid); 1561168404Spjd } 1562185029Spjd zfs_fixup_group_entries(aclp, acep, 1563185029Spjd prevacep, mode); 1564185029Spjd 1565168404Spjd } 1566168404Spjd } 1567168404Spjd } 1568185029Spjdnextace: 1569185029Spjd prevacep = acep; 1570168404Spjd } 1571168404Spjd 1572168404Spjd /* 1573168404Spjd * Check out last six aces, if we have six. 1574168404Spjd */ 1575168404Spjd 1576168404Spjd if (aclp->z_acl_count >= 6) { 1577185029Spjd if (zfs_have_canonical_six(aclp)) { 1578168404Spjd need_canonical_six = 0; 1579168404Spjd } 1580168404Spjd } 1581168404Spjd 1582168404Spjd if (need_canonical_six) { 1583185029Spjd size_t abstract_size = aclp->z_ops.ace_abstract_size(); 1584185029Spjd void *zacep; 1585185029Spjd zfs_acl_node_t *aclnode = 1586185029Spjd zfs_acl_node_alloc(abstract_size * 6); 1587168404Spjd 1588185029Spjd aclnode->z_size = abstract_size * 6; 1589185029Spjd aclnode->z_ace_count = 6; 1590185029Spjd aclp->z_acl_bytes += aclnode->z_size; 1591185029Spjd list_insert_tail(&aclp->z_acl, aclnode); 1592185029Spjd 1593185029Spjd zacep = aclnode->z_acldata; 1594185029Spjd 1595185029Spjd i = 0; 1596185029Spjd zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 1597185029Spjd 0, DENY, -1, ACE_OWNER); 1598185029Spjd zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 1599185029Spjd OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER); 1600185029Spjd zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 0, 1601185029Spjd DENY, -1, OWNING_GROUP); 1602185029Spjd zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 0, 1603185029Spjd ALLOW, -1, OWNING_GROUP); 1604185029Spjd zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 1605185029Spjd EVERYONE_DENY_MASK, DENY, -1, ACE_EVERYONE); 1606185029Spjd zfs_set_ace(aclp, (caddr_t)zacep + (abstract_size * i++), 1607185029Spjd EVERYONE_ALLOW_MASK, ALLOW, -1, ACE_EVERYONE); 1608168404Spjd aclp->z_acl_count += 6; 1609168404Spjd } 1610168404Spjd 1611168404Spjd zfs_acl_fixup_canonical_six(aclp, mode); 1612168404Spjd} 1613168404Spjd 1614168404Spjdint 1615185029Spjdzfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) 1616168404Spjd{ 1617168404Spjd int error; 1618168404Spjd 1619185029Spjd mutex_enter(&zp->z_lock); 1620168404Spjd mutex_enter(&zp->z_acl_lock); 1621185029Spjd *aclp = NULL; 1622185029Spjd error = zfs_acl_node_read(zp, aclp, B_TRUE); 1623168404Spjd if (error == 0) 1624185029Spjd zfs_acl_chmod(zp, mode, *aclp); 1625168404Spjd mutex_exit(&zp->z_acl_lock); 1626185029Spjd mutex_exit(&zp->z_lock); 1627168404Spjd return (error); 1628168404Spjd} 1629168404Spjd 1630168404Spjd/* 1631168404Spjd * strip off write_owner and write_acl 1632168404Spjd */ 1633168404Spjdstatic void 1634185029Spjdzfs_restricted_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep) 1635168404Spjd{ 1636185029Spjd uint32_t mask = aclp->z_ops.ace_mask_get(acep); 1637185029Spjd 1638185029Spjd if ((zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) && 1639185029Spjd (aclp->z_ops.ace_type_get(acep) == ALLOW)) { 1640185029Spjd mask &= ~RESTRICTED_CLEAR; 1641185029Spjd aclp->z_ops.ace_mask_set(acep, mask); 1642185029Spjd } 1643168404Spjd} 1644168404Spjd 1645168404Spjd/* 1646185029Spjd * Should ACE be inherited? 1647185029Spjd */ 1648185029Spjdstatic int 1649185029Spjdzfs_ace_can_use(znode_t *zp, uint16_t acep_flags) 1650185029Spjd{ 1651185029Spjd int vtype = ZTOV(zp)->v_type; 1652185029Spjd int iflags = (acep_flags & 0xf); 1653185029Spjd 1654185029Spjd if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1655185029Spjd return (1); 1656185029Spjd else if (iflags & ACE_FILE_INHERIT_ACE) 1657185029Spjd return (!((vtype == VDIR) && 1658185029Spjd (iflags & ACE_NO_PROPAGATE_INHERIT_ACE))); 1659185029Spjd return (0); 1660185029Spjd} 1661185029Spjd 1662185029Spjd/* 1663168404Spjd * inherit inheritable ACEs from parent 1664168404Spjd */ 1665168404Spjdstatic zfs_acl_t * 1666201143Sdelphijzfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp, uint64_t mode, 1667201143Sdelphij boolean_t *need_chmod) 1668168404Spjd{ 1669168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1670185029Spjd void *pacep; 1671185029Spjd void *acep, *acep2; 1672185029Spjd zfs_acl_node_t *aclnode, *aclnode2; 1673168404Spjd zfs_acl_t *aclp = NULL; 1674185029Spjd uint64_t who; 1675185029Spjd uint32_t access_mask; 1676185029Spjd uint16_t iflags, newflags, type; 1677185029Spjd size_t ace_size; 1678185029Spjd void *data1, *data2; 1679185029Spjd size_t data1sz, data2sz; 1680201143Sdelphij boolean_t vdir = ZTOV(zp)->v_type == VDIR; 1681201143Sdelphij boolean_t vreg = ZTOV(zp)->v_type == VREG; 1682201143Sdelphij boolean_t passthrough, passthrough_x, noallow; 1683168404Spjd 1684201143Sdelphij passthrough_x = 1685201143Sdelphij zfsvfs->z_acl_inherit == ZFS_ACL_PASSTHROUGH_X; 1686201143Sdelphij passthrough = passthrough_x || 1687201143Sdelphij zfsvfs->z_acl_inherit == ZFS_ACL_PASSTHROUGH; 1688201143Sdelphij noallow = 1689201143Sdelphij zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW; 1690201143Sdelphij 1691185029Spjd *need_chmod = B_TRUE; 1692185029Spjd pacep = NULL; 1693185029Spjd aclp = zfs_acl_alloc(paclp->z_version); 1694201143Sdelphij if (zfsvfs->z_acl_inherit == ZFS_ACL_DISCARD) 1695201143Sdelphij return (aclp); 1696201143Sdelphij while (pacep = zfs_acl_next_ace(paclp, pacep, &who, 1697201143Sdelphij &access_mask, &iflags, &type)) { 1698168404Spjd 1699201143Sdelphij /* 1700201143Sdelphij * don't inherit bogus ACEs 1701201143Sdelphij */ 1702201143Sdelphij if (!zfs_acl_valid_ace_type(type, iflags)) 1703201143Sdelphij continue; 1704185029Spjd 1705201143Sdelphij if (noallow && type == ALLOW) 1706201143Sdelphij continue; 1707168404Spjd 1708201143Sdelphij ace_size = aclp->z_ops.ace_size(pacep); 1709168404Spjd 1710201143Sdelphij if (!zfs_ace_can_use(zp, iflags)) 1711201143Sdelphij continue; 1712168404Spjd 1713201143Sdelphij /* 1714201143Sdelphij * If owner@, group@, or everyone@ inheritable 1715201143Sdelphij * then zfs_acl_chmod() isn't needed. 1716201143Sdelphij */ 1717201143Sdelphij if (passthrough && 1718201143Sdelphij ((iflags & (ACE_OWNER|ACE_EVERYONE)) || 1719201143Sdelphij ((iflags & OWNING_GROUP) == 1720201143Sdelphij OWNING_GROUP)) && (vreg || (vdir && (iflags & 1721201143Sdelphij ACE_DIRECTORY_INHERIT_ACE)))) { 1722201143Sdelphij *need_chmod = B_FALSE; 1723168404Spjd 1724201143Sdelphij if (!vdir && passthrough_x && 1725201143Sdelphij ((mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)) { 1726201143Sdelphij access_mask &= ~ACE_EXECUTE; 1727201143Sdelphij } 1728201143Sdelphij } 1729168404Spjd 1730201143Sdelphij aclnode = zfs_acl_node_alloc(ace_size); 1731201143Sdelphij list_insert_tail(&aclp->z_acl, aclnode); 1732201143Sdelphij acep = aclnode->z_acldata; 1733201143Sdelphij 1734201143Sdelphij zfs_set_ace(aclp, acep, access_mask, type, 1735201143Sdelphij who, iflags|ACE_INHERITED_ACE); 1736201143Sdelphij 1737201143Sdelphij /* 1738201143Sdelphij * Copy special opaque data if any 1739201143Sdelphij */ 1740201143Sdelphij if ((data1sz = paclp->z_ops.ace_data(pacep, &data1)) != 0) { 1741201143Sdelphij VERIFY((data2sz = aclp->z_ops.ace_data(acep, 1742201143Sdelphij &data2)) == data1sz); 1743201143Sdelphij bcopy(data1, data2, data2sz); 1744201143Sdelphij } 1745201143Sdelphij aclp->z_acl_count++; 1746201143Sdelphij aclnode->z_ace_count++; 1747201143Sdelphij aclp->z_acl_bytes += aclnode->z_size; 1748201143Sdelphij newflags = aclp->z_ops.ace_flags_get(acep); 1749201143Sdelphij 1750201143Sdelphij if (vdir) 1751201143Sdelphij aclp->z_hints |= ZFS_INHERIT_ACE; 1752201143Sdelphij 1753201143Sdelphij if ((iflags & ACE_NO_PROPAGATE_INHERIT_ACE) || !vdir) { 1754201143Sdelphij newflags &= ~ALL_INHERIT; 1755201143Sdelphij aclp->z_ops.ace_flags_set(acep, 1756201143Sdelphij newflags|ACE_INHERITED_ACE); 1757201143Sdelphij zfs_restricted_update(zfsvfs, aclp, acep); 1758201143Sdelphij continue; 1759201143Sdelphij } 1760201143Sdelphij 1761201143Sdelphij ASSERT(vdir); 1762201143Sdelphij 1763201143Sdelphij newflags = aclp->z_ops.ace_flags_get(acep); 1764201143Sdelphij if ((iflags & (ACE_FILE_INHERIT_ACE | 1765201143Sdelphij ACE_DIRECTORY_INHERIT_ACE)) != 1766201143Sdelphij ACE_FILE_INHERIT_ACE) { 1767201143Sdelphij aclnode2 = zfs_acl_node_alloc(ace_size); 1768201143Sdelphij list_insert_tail(&aclp->z_acl, aclnode2); 1769201143Sdelphij acep2 = aclnode2->z_acldata; 1770201143Sdelphij zfs_set_ace(aclp, acep2, 1771201143Sdelphij access_mask, type, who, 1772201143Sdelphij iflags|ACE_INHERITED_ACE); 1773201143Sdelphij newflags |= ACE_INHERIT_ONLY_ACE; 1774201143Sdelphij aclp->z_ops.ace_flags_set(acep, newflags); 1775201143Sdelphij newflags &= ~ALL_INHERIT; 1776201143Sdelphij aclp->z_ops.ace_flags_set(acep2, 1777201143Sdelphij newflags|ACE_INHERITED_ACE); 1778201143Sdelphij 1779185029Spjd /* 1780185029Spjd * Copy special opaque data if any 1781185029Spjd */ 1782201143Sdelphij if ((data1sz = aclp->z_ops.ace_data(acep, 1783185029Spjd &data1)) != 0) { 1784201143Sdelphij VERIFY((data2sz = 1785201143Sdelphij aclp->z_ops.ace_data(acep2, 1786185029Spjd &data2)) == data1sz); 1787201143Sdelphij bcopy(data1, data2, data1sz); 1788185029Spjd } 1789185029Spjd aclp->z_acl_count++; 1790201143Sdelphij aclnode2->z_ace_count++; 1791185029Spjd aclp->z_acl_bytes += aclnode->z_size; 1792201143Sdelphij zfs_restricted_update(zfsvfs, aclp, acep2); 1793201143Sdelphij } else { 1794201143Sdelphij newflags |= ACE_INHERIT_ONLY_ACE; 1795201143Sdelphij aclp->z_ops.ace_flags_set(acep, 1796201143Sdelphij newflags|ACE_INHERITED_ACE); 1797168404Spjd } 1798168404Spjd } 1799168404Spjd return (aclp); 1800168404Spjd} 1801168404Spjd 1802168404Spjd/* 1803168404Spjd * Create file system object initial permissions 1804168404Spjd * including inheritable ACEs. 1805168404Spjd */ 1806168404Spjdvoid 1807168404Spjdzfs_perm_init(znode_t *zp, znode_t *parent, int flag, 1808185029Spjd vattr_t *vap, dmu_tx_t *tx, cred_t *cr, 1809185029Spjd zfs_acl_t *setaclp, zfs_fuid_info_t **fuidp) 1810168404Spjd{ 1811185029Spjd uint64_t mode, fuid, fgid; 1812185029Spjd int error; 1813185029Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1814185029Spjd zfs_acl_t *aclp = NULL; 1815185029Spjd zfs_acl_t *paclp; 1816185029Spjd xvattr_t *xvap = (xvattr_t *)vap; 1817168404Spjd gid_t gid; 1818185029Spjd boolean_t need_chmod = B_TRUE; 1819168404Spjd 1820185029Spjd if (setaclp) 1821185029Spjd aclp = setaclp; 1822185029Spjd 1823168404Spjd mode = MAKEIMODE(vap->va_type, vap->va_mode); 1824168404Spjd 1825168404Spjd /* 1826168404Spjd * Determine uid and gid. 1827168404Spjd */ 1828168404Spjd if ((flag & (IS_ROOT_NODE | IS_REPLAY)) || 1829168404Spjd ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 1830185029Spjd fuid = zfs_fuid_create(zfsvfs, vap->va_uid, cr, 1831185029Spjd ZFS_OWNER, tx, fuidp); 1832185029Spjd fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr, 1833185029Spjd ZFS_GROUP, tx, fuidp); 1834168404Spjd gid = vap->va_gid; 1835168404Spjd } else { 1836185029Spjd fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, tx, cr, fuidp); 1837185029Spjd fgid = 0; 1838185029Spjd if (vap->va_mask & AT_GID) { 1839185029Spjd fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr, 1840185029Spjd ZFS_GROUP, tx, fuidp); 1841168404Spjd gid = vap->va_gid; 1842185029Spjd if (fgid != parent->z_phys->zp_gid && 1843185029Spjd !groupmember(vap->va_gid, cr) && 1844185029Spjd secpolicy_vnode_create_gid(cr) != 0) 1845185029Spjd fgid = 0; 1846185029Spjd } 1847185029Spjd if (fgid == 0) { 1848185029Spjd if (parent->z_phys->zp_mode & S_ISGID) { 1849185029Spjd fgid = parent->z_phys->zp_gid; 1850185029Spjd gid = zfs_fuid_map_id(zfsvfs, fgid, 1851185029Spjd cr, ZFS_GROUP); 1852185029Spjd } else { 1853185029Spjd fgid = zfs_fuid_create_cred(zfsvfs, 1854185029Spjd ZFS_GROUP, tx, cr, fuidp); 1855168404Spjd#ifdef __FreeBSD__ 1856197426Spjd gid = fgid = parent->z_phys->zp_gid; 1857168404Spjd#else 1858185029Spjd gid = crgetgid(cr); 1859168404Spjd#endif 1860185029Spjd } 1861185029Spjd } 1862168404Spjd } 1863168404Spjd 1864168404Spjd /* 1865168404Spjd * If we're creating a directory, and the parent directory has the 1866168404Spjd * set-GID bit set, set in on the new directory. 1867168404Spjd * Otherwise, if the user is neither privileged nor a member of the 1868168404Spjd * file's new group, clear the file's set-GID bit. 1869168404Spjd */ 1870168404Spjd 1871185029Spjd if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) { 1872168404Spjd mode |= S_ISGID; 1873185029Spjd } else { 1874168404Spjd if ((mode & S_ISGID) && 1875185029Spjd secpolicy_vnode_setids_setgids(ZTOV(zp), cr, gid) != 0) 1876168404Spjd mode &= ~S_ISGID; 1877168404Spjd } 1878168404Spjd 1879185029Spjd zp->z_phys->zp_uid = fuid; 1880185029Spjd zp->z_phys->zp_gid = fgid; 1881168404Spjd zp->z_phys->zp_mode = mode; 1882168404Spjd 1883185029Spjd if (aclp == NULL) { 1884185029Spjd mutex_enter(&parent->z_lock); 1885185029Spjd if ((ZTOV(parent)->v_type == VDIR && 1886185029Spjd (parent->z_phys->zp_flags & ZFS_INHERIT_ACE)) && 1887185029Spjd !(zp->z_phys->zp_flags & ZFS_XATTR)) { 1888185029Spjd mutex_enter(&parent->z_acl_lock); 1889185029Spjd VERIFY(0 == zfs_acl_node_read(parent, &paclp, B_FALSE)); 1890185029Spjd mutex_exit(&parent->z_acl_lock); 1891201143Sdelphij aclp = zfs_acl_inherit(zp, paclp, mode, &need_chmod); 1892185029Spjd zfs_acl_free(paclp); 1893185029Spjd } else { 1894185029Spjd aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); 1895185029Spjd } 1896185029Spjd mutex_exit(&parent->z_lock); 1897185029Spjd mutex_enter(&zp->z_lock); 1898185029Spjd mutex_enter(&zp->z_acl_lock); 1899185029Spjd if (need_chmod) 1900185029Spjd zfs_acl_chmod(zp, mode, aclp); 1901168404Spjd } else { 1902185029Spjd mutex_enter(&zp->z_lock); 1903185029Spjd mutex_enter(&zp->z_acl_lock); 1904168404Spjd } 1905185029Spjd 1906185029Spjd /* Force auto_inherit on all new directory objects */ 1907185029Spjd if (vap->va_type == VDIR) 1908185029Spjd aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 1909185029Spjd 1910185029Spjd error = zfs_aclset_common(zp, aclp, cr, fuidp, tx); 1911185029Spjd 1912185029Spjd /* Set optional attributes if any */ 1913185029Spjd if (vap->va_mask & AT_XVATTR) 1914185029Spjd zfs_xvattr_set(zp, xvap); 1915185029Spjd 1916168404Spjd mutex_exit(&zp->z_lock); 1917168404Spjd mutex_exit(&zp->z_acl_lock); 1918168404Spjd ASSERT3U(error, ==, 0); 1919168404Spjd 1920185029Spjd if (aclp != setaclp) 1921185029Spjd zfs_acl_free(aclp); 1922168404Spjd} 1923168404Spjd 1924168404Spjd/* 1925168404Spjd * Retrieve a files ACL 1926168404Spjd */ 1927168404Spjdint 1928185029Spjdzfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1929168404Spjd{ 1930168404Spjd zfs_acl_t *aclp; 1931185029Spjd ulong_t mask; 1932168404Spjd int error; 1933185029Spjd int count = 0; 1934185029Spjd int largeace = 0; 1935168404Spjd 1936185029Spjd mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT | 1937185029Spjd VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 1938168404Spjd 1939185029Spjd if (error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)) 1940185029Spjd return (error); 1941185029Spjd 1942168404Spjd if (mask == 0) 1943168404Spjd return (ENOSYS); 1944168404Spjd 1945168404Spjd mutex_enter(&zp->z_acl_lock); 1946168404Spjd 1947185029Spjd error = zfs_acl_node_read(zp, &aclp, B_FALSE); 1948168404Spjd if (error != 0) { 1949168404Spjd mutex_exit(&zp->z_acl_lock); 1950168404Spjd return (error); 1951168404Spjd } 1952168404Spjd 1953185029Spjd /* 1954185029Spjd * Scan ACL to determine number of ACEs 1955185029Spjd */ 1956185029Spjd if ((zp->z_phys->zp_flags & ZFS_ACL_OBJ_ACE) && 1957185029Spjd !(mask & VSA_ACE_ALLTYPES)) { 1958185029Spjd void *zacep = NULL; 1959185029Spjd uint64_t who; 1960185029Spjd uint32_t access_mask; 1961185029Spjd uint16_t type, iflags; 1962168404Spjd 1963185029Spjd while (zacep = zfs_acl_next_ace(aclp, zacep, 1964185029Spjd &who, &access_mask, &iflags, &type)) { 1965185029Spjd switch (type) { 1966185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1967185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1968185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1969185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1970185029Spjd largeace++; 1971185029Spjd continue; 1972185029Spjd default: 1973185029Spjd count++; 1974185029Spjd } 1975185029Spjd } 1976185029Spjd vsecp->vsa_aclcnt = count; 1977185029Spjd } else 1978185029Spjd count = aclp->z_acl_count; 1979185029Spjd 1980168404Spjd if (mask & VSA_ACECNT) { 1981185029Spjd vsecp->vsa_aclcnt = count; 1982168404Spjd } 1983168404Spjd 1984168404Spjd if (mask & VSA_ACE) { 1985185029Spjd size_t aclsz; 1986185029Spjd 1987185029Spjd zfs_acl_node_t *aclnode = list_head(&aclp->z_acl); 1988185029Spjd 1989185029Spjd aclsz = count * sizeof (ace_t) + 1990185029Spjd sizeof (ace_object_t) * largeace; 1991185029Spjd 1992185029Spjd vsecp->vsa_aclentp = kmem_alloc(aclsz, KM_SLEEP); 1993185029Spjd vsecp->vsa_aclentsz = aclsz; 1994185029Spjd 1995185029Spjd if (aclp->z_version == ZFS_ACL_VERSION_FUID) 1996185029Spjd zfs_copy_fuid_2_ace(zp->z_zfsvfs, aclp, cr, 1997185029Spjd vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES)); 1998185029Spjd else { 1999185029Spjd bcopy(aclnode->z_acldata, vsecp->vsa_aclentp, 2000185029Spjd count * sizeof (ace_t)); 2001185029Spjd } 2002168404Spjd } 2003185029Spjd if (mask & VSA_ACE_ACLFLAGS) { 2004185029Spjd vsecp->vsa_aclflags = 0; 2005185029Spjd if (zp->z_phys->zp_flags & ZFS_ACL_DEFAULTED) 2006185029Spjd vsecp->vsa_aclflags |= ACL_DEFAULTED; 2007185029Spjd if (zp->z_phys->zp_flags & ZFS_ACL_PROTECTED) 2008185029Spjd vsecp->vsa_aclflags |= ACL_PROTECTED; 2009185029Spjd if (zp->z_phys->zp_flags & ZFS_ACL_AUTO_INHERIT) 2010185029Spjd vsecp->vsa_aclflags |= ACL_AUTO_INHERIT; 2011185029Spjd } 2012168404Spjd 2013168404Spjd mutex_exit(&zp->z_acl_lock); 2014168404Spjd 2015168404Spjd zfs_acl_free(aclp); 2016168404Spjd 2017168404Spjd return (0); 2018168404Spjd} 2019168404Spjd 2020185029Spjdint 2021185029Spjdzfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type, 2022185029Spjd vsecattr_t *vsecp, zfs_acl_t **zaclp) 2023185029Spjd{ 2024185029Spjd zfs_acl_t *aclp; 2025185029Spjd zfs_acl_node_t *aclnode; 2026185029Spjd int aclcnt = vsecp->vsa_aclcnt; 2027185029Spjd int error; 2028185029Spjd 2029185029Spjd if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0) 2030185029Spjd return (EINVAL); 2031185029Spjd 2032185029Spjd aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version)); 2033185029Spjd 2034185029Spjd aclp->z_hints = 0; 2035185029Spjd aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t)); 2036185029Spjd if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 2037185029Spjd if ((error = zfs_copy_ace_2_oldace(obj_type, aclp, 2038185029Spjd (ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata, 2039185029Spjd aclcnt, &aclnode->z_size)) != 0) { 2040185029Spjd zfs_acl_free(aclp); 2041185029Spjd zfs_acl_node_free(aclnode); 2042185029Spjd return (error); 2043185029Spjd } 2044185029Spjd } else { 2045185029Spjd if ((error = zfs_copy_ace_2_fuid(obj_type, aclp, 2046185029Spjd vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt, 2047185029Spjd &aclnode->z_size)) != 0) { 2048185029Spjd zfs_acl_free(aclp); 2049185029Spjd zfs_acl_node_free(aclnode); 2050185029Spjd return (error); 2051185029Spjd } 2052185029Spjd } 2053185029Spjd aclp->z_acl_bytes = aclnode->z_size; 2054185029Spjd aclnode->z_ace_count = aclcnt; 2055185029Spjd aclp->z_acl_count = aclcnt; 2056185029Spjd list_insert_head(&aclp->z_acl, aclnode); 2057185029Spjd 2058185029Spjd /* 2059185029Spjd * If flags are being set then add them to z_hints 2060185029Spjd */ 2061185029Spjd if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) { 2062185029Spjd if (vsecp->vsa_aclflags & ACL_PROTECTED) 2063185029Spjd aclp->z_hints |= ZFS_ACL_PROTECTED; 2064185029Spjd if (vsecp->vsa_aclflags & ACL_DEFAULTED) 2065185029Spjd aclp->z_hints |= ZFS_ACL_DEFAULTED; 2066185029Spjd if (vsecp->vsa_aclflags & ACL_AUTO_INHERIT) 2067185029Spjd aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 2068185029Spjd } 2069185029Spjd 2070185029Spjd *zaclp = aclp; 2071185029Spjd 2072185029Spjd return (0); 2073185029Spjd} 2074185029Spjd 2075168404Spjd/* 2076168404Spjd * Set a files ACL 2077168404Spjd */ 2078168404Spjdint 2079185029Spjdzfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 2080168404Spjd{ 2081168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2082168404Spjd zilog_t *zilog = zfsvfs->z_log; 2083168404Spjd ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 2084168404Spjd dmu_tx_t *tx; 2085168404Spjd int error; 2086168404Spjd zfs_acl_t *aclp; 2087185029Spjd zfs_fuid_info_t *fuidp = NULL; 2088168404Spjd 2089168404Spjd if (mask == 0) 2090185029Spjd return (ENOSYS); 2091168404Spjd 2092185029Spjd if (zp->z_phys->zp_flags & ZFS_IMMUTABLE) 2093185029Spjd return (EPERM); 2094185029Spjd 2095185029Spjd if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) 2096185029Spjd return (error); 2097185029Spjd 2098185029Spjd error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, &aclp); 2099185029Spjd if (error) 2100185029Spjd return (error); 2101185029Spjd 2102185029Spjd /* 2103185029Spjd * If ACL wide flags aren't being set then preserve any 2104185029Spjd * existing flags. 2105185029Spjd */ 2106185029Spjd if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { 2107185029Spjd aclp->z_hints |= (zp->z_phys->zp_flags & V4_ACL_WIDE_FLAGS); 2108185029Spjd } 2109168404Spjdtop: 2110185029Spjd if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) { 2111185029Spjd zfs_acl_free(aclp); 2112185029Spjd return (error); 2113168404Spjd } 2114168404Spjd 2115168404Spjd mutex_enter(&zp->z_lock); 2116168404Spjd mutex_enter(&zp->z_acl_lock); 2117168404Spjd 2118168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 2119168404Spjd dmu_tx_hold_bonus(tx, zp->z_id); 2120168404Spjd 2121168404Spjd if (zp->z_phys->zp_acl.z_acl_extern_obj) { 2122185029Spjd /* Are we upgrading ACL? */ 2123185029Spjd if (zfsvfs->z_version <= ZPL_VERSION_FUID && 2124185029Spjd zp->z_phys->zp_acl.z_acl_version == 2125185029Spjd ZFS_ACL_VERSION_INITIAL) { 2126185029Spjd dmu_tx_hold_free(tx, 2127185029Spjd zp->z_phys->zp_acl.z_acl_extern_obj, 2128185029Spjd 0, DMU_OBJECT_END); 2129185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 2130185029Spjd 0, aclp->z_acl_bytes); 2131185029Spjd } else { 2132185029Spjd dmu_tx_hold_write(tx, 2133185029Spjd zp->z_phys->zp_acl.z_acl_extern_obj, 2134185029Spjd 0, aclp->z_acl_bytes); 2135185029Spjd } 2136185029Spjd } else if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 2137185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); 2138168404Spjd } 2139185029Spjd if (aclp->z_has_fuids) { 2140185029Spjd if (zfsvfs->z_fuid_obj == 0) { 2141185029Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 2142185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 2143185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 2144185029Spjd dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL); 2145185029Spjd } else { 2146185029Spjd dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 2147185029Spjd dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 2148185029Spjd FUID_SIZE_ESTIMATE(zfsvfs)); 2149185029Spjd } 2150185029Spjd } 2151168404Spjd 2152168404Spjd error = dmu_tx_assign(tx, zfsvfs->z_assign); 2153168404Spjd if (error) { 2154168404Spjd mutex_exit(&zp->z_acl_lock); 2155168404Spjd mutex_exit(&zp->z_lock); 2156168404Spjd 2157168404Spjd if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) { 2158168404Spjd dmu_tx_wait(tx); 2159168404Spjd dmu_tx_abort(tx); 2160168404Spjd goto top; 2161168404Spjd } 2162168404Spjd dmu_tx_abort(tx); 2163185029Spjd zfs_acl_free(aclp); 2164168404Spjd return (error); 2165168404Spjd } 2166168404Spjd 2167185029Spjd error = zfs_aclset_common(zp, aclp, cr, &fuidp, tx); 2168168404Spjd ASSERT(error == 0); 2169168404Spjd 2170185029Spjd zfs_log_acl(zilog, tx, zp, vsecp, fuidp); 2171185029Spjd 2172185029Spjd if (fuidp) 2173185029Spjd zfs_fuid_info_free(fuidp); 2174168404Spjd zfs_acl_free(aclp); 2175168404Spjd dmu_tx_commit(tx); 2176168404Spjddone: 2177168404Spjd mutex_exit(&zp->z_acl_lock); 2178168404Spjd mutex_exit(&zp->z_lock); 2179168404Spjd 2180168404Spjd return (error); 2181168404Spjd} 2182168404Spjd 2183185029Spjd/* 2184185029Spjd * working_mode returns the permissions that were not granted 2185185029Spjd */ 2186168404Spjdstatic int 2187185029Spjdzfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, 2188185029Spjd boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) 2189168404Spjd{ 2190185029Spjd zfs_acl_t *aclp; 2191185029Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2192185029Spjd int error; 2193185029Spjd uid_t uid = crgetuid(cr); 2194185029Spjd uint64_t who; 2195185029Spjd uint16_t type, iflags; 2196185029Spjd uint16_t entry_type; 2197185029Spjd uint32_t access_mask; 2198185029Spjd uint32_t deny_mask = 0; 2199185029Spjd zfs_ace_hdr_t *acep = NULL; 2200185029Spjd boolean_t checkit; 2201185029Spjd uid_t fowner; 2202185029Spjd uid_t gowner; 2203168404Spjd 2204168404Spjd /* 2205185029Spjd * Short circuit empty requests 2206168404Spjd */ 2207185029Spjd if (v4_mode == 0) 2208185029Spjd return (0); 2209168404Spjd 2210185029Spjd *check_privs = B_TRUE; 2211168404Spjd 2212168404Spjd if (zfsvfs->z_assign >= TXG_INITIAL) { /* ZIL replay */ 2213168404Spjd *working_mode = 0; 2214168404Spjd return (0); 2215168404Spjd } 2216168404Spjd 2217168404Spjd *working_mode = v4_mode; 2218168404Spjd 2219168404Spjd if ((v4_mode & WRITE_MASK) && 2220168404Spjd (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 2221168404Spjd (!IS_DEVVP(ZTOV(zp)))) { 2222185029Spjd *check_privs = B_FALSE; 2223168404Spjd return (EROFS); 2224168404Spjd } 2225168404Spjd 2226185029Spjd /* 2227185029Spjd * Only check for READONLY on non-directories. 2228185029Spjd */ 2229185029Spjd if ((v4_mode & WRITE_MASK_DATA) && 2230185029Spjd (((ZTOV(zp)->v_type != VDIR) && 2231185029Spjd (zp->z_phys->zp_flags & (ZFS_READONLY | ZFS_IMMUTABLE))) || 2232185029Spjd (ZTOV(zp)->v_type == VDIR && 2233185029Spjd (zp->z_phys->zp_flags & ZFS_IMMUTABLE)))) { 2234185029Spjd *check_privs = B_FALSE; 2235185029Spjd return (EPERM); 2236185029Spjd } 2237185029Spjd 2238185029Spjd if ((v4_mode & (ACE_DELETE | ACE_DELETE_CHILD)) && 2239185029Spjd (zp->z_phys->zp_flags & ZFS_NOUNLINK)) { 2240185029Spjd *check_privs = B_FALSE; 2241185029Spjd return (EPERM); 2242185029Spjd } 2243185029Spjd 2244185029Spjd if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) && 2245185029Spjd (zp->z_phys->zp_flags & ZFS_AV_QUARANTINED))) { 2246185029Spjd *check_privs = B_FALSE; 2247185029Spjd return (EACCES); 2248185029Spjd } 2249185029Spjd 2250185029Spjd /* 2251185029Spjd * The caller requested that the ACL check be skipped. This 2252185029Spjd * would only happen if the caller checked VOP_ACCESS() with a 2253185029Spjd * 32 bit ACE mask and already had the appropriate permissions. 2254185029Spjd */ 2255185029Spjd if (skipaclchk) { 2256185029Spjd *working_mode = 0; 2257185029Spjd return (0); 2258185029Spjd } 2259185029Spjd 2260185029Spjd zfs_fuid_map_ids(zp, cr, &fowner, &gowner); 2261185029Spjd 2262168404Spjd mutex_enter(&zp->z_acl_lock); 2263168404Spjd 2264185029Spjd error = zfs_acl_node_read(zp, &aclp, B_FALSE); 2265168404Spjd if (error != 0) { 2266168404Spjd mutex_exit(&zp->z_acl_lock); 2267168404Spjd return (error); 2268168404Spjd } 2269168404Spjd 2270185029Spjd while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 2271185029Spjd &iflags, &type)) { 2272168404Spjd 2273185029Spjd if (!zfs_acl_valid_ace_type(type, iflags)) 2274185029Spjd continue; 2275168404Spjd 2276185029Spjd if (ZTOV(zp)->v_type == VDIR && (iflags & ACE_INHERIT_ONLY_ACE)) 2277185029Spjd continue; 2278168404Spjd 2279185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 2280168404Spjd 2281185029Spjd checkit = B_FALSE; 2282168404Spjd 2283168404Spjd switch (entry_type) { 2284168404Spjd case ACE_OWNER: 2285185029Spjd if (uid == fowner) 2286185029Spjd checkit = B_TRUE; 2287168404Spjd break; 2288185029Spjd case OWNING_GROUP: 2289185029Spjd who = gowner; 2290185029Spjd /*FALLTHROUGH*/ 2291168404Spjd case ACE_IDENTIFIER_GROUP: 2292185029Spjd checkit = zfs_groupmember(zfsvfs, who, cr); 2293168404Spjd break; 2294168404Spjd case ACE_EVERYONE: 2295185029Spjd checkit = B_TRUE; 2296168404Spjd break; 2297168404Spjd 2298168404Spjd /* USER Entry */ 2299168404Spjd default: 2300168404Spjd if (entry_type == 0) { 2301185029Spjd uid_t newid; 2302185029Spjd 2303185029Spjd newid = zfs_fuid_map_id(zfsvfs, who, cr, 2304185029Spjd ZFS_ACE_USER); 2305185029Spjd if (newid != IDMAP_WK_CREATOR_OWNER_UID && 2306185029Spjd uid == newid) 2307185029Spjd checkit = B_TRUE; 2308168404Spjd break; 2309185029Spjd } else { 2310185029Spjd zfs_acl_free(aclp); 2311185029Spjd mutex_exit(&zp->z_acl_lock); 2312185029Spjd return (EIO); 2313168404Spjd } 2314168404Spjd } 2315168404Spjd 2316185029Spjd if (checkit) { 2317185029Spjd uint32_t mask_matched = (access_mask & *working_mode); 2318185029Spjd 2319185029Spjd if (mask_matched) { 2320185029Spjd if (type == DENY) 2321185029Spjd deny_mask |= mask_matched; 2322185029Spjd 2323185029Spjd *working_mode &= ~mask_matched; 2324185029Spjd } 2325185029Spjd } 2326185029Spjd 2327185029Spjd /* Are we done? */ 2328185029Spjd if (*working_mode == 0) 2329168404Spjd break; 2330168404Spjd } 2331168404Spjd 2332168404Spjd mutex_exit(&zp->z_acl_lock); 2333168404Spjd zfs_acl_free(aclp); 2334168404Spjd 2335185029Spjd /* Put the found 'denies' back on the working mode */ 2336185029Spjd if (deny_mask) { 2337185029Spjd *working_mode |= deny_mask; 2338185029Spjd return (EACCES); 2339185029Spjd } else if (*working_mode) { 2340185029Spjd return (-1); 2341185029Spjd } 2342185029Spjd 2343185029Spjd return (0); 2344168404Spjd} 2345168404Spjd 2346185029Spjdstatic int 2347185029Spjdzfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, 2348185029Spjd cred_t *cr) 2349185029Spjd{ 2350185029Spjd if (*working_mode != ACE_WRITE_DATA) 2351185029Spjd return (EACCES); 2352168404Spjd 2353185029Spjd return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, 2354185029Spjd check_privs, B_FALSE, cr)); 2355185029Spjd} 2356185029Spjd 2357168404Spjd/* 2358168404Spjd * Determine whether Access should be granted/denied, invoking least 2359168404Spjd * priv subsytem when a deny is determined. 2360168404Spjd */ 2361168404Spjdint 2362185029Spjdzfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) 2363168404Spjd{ 2364185029Spjd uint32_t working_mode; 2365185029Spjd int error; 2366185029Spjd int is_attr; 2367185029Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2368185029Spjd boolean_t check_privs; 2369185029Spjd znode_t *xzp; 2370185029Spjd znode_t *check_zp = zp; 2371168404Spjd 2372168404Spjd is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) && 2373168404Spjd (ZTOV(zp)->v_type == VDIR)); 2374168404Spjd 2375195785Strasz#ifdef __FreeBSD__ 2376168404Spjd /* 2377195785Strasz * In FreeBSD, we don't care about permissions of individual ADS. 2378195785Strasz * Note that not checking them is not just an optimization - without 2379195785Strasz * this shortcut, EA operations may bogusly fail with EACCES. 2380195785Strasz */ 2381195785Strasz if (zp->z_phys->zp_flags & ZFS_XATTR) 2382195785Strasz return (0); 2383195785Strasz#else 2384195785Strasz /* 2385168404Spjd * If attribute then validate against base file 2386168404Spjd */ 2387168404Spjd if (is_attr) { 2388168404Spjd if ((error = zfs_zget(zp->z_zfsvfs, 2389168404Spjd zp->z_phys->zp_parent, &xzp)) != 0) { 2390168404Spjd return (error); 2391168404Spjd } 2392185029Spjd 2393168404Spjd check_zp = xzp; 2394185029Spjd 2395168404Spjd /* 2396168404Spjd * fixup mode to map to xattr perms 2397168404Spjd */ 2398168404Spjd 2399168404Spjd if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 2400168404Spjd mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 2401168404Spjd mode |= ACE_WRITE_NAMED_ATTRS; 2402168404Spjd } 2403168404Spjd 2404168404Spjd if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 2405168404Spjd mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 2406168404Spjd mode |= ACE_READ_NAMED_ATTRS; 2407168404Spjd } 2408168404Spjd } 2409195785Strasz#endif 2410168404Spjd 2411185029Spjd if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, 2412185029Spjd &check_privs, skipaclchk, cr)) == 0) { 2413185029Spjd if (is_attr) 2414185029Spjd VN_RELE(ZTOV(xzp)); 2415185029Spjd return (0); 2416185029Spjd } 2417168404Spjd 2418185029Spjd if (error && !check_privs) { 2419168404Spjd if (is_attr) 2420168404Spjd VN_RELE(ZTOV(xzp)); 2421168404Spjd return (error); 2422168404Spjd } 2423168404Spjd 2424185029Spjd if (error && (flags & V_APPEND)) { 2425185029Spjd error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr); 2426168404Spjd } 2427168404Spjd 2428185029Spjd if (error && check_privs) { 2429185029Spjd uid_t owner; 2430185029Spjd mode_t checkmode = 0; 2431185029Spjd 2432185029Spjd owner = zfs_fuid_map_id(zfsvfs, check_zp->z_phys->zp_uid, cr, 2433185029Spjd ZFS_OWNER); 2434185029Spjd 2435185029Spjd /* 2436185029Spjd * First check for implicit owner permission on 2437185029Spjd * read_acl/read_attributes 2438185029Spjd */ 2439185029Spjd 2440185029Spjd error = 0; 2441185029Spjd ASSERT(working_mode != 0); 2442185029Spjd 2443185029Spjd if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) && 2444185029Spjd owner == crgetuid(cr))) 2445185029Spjd working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2446185029Spjd 2447185029Spjd if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2448185029Spjd ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2449185029Spjd checkmode |= VREAD; 2450185029Spjd if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2451185029Spjd ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2452185029Spjd checkmode |= VWRITE; 2453185029Spjd if (working_mode & ACE_EXECUTE) 2454185029Spjd checkmode |= VEXEC; 2455185029Spjd 2456185029Spjd if (checkmode) 2457185029Spjd error = secpolicy_vnode_access(cr, ZTOV(check_zp), 2458185029Spjd owner, checkmode); 2459185029Spjd 2460185029Spjd if (error == 0 && (working_mode & ACE_WRITE_OWNER)) 2461185029Spjd error = secpolicy_vnode_chown(ZTOV(check_zp), cr, B_TRUE); 2462185029Spjd if (error == 0 && (working_mode & ACE_WRITE_ACL)) 2463185029Spjd error = secpolicy_vnode_setdac(ZTOV(check_zp), cr, owner); 2464185029Spjd 2465185029Spjd if (error == 0 && (working_mode & 2466185029Spjd (ACE_DELETE|ACE_DELETE_CHILD))) 2467185029Spjd error = secpolicy_vnode_remove(ZTOV(check_zp), cr); 2468185029Spjd 2469185029Spjd if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) { 2470185029Spjd error = secpolicy_vnode_chown(ZTOV(check_zp), cr, B_FALSE); 2471185029Spjd } 2472185029Spjd if (error == 0) { 2473185029Spjd /* 2474185029Spjd * See if any bits other than those already checked 2475185029Spjd * for are still present. If so then return EACCES 2476185029Spjd */ 2477185029Spjd if (working_mode & ~(ZFS_CHECKED_MASKS)) { 2478185029Spjd error = EACCES; 2479185029Spjd } 2480185029Spjd } 2481185029Spjd } 2482185029Spjd 2483168404Spjd if (is_attr) 2484168404Spjd VN_RELE(ZTOV(xzp)); 2485168404Spjd 2486168404Spjd return (error); 2487168404Spjd} 2488168404Spjd 2489168404Spjd/* 2490185029Spjd * Translate traditional unix VREAD/VWRITE/VEXEC mode into 2491185029Spjd * native ACL format and call zfs_zaccess() 2492168404Spjd */ 2493168404Spjdint 2494185029Spjdzfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) 2495168404Spjd{ 2496185029Spjd return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); 2497168404Spjd} 2498168404Spjd 2499168404Spjd/* 2500185029Spjd * Access function for secpolicy_vnode_setattr 2501168404Spjd */ 2502168404Spjdint 2503185029Spjdzfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) 2504168404Spjd{ 2505168404Spjd int v4_mode = zfs_unix_to_v4(mode >> 6); 2506168404Spjd 2507185029Spjd return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr)); 2508168404Spjd} 2509168404Spjd 2510168404Spjdstatic int 2511185029Spjdzfs_delete_final_check(znode_t *zp, znode_t *dzp, 2512185029Spjd mode_t missing_perms, cred_t *cr) 2513168404Spjd{ 2514168404Spjd int error; 2515185029Spjd uid_t downer; 2516185029Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2517168404Spjd 2518185029Spjd downer = zfs_fuid_map_id(zfsvfs, dzp->z_phys->zp_uid, cr, ZFS_OWNER); 2519168404Spjd 2520185029Spjd error = secpolicy_vnode_access(cr, ZTOV(dzp), downer, missing_perms); 2521185029Spjd 2522168404Spjd if (error == 0) 2523168404Spjd error = zfs_sticky_remove_access(dzp, zp, cr); 2524168404Spjd 2525168404Spjd return (error); 2526168404Spjd} 2527168404Spjd 2528168404Spjd/* 2529168404Spjd * Determine whether Access should be granted/deny, without 2530168404Spjd * consulting least priv subsystem. 2531168404Spjd * 2532168404Spjd * 2533168404Spjd * The following chart is the recommended NFSv4 enforcement for 2534168404Spjd * ability to delete an object. 2535168404Spjd * 2536168404Spjd * ------------------------------------------------------- 2537168404Spjd * | Parent Dir | Target Object Permissions | 2538168404Spjd * | permissions | | 2539168404Spjd * ------------------------------------------------------- 2540168404Spjd * | | ACL Allows | ACL Denies| Delete | 2541168404Spjd * | | Delete | Delete | unspecified| 2542168404Spjd * ------------------------------------------------------- 2543168404Spjd * | ACL Allows | Permit | Permit | Permit | 2544168404Spjd * | DELETE_CHILD | | 2545168404Spjd * ------------------------------------------------------- 2546168404Spjd * | ACL Denies | Permit | Deny | Deny | 2547168404Spjd * | DELETE_CHILD | | | | 2548168404Spjd * ------------------------------------------------------- 2549168404Spjd * | ACL specifies | | | | 2550168404Spjd * | only allow | Permit | Permit | Permit | 2551168404Spjd * | write and | | | | 2552168404Spjd * | execute | | | | 2553168404Spjd * ------------------------------------------------------- 2554168404Spjd * | ACL denies | | | | 2555168404Spjd * | write and | Permit | Deny | Deny | 2556168404Spjd * | execute | | | | 2557168404Spjd * ------------------------------------------------------- 2558168404Spjd * ^ 2559168404Spjd * | 2560168404Spjd * No search privilege, can't even look up file? 2561168404Spjd * 2562168404Spjd */ 2563168404Spjdint 2564168404Spjdzfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) 2565168404Spjd{ 2566185029Spjd uint32_t dzp_working_mode = 0; 2567185029Spjd uint32_t zp_working_mode = 0; 2568168404Spjd int dzp_error, zp_error; 2569185029Spjd mode_t missing_perms; 2570185029Spjd boolean_t dzpcheck_privs = B_TRUE; 2571185029Spjd boolean_t zpcheck_privs = B_TRUE; 2572168404Spjd 2573168404Spjd /* 2574185029Spjd * We want specific DELETE permissions to 2575168404Spjd * take precedence over WRITE/EXECUTE. We don't 2576168404Spjd * want an ACL such as this to mess us up. 2577168404Spjd * user:joe:write_data:deny,user:joe:delete:allow 2578168404Spjd * 2579168404Spjd * However, deny permissions may ultimately be overridden 2580168404Spjd * by secpolicy_vnode_access(). 2581185029Spjd * 2582185029Spjd * We will ask for all of the necessary permissions and then 2583185029Spjd * look at the working modes from the directory and target object 2584185029Spjd * to determine what was found. 2585168404Spjd */ 2586168404Spjd 2587185029Spjd if (zp->z_phys->zp_flags & (ZFS_IMMUTABLE | ZFS_NOUNLINK)) 2588185029Spjd return (EPERM); 2589168404Spjd 2590168404Spjd /* 2591185029Spjd * First row 2592185029Spjd * If the directory permissions allow the delete, we are done. 2593168404Spjd */ 2594185029Spjd if ((dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 2595185029Spjd &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0) 2596168404Spjd return (0); 2597168404Spjd 2598168404Spjd /* 2599185029Spjd * If target object has delete permission then we are done 2600168404Spjd */ 2601185029Spjd if ((zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, 2602185029Spjd &zpcheck_privs, B_FALSE, cr)) == 0) 2603168404Spjd return (0); 2604168404Spjd 2605185029Spjd ASSERT(dzp_error && zp_error); 2606185029Spjd 2607185029Spjd if (!dzpcheck_privs) 2608185029Spjd return (dzp_error); 2609185029Spjd if (!zpcheck_privs) 2610185029Spjd return (zp_error); 2611185029Spjd 2612168404Spjd /* 2613185029Spjd * Second row 2614168404Spjd * 2615185029Spjd * If directory returns EACCES then delete_child was denied 2616185029Spjd * due to deny delete_child. In this case send the request through 2617185029Spjd * secpolicy_vnode_remove(). We don't use zfs_delete_final_check() 2618185029Spjd * since that *could* allow the delete based on write/execute permission 2619185029Spjd * and we want delete permissions to override write/execute. 2620168404Spjd */ 2621168404Spjd 2622168404Spjd if (dzp_error == EACCES) 2623185029Spjd return (secpolicy_vnode_remove(ZTOV(dzp), cr)); /* XXXPJD: s/dzp/zp/ ? */ 2624168404Spjd 2625168404Spjd /* 2626168404Spjd * Third Row 2627185029Spjd * only need to see if we have write/execute on directory. 2628168404Spjd */ 2629168404Spjd 2630185029Spjd if ((dzp_error = zfs_zaccess_common(dzp, ACE_EXECUTE|ACE_WRITE_DATA, 2631185029Spjd &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0) 2632185029Spjd return (zfs_sticky_remove_access(dzp, zp, cr)); 2633168404Spjd 2634185029Spjd if (!dzpcheck_privs) 2635168404Spjd return (dzp_error); 2636168404Spjd 2637168404Spjd /* 2638185029Spjd * Fourth row 2639168404Spjd */ 2640168404Spjd 2641185029Spjd missing_perms = (dzp_working_mode & ACE_WRITE_DATA) ? VWRITE : 0; 2642185029Spjd missing_perms |= (dzp_working_mode & ACE_EXECUTE) ? VEXEC : 0; 2643168404Spjd 2644185029Spjd ASSERT(missing_perms); 2645185029Spjd 2646185029Spjd return (zfs_delete_final_check(zp, dzp, missing_perms, cr)); 2647185029Spjd 2648168404Spjd} 2649168404Spjd 2650168404Spjdint 2651168404Spjdzfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 2652168404Spjd znode_t *tzp, cred_t *cr) 2653168404Spjd{ 2654168404Spjd int add_perm; 2655168404Spjd int error; 2656168404Spjd 2657185029Spjd if (szp->z_phys->zp_flags & ZFS_AV_QUARANTINED) 2658185029Spjd return (EACCES); 2659185029Spjd 2660168404Spjd add_perm = (ZTOV(szp)->v_type == VDIR) ? 2661168404Spjd ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 2662168404Spjd 2663168404Spjd /* 2664168404Spjd * Rename permissions are combination of delete permission + 2665168404Spjd * add file/subdir permission. 2666184770Strasz * 2667184770Strasz * BSD operating systems also require write permission 2668184770Strasz * on the directory being moved from one parent directory 2669184770Strasz * to another. 2670168404Spjd */ 2671184770Strasz if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) { 2672185029Spjd if (error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr)) 2673184770Strasz return (error); 2674184770Strasz } 2675168404Spjd 2676168404Spjd /* 2677168404Spjd * first make sure we do the delete portion. 2678168404Spjd * 2679168404Spjd * If that succeeds then check for add_file/add_subdir permissions 2680168404Spjd */ 2681168404Spjd 2682168404Spjd if (error = zfs_zaccess_delete(sdzp, szp, cr)) 2683168404Spjd return (error); 2684168404Spjd 2685168404Spjd /* 2686168404Spjd * If we have a tzp, see if we can delete it? 2687168404Spjd */ 2688168404Spjd if (tzp) { 2689168404Spjd if (error = zfs_zaccess_delete(tdzp, tzp, cr)) 2690168404Spjd return (error); 2691168404Spjd } 2692168404Spjd 2693168404Spjd /* 2694168404Spjd * Now check for add permissions 2695168404Spjd */ 2696185029Spjd error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); 2697168404Spjd 2698168404Spjd return (error); 2699168404Spjd} 2700