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/* 22219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23224174Smm * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24249643Smm * Copyright (c) 2013 by Delphix. All rights reserved. 25168404Spjd */ 26168404Spjd 27168404Spjd#include <sys/types.h> 28168404Spjd#include <sys/param.h> 29168404Spjd#include <sys/time.h> 30168404Spjd#include <sys/systm.h> 31168404Spjd#include <sys/sysmacros.h> 32168404Spjd#include <sys/resource.h> 33168404Spjd#include <sys/vfs.h> 34168404Spjd#include <sys/vnode.h> 35168404Spjd#include <sys/file.h> 36168404Spjd#include <sys/stat.h> 37168404Spjd#include <sys/kmem.h> 38168404Spjd#include <sys/cmn_err.h> 39168404Spjd#include <sys/errno.h> 40168404Spjd#include <sys/unistd.h> 41168404Spjd#include <sys/sdt.h> 42168404Spjd#include <sys/fs/zfs.h> 43169023Spjd#include <sys/policy.h> 44168404Spjd#include <sys/zfs_znode.h> 45185029Spjd#include <sys/zfs_fuid.h> 46168404Spjd#include <sys/zfs_acl.h> 47168404Spjd#include <sys/zfs_dir.h> 48168404Spjd#include <sys/zfs_vfsops.h> 49168404Spjd#include <sys/dmu.h> 50185029Spjd#include <sys/dnode.h> 51168404Spjd#include <sys/zap.h> 52219089Spjd#include <sys/sa.h> 53168404Spjd#include <acl/acl_common.h> 54168404Spjd 55168404Spjd#define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE 56168404Spjd#define DENY ACE_ACCESS_DENIED_ACE_TYPE 57185029Spjd#define MAX_ACE_TYPE ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 58185029Spjd#define MIN_ACE_TYPE ALLOW 59168404Spjd 60168404Spjd#define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 61168404Spjd#define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 62168404Spjd ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 63168404Spjd#define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 64168404Spjd ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 65168404Spjd#define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 66168404Spjd ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 67168404Spjd 68185029Spjd#define ZFS_CHECKED_MASKS (ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_DATA| \ 69185029Spjd ACE_READ_NAMED_ATTRS|ACE_WRITE_DATA|ACE_WRITE_ATTRIBUTES| \ 70185029Spjd ACE_WRITE_NAMED_ATTRS|ACE_APPEND_DATA|ACE_EXECUTE|ACE_WRITE_OWNER| \ 71185029Spjd ACE_WRITE_ACL|ACE_DELETE|ACE_DELETE_CHILD|ACE_SYNCHRONIZE) 72185029Spjd 73209962Smm#define WRITE_MASK_DATA (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS) 74209962Smm#define WRITE_MASK_ATTRS (ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES| \ 75209962Smm ACE_DELETE|ACE_DELETE_CHILD) 76219089Spjd#define WRITE_MASK (WRITE_MASK_DATA|WRITE_MASK_ATTRS) 77185029Spjd 78168404Spjd#define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 79168404Spjd ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 80168404Spjd 81168404Spjd#define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 82168404Spjd ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 83168404Spjd 84168404Spjd#define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 85185029Spjd ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE) 86168404Spjd 87185029Spjd#define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) 88168404Spjd 89185029Spjd#define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\ 90185029Spjd ZFS_ACL_PROTECTED) 91168404Spjd 92185029Spjd#define ZFS_ACL_WIDE_FLAGS (V4_ACL_WIDE_FLAGS|ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|\ 93185029Spjd ZFS_ACL_OBJ_ACE) 94168404Spjd 95211932Smm#define ALL_MODE_EXECS (S_IXUSR | S_IXGRP | S_IXOTH) 96211932Smm 97185029Spjdstatic uint16_t 98185029Spjdzfs_ace_v0_get_type(void *acep) 99185029Spjd{ 100185029Spjd return (((zfs_oldace_t *)acep)->z_type); 101185029Spjd} 102185029Spjd 103185029Spjdstatic uint16_t 104185029Spjdzfs_ace_v0_get_flags(void *acep) 105185029Spjd{ 106185029Spjd return (((zfs_oldace_t *)acep)->z_flags); 107185029Spjd} 108185029Spjd 109185029Spjdstatic uint32_t 110185029Spjdzfs_ace_v0_get_mask(void *acep) 111185029Spjd{ 112185029Spjd return (((zfs_oldace_t *)acep)->z_access_mask); 113185029Spjd} 114185029Spjd 115185029Spjdstatic uint64_t 116185029Spjdzfs_ace_v0_get_who(void *acep) 117185029Spjd{ 118185029Spjd return (((zfs_oldace_t *)acep)->z_fuid); 119185029Spjd} 120185029Spjd 121185029Spjdstatic void 122185029Spjdzfs_ace_v0_set_type(void *acep, uint16_t type) 123185029Spjd{ 124185029Spjd ((zfs_oldace_t *)acep)->z_type = type; 125185029Spjd} 126185029Spjd 127185029Spjdstatic void 128185029Spjdzfs_ace_v0_set_flags(void *acep, uint16_t flags) 129185029Spjd{ 130185029Spjd ((zfs_oldace_t *)acep)->z_flags = flags; 131185029Spjd} 132185029Spjd 133185029Spjdstatic void 134185029Spjdzfs_ace_v0_set_mask(void *acep, uint32_t mask) 135185029Spjd{ 136185029Spjd ((zfs_oldace_t *)acep)->z_access_mask = mask; 137185029Spjd} 138185029Spjd 139185029Spjdstatic void 140185029Spjdzfs_ace_v0_set_who(void *acep, uint64_t who) 141185029Spjd{ 142185029Spjd ((zfs_oldace_t *)acep)->z_fuid = who; 143185029Spjd} 144185029Spjd 145185029Spjd/*ARGSUSED*/ 146185029Spjdstatic size_t 147185029Spjdzfs_ace_v0_size(void *acep) 148185029Spjd{ 149185029Spjd return (sizeof (zfs_oldace_t)); 150185029Spjd} 151185029Spjd 152185029Spjdstatic size_t 153185029Spjdzfs_ace_v0_abstract_size(void) 154185029Spjd{ 155185029Spjd return (sizeof (zfs_oldace_t)); 156185029Spjd} 157185029Spjd 158185029Spjdstatic int 159185029Spjdzfs_ace_v0_mask_off(void) 160185029Spjd{ 161185029Spjd return (offsetof(zfs_oldace_t, z_access_mask)); 162185029Spjd} 163185029Spjd 164185029Spjd/*ARGSUSED*/ 165185029Spjdstatic int 166185029Spjdzfs_ace_v0_data(void *acep, void **datap) 167185029Spjd{ 168185029Spjd *datap = NULL; 169185029Spjd return (0); 170185029Spjd} 171185029Spjd 172185029Spjdstatic acl_ops_t zfs_acl_v0_ops = { 173185029Spjd zfs_ace_v0_get_mask, 174185029Spjd zfs_ace_v0_set_mask, 175185029Spjd zfs_ace_v0_get_flags, 176185029Spjd zfs_ace_v0_set_flags, 177185029Spjd zfs_ace_v0_get_type, 178185029Spjd zfs_ace_v0_set_type, 179185029Spjd zfs_ace_v0_get_who, 180185029Spjd zfs_ace_v0_set_who, 181185029Spjd zfs_ace_v0_size, 182185029Spjd zfs_ace_v0_abstract_size, 183185029Spjd zfs_ace_v0_mask_off, 184185029Spjd zfs_ace_v0_data 185185029Spjd}; 186185029Spjd 187185029Spjdstatic uint16_t 188185029Spjdzfs_ace_fuid_get_type(void *acep) 189185029Spjd{ 190185029Spjd return (((zfs_ace_hdr_t *)acep)->z_type); 191185029Spjd} 192185029Spjd 193185029Spjdstatic uint16_t 194185029Spjdzfs_ace_fuid_get_flags(void *acep) 195185029Spjd{ 196185029Spjd return (((zfs_ace_hdr_t *)acep)->z_flags); 197185029Spjd} 198185029Spjd 199185029Spjdstatic uint32_t 200185029Spjdzfs_ace_fuid_get_mask(void *acep) 201185029Spjd{ 202185029Spjd return (((zfs_ace_hdr_t *)acep)->z_access_mask); 203185029Spjd} 204185029Spjd 205185029Spjdstatic uint64_t 206185029Spjdzfs_ace_fuid_get_who(void *args) 207185029Spjd{ 208185029Spjd uint16_t entry_type; 209185029Spjd zfs_ace_t *acep = args; 210185029Spjd 211185029Spjd entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 212185029Spjd 213185029Spjd if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 214185029Spjd entry_type == ACE_EVERYONE) 215185029Spjd return (-1); 216185029Spjd return (((zfs_ace_t *)acep)->z_fuid); 217185029Spjd} 218185029Spjd 219185029Spjdstatic void 220185029Spjdzfs_ace_fuid_set_type(void *acep, uint16_t type) 221185029Spjd{ 222185029Spjd ((zfs_ace_hdr_t *)acep)->z_type = type; 223185029Spjd} 224185029Spjd 225185029Spjdstatic void 226185029Spjdzfs_ace_fuid_set_flags(void *acep, uint16_t flags) 227185029Spjd{ 228185029Spjd ((zfs_ace_hdr_t *)acep)->z_flags = flags; 229185029Spjd} 230185029Spjd 231185029Spjdstatic void 232185029Spjdzfs_ace_fuid_set_mask(void *acep, uint32_t mask) 233185029Spjd{ 234185029Spjd ((zfs_ace_hdr_t *)acep)->z_access_mask = mask; 235185029Spjd} 236185029Spjd 237185029Spjdstatic void 238185029Spjdzfs_ace_fuid_set_who(void *arg, uint64_t who) 239185029Spjd{ 240185029Spjd zfs_ace_t *acep = arg; 241185029Spjd 242185029Spjd uint16_t entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 243185029Spjd 244185029Spjd if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 245185029Spjd entry_type == ACE_EVERYONE) 246185029Spjd return; 247185029Spjd acep->z_fuid = who; 248185029Spjd} 249185029Spjd 250185029Spjdstatic size_t 251185029Spjdzfs_ace_fuid_size(void *acep) 252185029Spjd{ 253185029Spjd zfs_ace_hdr_t *zacep = acep; 254185029Spjd uint16_t entry_type; 255185029Spjd 256185029Spjd switch (zacep->z_type) { 257185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 258185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 259185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 260185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 261185029Spjd return (sizeof (zfs_object_ace_t)); 262185029Spjd case ALLOW: 263185029Spjd case DENY: 264185029Spjd entry_type = 265185029Spjd (((zfs_ace_hdr_t *)acep)->z_flags & ACE_TYPE_FLAGS); 266185029Spjd if (entry_type == ACE_OWNER || 267185029Spjd entry_type == OWNING_GROUP || 268185029Spjd entry_type == ACE_EVERYONE) 269185029Spjd return (sizeof (zfs_ace_hdr_t)); 270185029Spjd /*FALLTHROUGH*/ 271185029Spjd default: 272185029Spjd return (sizeof (zfs_ace_t)); 273185029Spjd } 274185029Spjd} 275185029Spjd 276185029Spjdstatic size_t 277185029Spjdzfs_ace_fuid_abstract_size(void) 278185029Spjd{ 279185029Spjd return (sizeof (zfs_ace_hdr_t)); 280185029Spjd} 281185029Spjd 282185029Spjdstatic int 283185029Spjdzfs_ace_fuid_mask_off(void) 284185029Spjd{ 285185029Spjd return (offsetof(zfs_ace_hdr_t, z_access_mask)); 286185029Spjd} 287185029Spjd 288185029Spjdstatic int 289185029Spjdzfs_ace_fuid_data(void *acep, void **datap) 290185029Spjd{ 291185029Spjd zfs_ace_t *zacep = acep; 292185029Spjd zfs_object_ace_t *zobjp; 293185029Spjd 294185029Spjd switch (zacep->z_hdr.z_type) { 295185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 296185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 297185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 298185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 299185029Spjd zobjp = acep; 300185029Spjd *datap = (caddr_t)zobjp + sizeof (zfs_ace_t); 301185029Spjd return (sizeof (zfs_object_ace_t) - sizeof (zfs_ace_t)); 302185029Spjd default: 303185029Spjd *datap = NULL; 304185029Spjd return (0); 305185029Spjd } 306185029Spjd} 307185029Spjd 308185029Spjdstatic acl_ops_t zfs_acl_fuid_ops = { 309185029Spjd zfs_ace_fuid_get_mask, 310185029Spjd zfs_ace_fuid_set_mask, 311185029Spjd zfs_ace_fuid_get_flags, 312185029Spjd zfs_ace_fuid_set_flags, 313185029Spjd zfs_ace_fuid_get_type, 314185029Spjd zfs_ace_fuid_set_type, 315185029Spjd zfs_ace_fuid_get_who, 316185029Spjd zfs_ace_fuid_set_who, 317185029Spjd zfs_ace_fuid_size, 318185029Spjd zfs_ace_fuid_abstract_size, 319185029Spjd zfs_ace_fuid_mask_off, 320185029Spjd zfs_ace_fuid_data 321185029Spjd}; 322185029Spjd 323219089Spjd/* 324219089Spjd * The following three functions are provided for compatibility with 325219089Spjd * older ZPL version in order to determine if the file use to have 326219089Spjd * an external ACL and what version of ACL previously existed on the 327219089Spjd * file. Would really be nice to not need this, sigh. 328219089Spjd */ 329219089Spjduint64_t 330219089Spjdzfs_external_acl(znode_t *zp) 331219089Spjd{ 332219089Spjd zfs_acl_phys_t acl_phys; 333219089Spjd int error; 334219089Spjd 335219089Spjd if (zp->z_is_sa) 336219089Spjd return (0); 337219089Spjd 338219089Spjd /* 339219089Spjd * Need to deal with a potential 340219089Spjd * race where zfs_sa_upgrade could cause 341219089Spjd * z_isa_sa to change. 342219089Spjd * 343219089Spjd * If the lookup fails then the state of z_is_sa should have 344219089Spjd * changed. 345219089Spjd */ 346219089Spjd 347219089Spjd if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zp->z_zfsvfs), 348219089Spjd &acl_phys, sizeof (acl_phys))) == 0) 349219089Spjd return (acl_phys.z_acl_extern_obj); 350219089Spjd else { 351219089Spjd /* 352219089Spjd * after upgrade the SA_ZPL_ZNODE_ACL should have been 353219089Spjd * removed 354219089Spjd */ 355219089Spjd VERIFY(zp->z_is_sa && error == ENOENT); 356219089Spjd return (0); 357219089Spjd } 358219089Spjd} 359219089Spjd 360219089Spjd/* 361219089Spjd * Determine size of ACL in bytes 362219089Spjd * 363219089Spjd * This is more complicated than it should be since we have to deal 364219089Spjd * with old external ACLs. 365219089Spjd */ 366185029Spjdstatic int 367219089Spjdzfs_acl_znode_info(znode_t *zp, int *aclsize, int *aclcount, 368219089Spjd zfs_acl_phys_t *aclphys) 369219089Spjd{ 370219089Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 371219089Spjd uint64_t acl_count; 372219089Spjd int size; 373219089Spjd int error; 374219089Spjd 375219089Spjd ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 376219089Spjd if (zp->z_is_sa) { 377219089Spjd if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zfsvfs), 378219089Spjd &size)) != 0) 379219089Spjd return (error); 380219089Spjd *aclsize = size; 381219089Spjd if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_COUNT(zfsvfs), 382219089Spjd &acl_count, sizeof (acl_count))) != 0) 383219089Spjd return (error); 384219089Spjd *aclcount = acl_count; 385219089Spjd } else { 386219089Spjd if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), 387219089Spjd aclphys, sizeof (*aclphys))) != 0) 388219089Spjd return (error); 389219089Spjd 390219089Spjd if (aclphys->z_acl_version == ZFS_ACL_VERSION_INITIAL) { 391219089Spjd *aclsize = ZFS_ACL_SIZE(aclphys->z_acl_size); 392219089Spjd *aclcount = aclphys->z_acl_size; 393219089Spjd } else { 394219089Spjd *aclsize = aclphys->z_acl_size; 395219089Spjd *aclcount = aclphys->z_acl_count; 396219089Spjd } 397219089Spjd } 398219089Spjd return (0); 399219089Spjd} 400219089Spjd 401219089Spjdint 402219089Spjdzfs_znode_acl_version(znode_t *zp) 403219089Spjd{ 404219089Spjd zfs_acl_phys_t acl_phys; 405219089Spjd 406219089Spjd if (zp->z_is_sa) 407219089Spjd return (ZFS_ACL_VERSION_FUID); 408219089Spjd else { 409219089Spjd int error; 410219089Spjd 411219089Spjd /* 412219089Spjd * Need to deal with a potential 413219089Spjd * race where zfs_sa_upgrade could cause 414219089Spjd * z_isa_sa to change. 415219089Spjd * 416219089Spjd * If the lookup fails then the state of z_is_sa should have 417219089Spjd * changed. 418219089Spjd */ 419219089Spjd if ((error = sa_lookup(zp->z_sa_hdl, 420219089Spjd SA_ZPL_ZNODE_ACL(zp->z_zfsvfs), 421219089Spjd &acl_phys, sizeof (acl_phys))) == 0) 422219089Spjd return (acl_phys.z_acl_version); 423219089Spjd else { 424219089Spjd /* 425219089Spjd * After upgrade SA_ZPL_ZNODE_ACL should have 426219089Spjd * been removed. 427219089Spjd */ 428219089Spjd VERIFY(zp->z_is_sa && error == ENOENT); 429219089Spjd return (ZFS_ACL_VERSION_FUID); 430219089Spjd } 431219089Spjd } 432219089Spjd} 433219089Spjd 434219089Spjdstatic int 435185029Spjdzfs_acl_version(int version) 436185029Spjd{ 437185029Spjd if (version < ZPL_VERSION_FUID) 438185029Spjd return (ZFS_ACL_VERSION_INITIAL); 439185029Spjd else 440185029Spjd return (ZFS_ACL_VERSION_FUID); 441185029Spjd} 442185029Spjd 443185029Spjdstatic int 444185029Spjdzfs_acl_version_zp(znode_t *zp) 445185029Spjd{ 446185029Spjd return (zfs_acl_version(zp->z_zfsvfs->z_version)); 447185029Spjd} 448185029Spjd 449219089Spjdzfs_acl_t * 450185029Spjdzfs_acl_alloc(int vers) 451168404Spjd{ 452168404Spjd zfs_acl_t *aclp; 453168404Spjd 454168404Spjd aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 455185029Spjd list_create(&aclp->z_acl, sizeof (zfs_acl_node_t), 456185029Spjd offsetof(zfs_acl_node_t, z_next)); 457185029Spjd aclp->z_version = vers; 458185029Spjd if (vers == ZFS_ACL_VERSION_FUID) 459185029Spjd aclp->z_ops = zfs_acl_fuid_ops; 460185029Spjd else 461185029Spjd aclp->z_ops = zfs_acl_v0_ops; 462168404Spjd return (aclp); 463168404Spjd} 464168404Spjd 465219089Spjdzfs_acl_node_t * 466185029Spjdzfs_acl_node_alloc(size_t bytes) 467185029Spjd{ 468185029Spjd zfs_acl_node_t *aclnode; 469185029Spjd 470185029Spjd aclnode = kmem_zalloc(sizeof (zfs_acl_node_t), KM_SLEEP); 471185029Spjd if (bytes) { 472185029Spjd aclnode->z_acldata = kmem_alloc(bytes, KM_SLEEP); 473185029Spjd aclnode->z_allocdata = aclnode->z_acldata; 474185029Spjd aclnode->z_allocsize = bytes; 475185029Spjd aclnode->z_size = bytes; 476185029Spjd } 477185029Spjd 478185029Spjd return (aclnode); 479185029Spjd} 480185029Spjd 481185029Spjdstatic void 482185029Spjdzfs_acl_node_free(zfs_acl_node_t *aclnode) 483185029Spjd{ 484185029Spjd if (aclnode->z_allocsize) 485185029Spjd kmem_free(aclnode->z_allocdata, aclnode->z_allocsize); 486185029Spjd kmem_free(aclnode, sizeof (zfs_acl_node_t)); 487185029Spjd} 488185029Spjd 489185029Spjdstatic void 490185029Spjdzfs_acl_release_nodes(zfs_acl_t *aclp) 491185029Spjd{ 492185029Spjd zfs_acl_node_t *aclnode; 493185029Spjd 494185029Spjd while (aclnode = list_head(&aclp->z_acl)) { 495185029Spjd list_remove(&aclp->z_acl, aclnode); 496185029Spjd zfs_acl_node_free(aclnode); 497185029Spjd } 498185029Spjd aclp->z_acl_count = 0; 499185029Spjd aclp->z_acl_bytes = 0; 500185029Spjd} 501185029Spjd 502168404Spjdvoid 503168404Spjdzfs_acl_free(zfs_acl_t *aclp) 504168404Spjd{ 505185029Spjd zfs_acl_release_nodes(aclp); 506185029Spjd list_destroy(&aclp->z_acl); 507168404Spjd kmem_free(aclp, sizeof (zfs_acl_t)); 508168404Spjd} 509168404Spjd 510185029Spjdstatic boolean_t 511185029Spjdzfs_acl_valid_ace_type(uint_t type, uint_t flags) 512168404Spjd{ 513185029Spjd uint16_t entry_type; 514168404Spjd 515185029Spjd switch (type) { 516185029Spjd case ALLOW: 517185029Spjd case DENY: 518185029Spjd case ACE_SYSTEM_AUDIT_ACE_TYPE: 519185029Spjd case ACE_SYSTEM_ALARM_ACE_TYPE: 520185029Spjd entry_type = flags & ACE_TYPE_FLAGS; 521185029Spjd return (entry_type == ACE_OWNER || 522185029Spjd entry_type == OWNING_GROUP || 523185029Spjd entry_type == ACE_EVERYONE || entry_type == 0 || 524185029Spjd entry_type == ACE_IDENTIFIER_GROUP); 525185029Spjd default: 526185029Spjd if (type >= MIN_ACE_TYPE && type <= MAX_ACE_TYPE) 527185029Spjd return (B_TRUE); 528185029Spjd } 529185029Spjd return (B_FALSE); 530185029Spjd} 531185029Spjd 532185029Spjdstatic boolean_t 533185029Spjdzfs_ace_valid(vtype_t obj_type, zfs_acl_t *aclp, uint16_t type, uint16_t iflags) 534185029Spjd{ 535168404Spjd /* 536185029Spjd * first check type of entry 537168404Spjd */ 538168404Spjd 539185029Spjd if (!zfs_acl_valid_ace_type(type, iflags)) 540185029Spjd return (B_FALSE); 541185029Spjd 542185029Spjd switch (type) { 543185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 544185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 545185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 546185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 547185029Spjd if (aclp->z_version < ZFS_ACL_VERSION_FUID) 548185029Spjd return (B_FALSE); 549185029Spjd aclp->z_hints |= ZFS_ACL_OBJ_ACE; 550185029Spjd } 551185029Spjd 552185029Spjd /* 553185029Spjd * next check inheritance level flags 554185029Spjd */ 555185029Spjd 556185029Spjd if (obj_type == VDIR && 557185029Spjd (iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 558185029Spjd aclp->z_hints |= ZFS_INHERIT_ACE; 559185029Spjd 560185029Spjd if (iflags & (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 561185029Spjd if ((iflags & (ACE_FILE_INHERIT_ACE| 562185029Spjd ACE_DIRECTORY_INHERIT_ACE)) == 0) { 563185029Spjd return (B_FALSE); 564185029Spjd } 565185029Spjd } 566185029Spjd 567185029Spjd return (B_TRUE); 568168404Spjd} 569168404Spjd 570185029Spjdstatic void * 571185029Spjdzfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who, 572185029Spjd uint32_t *access_mask, uint16_t *iflags, uint16_t *type) 573185029Spjd{ 574185029Spjd zfs_acl_node_t *aclnode; 575185029Spjd 576219089Spjd ASSERT(aclp); 577219089Spjd 578185029Spjd if (start == NULL) { 579185029Spjd aclnode = list_head(&aclp->z_acl); 580185029Spjd if (aclnode == NULL) 581185029Spjd return (NULL); 582185029Spjd 583185029Spjd aclp->z_next_ace = aclnode->z_acldata; 584185029Spjd aclp->z_curr_node = aclnode; 585185029Spjd aclnode->z_ace_idx = 0; 586185029Spjd } 587185029Spjd 588185029Spjd aclnode = aclp->z_curr_node; 589185029Spjd 590185029Spjd if (aclnode == NULL) 591185029Spjd return (NULL); 592185029Spjd 593185029Spjd if (aclnode->z_ace_idx >= aclnode->z_ace_count) { 594185029Spjd aclnode = list_next(&aclp->z_acl, aclnode); 595185029Spjd if (aclnode == NULL) 596185029Spjd return (NULL); 597185029Spjd else { 598185029Spjd aclp->z_curr_node = aclnode; 599185029Spjd aclnode->z_ace_idx = 0; 600185029Spjd aclp->z_next_ace = aclnode->z_acldata; 601185029Spjd } 602185029Spjd } 603185029Spjd 604185029Spjd if (aclnode->z_ace_idx < aclnode->z_ace_count) { 605185029Spjd void *acep = aclp->z_next_ace; 606185029Spjd size_t ace_size; 607185029Spjd 608185029Spjd /* 609185029Spjd * Make sure we don't overstep our bounds 610185029Spjd */ 611185029Spjd ace_size = aclp->z_ops.ace_size(acep); 612185029Spjd 613185029Spjd if (((caddr_t)acep + ace_size) > 614185029Spjd ((caddr_t)aclnode->z_acldata + aclnode->z_size)) { 615185029Spjd return (NULL); 616185029Spjd } 617185029Spjd 618185029Spjd *iflags = aclp->z_ops.ace_flags_get(acep); 619185029Spjd *type = aclp->z_ops.ace_type_get(acep); 620185029Spjd *access_mask = aclp->z_ops.ace_mask_get(acep); 621185029Spjd *who = aclp->z_ops.ace_who_get(acep); 622185029Spjd aclp->z_next_ace = (caddr_t)aclp->z_next_ace + ace_size; 623185029Spjd aclnode->z_ace_idx++; 624219089Spjd 625185029Spjd return ((void *)acep); 626185029Spjd } 627185029Spjd return (NULL); 628185029Spjd} 629185029Spjd 630185029Spjd/*ARGSUSED*/ 631185029Spjdstatic uint64_t 632185029Spjdzfs_ace_walk(void *datap, uint64_t cookie, int aclcnt, 633185029Spjd uint16_t *flags, uint16_t *type, uint32_t *mask) 634185029Spjd{ 635185029Spjd zfs_acl_t *aclp = datap; 636185029Spjd zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)(uintptr_t)cookie; 637185029Spjd uint64_t who; 638185029Spjd 639185029Spjd acep = zfs_acl_next_ace(aclp, acep, &who, mask, 640185029Spjd flags, type); 641185029Spjd return ((uint64_t)(uintptr_t)acep); 642185029Spjd} 643185029Spjd 644185029Spjdstatic zfs_acl_node_t * 645185029Spjdzfs_acl_curr_node(zfs_acl_t *aclp) 646185029Spjd{ 647185029Spjd ASSERT(aclp->z_curr_node); 648185029Spjd return (aclp->z_curr_node); 649185029Spjd} 650185029Spjd 651168404Spjd/* 652185029Spjd * Copy ACE to internal ZFS format. 653185029Spjd * While processing the ACL each ACE will be validated for correctness. 654185029Spjd * ACE FUIDs will be created later. 655185029Spjd */ 656185029Spjdint 657209962Smmzfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp, 658219089Spjd void *datap, zfs_ace_t *z_acl, uint64_t aclcnt, size_t *size, 659209962Smm zfs_fuid_info_t **fuidp, cred_t *cr) 660185029Spjd{ 661185029Spjd int i; 662185029Spjd uint16_t entry_type; 663185029Spjd zfs_ace_t *aceptr = z_acl; 664185029Spjd ace_t *acep = datap; 665185029Spjd zfs_object_ace_t *zobjacep; 666185029Spjd ace_object_t *aceobjp; 667185029Spjd 668185029Spjd for (i = 0; i != aclcnt; i++) { 669185029Spjd aceptr->z_hdr.z_access_mask = acep->a_access_mask; 670185029Spjd aceptr->z_hdr.z_flags = acep->a_flags; 671185029Spjd aceptr->z_hdr.z_type = acep->a_type; 672185029Spjd entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS; 673185029Spjd if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP && 674185029Spjd entry_type != ACE_EVERYONE) { 675209962Smm aceptr->z_fuid = zfs_fuid_create(zfsvfs, acep->a_who, 676209962Smm cr, (entry_type == 0) ? 677209962Smm ZFS_ACE_USER : ZFS_ACE_GROUP, fuidp); 678185029Spjd } 679185029Spjd 680185029Spjd /* 681185029Spjd * Make sure ACE is valid 682185029Spjd */ 683185029Spjd if (zfs_ace_valid(obj_type, aclp, aceptr->z_hdr.z_type, 684185029Spjd aceptr->z_hdr.z_flags) != B_TRUE) 685249643Smm return (SET_ERROR(EINVAL)); 686185029Spjd 687185029Spjd switch (acep->a_type) { 688185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 689185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 690185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 691185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 692185029Spjd zobjacep = (zfs_object_ace_t *)aceptr; 693185029Spjd aceobjp = (ace_object_t *)acep; 694185029Spjd 695185029Spjd bcopy(aceobjp->a_obj_type, zobjacep->z_object_type, 696185029Spjd sizeof (aceobjp->a_obj_type)); 697185029Spjd bcopy(aceobjp->a_inherit_obj_type, 698185029Spjd zobjacep->z_inherit_type, 699185029Spjd sizeof (aceobjp->a_inherit_obj_type)); 700185029Spjd acep = (ace_t *)((caddr_t)acep + sizeof (ace_object_t)); 701185029Spjd break; 702185029Spjd default: 703185029Spjd acep = (ace_t *)((caddr_t)acep + sizeof (ace_t)); 704185029Spjd } 705185029Spjd 706185029Spjd aceptr = (zfs_ace_t *)((caddr_t)aceptr + 707185029Spjd aclp->z_ops.ace_size(aceptr)); 708185029Spjd } 709185029Spjd 710185029Spjd *size = (caddr_t)aceptr - (caddr_t)z_acl; 711185029Spjd 712185029Spjd return (0); 713185029Spjd} 714185029Spjd 715185029Spjd/* 716185029Spjd * Copy ZFS ACEs to fixed size ace_t layout 717185029Spjd */ 718185029Spjdstatic void 719185029Spjdzfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr, 720185029Spjd void *datap, int filter) 721185029Spjd{ 722185029Spjd uint64_t who; 723185029Spjd uint32_t access_mask; 724185029Spjd uint16_t iflags, type; 725185029Spjd zfs_ace_hdr_t *zacep = NULL; 726185029Spjd ace_t *acep = datap; 727185029Spjd ace_object_t *objacep; 728185029Spjd zfs_object_ace_t *zobjacep; 729185029Spjd size_t ace_size; 730185029Spjd uint16_t entry_type; 731185029Spjd 732185029Spjd while (zacep = zfs_acl_next_ace(aclp, zacep, 733185029Spjd &who, &access_mask, &iflags, &type)) { 734185029Spjd 735185029Spjd switch (type) { 736185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 737185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 738185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 739185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 740185029Spjd if (filter) { 741185029Spjd continue; 742185029Spjd } 743185029Spjd zobjacep = (zfs_object_ace_t *)zacep; 744185029Spjd objacep = (ace_object_t *)acep; 745185029Spjd bcopy(zobjacep->z_object_type, 746185029Spjd objacep->a_obj_type, 747185029Spjd sizeof (zobjacep->z_object_type)); 748185029Spjd bcopy(zobjacep->z_inherit_type, 749185029Spjd objacep->a_inherit_obj_type, 750185029Spjd sizeof (zobjacep->z_inherit_type)); 751185029Spjd ace_size = sizeof (ace_object_t); 752185029Spjd break; 753185029Spjd default: 754185029Spjd ace_size = sizeof (ace_t); 755185029Spjd break; 756185029Spjd } 757185029Spjd 758185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 759185029Spjd if ((entry_type != ACE_OWNER && 760185029Spjd entry_type != OWNING_GROUP && 761185029Spjd entry_type != ACE_EVERYONE)) { 762185029Spjd acep->a_who = zfs_fuid_map_id(zfsvfs, who, 763185029Spjd cr, (entry_type & ACE_IDENTIFIER_GROUP) ? 764185029Spjd ZFS_ACE_GROUP : ZFS_ACE_USER); 765185029Spjd } else { 766185029Spjd acep->a_who = (uid_t)(int64_t)who; 767185029Spjd } 768185029Spjd acep->a_access_mask = access_mask; 769185029Spjd acep->a_flags = iflags; 770185029Spjd acep->a_type = type; 771185029Spjd acep = (ace_t *)((caddr_t)acep + ace_size); 772185029Spjd } 773185029Spjd} 774185029Spjd 775185029Spjdstatic int 776185029Spjdzfs_copy_ace_2_oldace(vtype_t obj_type, zfs_acl_t *aclp, ace_t *acep, 777185029Spjd zfs_oldace_t *z_acl, int aclcnt, size_t *size) 778185029Spjd{ 779185029Spjd int i; 780185029Spjd zfs_oldace_t *aceptr = z_acl; 781185029Spjd 782185029Spjd for (i = 0; i != aclcnt; i++, aceptr++) { 783185029Spjd aceptr->z_access_mask = acep[i].a_access_mask; 784185029Spjd aceptr->z_type = acep[i].a_type; 785185029Spjd aceptr->z_flags = acep[i].a_flags; 786185029Spjd aceptr->z_fuid = acep[i].a_who; 787185029Spjd /* 788185029Spjd * Make sure ACE is valid 789185029Spjd */ 790185029Spjd if (zfs_ace_valid(obj_type, aclp, aceptr->z_type, 791185029Spjd aceptr->z_flags) != B_TRUE) 792249643Smm return (SET_ERROR(EINVAL)); 793185029Spjd } 794185029Spjd *size = (caddr_t)aceptr - (caddr_t)z_acl; 795185029Spjd return (0); 796185029Spjd} 797185029Spjd 798185029Spjd/* 799185029Spjd * convert old ACL format to new 800185029Spjd */ 801185029Spjdvoid 802209962Smmzfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr) 803185029Spjd{ 804185029Spjd zfs_oldace_t *oldaclp; 805185029Spjd int i; 806185029Spjd uint16_t type, iflags; 807185029Spjd uint32_t access_mask; 808185029Spjd uint64_t who; 809185029Spjd void *cookie = NULL; 810185029Spjd zfs_acl_node_t *newaclnode; 811185029Spjd 812185029Spjd ASSERT(aclp->z_version == ZFS_ACL_VERSION_INITIAL); 813185029Spjd /* 814185029Spjd * First create the ACE in a contiguous piece of memory 815185029Spjd * for zfs_copy_ace_2_fuid(). 816185029Spjd * 817185029Spjd * We only convert an ACL once, so this won't happen 818185029Spjd * everytime. 819185029Spjd */ 820185029Spjd oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count, 821185029Spjd KM_SLEEP); 822185029Spjd i = 0; 823185029Spjd while (cookie = zfs_acl_next_ace(aclp, cookie, &who, 824185029Spjd &access_mask, &iflags, &type)) { 825185029Spjd oldaclp[i].z_flags = iflags; 826185029Spjd oldaclp[i].z_type = type; 827185029Spjd oldaclp[i].z_fuid = who; 828185029Spjd oldaclp[i++].z_access_mask = access_mask; 829185029Spjd } 830185029Spjd 831185029Spjd newaclnode = zfs_acl_node_alloc(aclp->z_acl_count * 832185029Spjd sizeof (zfs_object_ace_t)); 833185029Spjd aclp->z_ops = zfs_acl_fuid_ops; 834209962Smm VERIFY(zfs_copy_ace_2_fuid(zp->z_zfsvfs, ZTOV(zp)->v_type, aclp, 835209962Smm oldaclp, newaclnode->z_acldata, aclp->z_acl_count, 836209962Smm &newaclnode->z_size, NULL, cr) == 0); 837185029Spjd newaclnode->z_ace_count = aclp->z_acl_count; 838185029Spjd aclp->z_version = ZFS_ACL_VERSION; 839185029Spjd kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t)); 840185029Spjd 841185029Spjd /* 842185029Spjd * Release all previous ACL nodes 843185029Spjd */ 844185029Spjd 845185029Spjd zfs_acl_release_nodes(aclp); 846185029Spjd 847185029Spjd list_insert_head(&aclp->z_acl, newaclnode); 848185029Spjd 849185029Spjd aclp->z_acl_bytes = newaclnode->z_size; 850185029Spjd aclp->z_acl_count = newaclnode->z_ace_count; 851185029Spjd 852185029Spjd} 853185029Spjd 854185029Spjd/* 855168404Spjd * Convert unix access mask to v4 access mask 856168404Spjd */ 857168404Spjdstatic uint32_t 858168404Spjdzfs_unix_to_v4(uint32_t access_mask) 859168404Spjd{ 860168404Spjd uint32_t new_mask = 0; 861168404Spjd 862185029Spjd if (access_mask & S_IXOTH) 863185029Spjd new_mask |= ACE_EXECUTE; 864185029Spjd if (access_mask & S_IWOTH) 865185029Spjd new_mask |= ACE_WRITE_DATA; 866185029Spjd if (access_mask & S_IROTH) 867168404Spjd new_mask |= ACE_READ_DATA; 868168404Spjd return (new_mask); 869168404Spjd} 870168404Spjd 871168404Spjdstatic void 872185029Spjdzfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask, 873185029Spjd uint16_t access_type, uint64_t fuid, uint16_t entry_type) 874168404Spjd{ 875185029Spjd uint16_t type = entry_type & ACE_TYPE_FLAGS; 876185029Spjd 877185029Spjd aclp->z_ops.ace_mask_set(acep, access_mask); 878185029Spjd aclp->z_ops.ace_type_set(acep, access_type); 879185029Spjd aclp->z_ops.ace_flags_set(acep, entry_type); 880185029Spjd if ((type != ACE_OWNER && type != OWNING_GROUP && 881185029Spjd type != ACE_EVERYONE)) 882185029Spjd aclp->z_ops.ace_who_set(acep, fuid); 883168404Spjd} 884168404Spjd 885185029Spjd/* 886185029Spjd * Determine mode of file based on ACL. 887185029Spjd * Also, create FUIDs for any User/Group ACEs 888185029Spjd */ 889219089Spjduint64_t 890219089Spjdzfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, 891219089Spjd uint64_t *pflags, uint64_t fuid, uint64_t fgid) 892168404Spjd{ 893185029Spjd int entry_type; 894185029Spjd mode_t mode; 895185029Spjd mode_t seen = 0; 896185029Spjd zfs_ace_hdr_t *acep = NULL; 897185029Spjd uint64_t who; 898185029Spjd uint16_t iflags, type; 899185029Spjd uint32_t access_mask; 900211932Smm boolean_t an_exec_denied = B_FALSE; 901168404Spjd 902219089Spjd mode = (fmode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 903185029Spjd 904185029Spjd while (acep = zfs_acl_next_ace(aclp, acep, &who, 905185029Spjd &access_mask, &iflags, &type)) { 906185029Spjd 907185029Spjd if (!zfs_acl_valid_ace_type(type, iflags)) 908185029Spjd continue; 909185029Spjd 910185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 911185029Spjd 912185029Spjd /* 913185029Spjd * Skip over owner@, group@ or everyone@ inherit only ACEs 914185029Spjd */ 915185029Spjd if ((iflags & ACE_INHERIT_ONLY_ACE) && 916185029Spjd (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 917185029Spjd entry_type == OWNING_GROUP)) 918185029Spjd continue; 919185029Spjd 920219089Spjd if (entry_type == ACE_OWNER || (entry_type == 0 && 921219089Spjd who == fuid)) { 922185029Spjd if ((access_mask & ACE_READ_DATA) && 923168404Spjd (!(seen & S_IRUSR))) { 924168404Spjd seen |= S_IRUSR; 925185029Spjd if (type == ALLOW) { 926168404Spjd mode |= S_IRUSR; 927168404Spjd } 928168404Spjd } 929185029Spjd if ((access_mask & ACE_WRITE_DATA) && 930168404Spjd (!(seen & S_IWUSR))) { 931168404Spjd seen |= S_IWUSR; 932185029Spjd if (type == ALLOW) { 933168404Spjd mode |= S_IWUSR; 934168404Spjd } 935168404Spjd } 936185029Spjd if ((access_mask & ACE_EXECUTE) && 937168404Spjd (!(seen & S_IXUSR))) { 938168404Spjd seen |= S_IXUSR; 939185029Spjd if (type == ALLOW) { 940168404Spjd mode |= S_IXUSR; 941168404Spjd } 942168404Spjd } 943219089Spjd } else if (entry_type == OWNING_GROUP || 944219089Spjd (entry_type == ACE_IDENTIFIER_GROUP && who == fgid)) { 945185029Spjd if ((access_mask & ACE_READ_DATA) && 946168404Spjd (!(seen & S_IRGRP))) { 947168404Spjd seen |= S_IRGRP; 948185029Spjd if (type == ALLOW) { 949168404Spjd mode |= S_IRGRP; 950168404Spjd } 951168404Spjd } 952185029Spjd if ((access_mask & ACE_WRITE_DATA) && 953168404Spjd (!(seen & S_IWGRP))) { 954168404Spjd seen |= S_IWGRP; 955185029Spjd if (type == ALLOW) { 956168404Spjd mode |= S_IWGRP; 957168404Spjd } 958168404Spjd } 959185029Spjd if ((access_mask & ACE_EXECUTE) && 960168404Spjd (!(seen & S_IXGRP))) { 961168404Spjd seen |= S_IXGRP; 962185029Spjd if (type == ALLOW) { 963168404Spjd mode |= S_IXGRP; 964168404Spjd } 965168404Spjd } 966168404Spjd } else if (entry_type == ACE_EVERYONE) { 967185029Spjd if ((access_mask & ACE_READ_DATA)) { 968168404Spjd if (!(seen & S_IRUSR)) { 969168404Spjd seen |= S_IRUSR; 970185029Spjd if (type == ALLOW) { 971168404Spjd mode |= S_IRUSR; 972168404Spjd } 973168404Spjd } 974168404Spjd if (!(seen & S_IRGRP)) { 975168404Spjd seen |= S_IRGRP; 976185029Spjd if (type == ALLOW) { 977168404Spjd mode |= S_IRGRP; 978168404Spjd } 979168404Spjd } 980168404Spjd if (!(seen & S_IROTH)) { 981168404Spjd seen |= S_IROTH; 982185029Spjd if (type == ALLOW) { 983168404Spjd mode |= S_IROTH; 984168404Spjd } 985168404Spjd } 986168404Spjd } 987185029Spjd if ((access_mask & ACE_WRITE_DATA)) { 988168404Spjd if (!(seen & S_IWUSR)) { 989168404Spjd seen |= S_IWUSR; 990185029Spjd if (type == ALLOW) { 991168404Spjd mode |= S_IWUSR; 992168404Spjd } 993168404Spjd } 994168404Spjd if (!(seen & S_IWGRP)) { 995168404Spjd seen |= S_IWGRP; 996185029Spjd if (type == ALLOW) { 997168404Spjd mode |= S_IWGRP; 998168404Spjd } 999168404Spjd } 1000168404Spjd if (!(seen & S_IWOTH)) { 1001168404Spjd seen |= S_IWOTH; 1002185029Spjd if (type == ALLOW) { 1003168404Spjd mode |= S_IWOTH; 1004168404Spjd } 1005168404Spjd } 1006168404Spjd } 1007185029Spjd if ((access_mask & ACE_EXECUTE)) { 1008168404Spjd if (!(seen & S_IXUSR)) { 1009168404Spjd seen |= S_IXUSR; 1010185029Spjd if (type == ALLOW) { 1011168404Spjd mode |= S_IXUSR; 1012168404Spjd } 1013168404Spjd } 1014168404Spjd if (!(seen & S_IXGRP)) { 1015168404Spjd seen |= S_IXGRP; 1016185029Spjd if (type == ALLOW) { 1017168404Spjd mode |= S_IXGRP; 1018168404Spjd } 1019168404Spjd } 1020168404Spjd if (!(seen & S_IXOTH)) { 1021168404Spjd seen |= S_IXOTH; 1022185029Spjd if (type == ALLOW) { 1023168404Spjd mode |= S_IXOTH; 1024168404Spjd } 1025168404Spjd } 1026168404Spjd } 1027211932Smm } else { 1028211932Smm /* 1029211932Smm * Only care if this IDENTIFIER_GROUP or 1030211932Smm * USER ACE denies execute access to someone, 1031211932Smm * mode is not affected 1032211932Smm */ 1033211932Smm if ((access_mask & ACE_EXECUTE) && type == DENY) 1034211932Smm an_exec_denied = B_TRUE; 1035168404Spjd } 1036168404Spjd } 1037211932Smm 1038211932Smm /* 1039211932Smm * Failure to allow is effectively a deny, so execute permission 1040211932Smm * is denied if it was never mentioned or if we explicitly 1041211932Smm * weren't allowed it. 1042211932Smm */ 1043211932Smm if (!an_exec_denied && 1044211932Smm ((seen & ALL_MODE_EXECS) != ALL_MODE_EXECS || 1045211932Smm (mode & ALL_MODE_EXECS) != ALL_MODE_EXECS)) 1046211932Smm an_exec_denied = B_TRUE; 1047211932Smm 1048211932Smm if (an_exec_denied) 1049219089Spjd *pflags &= ~ZFS_NO_EXECS_DENIED; 1050211932Smm else 1051219089Spjd *pflags |= ZFS_NO_EXECS_DENIED; 1052211932Smm 1053168404Spjd return (mode); 1054168404Spjd} 1055168404Spjd 1056168404Spjd/* 1057211932Smm * Read an external acl object. If the intent is to modify, always 1058211932Smm * create a new acl and leave any cached acl in place. 1059168404Spjd */ 1060168404Spjdstatic int 1061219089Spjdzfs_acl_node_read(znode_t *zp, boolean_t have_lock, zfs_acl_t **aclpp, 1062219089Spjd boolean_t will_modify) 1063168404Spjd{ 1064168404Spjd zfs_acl_t *aclp; 1065219089Spjd int aclsize; 1066219089Spjd int acl_count; 1067185029Spjd zfs_acl_node_t *aclnode; 1068219089Spjd zfs_acl_phys_t znode_acl; 1069219089Spjd int version; 1070219089Spjd int error; 1071219089Spjd boolean_t drop_lock = B_FALSE; 1072168404Spjd 1073168404Spjd ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1074168404Spjd 1075211932Smm if (zp->z_acl_cached && !will_modify) { 1076211932Smm *aclpp = zp->z_acl_cached; 1077211932Smm return (0); 1078211932Smm } 1079211932Smm 1080219089Spjd /* 1081219089Spjd * close race where znode could be upgrade while trying to 1082219089Spjd * read the znode attributes. 1083219089Spjd * 1084219089Spjd * But this could only happen if the file isn't already an SA 1085219089Spjd * znode 1086219089Spjd */ 1087219089Spjd if (!zp->z_is_sa && !have_lock) { 1088219089Spjd mutex_enter(&zp->z_lock); 1089219089Spjd drop_lock = B_TRUE; 1090168404Spjd } 1091219089Spjd version = zfs_znode_acl_version(zp); 1092168404Spjd 1093219089Spjd if ((error = zfs_acl_znode_info(zp, &aclsize, 1094219089Spjd &acl_count, &znode_acl)) != 0) { 1095219089Spjd goto done; 1096219089Spjd } 1097168404Spjd 1098219089Spjd aclp = zfs_acl_alloc(version); 1099219089Spjd 1100185029Spjd aclp->z_acl_count = acl_count; 1101185029Spjd aclp->z_acl_bytes = aclsize; 1102185029Spjd 1103219089Spjd aclnode = zfs_acl_node_alloc(aclsize); 1104219089Spjd aclnode->z_ace_count = aclp->z_acl_count; 1105219089Spjd aclnode->z_size = aclsize; 1106219089Spjd 1107219089Spjd if (!zp->z_is_sa) { 1108219089Spjd if (znode_acl.z_acl_extern_obj) { 1109219089Spjd error = dmu_read(zp->z_zfsvfs->z_os, 1110219089Spjd znode_acl.z_acl_extern_obj, 0, aclnode->z_size, 1111219089Spjd aclnode->z_acldata, DMU_READ_PREFETCH); 1112219089Spjd } else { 1113219089Spjd bcopy(znode_acl.z_ace_data, aclnode->z_acldata, 1114219089Spjd aclnode->z_size); 1115219089Spjd } 1116219089Spjd } else { 1117219089Spjd error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zp->z_zfsvfs), 1118219089Spjd aclnode->z_acldata, aclnode->z_size); 1119219089Spjd } 1120219089Spjd 1121168404Spjd if (error != 0) { 1122168404Spjd zfs_acl_free(aclp); 1123219089Spjd zfs_acl_node_free(aclnode); 1124185029Spjd /* convert checksum errors into IO errors */ 1125185029Spjd if (error == ECKSUM) 1126249643Smm error = SET_ERROR(EIO); 1127219089Spjd goto done; 1128168404Spjd } 1129168404Spjd 1130219089Spjd list_insert_head(&aclp->z_acl, aclnode); 1131219089Spjd 1132168404Spjd *aclpp = aclp; 1133211932Smm if (!will_modify) 1134211932Smm zp->z_acl_cached = aclp; 1135219089Spjddone: 1136219089Spjd if (drop_lock) 1137219089Spjd mutex_exit(&zp->z_lock); 1138219089Spjd return (error); 1139168404Spjd} 1140168404Spjd 1141219089Spjd/*ARGSUSED*/ 1142219089Spjdvoid 1143219089Spjdzfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen, 1144219089Spjd boolean_t start, void *userdata) 1145219089Spjd{ 1146219089Spjd zfs_acl_locator_cb_t *cb = (zfs_acl_locator_cb_t *)userdata; 1147219089Spjd 1148219089Spjd if (start) { 1149219089Spjd cb->cb_acl_node = list_head(&cb->cb_aclp->z_acl); 1150219089Spjd } else { 1151219089Spjd cb->cb_acl_node = list_next(&cb->cb_aclp->z_acl, 1152219089Spjd cb->cb_acl_node); 1153219089Spjd } 1154219089Spjd *dataptr = cb->cb_acl_node->z_acldata; 1155219089Spjd *length = cb->cb_acl_node->z_size; 1156219089Spjd} 1157219089Spjd 1158219089Spjdint 1159219089Spjdzfs_acl_chown_setattr(znode_t *zp) 1160219089Spjd{ 1161219089Spjd int error; 1162219089Spjd zfs_acl_t *aclp; 1163219089Spjd 1164219089Spjd ASSERT(MUTEX_HELD(&zp->z_lock)); 1165219089Spjd ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1166219089Spjd 1167219089Spjd if ((error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE)) == 0) 1168219089Spjd zp->z_mode = zfs_mode_compute(zp->z_mode, aclp, 1169219089Spjd &zp->z_pflags, zp->z_uid, zp->z_gid); 1170219089Spjd return (error); 1171219089Spjd} 1172219089Spjd 1173168404Spjd/* 1174185029Spjd * common code for setting ACLs. 1175168404Spjd * 1176168404Spjd * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 1177168404Spjd * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 1178168404Spjd * already checked the acl and knows whether to inherit. 1179168404Spjd */ 1180168404Spjdint 1181209962Smmzfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx) 1182168404Spjd{ 1183219089Spjd int error; 1184219089Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1185219089Spjd dmu_object_type_t otype; 1186219089Spjd zfs_acl_locator_cb_t locate = { 0 }; 1187219089Spjd uint64_t mode; 1188219089Spjd sa_bulk_attr_t bulk[5]; 1189219089Spjd uint64_t ctime[2]; 1190219089Spjd int count = 0; 1191168404Spjd 1192219089Spjd mode = zp->z_mode; 1193168404Spjd 1194219089Spjd mode = zfs_mode_compute(mode, aclp, &zp->z_pflags, 1195219089Spjd zp->z_uid, zp->z_gid); 1196219089Spjd 1197219089Spjd zp->z_mode = mode; 1198219089Spjd SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, 1199219089Spjd &mode, sizeof (mode)); 1200219089Spjd SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 1201219089Spjd &zp->z_pflags, sizeof (zp->z_pflags)); 1202219089Spjd SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, 1203219089Spjd &ctime, sizeof (ctime)); 1204219089Spjd 1205211932Smm if (zp->z_acl_cached) { 1206211932Smm zfs_acl_free(zp->z_acl_cached); 1207211932Smm zp->z_acl_cached = NULL; 1208211932Smm } 1209211932Smm 1210168404Spjd /* 1211219089Spjd * Upgrade needed? 1212168404Spjd */ 1213185029Spjd if (!zfsvfs->z_use_fuids) { 1214185029Spjd otype = DMU_OT_OLDACL; 1215185029Spjd } else { 1216185029Spjd if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) && 1217185029Spjd (zfsvfs->z_version >= ZPL_VERSION_FUID)) 1218209962Smm zfs_acl_xform(zp, aclp, cr); 1219185029Spjd ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID); 1220185029Spjd otype = DMU_OT_ACL; 1221185029Spjd } 1222185029Spjd 1223219089Spjd /* 1224219089Spjd * Arrgh, we have to handle old on disk format 1225219089Spjd * as well as newer (preferred) SA format. 1226219089Spjd */ 1227219089Spjd 1228219089Spjd if (zp->z_is_sa) { /* the easy case, just update the ACL attribute */ 1229219089Spjd locate.cb_aclp = aclp; 1230219089Spjd SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_ACES(zfsvfs), 1231219089Spjd zfs_acl_data_locator, &locate, aclp->z_acl_bytes); 1232219089Spjd SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_COUNT(zfsvfs), 1233219089Spjd NULL, &aclp->z_acl_count, sizeof (uint64_t)); 1234219089Spjd } else { /* Painful legacy way */ 1235219089Spjd zfs_acl_node_t *aclnode; 1236219089Spjd uint64_t off = 0; 1237219089Spjd zfs_acl_phys_t acl_phys; 1238219089Spjd uint64_t aoid; 1239219089Spjd 1240219089Spjd if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), 1241219089Spjd &acl_phys, sizeof (acl_phys))) != 0) 1242219089Spjd return (error); 1243219089Spjd 1244219089Spjd aoid = acl_phys.z_acl_extern_obj; 1245219089Spjd 1246219089Spjd if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 1247219089Spjd /* 1248219089Spjd * If ACL was previously external and we are now 1249219089Spjd * converting to new ACL format then release old 1250219089Spjd * ACL object and create a new one. 1251219089Spjd */ 1252219089Spjd if (aoid && 1253219089Spjd aclp->z_version != acl_phys.z_acl_version) { 1254219089Spjd error = dmu_object_free(zfsvfs->z_os, aoid, tx); 1255219089Spjd if (error) 1256219089Spjd return (error); 1257219089Spjd aoid = 0; 1258219089Spjd } 1259219089Spjd if (aoid == 0) { 1260219089Spjd aoid = dmu_object_alloc(zfsvfs->z_os, 1261219089Spjd otype, aclp->z_acl_bytes, 1262219089Spjd otype == DMU_OT_ACL ? 1263219089Spjd DMU_OT_SYSACL : DMU_OT_NONE, 1264219089Spjd otype == DMU_OT_ACL ? 1265219089Spjd DN_MAX_BONUSLEN : 0, tx); 1266219089Spjd } else { 1267219089Spjd (void) dmu_object_set_blocksize(zfsvfs->z_os, 1268219089Spjd aoid, aclp->z_acl_bytes, 0, tx); 1269219089Spjd } 1270219089Spjd acl_phys.z_acl_extern_obj = aoid; 1271219089Spjd for (aclnode = list_head(&aclp->z_acl); aclnode; 1272219089Spjd aclnode = list_next(&aclp->z_acl, aclnode)) { 1273219089Spjd if (aclnode->z_ace_count == 0) 1274219089Spjd continue; 1275219089Spjd dmu_write(zfsvfs->z_os, aoid, off, 1276219089Spjd aclnode->z_size, aclnode->z_acldata, tx); 1277219089Spjd off += aclnode->z_size; 1278219089Spjd } 1279168404Spjd } else { 1280219089Spjd void *start = acl_phys.z_ace_data; 1281219089Spjd /* 1282219089Spjd * Migrating back embedded? 1283219089Spjd */ 1284219089Spjd if (acl_phys.z_acl_extern_obj) { 1285219089Spjd error = dmu_object_free(zfsvfs->z_os, 1286219089Spjd acl_phys.z_acl_extern_obj, tx); 1287219089Spjd if (error) 1288219089Spjd return (error); 1289219089Spjd acl_phys.z_acl_extern_obj = 0; 1290219089Spjd } 1291219089Spjd 1292219089Spjd for (aclnode = list_head(&aclp->z_acl); aclnode; 1293219089Spjd aclnode = list_next(&aclp->z_acl, aclnode)) { 1294219089Spjd if (aclnode->z_ace_count == 0) 1295219089Spjd continue; 1296219089Spjd bcopy(aclnode->z_acldata, start, 1297219089Spjd aclnode->z_size); 1298219089Spjd start = (caddr_t)start + aclnode->z_size; 1299219089Spjd } 1300168404Spjd } 1301168404Spjd /* 1302219089Spjd * If Old version then swap count/bytes to match old 1303219089Spjd * layout of znode_acl_phys_t. 1304168404Spjd */ 1305219089Spjd if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 1306219089Spjd acl_phys.z_acl_size = aclp->z_acl_count; 1307219089Spjd acl_phys.z_acl_count = aclp->z_acl_bytes; 1308219089Spjd } else { 1309219089Spjd acl_phys.z_acl_size = aclp->z_acl_bytes; 1310219089Spjd acl_phys.z_acl_count = aclp->z_acl_count; 1311168404Spjd } 1312219089Spjd acl_phys.z_acl_version = aclp->z_version; 1313185029Spjd 1314219089Spjd SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL, 1315219089Spjd &acl_phys, sizeof (acl_phys)); 1316168404Spjd } 1317168404Spjd 1318185029Spjd /* 1319185029Spjd * Replace ACL wide bits, but first clear them. 1320185029Spjd */ 1321219089Spjd zp->z_pflags &= ~ZFS_ACL_WIDE_FLAGS; 1322168404Spjd 1323219089Spjd zp->z_pflags |= aclp->z_hints; 1324168404Spjd 1325185029Spjd if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0) 1326219089Spjd zp->z_pflags |= ZFS_ACL_TRIVIAL; 1327168404Spjd 1328219089Spjd zfs_tstamp_update_setup(zp, STATE_CHANGED, NULL, ctime, B_TRUE); 1329219089Spjd return (sa_bulk_update(zp->z_sa_hdl, bulk, count, tx)); 1330168404Spjd} 1331168404Spjd 1332168404Spjdstatic void 1333224174Smmzfs_acl_chmod(vtype_t vtype, uint64_t mode, boolean_t trim, zfs_acl_t *aclp) 1334168404Spjd{ 1335219089Spjd void *acep = NULL; 1336219089Spjd uint64_t who; 1337219089Spjd int new_count, new_bytes; 1338219089Spjd int ace_size; 1339219089Spjd int entry_type; 1340219089Spjd uint16_t iflags, type; 1341219089Spjd uint32_t access_mask; 1342219089Spjd zfs_acl_node_t *newnode; 1343219089Spjd size_t abstract_size = aclp->z_ops.ace_abstract_size(); 1344219089Spjd void *zacep; 1345224174Smm boolean_t isdir; 1346224174Smm trivial_acl_t masks; 1347168404Spjd 1348219089Spjd new_count = new_bytes = 0; 1349168404Spjd 1350224174Smm isdir = (vtype == VDIR); 1351185029Spjd 1352224174Smm acl_trivial_access_masks((mode_t)mode, isdir, &masks); 1353224174Smm 1354219089Spjd newnode = zfs_acl_node_alloc((abstract_size * 6) + aclp->z_acl_bytes); 1355168404Spjd 1356219089Spjd zacep = newnode->z_acldata; 1357224174Smm if (masks.allow0) { 1358224174Smm zfs_set_ace(aclp, zacep, masks.allow0, ALLOW, -1, ACE_OWNER); 1359219089Spjd zacep = (void *)((uintptr_t)zacep + abstract_size); 1360219089Spjd new_count++; 1361219089Spjd new_bytes += abstract_size; 1362252751Sdelphij } 1363252751Sdelphij if (masks.deny1) { 1364224174Smm zfs_set_ace(aclp, zacep, masks.deny1, DENY, -1, ACE_OWNER); 1365219089Spjd zacep = (void *)((uintptr_t)zacep + abstract_size); 1366219089Spjd new_count++; 1367219089Spjd new_bytes += abstract_size; 1368168404Spjd } 1369224174Smm if (masks.deny2) { 1370224174Smm zfs_set_ace(aclp, zacep, masks.deny2, DENY, -1, OWNING_GROUP); 1371219089Spjd zacep = (void *)((uintptr_t)zacep + abstract_size); 1372219089Spjd new_count++; 1373219089Spjd new_bytes += abstract_size; 1374168404Spjd } 1375168404Spjd 1376185029Spjd while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 1377185029Spjd &iflags, &type)) { 1378219089Spjd uint16_t inherit_flags; 1379185029Spjd 1380185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 1381219089Spjd inherit_flags = (iflags & ALL_INHERIT); 1382185029Spjd 1383219089Spjd if ((entry_type == ACE_OWNER || entry_type == ACE_EVERYONE || 1384219089Spjd (entry_type == OWNING_GROUP)) && 1385219089Spjd ((inherit_flags & ACE_INHERIT_ONLY_ACE) == 0)) { 1386219089Spjd continue; 1387219089Spjd } 1388219089Spjd 1389224174Smm /* 1390224174Smm * If this ACL has any inheritable ACEs, mark that in 1391224174Smm * the hints (which are later masked into the pflags) 1392224174Smm * so create knows to do inheritance. 1393224174Smm */ 1394224174Smm if (isdir && (inherit_flags & 1395224174Smm (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 1396224174Smm aclp->z_hints |= ZFS_INHERIT_ACE; 1397224174Smm 1398185029Spjd if ((type != ALLOW && type != DENY) || 1399219089Spjd (inherit_flags & ACE_INHERIT_ONLY_ACE)) { 1400185029Spjd switch (type) { 1401185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1402185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1403185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1404185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1405185029Spjd aclp->z_hints |= ZFS_ACL_OBJ_ACE; 1406185029Spjd break; 1407185029Spjd } 1408168404Spjd } else { 1409168404Spjd 1410219089Spjd /* 1411219089Spjd * Limit permissions to be no greater than 1412224174Smm * group permissions. 1413224174Smm * The "aclinherit" and "aclmode" properties 1414224174Smm * affect policy for create and chmod(2), 1415224174Smm * respectively. 1416219089Spjd */ 1417224174Smm if ((type == ALLOW) && trim) 1418224174Smm access_mask &= masks.group; 1419168404Spjd } 1420219089Spjd zfs_set_ace(aclp, zacep, access_mask, type, who, iflags); 1421219089Spjd ace_size = aclp->z_ops.ace_size(acep); 1422219089Spjd zacep = (void *)((uintptr_t)zacep + ace_size); 1423219089Spjd new_count++; 1424219089Spjd new_bytes += ace_size; 1425168404Spjd } 1426224174Smm zfs_set_ace(aclp, zacep, masks.owner, 0, -1, ACE_OWNER); 1427219089Spjd zacep = (void *)((uintptr_t)zacep + abstract_size); 1428224174Smm zfs_set_ace(aclp, zacep, masks.group, 0, -1, OWNING_GROUP); 1429219089Spjd zacep = (void *)((uintptr_t)zacep + abstract_size); 1430224174Smm zfs_set_ace(aclp, zacep, masks.everyone, 0, -1, ACE_EVERYONE); 1431168404Spjd 1432219089Spjd new_count += 3; 1433219089Spjd new_bytes += abstract_size * 3; 1434219089Spjd zfs_acl_release_nodes(aclp); 1435219089Spjd aclp->z_acl_count = new_count; 1436219089Spjd aclp->z_acl_bytes = new_bytes; 1437219089Spjd newnode->z_ace_count = new_count; 1438219089Spjd newnode->z_size = new_bytes; 1439219089Spjd list_insert_tail(&aclp->z_acl, newnode); 1440168404Spjd} 1441168404Spjd 1442224174Smmint 1443185029Spjdzfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) 1444168404Spjd{ 1445224174Smm int error = 0; 1446224174Smm 1447219089Spjd mutex_enter(&zp->z_acl_lock); 1448185029Spjd mutex_enter(&zp->z_lock); 1449224174Smm if (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) 1450224174Smm *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); 1451224174Smm else 1452224174Smm error = zfs_acl_node_read(zp, B_TRUE, aclp, B_TRUE); 1453224174Smm 1454224174Smm if (error == 0) { 1455224174Smm (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS; 1456224174Smm zfs_acl_chmod(ZTOV(zp)->v_type, mode, 1457224174Smm (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK), *aclp); 1458224174Smm } 1459219089Spjd mutex_exit(&zp->z_lock); 1460168404Spjd mutex_exit(&zp->z_acl_lock); 1461224174Smm 1462224174Smm return (error); 1463168404Spjd} 1464168404Spjd 1465168404Spjd/* 1466168404Spjd * strip off write_owner and write_acl 1467168404Spjd */ 1468168404Spjdstatic void 1469185029Spjdzfs_restricted_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep) 1470168404Spjd{ 1471185029Spjd uint32_t mask = aclp->z_ops.ace_mask_get(acep); 1472185029Spjd 1473185029Spjd if ((zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) && 1474185029Spjd (aclp->z_ops.ace_type_get(acep) == ALLOW)) { 1475185029Spjd mask &= ~RESTRICTED_CLEAR; 1476185029Spjd aclp->z_ops.ace_mask_set(acep, mask); 1477185029Spjd } 1478168404Spjd} 1479168404Spjd 1480168404Spjd/* 1481185029Spjd * Should ACE be inherited? 1482185029Spjd */ 1483185029Spjdstatic int 1484209962Smmzfs_ace_can_use(vtype_t vtype, uint16_t acep_flags) 1485185029Spjd{ 1486185029Spjd int iflags = (acep_flags & 0xf); 1487185029Spjd 1488185029Spjd if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1489185029Spjd return (1); 1490185029Spjd else if (iflags & ACE_FILE_INHERIT_ACE) 1491185029Spjd return (!((vtype == VDIR) && 1492185029Spjd (iflags & ACE_NO_PROPAGATE_INHERIT_ACE))); 1493185029Spjd return (0); 1494185029Spjd} 1495185029Spjd 1496185029Spjd/* 1497168404Spjd * inherit inheritable ACEs from parent 1498168404Spjd */ 1499168404Spjdstatic zfs_acl_t * 1500209962Smmzfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp, 1501209962Smm uint64_t mode, boolean_t *need_chmod) 1502168404Spjd{ 1503185029Spjd void *pacep; 1504219089Spjd void *acep; 1505219089Spjd zfs_acl_node_t *aclnode; 1506168404Spjd zfs_acl_t *aclp = NULL; 1507185029Spjd uint64_t who; 1508185029Spjd uint32_t access_mask; 1509185029Spjd uint16_t iflags, newflags, type; 1510185029Spjd size_t ace_size; 1511185029Spjd void *data1, *data2; 1512185029Spjd size_t data1sz, data2sz; 1513209962Smm boolean_t vdir = vtype == VDIR; 1514209962Smm boolean_t vreg = vtype == VREG; 1515201143Sdelphij boolean_t passthrough, passthrough_x, noallow; 1516168404Spjd 1517201143Sdelphij passthrough_x = 1518201143Sdelphij zfsvfs->z_acl_inherit == ZFS_ACL_PASSTHROUGH_X; 1519201143Sdelphij passthrough = passthrough_x || 1520201143Sdelphij zfsvfs->z_acl_inherit == ZFS_ACL_PASSTHROUGH; 1521201143Sdelphij noallow = 1522201143Sdelphij zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW; 1523201143Sdelphij 1524185029Spjd *need_chmod = B_TRUE; 1525185029Spjd pacep = NULL; 1526185029Spjd aclp = zfs_acl_alloc(paclp->z_version); 1527219089Spjd if (zfsvfs->z_acl_inherit == ZFS_ACL_DISCARD || vtype == VLNK) 1528201143Sdelphij return (aclp); 1529201143Sdelphij while (pacep = zfs_acl_next_ace(paclp, pacep, &who, 1530201143Sdelphij &access_mask, &iflags, &type)) { 1531168404Spjd 1532201143Sdelphij /* 1533201143Sdelphij * don't inherit bogus ACEs 1534201143Sdelphij */ 1535201143Sdelphij if (!zfs_acl_valid_ace_type(type, iflags)) 1536201143Sdelphij continue; 1537185029Spjd 1538201143Sdelphij if (noallow && type == ALLOW) 1539201143Sdelphij continue; 1540168404Spjd 1541201143Sdelphij ace_size = aclp->z_ops.ace_size(pacep); 1542168404Spjd 1543209962Smm if (!zfs_ace_can_use(vtype, iflags)) 1544201143Sdelphij continue; 1545168404Spjd 1546201143Sdelphij /* 1547201143Sdelphij * If owner@, group@, or everyone@ inheritable 1548201143Sdelphij * then zfs_acl_chmod() isn't needed. 1549201143Sdelphij */ 1550201143Sdelphij if (passthrough && 1551201143Sdelphij ((iflags & (ACE_OWNER|ACE_EVERYONE)) || 1552201143Sdelphij ((iflags & OWNING_GROUP) == 1553201143Sdelphij OWNING_GROUP)) && (vreg || (vdir && (iflags & 1554201143Sdelphij ACE_DIRECTORY_INHERIT_ACE)))) { 1555201143Sdelphij *need_chmod = B_FALSE; 1556219089Spjd } 1557168404Spjd 1558219089Spjd if (!vdir && passthrough_x && 1559219089Spjd ((mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)) { 1560219089Spjd access_mask &= ~ACE_EXECUTE; 1561201143Sdelphij } 1562168404Spjd 1563201143Sdelphij aclnode = zfs_acl_node_alloc(ace_size); 1564201143Sdelphij list_insert_tail(&aclp->z_acl, aclnode); 1565201143Sdelphij acep = aclnode->z_acldata; 1566201143Sdelphij 1567201143Sdelphij zfs_set_ace(aclp, acep, access_mask, type, 1568201143Sdelphij who, iflags|ACE_INHERITED_ACE); 1569201143Sdelphij 1570201143Sdelphij /* 1571201143Sdelphij * Copy special opaque data if any 1572201143Sdelphij */ 1573201143Sdelphij if ((data1sz = paclp->z_ops.ace_data(pacep, &data1)) != 0) { 1574201143Sdelphij VERIFY((data2sz = aclp->z_ops.ace_data(acep, 1575201143Sdelphij &data2)) == data1sz); 1576201143Sdelphij bcopy(data1, data2, data2sz); 1577201143Sdelphij } 1578219089Spjd 1579201143Sdelphij aclp->z_acl_count++; 1580201143Sdelphij aclnode->z_ace_count++; 1581201143Sdelphij aclp->z_acl_bytes += aclnode->z_size; 1582201143Sdelphij newflags = aclp->z_ops.ace_flags_get(acep); 1583201143Sdelphij 1584201143Sdelphij if (vdir) 1585201143Sdelphij aclp->z_hints |= ZFS_INHERIT_ACE; 1586201143Sdelphij 1587201143Sdelphij if ((iflags & ACE_NO_PROPAGATE_INHERIT_ACE) || !vdir) { 1588201143Sdelphij newflags &= ~ALL_INHERIT; 1589201143Sdelphij aclp->z_ops.ace_flags_set(acep, 1590201143Sdelphij newflags|ACE_INHERITED_ACE); 1591201143Sdelphij zfs_restricted_update(zfsvfs, aclp, acep); 1592201143Sdelphij continue; 1593201143Sdelphij } 1594201143Sdelphij 1595201143Sdelphij ASSERT(vdir); 1596201143Sdelphij 1597219089Spjd /* 1598219089Spjd * If only FILE_INHERIT is set then turn on 1599219089Spjd * inherit_only 1600219089Spjd */ 1601201143Sdelphij if ((iflags & (ACE_FILE_INHERIT_ACE | 1602219089Spjd ACE_DIRECTORY_INHERIT_ACE)) == ACE_FILE_INHERIT_ACE) { 1603201143Sdelphij newflags |= ACE_INHERIT_ONLY_ACE; 1604219089Spjd aclp->z_ops.ace_flags_set(acep, 1605201143Sdelphij newflags|ACE_INHERITED_ACE); 1606201143Sdelphij } else { 1607219089Spjd newflags &= ~ACE_INHERIT_ONLY_ACE; 1608201143Sdelphij aclp->z_ops.ace_flags_set(acep, 1609201143Sdelphij newflags|ACE_INHERITED_ACE); 1610168404Spjd } 1611168404Spjd } 1612168404Spjd return (aclp); 1613168404Spjd} 1614168404Spjd 1615168404Spjd/* 1616168404Spjd * Create file system object initial permissions 1617168404Spjd * including inheritable ACEs. 1618168404Spjd */ 1619209962Smmint 1620209962Smmzfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, 1621209962Smm vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids) 1622168404Spjd{ 1623185029Spjd int error; 1624209962Smm zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1625185029Spjd zfs_acl_t *paclp; 1626168404Spjd gid_t gid; 1627185029Spjd boolean_t need_chmod = B_TRUE; 1628219089Spjd boolean_t inherited = B_FALSE; 1629168404Spjd 1630209962Smm bzero(acl_ids, sizeof (zfs_acl_ids_t)); 1631209962Smm acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1632185029Spjd 1633209962Smm if (vsecp) 1634209962Smm if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr, 1635209962Smm &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0) 1636209962Smm return (error); 1637168404Spjd /* 1638168404Spjd * Determine uid and gid. 1639168404Spjd */ 1640209962Smm if ((flag & IS_ROOT_NODE) || zfsvfs->z_replay || 1641168404Spjd ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 1642209962Smm acl_ids->z_fuid = zfs_fuid_create(zfsvfs, 1643209962Smm (uint64_t)vap->va_uid, cr, 1644209962Smm ZFS_OWNER, &acl_ids->z_fuidp); 1645209962Smm acl_ids->z_fgid = zfs_fuid_create(zfsvfs, 1646209962Smm (uint64_t)vap->va_gid, cr, 1647209962Smm ZFS_GROUP, &acl_ids->z_fuidp); 1648168404Spjd gid = vap->va_gid; 1649168404Spjd } else { 1650209962Smm acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, 1651209962Smm cr, &acl_ids->z_fuidp); 1652209962Smm acl_ids->z_fgid = 0; 1653185029Spjd if (vap->va_mask & AT_GID) { 1654209962Smm acl_ids->z_fgid = zfs_fuid_create(zfsvfs, 1655209962Smm (uint64_t)vap->va_gid, 1656209962Smm cr, ZFS_GROUP, &acl_ids->z_fuidp); 1657168404Spjd gid = vap->va_gid; 1658219089Spjd if (acl_ids->z_fgid != dzp->z_gid && 1659185029Spjd !groupmember(vap->va_gid, cr) && 1660185029Spjd secpolicy_vnode_create_gid(cr) != 0) 1661209962Smm acl_ids->z_fgid = 0; 1662185029Spjd } 1663209962Smm if (acl_ids->z_fgid == 0) { 1664219089Spjd if (dzp->z_mode & S_ISGID) { 1665219089Spjd char *domain; 1666219089Spjd uint32_t rid; 1667219089Spjd 1668219089Spjd acl_ids->z_fgid = dzp->z_gid; 1669209962Smm gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid, 1670185029Spjd cr, ZFS_GROUP); 1671219089Spjd 1672219089Spjd if (zfsvfs->z_use_fuids && 1673219089Spjd IS_EPHEMERAL(acl_ids->z_fgid)) { 1674219089Spjd domain = zfs_fuid_idx_domain( 1675219089Spjd &zfsvfs->z_fuid_idx, 1676219089Spjd FUID_INDEX(acl_ids->z_fgid)); 1677219089Spjd rid = FUID_RID(acl_ids->z_fgid); 1678219089Spjd zfs_fuid_node_add(&acl_ids->z_fuidp, 1679219089Spjd domain, rid, 1680219089Spjd FUID_INDEX(acl_ids->z_fgid), 1681219089Spjd acl_ids->z_fgid, ZFS_GROUP); 1682219089Spjd } 1683185029Spjd } else { 1684209962Smm acl_ids->z_fgid = zfs_fuid_create_cred(zfsvfs, 1685209962Smm ZFS_GROUP, cr, &acl_ids->z_fuidp); 1686168404Spjd#ifdef __FreeBSD__ 1687219089Spjd gid = acl_ids->z_fgid = dzp->z_gid; 1688168404Spjd#else 1689185029Spjd gid = crgetgid(cr); 1690168404Spjd#endif 1691185029Spjd } 1692185029Spjd } 1693168404Spjd } 1694168404Spjd 1695168404Spjd /* 1696168404Spjd * If we're creating a directory, and the parent directory has the 1697168404Spjd * set-GID bit set, set in on the new directory. 1698168404Spjd * Otherwise, if the user is neither privileged nor a member of the 1699168404Spjd * file's new group, clear the file's set-GID bit. 1700168404Spjd */ 1701168404Spjd 1702219089Spjd if (!(flag & IS_ROOT_NODE) && (dzp->z_mode & S_ISGID) && 1703209962Smm (vap->va_type == VDIR)) { 1704209962Smm acl_ids->z_mode |= S_ISGID; 1705185029Spjd } else { 1706209962Smm if ((acl_ids->z_mode & S_ISGID) && 1707209962Smm secpolicy_vnode_setids_setgids(ZTOV(dzp), cr, gid) != 0) 1708209962Smm acl_ids->z_mode &= ~S_ISGID; 1709168404Spjd } 1710168404Spjd 1711209962Smm if (acl_ids->z_aclp == NULL) { 1712219089Spjd mutex_enter(&dzp->z_acl_lock); 1713209962Smm mutex_enter(&dzp->z_lock); 1714224174Smm if (!(flag & IS_ROOT_NODE) && 1715224174Smm (dzp->z_pflags & ZFS_INHERIT_ACE) && 1716219089Spjd !(dzp->z_pflags & ZFS_XATTR)) { 1717219089Spjd VERIFY(0 == zfs_acl_node_read(dzp, B_TRUE, 1718219089Spjd &paclp, B_FALSE)); 1719209962Smm acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, 1720209962Smm vap->va_type, paclp, acl_ids->z_mode, &need_chmod); 1721219089Spjd inherited = B_TRUE; 1722185029Spjd } else { 1723209962Smm acl_ids->z_aclp = 1724209962Smm zfs_acl_alloc(zfs_acl_version_zp(dzp)); 1725219089Spjd acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; 1726185029Spjd } 1727209962Smm mutex_exit(&dzp->z_lock); 1728219089Spjd mutex_exit(&dzp->z_acl_lock); 1729209962Smm if (need_chmod) { 1730219089Spjd acl_ids->z_aclp->z_hints |= (vap->va_type == VDIR) ? 1731209962Smm ZFS_ACL_AUTO_INHERIT : 0; 1732224174Smm zfs_acl_chmod(vap->va_type, acl_ids->z_mode, 1733224174Smm (zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED), 1734224174Smm acl_ids->z_aclp); 1735209962Smm } 1736168404Spjd } 1737185029Spjd 1738219089Spjd if (inherited || vsecp) { 1739219089Spjd acl_ids->z_mode = zfs_mode_compute(acl_ids->z_mode, 1740219089Spjd acl_ids->z_aclp, &acl_ids->z_aclp->z_hints, 1741219089Spjd acl_ids->z_fuid, acl_ids->z_fgid); 1742219089Spjd if (ace_trivial_common(acl_ids->z_aclp, 0, zfs_ace_walk) == 0) 1743219089Spjd acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; 1744219089Spjd } 1745219089Spjd 1746209962Smm return (0); 1747209962Smm} 1748185029Spjd 1749209962Smm/* 1750209962Smm * Free ACL and fuid_infop, but not the acl_ids structure 1751209962Smm */ 1752209962Smmvoid 1753209962Smmzfs_acl_ids_free(zfs_acl_ids_t *acl_ids) 1754209962Smm{ 1755209962Smm if (acl_ids->z_aclp) 1756209962Smm zfs_acl_free(acl_ids->z_aclp); 1757209962Smm if (acl_ids->z_fuidp) 1758209962Smm zfs_fuid_info_free(acl_ids->z_fuidp); 1759209962Smm acl_ids->z_aclp = NULL; 1760209962Smm acl_ids->z_fuidp = NULL; 1761209962Smm} 1762185029Spjd 1763209962Smmboolean_t 1764209962Smmzfs_acl_ids_overquota(zfsvfs_t *zfsvfs, zfs_acl_ids_t *acl_ids) 1765209962Smm{ 1766219089Spjd return (zfs_fuid_overquota(zfsvfs, B_FALSE, acl_ids->z_fuid) || 1767219089Spjd zfs_fuid_overquota(zfsvfs, B_TRUE, acl_ids->z_fgid)); 1768168404Spjd} 1769168404Spjd 1770168404Spjd/* 1771252751Sdelphij * Retrieve a file's ACL 1772168404Spjd */ 1773168404Spjdint 1774185029Spjdzfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1775168404Spjd{ 1776168404Spjd zfs_acl_t *aclp; 1777185029Spjd ulong_t mask; 1778168404Spjd int error; 1779185029Spjd int count = 0; 1780185029Spjd int largeace = 0; 1781168404Spjd 1782185029Spjd mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT | 1783185029Spjd VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 1784168404Spjd 1785219089Spjd if (mask == 0) 1786249643Smm return (SET_ERROR(ENOSYS)); 1787219089Spjd 1788185029Spjd if (error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)) 1789185029Spjd return (error); 1790185029Spjd 1791168404Spjd mutex_enter(&zp->z_acl_lock); 1792168404Spjd 1793219089Spjd error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); 1794168404Spjd if (error != 0) { 1795168404Spjd mutex_exit(&zp->z_acl_lock); 1796168404Spjd return (error); 1797168404Spjd } 1798168404Spjd 1799185029Spjd /* 1800185029Spjd * Scan ACL to determine number of ACEs 1801185029Spjd */ 1802219089Spjd if ((zp->z_pflags & ZFS_ACL_OBJ_ACE) && !(mask & VSA_ACE_ALLTYPES)) { 1803185029Spjd void *zacep = NULL; 1804185029Spjd uint64_t who; 1805185029Spjd uint32_t access_mask; 1806185029Spjd uint16_t type, iflags; 1807168404Spjd 1808185029Spjd while (zacep = zfs_acl_next_ace(aclp, zacep, 1809185029Spjd &who, &access_mask, &iflags, &type)) { 1810185029Spjd switch (type) { 1811185029Spjd case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1812185029Spjd case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1813185029Spjd case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1814185029Spjd case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1815185029Spjd largeace++; 1816185029Spjd continue; 1817185029Spjd default: 1818185029Spjd count++; 1819185029Spjd } 1820185029Spjd } 1821185029Spjd vsecp->vsa_aclcnt = count; 1822185029Spjd } else 1823219089Spjd count = (int)aclp->z_acl_count; 1824185029Spjd 1825168404Spjd if (mask & VSA_ACECNT) { 1826185029Spjd vsecp->vsa_aclcnt = count; 1827168404Spjd } 1828168404Spjd 1829168404Spjd if (mask & VSA_ACE) { 1830185029Spjd size_t aclsz; 1831185029Spjd 1832185029Spjd aclsz = count * sizeof (ace_t) + 1833185029Spjd sizeof (ace_object_t) * largeace; 1834185029Spjd 1835185029Spjd vsecp->vsa_aclentp = kmem_alloc(aclsz, KM_SLEEP); 1836185029Spjd vsecp->vsa_aclentsz = aclsz; 1837185029Spjd 1838185029Spjd if (aclp->z_version == ZFS_ACL_VERSION_FUID) 1839185029Spjd zfs_copy_fuid_2_ace(zp->z_zfsvfs, aclp, cr, 1840185029Spjd vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES)); 1841185029Spjd else { 1842211932Smm zfs_acl_node_t *aclnode; 1843211932Smm void *start = vsecp->vsa_aclentp; 1844211932Smm 1845211932Smm for (aclnode = list_head(&aclp->z_acl); aclnode; 1846211932Smm aclnode = list_next(&aclp->z_acl, aclnode)) { 1847211932Smm bcopy(aclnode->z_acldata, start, 1848211932Smm aclnode->z_size); 1849211932Smm start = (caddr_t)start + aclnode->z_size; 1850211932Smm } 1851211932Smm ASSERT((caddr_t)start - (caddr_t)vsecp->vsa_aclentp == 1852211932Smm aclp->z_acl_bytes); 1853185029Spjd } 1854168404Spjd } 1855185029Spjd if (mask & VSA_ACE_ACLFLAGS) { 1856185029Spjd vsecp->vsa_aclflags = 0; 1857219089Spjd if (zp->z_pflags & ZFS_ACL_DEFAULTED) 1858185029Spjd vsecp->vsa_aclflags |= ACL_DEFAULTED; 1859219089Spjd if (zp->z_pflags & ZFS_ACL_PROTECTED) 1860185029Spjd vsecp->vsa_aclflags |= ACL_PROTECTED; 1861219089Spjd if (zp->z_pflags & ZFS_ACL_AUTO_INHERIT) 1862185029Spjd vsecp->vsa_aclflags |= ACL_AUTO_INHERIT; 1863185029Spjd } 1864168404Spjd 1865168404Spjd mutex_exit(&zp->z_acl_lock); 1866168404Spjd 1867168404Spjd return (0); 1868168404Spjd} 1869168404Spjd 1870185029Spjdint 1871185029Spjdzfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type, 1872209962Smm vsecattr_t *vsecp, cred_t *cr, zfs_fuid_info_t **fuidp, zfs_acl_t **zaclp) 1873185029Spjd{ 1874185029Spjd zfs_acl_t *aclp; 1875185029Spjd zfs_acl_node_t *aclnode; 1876185029Spjd int aclcnt = vsecp->vsa_aclcnt; 1877185029Spjd int error; 1878185029Spjd 1879185029Spjd if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0) 1880249643Smm return (SET_ERROR(EINVAL)); 1881185029Spjd 1882185029Spjd aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version)); 1883185029Spjd 1884185029Spjd aclp->z_hints = 0; 1885185029Spjd aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t)); 1886185029Spjd if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 1887185029Spjd if ((error = zfs_copy_ace_2_oldace(obj_type, aclp, 1888185029Spjd (ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata, 1889185029Spjd aclcnt, &aclnode->z_size)) != 0) { 1890185029Spjd zfs_acl_free(aclp); 1891185029Spjd zfs_acl_node_free(aclnode); 1892185029Spjd return (error); 1893185029Spjd } 1894185029Spjd } else { 1895209962Smm if ((error = zfs_copy_ace_2_fuid(zfsvfs, obj_type, aclp, 1896185029Spjd vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt, 1897209962Smm &aclnode->z_size, fuidp, cr)) != 0) { 1898185029Spjd zfs_acl_free(aclp); 1899185029Spjd zfs_acl_node_free(aclnode); 1900185029Spjd return (error); 1901185029Spjd } 1902185029Spjd } 1903185029Spjd aclp->z_acl_bytes = aclnode->z_size; 1904185029Spjd aclnode->z_ace_count = aclcnt; 1905185029Spjd aclp->z_acl_count = aclcnt; 1906185029Spjd list_insert_head(&aclp->z_acl, aclnode); 1907185029Spjd 1908185029Spjd /* 1909185029Spjd * If flags are being set then add them to z_hints 1910185029Spjd */ 1911185029Spjd if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) { 1912185029Spjd if (vsecp->vsa_aclflags & ACL_PROTECTED) 1913185029Spjd aclp->z_hints |= ZFS_ACL_PROTECTED; 1914185029Spjd if (vsecp->vsa_aclflags & ACL_DEFAULTED) 1915185029Spjd aclp->z_hints |= ZFS_ACL_DEFAULTED; 1916185029Spjd if (vsecp->vsa_aclflags & ACL_AUTO_INHERIT) 1917185029Spjd aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 1918185029Spjd } 1919185029Spjd 1920185029Spjd *zaclp = aclp; 1921185029Spjd 1922185029Spjd return (0); 1923185029Spjd} 1924185029Spjd 1925168404Spjd/* 1926252751Sdelphij * Set a file's ACL 1927168404Spjd */ 1928168404Spjdint 1929185029Spjdzfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1930168404Spjd{ 1931168404Spjd zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1932168404Spjd zilog_t *zilog = zfsvfs->z_log; 1933168404Spjd ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1934168404Spjd dmu_tx_t *tx; 1935168404Spjd int error; 1936168404Spjd zfs_acl_t *aclp; 1937185029Spjd zfs_fuid_info_t *fuidp = NULL; 1938209962Smm boolean_t fuid_dirtied; 1939219089Spjd uint64_t acl_obj; 1940168404Spjd 1941168404Spjd if (mask == 0) 1942249643Smm return (SET_ERROR(ENOSYS)); 1943168404Spjd 1944219089Spjd if (zp->z_pflags & ZFS_IMMUTABLE) 1945249643Smm return (SET_ERROR(EPERM)); 1946185029Spjd 1947185029Spjd if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)) 1948185029Spjd return (error); 1949185029Spjd 1950209962Smm error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, 1951209962Smm &aclp); 1952185029Spjd if (error) 1953185029Spjd return (error); 1954185029Spjd 1955185029Spjd /* 1956185029Spjd * If ACL wide flags aren't being set then preserve any 1957185029Spjd * existing flags. 1958185029Spjd */ 1959185029Spjd if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { 1960219089Spjd aclp->z_hints |= 1961219089Spjd (zp->z_pflags & V4_ACL_WIDE_FLAGS); 1962185029Spjd } 1963168404Spjdtop: 1964219089Spjd mutex_enter(&zp->z_acl_lock); 1965168404Spjd mutex_enter(&zp->z_lock); 1966168404Spjd 1967168404Spjd tx = dmu_tx_create(zfsvfs->z_os); 1968168404Spjd 1969219089Spjd dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); 1970219089Spjd 1971219089Spjd fuid_dirtied = zfsvfs->z_fuid_dirty; 1972219089Spjd if (fuid_dirtied) 1973219089Spjd zfs_fuid_txhold(zfsvfs, tx); 1974219089Spjd 1975219089Spjd /* 1976219089Spjd * If old version and ACL won't fit in bonus and we aren't 1977219089Spjd * upgrading then take out necessary DMU holds 1978219089Spjd */ 1979219089Spjd 1980219089Spjd if ((acl_obj = zfs_external_acl(zp)) != 0) { 1981219089Spjd if (zfsvfs->z_version >= ZPL_VERSION_FUID && 1982219089Spjd zfs_znode_acl_version(zp) <= ZFS_ACL_VERSION_INITIAL) { 1983219089Spjd dmu_tx_hold_free(tx, acl_obj, 0, 1984219089Spjd DMU_OBJECT_END); 1985219089Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 1986219089Spjd aclp->z_acl_bytes); 1987185029Spjd } else { 1988219089Spjd dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes); 1989185029Spjd } 1990219089Spjd } else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { 1991185029Spjd dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); 1992168404Spjd } 1993168404Spjd 1994219089Spjd zfs_sa_upgrade_txholds(tx, zp); 1995209962Smm error = dmu_tx_assign(tx, TXG_NOWAIT); 1996168404Spjd if (error) { 1997168404Spjd mutex_exit(&zp->z_acl_lock); 1998168404Spjd mutex_exit(&zp->z_lock); 1999168404Spjd 2000209962Smm if (error == ERESTART) { 2001168404Spjd dmu_tx_wait(tx); 2002168404Spjd dmu_tx_abort(tx); 2003168404Spjd goto top; 2004168404Spjd } 2005168404Spjd dmu_tx_abort(tx); 2006185029Spjd zfs_acl_free(aclp); 2007168404Spjd return (error); 2008168404Spjd } 2009168404Spjd 2010209962Smm error = zfs_aclset_common(zp, aclp, cr, tx); 2011168404Spjd ASSERT(error == 0); 2012219089Spjd ASSERT(zp->z_acl_cached == NULL); 2013211932Smm zp->z_acl_cached = aclp; 2014168404Spjd 2015209962Smm if (fuid_dirtied) 2016209962Smm zfs_fuid_sync(zfsvfs, tx); 2017209962Smm 2018185029Spjd zfs_log_acl(zilog, tx, zp, vsecp, fuidp); 2019185029Spjd 2020185029Spjd if (fuidp) 2021185029Spjd zfs_fuid_info_free(fuidp); 2022168404Spjd dmu_tx_commit(tx); 2023168404Spjddone: 2024219089Spjd mutex_exit(&zp->z_lock); 2025168404Spjd mutex_exit(&zp->z_acl_lock); 2026168404Spjd 2027168404Spjd return (error); 2028168404Spjd} 2029168404Spjd 2030185029Spjd/* 2031211932Smm * Check accesses of interest (AoI) against attributes of the dataset 2032211932Smm * such as read-only. Returns zero if no AoI conflict with dataset 2033211932Smm * attributes, otherwise an appropriate errno is returned. 2034185029Spjd */ 2035168404Spjdstatic int 2036211932Smmzfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) 2037168404Spjd{ 2038168404Spjd if ((v4_mode & WRITE_MASK) && 2039168404Spjd (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 2040209962Smm (!IS_DEVVP(ZTOV(zp)) || 2041209962Smm (IS_DEVVP(ZTOV(zp)) && (v4_mode & WRITE_MASK_ATTRS)))) { 2042249643Smm return (SET_ERROR(EROFS)); 2043168404Spjd } 2044168404Spjd 2045185029Spjd /* 2046185029Spjd * Only check for READONLY on non-directories. 2047185029Spjd */ 2048185029Spjd if ((v4_mode & WRITE_MASK_DATA) && 2049185029Spjd (((ZTOV(zp)->v_type != VDIR) && 2050219089Spjd (zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) || 2051185029Spjd (ZTOV(zp)->v_type == VDIR && 2052219089Spjd (zp->z_pflags & ZFS_IMMUTABLE)))) { 2053249643Smm return (SET_ERROR(EPERM)); 2054185029Spjd } 2055185029Spjd 2056207068Spjd#ifdef sun 2057185029Spjd if ((v4_mode & (ACE_DELETE | ACE_DELETE_CHILD)) && 2058219089Spjd (zp->z_pflags & ZFS_NOUNLINK)) { 2059249643Smm return (SET_ERROR(EPERM)); 2060185029Spjd } 2061207068Spjd#else 2062207068Spjd /* 2063207068Spjd * In FreeBSD we allow to modify directory's content is ZFS_NOUNLINK 2064207068Spjd * (sunlnk) is set. We just don't allow directory removal, which is 2065207068Spjd * handled in zfs_zaccess_delete(). 2066207068Spjd */ 2067207068Spjd if ((v4_mode & ACE_DELETE) && 2068219089Spjd (zp->z_pflags & ZFS_NOUNLINK)) { 2069207068Spjd return (EPERM); 2070207068Spjd } 2071207068Spjd#endif 2072185029Spjd 2073185029Spjd if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) && 2074219089Spjd (zp->z_pflags & ZFS_AV_QUARANTINED))) { 2075249643Smm return (SET_ERROR(EACCES)); 2076185029Spjd } 2077185029Spjd 2078211932Smm return (0); 2079211932Smm} 2080185029Spjd 2081211932Smm/* 2082211932Smm * The primary usage of this function is to loop through all of the 2083211932Smm * ACEs in the znode, determining what accesses of interest (AoI) to 2084211932Smm * the caller are allowed or denied. The AoI are expressed as bits in 2085211932Smm * the working_mode parameter. As each ACE is processed, bits covered 2086211932Smm * by that ACE are removed from the working_mode. This removal 2087211932Smm * facilitates two things. The first is that when the working mode is 2088211932Smm * empty (= 0), we know we've looked at all the AoI. The second is 2089211932Smm * that the ACE interpretation rules don't allow a later ACE to undo 2090211932Smm * something granted or denied by an earlier ACE. Removing the 2091211932Smm * discovered access or denial enforces this rule. At the end of 2092211932Smm * processing the ACEs, all AoI that were found to be denied are 2093211932Smm * placed into the working_mode, giving the caller a mask of denied 2094211932Smm * accesses. Returns: 2095211932Smm * 0 if all AoI granted 2096211932Smm * EACCESS if the denied mask is non-zero 2097211932Smm * other error if abnormal failure (e.g., IO error) 2098211932Smm * 2099211932Smm * A secondary usage of the function is to determine if any of the 2100211932Smm * AoI are granted. If an ACE grants any access in 2101211932Smm * the working_mode, we immediately short circuit out of the function. 2102211932Smm * This mode is chosen by setting anyaccess to B_TRUE. The 2103211932Smm * working_mode is not a denied access mask upon exit if the function 2104211932Smm * is used in this manner. 2105211932Smm */ 2106211932Smmstatic int 2107211932Smmzfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, 2108211932Smm boolean_t anyaccess, cred_t *cr) 2109211932Smm{ 2110211932Smm zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2111211932Smm zfs_acl_t *aclp; 2112211932Smm int error; 2113211932Smm uid_t uid = crgetuid(cr); 2114211932Smm uint64_t who; 2115211932Smm uint16_t type, iflags; 2116211932Smm uint16_t entry_type; 2117211932Smm uint32_t access_mask; 2118211932Smm uint32_t deny_mask = 0; 2119211932Smm zfs_ace_hdr_t *acep = NULL; 2120211932Smm boolean_t checkit; 2121219089Spjd uid_t gowner; 2122211932Smm uid_t fowner; 2123211932Smm 2124185029Spjd zfs_fuid_map_ids(zp, cr, &fowner, &gowner); 2125185029Spjd 2126168404Spjd mutex_enter(&zp->z_acl_lock); 2127168404Spjd 2128219089Spjd error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); 2129168404Spjd if (error != 0) { 2130168404Spjd mutex_exit(&zp->z_acl_lock); 2131168404Spjd return (error); 2132168404Spjd } 2133168404Spjd 2134219089Spjd ASSERT(zp->z_acl_cached); 2135219089Spjd 2136185029Spjd while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 2137185029Spjd &iflags, &type)) { 2138211932Smm uint32_t mask_matched; 2139168404Spjd 2140185029Spjd if (!zfs_acl_valid_ace_type(type, iflags)) 2141185029Spjd continue; 2142168404Spjd 2143185029Spjd if (ZTOV(zp)->v_type == VDIR && (iflags & ACE_INHERIT_ONLY_ACE)) 2144185029Spjd continue; 2145168404Spjd 2146211932Smm /* Skip ACE if it does not affect any AoI */ 2147211932Smm mask_matched = (access_mask & *working_mode); 2148211932Smm if (!mask_matched) 2149211932Smm continue; 2150211932Smm 2151185029Spjd entry_type = (iflags & ACE_TYPE_FLAGS); 2152168404Spjd 2153185029Spjd checkit = B_FALSE; 2154168404Spjd 2155168404Spjd switch (entry_type) { 2156168404Spjd case ACE_OWNER: 2157185029Spjd if (uid == fowner) 2158185029Spjd checkit = B_TRUE; 2159168404Spjd break; 2160185029Spjd case OWNING_GROUP: 2161185029Spjd who = gowner; 2162185029Spjd /*FALLTHROUGH*/ 2163168404Spjd case ACE_IDENTIFIER_GROUP: 2164185029Spjd checkit = zfs_groupmember(zfsvfs, who, cr); 2165168404Spjd break; 2166168404Spjd case ACE_EVERYONE: 2167185029Spjd checkit = B_TRUE; 2168168404Spjd break; 2169168404Spjd 2170168404Spjd /* USER Entry */ 2171168404Spjd default: 2172168404Spjd if (entry_type == 0) { 2173185029Spjd uid_t newid; 2174185029Spjd 2175185029Spjd newid = zfs_fuid_map_id(zfsvfs, who, cr, 2176185029Spjd ZFS_ACE_USER); 2177185029Spjd if (newid != IDMAP_WK_CREATOR_OWNER_UID && 2178185029Spjd uid == newid) 2179185029Spjd checkit = B_TRUE; 2180168404Spjd break; 2181185029Spjd } else { 2182185029Spjd mutex_exit(&zp->z_acl_lock); 2183249643Smm return (SET_ERROR(EIO)); 2184168404Spjd } 2185168404Spjd } 2186168404Spjd 2187185029Spjd if (checkit) { 2188211932Smm if (type == DENY) { 2189211932Smm DTRACE_PROBE3(zfs__ace__denies, 2190211932Smm znode_t *, zp, 2191211932Smm zfs_ace_hdr_t *, acep, 2192211932Smm uint32_t, mask_matched); 2193211932Smm deny_mask |= mask_matched; 2194211932Smm } else { 2195211932Smm DTRACE_PROBE3(zfs__ace__allows, 2196211932Smm znode_t *, zp, 2197211932Smm zfs_ace_hdr_t *, acep, 2198211932Smm uint32_t, mask_matched); 2199211932Smm if (anyaccess) { 2200211932Smm mutex_exit(&zp->z_acl_lock); 2201211932Smm return (0); 2202211932Smm } 2203185029Spjd } 2204211932Smm *working_mode &= ~mask_matched; 2205185029Spjd } 2206185029Spjd 2207185029Spjd /* Are we done? */ 2208185029Spjd if (*working_mode == 0) 2209168404Spjd break; 2210168404Spjd } 2211168404Spjd 2212168404Spjd mutex_exit(&zp->z_acl_lock); 2213168404Spjd 2214185029Spjd /* Put the found 'denies' back on the working mode */ 2215185029Spjd if (deny_mask) { 2216185029Spjd *working_mode |= deny_mask; 2217249643Smm return (SET_ERROR(EACCES)); 2218185029Spjd } else if (*working_mode) { 2219185029Spjd return (-1); 2220185029Spjd } 2221185029Spjd 2222185029Spjd return (0); 2223168404Spjd} 2224168404Spjd 2225211932Smm/* 2226211932Smm * Return true if any access whatsoever granted, we don't actually 2227211932Smm * care what access is granted. 2228211932Smm */ 2229211932Smmboolean_t 2230211932Smmzfs_has_access(znode_t *zp, cred_t *cr) 2231211932Smm{ 2232211932Smm uint32_t have = ACE_ALL_PERMS; 2233211932Smm 2234211932Smm if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) { 2235219089Spjd uid_t owner; 2236211932Smm 2237219089Spjd owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER); 2238219089Spjd return (secpolicy_vnode_any_access(cr, ZTOV(zp), owner) == 0); 2239211932Smm } 2240211932Smm return (B_TRUE); 2241211932Smm} 2242211932Smm 2243185029Spjdstatic int 2244211932Smmzfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, 2245211932Smm boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) 2246211932Smm{ 2247211932Smm zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2248211932Smm int err; 2249211932Smm 2250211932Smm *working_mode = v4_mode; 2251211932Smm *check_privs = B_TRUE; 2252211932Smm 2253211932Smm /* 2254211932Smm * Short circuit empty requests 2255211932Smm */ 2256211932Smm if (v4_mode == 0 || zfsvfs->z_replay) { 2257211932Smm *working_mode = 0; 2258211932Smm return (0); 2259211932Smm } 2260211932Smm 2261211932Smm if ((err = zfs_zaccess_dataset_check(zp, v4_mode)) != 0) { 2262211932Smm *check_privs = B_FALSE; 2263211932Smm return (err); 2264211932Smm } 2265211932Smm 2266211932Smm /* 2267211932Smm * The caller requested that the ACL check be skipped. This 2268211932Smm * would only happen if the caller checked VOP_ACCESS() with a 2269211932Smm * 32 bit ACE mask and already had the appropriate permissions. 2270211932Smm */ 2271211932Smm if (skipaclchk) { 2272211932Smm *working_mode = 0; 2273211932Smm return (0); 2274211932Smm } 2275211932Smm 2276211932Smm return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr)); 2277211932Smm} 2278211932Smm 2279211932Smmstatic int 2280185029Spjdzfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, 2281185029Spjd cred_t *cr) 2282185029Spjd{ 2283185029Spjd if (*working_mode != ACE_WRITE_DATA) 2284249643Smm return (SET_ERROR(EACCES)); 2285168404Spjd 2286185029Spjd return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, 2287185029Spjd check_privs, B_FALSE, cr)); 2288185029Spjd} 2289185029Spjd 2290211932Smmint 2291211932Smmzfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) 2292211932Smm{ 2293211932Smm boolean_t owner = B_FALSE; 2294211932Smm boolean_t groupmbr = B_FALSE; 2295211932Smm boolean_t is_attr; 2296211932Smm uid_t uid = crgetuid(cr); 2297211932Smm int error; 2298211932Smm 2299219089Spjd if (zdp->z_pflags & ZFS_AV_QUARANTINED) 2300249643Smm return (SET_ERROR(EACCES)); 2301211932Smm 2302219089Spjd is_attr = ((zdp->z_pflags & ZFS_XATTR) && 2303211932Smm (ZTOV(zdp)->v_type == VDIR)); 2304211932Smm if (is_attr) 2305211932Smm goto slow; 2306211932Smm 2307219089Spjd 2308211932Smm mutex_enter(&zdp->z_acl_lock); 2309211932Smm 2310219089Spjd if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) { 2311211932Smm mutex_exit(&zdp->z_acl_lock); 2312211932Smm return (0); 2313211932Smm } 2314211932Smm 2315219089Spjd if (FUID_INDEX(zdp->z_uid) != 0 || FUID_INDEX(zdp->z_gid) != 0) { 2316211932Smm mutex_exit(&zdp->z_acl_lock); 2317211932Smm goto slow; 2318211932Smm } 2319211932Smm 2320219089Spjd if (uid == zdp->z_uid) { 2321211932Smm owner = B_TRUE; 2322219089Spjd if (zdp->z_mode & S_IXUSR) { 2323211932Smm mutex_exit(&zdp->z_acl_lock); 2324211932Smm return (0); 2325211932Smm } else { 2326211932Smm mutex_exit(&zdp->z_acl_lock); 2327211932Smm goto slow; 2328211932Smm } 2329211932Smm } 2330219089Spjd if (groupmember(zdp->z_gid, cr)) { 2331211932Smm groupmbr = B_TRUE; 2332219089Spjd if (zdp->z_mode & S_IXGRP) { 2333211932Smm mutex_exit(&zdp->z_acl_lock); 2334211932Smm return (0); 2335211932Smm } else { 2336211932Smm mutex_exit(&zdp->z_acl_lock); 2337211932Smm goto slow; 2338211932Smm } 2339211932Smm } 2340211932Smm if (!owner && !groupmbr) { 2341219089Spjd if (zdp->z_mode & S_IXOTH) { 2342211932Smm mutex_exit(&zdp->z_acl_lock); 2343211932Smm return (0); 2344211932Smm } 2345211932Smm } 2346211932Smm 2347211932Smm mutex_exit(&zdp->z_acl_lock); 2348211932Smm 2349211932Smmslow: 2350211932Smm DTRACE_PROBE(zfs__fastpath__execute__access__miss); 2351211932Smm ZFS_ENTER(zdp->z_zfsvfs); 2352211932Smm error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr); 2353211932Smm ZFS_EXIT(zdp->z_zfsvfs); 2354211932Smm return (error); 2355211932Smm} 2356211932Smm 2357168404Spjd/* 2358219089Spjd * Determine whether Access should be granted/denied. 2359252751Sdelphij * 2360219089Spjd * The least priv subsytem is always consulted as a basic privilege 2361219089Spjd * can define any form of access. 2362168404Spjd */ 2363168404Spjdint 2364185029Spjdzfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) 2365168404Spjd{ 2366185029Spjd uint32_t working_mode; 2367185029Spjd int error; 2368185029Spjd int is_attr; 2369185029Spjd boolean_t check_privs; 2370185029Spjd znode_t *xzp; 2371185029Spjd znode_t *check_zp = zp; 2372219089Spjd mode_t needed_bits; 2373219089Spjd uid_t owner; 2374168404Spjd 2375219089Spjd is_attr = ((zp->z_pflags & ZFS_XATTR) && (ZTOV(zp)->v_type == VDIR)); 2376168404Spjd 2377195785Strasz#ifdef __FreeBSD__ 2378168404Spjd /* 2379195785Strasz * In FreeBSD, we don't care about permissions of individual ADS. 2380195785Strasz * Note that not checking them is not just an optimization - without 2381195785Strasz * this shortcut, EA operations may bogusly fail with EACCES. 2382195785Strasz */ 2383219089Spjd if (zp->z_pflags & ZFS_XATTR) 2384195785Strasz return (0); 2385195785Strasz#else 2386195785Strasz /* 2387168404Spjd * If attribute then validate against base file 2388168404Spjd */ 2389168404Spjd if (is_attr) { 2390219089Spjd uint64_t parent; 2391219089Spjd 2392219089Spjd if ((error = sa_lookup(zp->z_sa_hdl, 2393219089Spjd SA_ZPL_PARENT(zp->z_zfsvfs), &parent, 2394219089Spjd sizeof (parent))) != 0) 2395219089Spjd return (error); 2396219089Spjd 2397168404Spjd if ((error = zfs_zget(zp->z_zfsvfs, 2398219089Spjd parent, &xzp)) != 0) { 2399168404Spjd return (error); 2400168404Spjd } 2401185029Spjd 2402168404Spjd check_zp = xzp; 2403185029Spjd 2404168404Spjd /* 2405168404Spjd * fixup mode to map to xattr perms 2406168404Spjd */ 2407168404Spjd 2408168404Spjd if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 2409168404Spjd mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 2410168404Spjd mode |= ACE_WRITE_NAMED_ATTRS; 2411168404Spjd } 2412168404Spjd 2413168404Spjd if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 2414168404Spjd mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 2415168404Spjd mode |= ACE_READ_NAMED_ATTRS; 2416168404Spjd } 2417168404Spjd } 2418195785Strasz#endif 2419168404Spjd 2420219089Spjd owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER); 2421219089Spjd /* 2422219089Spjd * Map the bits required to the standard vnode flags VREAD|VWRITE|VEXEC 2423219089Spjd * in needed_bits. Map the bits mapped by working_mode (currently 2424219089Spjd * missing) in missing_bits. 2425219089Spjd * Call secpolicy_vnode_access2() with (needed_bits & ~checkmode), 2426219089Spjd * needed_bits. 2427219089Spjd */ 2428219089Spjd needed_bits = 0; 2429219089Spjd 2430219089Spjd working_mode = mode; 2431219089Spjd if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) && 2432219089Spjd owner == crgetuid(cr)) 2433219089Spjd working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2434219089Spjd 2435219089Spjd if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2436219089Spjd ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2437219089Spjd needed_bits |= VREAD; 2438219089Spjd if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2439219089Spjd ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2440219089Spjd needed_bits |= VWRITE; 2441219089Spjd if (working_mode & ACE_EXECUTE) 2442219089Spjd needed_bits |= VEXEC; 2443219089Spjd 2444185029Spjd if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, 2445185029Spjd &check_privs, skipaclchk, cr)) == 0) { 2446185029Spjd if (is_attr) 2447185029Spjd VN_RELE(ZTOV(xzp)); 2448219089Spjd return (secpolicy_vnode_access2(cr, ZTOV(zp), owner, 2449219089Spjd needed_bits, needed_bits)); 2450185029Spjd } 2451168404Spjd 2452185029Spjd if (error && !check_privs) { 2453168404Spjd if (is_attr) 2454168404Spjd VN_RELE(ZTOV(xzp)); 2455168404Spjd return (error); 2456168404Spjd } 2457168404Spjd 2458185029Spjd if (error && (flags & V_APPEND)) { 2459185029Spjd error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr); 2460168404Spjd } 2461168404Spjd 2462185029Spjd if (error && check_privs) { 2463185029Spjd mode_t checkmode = 0; 2464185029Spjd 2465185029Spjd /* 2466185029Spjd * First check for implicit owner permission on 2467185029Spjd * read_acl/read_attributes 2468185029Spjd */ 2469185029Spjd 2470185029Spjd error = 0; 2471185029Spjd ASSERT(working_mode != 0); 2472185029Spjd 2473185029Spjd if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) && 2474185029Spjd owner == crgetuid(cr))) 2475185029Spjd working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2476185029Spjd 2477185029Spjd if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2478185029Spjd ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2479185029Spjd checkmode |= VREAD; 2480185029Spjd if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2481185029Spjd ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2482185029Spjd checkmode |= VWRITE; 2483185029Spjd if (working_mode & ACE_EXECUTE) 2484185029Spjd checkmode |= VEXEC; 2485185029Spjd 2486219089Spjd error = secpolicy_vnode_access2(cr, ZTOV(check_zp), owner, 2487219089Spjd needed_bits & ~checkmode, needed_bits); 2488185029Spjd 2489185029Spjd if (error == 0 && (working_mode & ACE_WRITE_OWNER)) 2490211932Smm error = secpolicy_vnode_chown(ZTOV(check_zp), cr, owner); 2491185029Spjd if (error == 0 && (working_mode & ACE_WRITE_ACL)) 2492185029Spjd error = secpolicy_vnode_setdac(ZTOV(check_zp), cr, owner); 2493185029Spjd 2494185029Spjd if (error == 0 && (working_mode & 2495185029Spjd (ACE_DELETE|ACE_DELETE_CHILD))) 2496185029Spjd error = secpolicy_vnode_remove(ZTOV(check_zp), cr); 2497185029Spjd 2498185029Spjd if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) { 2499211932Smm error = secpolicy_vnode_chown(ZTOV(check_zp), cr, owner); 2500185029Spjd } 2501185029Spjd if (error == 0) { 2502185029Spjd /* 2503185029Spjd * See if any bits other than those already checked 2504185029Spjd * for are still present. If so then return EACCES 2505185029Spjd */ 2506185029Spjd if (working_mode & ~(ZFS_CHECKED_MASKS)) { 2507249643Smm error = SET_ERROR(EACCES); 2508185029Spjd } 2509185029Spjd } 2510219089Spjd } else if (error == 0) { 2511219089Spjd error = secpolicy_vnode_access2(cr, ZTOV(zp), owner, 2512219089Spjd needed_bits, needed_bits); 2513185029Spjd } 2514185029Spjd 2515219089Spjd 2516168404Spjd if (is_attr) 2517168404Spjd VN_RELE(ZTOV(xzp)); 2518168404Spjd 2519168404Spjd return (error); 2520168404Spjd} 2521168404Spjd 2522168404Spjd/* 2523185029Spjd * Translate traditional unix VREAD/VWRITE/VEXEC mode into 2524185029Spjd * native ACL format and call zfs_zaccess() 2525168404Spjd */ 2526168404Spjdint 2527185029Spjdzfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) 2528168404Spjd{ 2529185029Spjd return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); 2530168404Spjd} 2531168404Spjd 2532168404Spjd/* 2533185029Spjd * Access function for secpolicy_vnode_setattr 2534168404Spjd */ 2535168404Spjdint 2536185029Spjdzfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) 2537168404Spjd{ 2538168404Spjd int v4_mode = zfs_unix_to_v4(mode >> 6); 2539168404Spjd 2540185029Spjd return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr)); 2541168404Spjd} 2542168404Spjd 2543168404Spjdstatic int 2544185029Spjdzfs_delete_final_check(znode_t *zp, znode_t *dzp, 2545219089Spjd mode_t available_perms, cred_t *cr) 2546168404Spjd{ 2547168404Spjd int error; 2548185029Spjd uid_t downer; 2549168404Spjd 2550219089Spjd downer = zfs_fuid_map_id(dzp->z_zfsvfs, dzp->z_uid, cr, ZFS_OWNER); 2551168404Spjd 2552219089Spjd error = secpolicy_vnode_access2(cr, ZTOV(dzp), 2553219089Spjd downer, available_perms, VWRITE|VEXEC); 2554185029Spjd 2555168404Spjd if (error == 0) 2556168404Spjd error = zfs_sticky_remove_access(dzp, zp, cr); 2557168404Spjd 2558168404Spjd return (error); 2559168404Spjd} 2560168404Spjd 2561168404Spjd/* 2562168404Spjd * Determine whether Access should be granted/deny, without 2563168404Spjd * consulting least priv subsystem. 2564168404Spjd * 2565168404Spjd * The following chart is the recommended NFSv4 enforcement for 2566168404Spjd * ability to delete an object. 2567168404Spjd * 2568168404Spjd * ------------------------------------------------------- 2569168404Spjd * | Parent Dir | Target Object Permissions | 2570168404Spjd * | permissions | | 2571168404Spjd * ------------------------------------------------------- 2572168404Spjd * | | ACL Allows | ACL Denies| Delete | 2573168404Spjd * | | Delete | Delete | unspecified| 2574168404Spjd * ------------------------------------------------------- 2575168404Spjd * | ACL Allows | Permit | Permit | Permit | 2576168404Spjd * | DELETE_CHILD | | 2577168404Spjd * ------------------------------------------------------- 2578168404Spjd * | ACL Denies | Permit | Deny | Deny | 2579168404Spjd * | DELETE_CHILD | | | | 2580168404Spjd * ------------------------------------------------------- 2581168404Spjd * | ACL specifies | | | | 2582168404Spjd * | only allow | Permit | Permit | Permit | 2583168404Spjd * | write and | | | | 2584168404Spjd * | execute | | | | 2585168404Spjd * ------------------------------------------------------- 2586168404Spjd * | ACL denies | | | | 2587168404Spjd * | write and | Permit | Deny | Deny | 2588168404Spjd * | execute | | | | 2589168404Spjd * ------------------------------------------------------- 2590168404Spjd * ^ 2591168404Spjd * | 2592168404Spjd * No search privilege, can't even look up file? 2593168404Spjd * 2594168404Spjd */ 2595168404Spjdint 2596168404Spjdzfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) 2597168404Spjd{ 2598185029Spjd uint32_t dzp_working_mode = 0; 2599185029Spjd uint32_t zp_working_mode = 0; 2600168404Spjd int dzp_error, zp_error; 2601219089Spjd mode_t available_perms; 2602185029Spjd boolean_t dzpcheck_privs = B_TRUE; 2603185029Spjd boolean_t zpcheck_privs = B_TRUE; 2604168404Spjd 2605168404Spjd /* 2606185029Spjd * We want specific DELETE permissions to 2607168404Spjd * take precedence over WRITE/EXECUTE. We don't 2608168404Spjd * want an ACL such as this to mess us up. 2609168404Spjd * user:joe:write_data:deny,user:joe:delete:allow 2610168404Spjd * 2611168404Spjd * However, deny permissions may ultimately be overridden 2612168404Spjd * by secpolicy_vnode_access(). 2613185029Spjd * 2614185029Spjd * We will ask for all of the necessary permissions and then 2615185029Spjd * look at the working modes from the directory and target object 2616185029Spjd * to determine what was found. 2617168404Spjd */ 2618168404Spjd 2619219089Spjd if (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_NOUNLINK)) 2620249643Smm return (SET_ERROR(EPERM)); 2621168404Spjd 2622168404Spjd /* 2623185029Spjd * First row 2624185029Spjd * If the directory permissions allow the delete, we are done. 2625168404Spjd */ 2626185029Spjd if ((dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 2627185029Spjd &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0) 2628168404Spjd return (0); 2629168404Spjd 2630168404Spjd /* 2631185029Spjd * If target object has delete permission then we are done 2632168404Spjd */ 2633185029Spjd if ((zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, 2634185029Spjd &zpcheck_privs, B_FALSE, cr)) == 0) 2635168404Spjd return (0); 2636168404Spjd 2637185029Spjd ASSERT(dzp_error && zp_error); 2638185029Spjd 2639185029Spjd if (!dzpcheck_privs) 2640185029Spjd return (dzp_error); 2641185029Spjd if (!zpcheck_privs) 2642185029Spjd return (zp_error); 2643185029Spjd 2644168404Spjd /* 2645185029Spjd * Second row 2646168404Spjd * 2647185029Spjd * If directory returns EACCES then delete_child was denied 2648185029Spjd * due to deny delete_child. In this case send the request through 2649185029Spjd * secpolicy_vnode_remove(). We don't use zfs_delete_final_check() 2650185029Spjd * since that *could* allow the delete based on write/execute permission 2651185029Spjd * and we want delete permissions to override write/execute. 2652168404Spjd */ 2653168404Spjd 2654168404Spjd if (dzp_error == EACCES) 2655185029Spjd return (secpolicy_vnode_remove(ZTOV(dzp), cr)); /* XXXPJD: s/dzp/zp/ ? */ 2656168404Spjd 2657168404Spjd /* 2658168404Spjd * Third Row 2659185029Spjd * only need to see if we have write/execute on directory. 2660168404Spjd */ 2661168404Spjd 2662219089Spjd dzp_error = zfs_zaccess_common(dzp, ACE_EXECUTE|ACE_WRITE_DATA, 2663219089Spjd &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr); 2664168404Spjd 2665219089Spjd if (dzp_error != 0 && !dzpcheck_privs) 2666168404Spjd return (dzp_error); 2667168404Spjd 2668168404Spjd /* 2669185029Spjd * Fourth row 2670168404Spjd */ 2671168404Spjd 2672219089Spjd available_perms = (dzp_working_mode & ACE_WRITE_DATA) ? 0 : VWRITE; 2673219089Spjd available_perms |= (dzp_working_mode & ACE_EXECUTE) ? 0 : VEXEC; 2674168404Spjd 2675219089Spjd return (zfs_delete_final_check(zp, dzp, available_perms, cr)); 2676185029Spjd 2677168404Spjd} 2678168404Spjd 2679168404Spjdint 2680168404Spjdzfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 2681168404Spjd znode_t *tzp, cred_t *cr) 2682168404Spjd{ 2683168404Spjd int add_perm; 2684168404Spjd int error; 2685168404Spjd 2686219089Spjd if (szp->z_pflags & ZFS_AV_QUARANTINED) 2687249643Smm return (SET_ERROR(EACCES)); 2688185029Spjd 2689168404Spjd add_perm = (ZTOV(szp)->v_type == VDIR) ? 2690168404Spjd ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 2691168404Spjd 2692168404Spjd /* 2693168404Spjd * Rename permissions are combination of delete permission + 2694168404Spjd * add file/subdir permission. 2695184770Strasz * 2696184770Strasz * BSD operating systems also require write permission 2697184770Strasz * on the directory being moved from one parent directory 2698184770Strasz * to another. 2699168404Spjd */ 2700184770Strasz if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) { 2701185029Spjd if (error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr)) 2702184770Strasz return (error); 2703184770Strasz } 2704168404Spjd 2705168404Spjd /* 2706168404Spjd * first make sure we do the delete portion. 2707168404Spjd * 2708168404Spjd * If that succeeds then check for add_file/add_subdir permissions 2709168404Spjd */ 2710168404Spjd 2711168404Spjd if (error = zfs_zaccess_delete(sdzp, szp, cr)) 2712168404Spjd return (error); 2713168404Spjd 2714168404Spjd /* 2715168404Spjd * If we have a tzp, see if we can delete it? 2716168404Spjd */ 2717168404Spjd if (tzp) { 2718168404Spjd if (error = zfs_zaccess_delete(tdzp, tzp, cr)) 2719168404Spjd return (error); 2720168404Spjd } 2721168404Spjd 2722168404Spjd /* 2723168404Spjd * Now check for add permissions 2724168404Spjd */ 2725185029Spjd error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); 2726168404Spjd 2727168404Spjd return (error); 2728168404Spjd} 2729