1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23eda14cbcSMatt Macy * Copyright (c) 2013 by Delphix. All rights reserved. 24eda14cbcSMatt Macy * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 25eda14cbcSMatt Macy */ 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy 28eda14cbcSMatt Macy #include <sys/types.h> 29eda14cbcSMatt Macy #include <sys/param.h> 30eda14cbcSMatt Macy #include <sys/time.h> 31eda14cbcSMatt Macy #include <sys/sysmacros.h> 32eda14cbcSMatt Macy #include <sys/vfs.h> 33eda14cbcSMatt Macy #include <sys/vnode.h> 34eda14cbcSMatt Macy #include <sys/sid.h> 35eda14cbcSMatt Macy #include <sys/file.h> 36eda14cbcSMatt Macy #include <sys/stat.h> 37eda14cbcSMatt Macy #include <sys/kmem.h> 38eda14cbcSMatt Macy #include <sys/cmn_err.h> 39eda14cbcSMatt Macy #include <sys/errno.h> 40eda14cbcSMatt Macy #include <sys/fs/zfs.h> 41eda14cbcSMatt Macy #include <sys/policy.h> 42eda14cbcSMatt Macy #include <sys/zfs_znode.h> 43eda14cbcSMatt Macy #include <sys/zfs_fuid.h> 44eda14cbcSMatt Macy #include <sys/zfs_acl.h> 45eda14cbcSMatt Macy #include <sys/zfs_dir.h> 46eda14cbcSMatt Macy #include <sys/zfs_quota.h> 47eda14cbcSMatt Macy #include <sys/zfs_vfsops.h> 48eda14cbcSMatt Macy #include <sys/dmu.h> 49eda14cbcSMatt Macy #include <sys/dnode.h> 50eda14cbcSMatt Macy #include <sys/zap.h> 51eda14cbcSMatt Macy #include <sys/sa.h> 52eda14cbcSMatt Macy #include <sys/trace_acl.h> 53eda14cbcSMatt Macy #include <sys/zpl.h> 54eda14cbcSMatt Macy 55eda14cbcSMatt Macy #define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE 56eda14cbcSMatt Macy #define DENY ACE_ACCESS_DENIED_ACE_TYPE 57eda14cbcSMatt Macy #define MAX_ACE_TYPE ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 58eda14cbcSMatt Macy #define MIN_ACE_TYPE ALLOW 59eda14cbcSMatt Macy 60eda14cbcSMatt Macy #define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 61eda14cbcSMatt Macy #define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 62eda14cbcSMatt Macy ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 63eda14cbcSMatt Macy #define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 64eda14cbcSMatt Macy ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 65eda14cbcSMatt Macy #define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 66eda14cbcSMatt Macy ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 67eda14cbcSMatt Macy 68eda14cbcSMatt Macy #define ZFS_CHECKED_MASKS (ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_DATA| \ 69eda14cbcSMatt Macy ACE_READ_NAMED_ATTRS|ACE_WRITE_DATA|ACE_WRITE_ATTRIBUTES| \ 70eda14cbcSMatt Macy ACE_WRITE_NAMED_ATTRS|ACE_APPEND_DATA|ACE_EXECUTE|ACE_WRITE_OWNER| \ 71eda14cbcSMatt Macy ACE_WRITE_ACL|ACE_DELETE|ACE_DELETE_CHILD|ACE_SYNCHRONIZE) 72eda14cbcSMatt Macy 73eda14cbcSMatt Macy #define WRITE_MASK_DATA (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS) 74eda14cbcSMatt Macy #define WRITE_MASK_ATTRS (ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES| \ 75eda14cbcSMatt Macy ACE_DELETE|ACE_DELETE_CHILD) 76eda14cbcSMatt Macy #define WRITE_MASK (WRITE_MASK_DATA|WRITE_MASK_ATTRS) 77eda14cbcSMatt Macy 78eda14cbcSMatt Macy #define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 79eda14cbcSMatt Macy ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 80eda14cbcSMatt Macy 81eda14cbcSMatt Macy #define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 82eda14cbcSMatt Macy ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 83eda14cbcSMatt Macy 84eda14cbcSMatt Macy #define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 85eda14cbcSMatt Macy ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE) 86eda14cbcSMatt Macy 87eda14cbcSMatt Macy #define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) 88eda14cbcSMatt Macy 89eda14cbcSMatt Macy #define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\ 90eda14cbcSMatt Macy ZFS_ACL_PROTECTED) 91eda14cbcSMatt Macy 92eda14cbcSMatt Macy #define ZFS_ACL_WIDE_FLAGS (V4_ACL_WIDE_FLAGS|ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|\ 93eda14cbcSMatt Macy ZFS_ACL_OBJ_ACE) 94eda14cbcSMatt Macy 95eda14cbcSMatt Macy #define ALL_MODE_EXECS (S_IXUSR | S_IXGRP | S_IXOTH) 96eda14cbcSMatt Macy 97eda14cbcSMatt Macy #define IDMAP_WK_CREATOR_OWNER_UID 2147483648U 98eda14cbcSMatt Macy 99eda14cbcSMatt Macy static uint16_t 100eda14cbcSMatt Macy zfs_ace_v0_get_type(void *acep) 101eda14cbcSMatt Macy { 102eda14cbcSMatt Macy return (((zfs_oldace_t *)acep)->z_type); 103eda14cbcSMatt Macy } 104eda14cbcSMatt Macy 105eda14cbcSMatt Macy static uint16_t 106eda14cbcSMatt Macy zfs_ace_v0_get_flags(void *acep) 107eda14cbcSMatt Macy { 108eda14cbcSMatt Macy return (((zfs_oldace_t *)acep)->z_flags); 109eda14cbcSMatt Macy } 110eda14cbcSMatt Macy 111eda14cbcSMatt Macy static uint32_t 112eda14cbcSMatt Macy zfs_ace_v0_get_mask(void *acep) 113eda14cbcSMatt Macy { 114eda14cbcSMatt Macy return (((zfs_oldace_t *)acep)->z_access_mask); 115eda14cbcSMatt Macy } 116eda14cbcSMatt Macy 117eda14cbcSMatt Macy static uint64_t 118eda14cbcSMatt Macy zfs_ace_v0_get_who(void *acep) 119eda14cbcSMatt Macy { 120eda14cbcSMatt Macy return (((zfs_oldace_t *)acep)->z_fuid); 121eda14cbcSMatt Macy } 122eda14cbcSMatt Macy 123eda14cbcSMatt Macy static void 124eda14cbcSMatt Macy zfs_ace_v0_set_type(void *acep, uint16_t type) 125eda14cbcSMatt Macy { 126eda14cbcSMatt Macy ((zfs_oldace_t *)acep)->z_type = type; 127eda14cbcSMatt Macy } 128eda14cbcSMatt Macy 129eda14cbcSMatt Macy static void 130eda14cbcSMatt Macy zfs_ace_v0_set_flags(void *acep, uint16_t flags) 131eda14cbcSMatt Macy { 132eda14cbcSMatt Macy ((zfs_oldace_t *)acep)->z_flags = flags; 133eda14cbcSMatt Macy } 134eda14cbcSMatt Macy 135eda14cbcSMatt Macy static void 136eda14cbcSMatt Macy zfs_ace_v0_set_mask(void *acep, uint32_t mask) 137eda14cbcSMatt Macy { 138eda14cbcSMatt Macy ((zfs_oldace_t *)acep)->z_access_mask = mask; 139eda14cbcSMatt Macy } 140eda14cbcSMatt Macy 141eda14cbcSMatt Macy static void 142eda14cbcSMatt Macy zfs_ace_v0_set_who(void *acep, uint64_t who) 143eda14cbcSMatt Macy { 144eda14cbcSMatt Macy ((zfs_oldace_t *)acep)->z_fuid = who; 145eda14cbcSMatt Macy } 146eda14cbcSMatt Macy 147eda14cbcSMatt Macy static size_t 148eda14cbcSMatt Macy zfs_ace_v0_size(void *acep) 149eda14cbcSMatt Macy { 150c03c5b1cSMartin Matuska (void) acep; 151eda14cbcSMatt Macy return (sizeof (zfs_oldace_t)); 152eda14cbcSMatt Macy } 153eda14cbcSMatt Macy 154eda14cbcSMatt Macy static size_t 155eda14cbcSMatt Macy zfs_ace_v0_abstract_size(void) 156eda14cbcSMatt Macy { 157eda14cbcSMatt Macy return (sizeof (zfs_oldace_t)); 158eda14cbcSMatt Macy } 159eda14cbcSMatt Macy 160eda14cbcSMatt Macy static int 161eda14cbcSMatt Macy zfs_ace_v0_mask_off(void) 162eda14cbcSMatt Macy { 163eda14cbcSMatt Macy return (offsetof(zfs_oldace_t, z_access_mask)); 164eda14cbcSMatt Macy } 165eda14cbcSMatt Macy 166eda14cbcSMatt Macy static int 167eda14cbcSMatt Macy zfs_ace_v0_data(void *acep, void **datap) 168eda14cbcSMatt Macy { 169c03c5b1cSMartin Matuska (void) acep; 170eda14cbcSMatt Macy *datap = NULL; 171eda14cbcSMatt Macy return (0); 172eda14cbcSMatt Macy } 173eda14cbcSMatt Macy 174e92ffd9bSMartin Matuska static const acl_ops_t zfs_acl_v0_ops = { 175eda14cbcSMatt Macy .ace_mask_get = zfs_ace_v0_get_mask, 176eda14cbcSMatt Macy .ace_mask_set = zfs_ace_v0_set_mask, 177eda14cbcSMatt Macy .ace_flags_get = zfs_ace_v0_get_flags, 178eda14cbcSMatt Macy .ace_flags_set = zfs_ace_v0_set_flags, 179eda14cbcSMatt Macy .ace_type_get = zfs_ace_v0_get_type, 180eda14cbcSMatt Macy .ace_type_set = zfs_ace_v0_set_type, 181eda14cbcSMatt Macy .ace_who_get = zfs_ace_v0_get_who, 182eda14cbcSMatt Macy .ace_who_set = zfs_ace_v0_set_who, 183eda14cbcSMatt Macy .ace_size = zfs_ace_v0_size, 184eda14cbcSMatt Macy .ace_abstract_size = zfs_ace_v0_abstract_size, 185eda14cbcSMatt Macy .ace_mask_off = zfs_ace_v0_mask_off, 186eda14cbcSMatt Macy .ace_data = zfs_ace_v0_data 187eda14cbcSMatt Macy }; 188eda14cbcSMatt Macy 189eda14cbcSMatt Macy static uint16_t 190eda14cbcSMatt Macy zfs_ace_fuid_get_type(void *acep) 191eda14cbcSMatt Macy { 192eda14cbcSMatt Macy return (((zfs_ace_hdr_t *)acep)->z_type); 193eda14cbcSMatt Macy } 194eda14cbcSMatt Macy 195eda14cbcSMatt Macy static uint16_t 196eda14cbcSMatt Macy zfs_ace_fuid_get_flags(void *acep) 197eda14cbcSMatt Macy { 198eda14cbcSMatt Macy return (((zfs_ace_hdr_t *)acep)->z_flags); 199eda14cbcSMatt Macy } 200eda14cbcSMatt Macy 201eda14cbcSMatt Macy static uint32_t 202eda14cbcSMatt Macy zfs_ace_fuid_get_mask(void *acep) 203eda14cbcSMatt Macy { 204eda14cbcSMatt Macy return (((zfs_ace_hdr_t *)acep)->z_access_mask); 205eda14cbcSMatt Macy } 206eda14cbcSMatt Macy 207eda14cbcSMatt Macy static uint64_t 208eda14cbcSMatt Macy zfs_ace_fuid_get_who(void *args) 209eda14cbcSMatt Macy { 210eda14cbcSMatt Macy uint16_t entry_type; 211eda14cbcSMatt Macy zfs_ace_t *acep = args; 212eda14cbcSMatt Macy 213eda14cbcSMatt Macy entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 214eda14cbcSMatt Macy 215eda14cbcSMatt Macy if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 216eda14cbcSMatt Macy entry_type == ACE_EVERYONE) 217eda14cbcSMatt Macy return (-1); 218eda14cbcSMatt Macy return (((zfs_ace_t *)acep)->z_fuid); 219eda14cbcSMatt Macy } 220eda14cbcSMatt Macy 221eda14cbcSMatt Macy static void 222eda14cbcSMatt Macy zfs_ace_fuid_set_type(void *acep, uint16_t type) 223eda14cbcSMatt Macy { 224eda14cbcSMatt Macy ((zfs_ace_hdr_t *)acep)->z_type = type; 225eda14cbcSMatt Macy } 226eda14cbcSMatt Macy 227eda14cbcSMatt Macy static void 228eda14cbcSMatt Macy zfs_ace_fuid_set_flags(void *acep, uint16_t flags) 229eda14cbcSMatt Macy { 230eda14cbcSMatt Macy ((zfs_ace_hdr_t *)acep)->z_flags = flags; 231eda14cbcSMatt Macy } 232eda14cbcSMatt Macy 233eda14cbcSMatt Macy static void 234eda14cbcSMatt Macy zfs_ace_fuid_set_mask(void *acep, uint32_t mask) 235eda14cbcSMatt Macy { 236eda14cbcSMatt Macy ((zfs_ace_hdr_t *)acep)->z_access_mask = mask; 237eda14cbcSMatt Macy } 238eda14cbcSMatt Macy 239eda14cbcSMatt Macy static void 240eda14cbcSMatt Macy zfs_ace_fuid_set_who(void *arg, uint64_t who) 241eda14cbcSMatt Macy { 242eda14cbcSMatt Macy zfs_ace_t *acep = arg; 243eda14cbcSMatt Macy 244eda14cbcSMatt Macy uint16_t entry_type = acep->z_hdr.z_flags & ACE_TYPE_FLAGS; 245eda14cbcSMatt Macy 246eda14cbcSMatt Macy if (entry_type == ACE_OWNER || entry_type == OWNING_GROUP || 247eda14cbcSMatt Macy entry_type == ACE_EVERYONE) 248eda14cbcSMatt Macy return; 249eda14cbcSMatt Macy acep->z_fuid = who; 250eda14cbcSMatt Macy } 251eda14cbcSMatt Macy 252eda14cbcSMatt Macy static size_t 253eda14cbcSMatt Macy zfs_ace_fuid_size(void *acep) 254eda14cbcSMatt Macy { 255eda14cbcSMatt Macy zfs_ace_hdr_t *zacep = acep; 256eda14cbcSMatt Macy uint16_t entry_type; 257eda14cbcSMatt Macy 258eda14cbcSMatt Macy switch (zacep->z_type) { 259eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 260eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 261eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 262eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 263eda14cbcSMatt Macy return (sizeof (zfs_object_ace_t)); 264eda14cbcSMatt Macy case ALLOW: 265eda14cbcSMatt Macy case DENY: 266eda14cbcSMatt Macy entry_type = 267eda14cbcSMatt Macy (((zfs_ace_hdr_t *)acep)->z_flags & ACE_TYPE_FLAGS); 268eda14cbcSMatt Macy if (entry_type == ACE_OWNER || 269eda14cbcSMatt Macy entry_type == OWNING_GROUP || 270eda14cbcSMatt Macy entry_type == ACE_EVERYONE) 271eda14cbcSMatt Macy return (sizeof (zfs_ace_hdr_t)); 272c03c5b1cSMartin Matuska zfs_fallthrough; 273eda14cbcSMatt Macy default: 274eda14cbcSMatt Macy return (sizeof (zfs_ace_t)); 275eda14cbcSMatt Macy } 276eda14cbcSMatt Macy } 277eda14cbcSMatt Macy 278eda14cbcSMatt Macy static size_t 279eda14cbcSMatt Macy zfs_ace_fuid_abstract_size(void) 280eda14cbcSMatt Macy { 281eda14cbcSMatt Macy return (sizeof (zfs_ace_hdr_t)); 282eda14cbcSMatt Macy } 283eda14cbcSMatt Macy 284eda14cbcSMatt Macy static int 285eda14cbcSMatt Macy zfs_ace_fuid_mask_off(void) 286eda14cbcSMatt Macy { 287eda14cbcSMatt Macy return (offsetof(zfs_ace_hdr_t, z_access_mask)); 288eda14cbcSMatt Macy } 289eda14cbcSMatt Macy 290eda14cbcSMatt Macy static int 291eda14cbcSMatt Macy zfs_ace_fuid_data(void *acep, void **datap) 292eda14cbcSMatt Macy { 293eda14cbcSMatt Macy zfs_ace_t *zacep = acep; 294eda14cbcSMatt Macy zfs_object_ace_t *zobjp; 295eda14cbcSMatt Macy 296eda14cbcSMatt Macy switch (zacep->z_hdr.z_type) { 297eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 298eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 299eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 300eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 301eda14cbcSMatt Macy zobjp = acep; 302eda14cbcSMatt Macy *datap = (caddr_t)zobjp + sizeof (zfs_ace_t); 303eda14cbcSMatt Macy return (sizeof (zfs_object_ace_t) - sizeof (zfs_ace_t)); 304eda14cbcSMatt Macy default: 305eda14cbcSMatt Macy *datap = NULL; 306eda14cbcSMatt Macy return (0); 307eda14cbcSMatt Macy } 308eda14cbcSMatt Macy } 309eda14cbcSMatt Macy 310e92ffd9bSMartin Matuska static const acl_ops_t zfs_acl_fuid_ops = { 311eda14cbcSMatt Macy .ace_mask_get = zfs_ace_fuid_get_mask, 312eda14cbcSMatt Macy .ace_mask_set = zfs_ace_fuid_set_mask, 313eda14cbcSMatt Macy .ace_flags_get = zfs_ace_fuid_get_flags, 314eda14cbcSMatt Macy .ace_flags_set = zfs_ace_fuid_set_flags, 315eda14cbcSMatt Macy .ace_type_get = zfs_ace_fuid_get_type, 316eda14cbcSMatt Macy .ace_type_set = zfs_ace_fuid_set_type, 317eda14cbcSMatt Macy .ace_who_get = zfs_ace_fuid_get_who, 318eda14cbcSMatt Macy .ace_who_set = zfs_ace_fuid_set_who, 319eda14cbcSMatt Macy .ace_size = zfs_ace_fuid_size, 320eda14cbcSMatt Macy .ace_abstract_size = zfs_ace_fuid_abstract_size, 321eda14cbcSMatt Macy .ace_mask_off = zfs_ace_fuid_mask_off, 322eda14cbcSMatt Macy .ace_data = zfs_ace_fuid_data 323eda14cbcSMatt Macy }; 324eda14cbcSMatt Macy 325eda14cbcSMatt Macy /* 326eda14cbcSMatt Macy * The following three functions are provided for compatibility with 327eda14cbcSMatt Macy * older ZPL version in order to determine if the file use to have 328eda14cbcSMatt Macy * an external ACL and what version of ACL previously existed on the 329eda14cbcSMatt Macy * file. Would really be nice to not need this, sigh. 330eda14cbcSMatt Macy */ 331eda14cbcSMatt Macy uint64_t 332eda14cbcSMatt Macy zfs_external_acl(znode_t *zp) 333eda14cbcSMatt Macy { 334eda14cbcSMatt Macy zfs_acl_phys_t acl_phys; 335eda14cbcSMatt Macy int error; 336eda14cbcSMatt Macy 337eda14cbcSMatt Macy if (zp->z_is_sa) 338eda14cbcSMatt Macy return (0); 339eda14cbcSMatt Macy 340eda14cbcSMatt Macy /* 341eda14cbcSMatt Macy * Need to deal with a potential 342eda14cbcSMatt Macy * race where zfs_sa_upgrade could cause 343eda14cbcSMatt Macy * z_isa_sa to change. 344eda14cbcSMatt Macy * 345eda14cbcSMatt Macy * If the lookup fails then the state of z_is_sa should have 346eda14cbcSMatt Macy * changed. 347eda14cbcSMatt Macy */ 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(ZTOZSB(zp)), 350eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys))) == 0) 351eda14cbcSMatt Macy return (acl_phys.z_acl_extern_obj); 352eda14cbcSMatt Macy else { 353eda14cbcSMatt Macy /* 354eda14cbcSMatt Macy * after upgrade the SA_ZPL_ZNODE_ACL should have been 355eda14cbcSMatt Macy * removed 356eda14cbcSMatt Macy */ 357eda14cbcSMatt Macy VERIFY(zp->z_is_sa && error == ENOENT); 358eda14cbcSMatt Macy return (0); 359eda14cbcSMatt Macy } 360eda14cbcSMatt Macy } 361eda14cbcSMatt Macy 362eda14cbcSMatt Macy /* 363eda14cbcSMatt Macy * Determine size of ACL in bytes 364eda14cbcSMatt Macy * 365eda14cbcSMatt Macy * This is more complicated than it should be since we have to deal 366eda14cbcSMatt Macy * with old external ACLs. 367eda14cbcSMatt Macy */ 368eda14cbcSMatt Macy static int 369eda14cbcSMatt Macy zfs_acl_znode_info(znode_t *zp, int *aclsize, int *aclcount, 370eda14cbcSMatt Macy zfs_acl_phys_t *aclphys) 371eda14cbcSMatt Macy { 372eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 373eda14cbcSMatt Macy uint64_t acl_count; 374eda14cbcSMatt Macy int size; 375eda14cbcSMatt Macy int error; 376eda14cbcSMatt Macy 377eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 378eda14cbcSMatt Macy if (zp->z_is_sa) { 379eda14cbcSMatt Macy if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zfsvfs), 380eda14cbcSMatt Macy &size)) != 0) 381eda14cbcSMatt Macy return (error); 382eda14cbcSMatt Macy *aclsize = size; 383eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_COUNT(zfsvfs), 384eda14cbcSMatt Macy &acl_count, sizeof (acl_count))) != 0) 385eda14cbcSMatt Macy return (error); 386eda14cbcSMatt Macy *aclcount = acl_count; 387eda14cbcSMatt Macy } else { 388eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), 389eda14cbcSMatt Macy aclphys, sizeof (*aclphys))) != 0) 390eda14cbcSMatt Macy return (error); 391eda14cbcSMatt Macy 392eda14cbcSMatt Macy if (aclphys->z_acl_version == ZFS_ACL_VERSION_INITIAL) { 393eda14cbcSMatt Macy *aclsize = ZFS_ACL_SIZE(aclphys->z_acl_size); 394eda14cbcSMatt Macy *aclcount = aclphys->z_acl_size; 395eda14cbcSMatt Macy } else { 396eda14cbcSMatt Macy *aclsize = aclphys->z_acl_size; 397eda14cbcSMatt Macy *aclcount = aclphys->z_acl_count; 398eda14cbcSMatt Macy } 399eda14cbcSMatt Macy } 400eda14cbcSMatt Macy return (0); 401eda14cbcSMatt Macy } 402eda14cbcSMatt Macy 403eda14cbcSMatt Macy int 404eda14cbcSMatt Macy zfs_znode_acl_version(znode_t *zp) 405eda14cbcSMatt Macy { 406eda14cbcSMatt Macy zfs_acl_phys_t acl_phys; 407eda14cbcSMatt Macy 408eda14cbcSMatt Macy if (zp->z_is_sa) 409eda14cbcSMatt Macy return (ZFS_ACL_VERSION_FUID); 410eda14cbcSMatt Macy else { 411eda14cbcSMatt Macy int error; 412eda14cbcSMatt Macy 413eda14cbcSMatt Macy /* 414eda14cbcSMatt Macy * Need to deal with a potential 415eda14cbcSMatt Macy * race where zfs_sa_upgrade could cause 416eda14cbcSMatt Macy * z_isa_sa to change. 417eda14cbcSMatt Macy * 418eda14cbcSMatt Macy * If the lookup fails then the state of z_is_sa should have 419eda14cbcSMatt Macy * changed. 420eda14cbcSMatt Macy */ 421eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, 422eda14cbcSMatt Macy SA_ZPL_ZNODE_ACL(ZTOZSB(zp)), 423eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys))) == 0) 424eda14cbcSMatt Macy return (acl_phys.z_acl_version); 425eda14cbcSMatt Macy else { 426eda14cbcSMatt Macy /* 427eda14cbcSMatt Macy * After upgrade SA_ZPL_ZNODE_ACL should have 428eda14cbcSMatt Macy * been removed. 429eda14cbcSMatt Macy */ 430eda14cbcSMatt Macy VERIFY(zp->z_is_sa && error == ENOENT); 431eda14cbcSMatt Macy return (ZFS_ACL_VERSION_FUID); 432eda14cbcSMatt Macy } 433eda14cbcSMatt Macy } 434eda14cbcSMatt Macy } 435eda14cbcSMatt Macy 436eda14cbcSMatt Macy static int 437eda14cbcSMatt Macy zfs_acl_version(int version) 438eda14cbcSMatt Macy { 439eda14cbcSMatt Macy if (version < ZPL_VERSION_FUID) 440eda14cbcSMatt Macy return (ZFS_ACL_VERSION_INITIAL); 441eda14cbcSMatt Macy else 442eda14cbcSMatt Macy return (ZFS_ACL_VERSION_FUID); 443eda14cbcSMatt Macy } 444eda14cbcSMatt Macy 445eda14cbcSMatt Macy static int 446eda14cbcSMatt Macy zfs_acl_version_zp(znode_t *zp) 447eda14cbcSMatt Macy { 448eda14cbcSMatt Macy return (zfs_acl_version(ZTOZSB(zp)->z_version)); 449eda14cbcSMatt Macy } 450eda14cbcSMatt Macy 451eda14cbcSMatt Macy zfs_acl_t * 452eda14cbcSMatt Macy zfs_acl_alloc(int vers) 453eda14cbcSMatt Macy { 454eda14cbcSMatt Macy zfs_acl_t *aclp; 455eda14cbcSMatt Macy 456eda14cbcSMatt Macy aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 457eda14cbcSMatt Macy list_create(&aclp->z_acl, sizeof (zfs_acl_node_t), 458eda14cbcSMatt Macy offsetof(zfs_acl_node_t, z_next)); 459eda14cbcSMatt Macy aclp->z_version = vers; 460eda14cbcSMatt Macy if (vers == ZFS_ACL_VERSION_FUID) 461eda14cbcSMatt Macy aclp->z_ops = &zfs_acl_fuid_ops; 462eda14cbcSMatt Macy else 463eda14cbcSMatt Macy aclp->z_ops = &zfs_acl_v0_ops; 464eda14cbcSMatt Macy return (aclp); 465eda14cbcSMatt Macy } 466eda14cbcSMatt Macy 467eda14cbcSMatt Macy zfs_acl_node_t * 468eda14cbcSMatt Macy zfs_acl_node_alloc(size_t bytes) 469eda14cbcSMatt Macy { 470eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 471eda14cbcSMatt Macy 472eda14cbcSMatt Macy aclnode = kmem_zalloc(sizeof (zfs_acl_node_t), KM_SLEEP); 473eda14cbcSMatt Macy if (bytes) { 474*7a7741afSMartin Matuska aclnode->z_acldata = kmem_zalloc(bytes, KM_SLEEP); 475eda14cbcSMatt Macy aclnode->z_allocdata = aclnode->z_acldata; 476eda14cbcSMatt Macy aclnode->z_allocsize = bytes; 477eda14cbcSMatt Macy aclnode->z_size = bytes; 478eda14cbcSMatt Macy } 479eda14cbcSMatt Macy 480eda14cbcSMatt Macy return (aclnode); 481eda14cbcSMatt Macy } 482eda14cbcSMatt Macy 483eda14cbcSMatt Macy static void 484eda14cbcSMatt Macy zfs_acl_node_free(zfs_acl_node_t *aclnode) 485eda14cbcSMatt Macy { 486eda14cbcSMatt Macy if (aclnode->z_allocsize) 487eda14cbcSMatt Macy kmem_free(aclnode->z_allocdata, aclnode->z_allocsize); 488eda14cbcSMatt Macy kmem_free(aclnode, sizeof (zfs_acl_node_t)); 489eda14cbcSMatt Macy } 490eda14cbcSMatt Macy 491eda14cbcSMatt Macy static void 492eda14cbcSMatt Macy zfs_acl_release_nodes(zfs_acl_t *aclp) 493eda14cbcSMatt Macy { 494eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 495eda14cbcSMatt Macy 4964e8d558cSMartin Matuska while ((aclnode = list_remove_head(&aclp->z_acl))) 497eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 498eda14cbcSMatt Macy aclp->z_acl_count = 0; 499eda14cbcSMatt Macy aclp->z_acl_bytes = 0; 500eda14cbcSMatt Macy } 501eda14cbcSMatt Macy 502eda14cbcSMatt Macy void 503eda14cbcSMatt Macy zfs_acl_free(zfs_acl_t *aclp) 504eda14cbcSMatt Macy { 505eda14cbcSMatt Macy zfs_acl_release_nodes(aclp); 506eda14cbcSMatt Macy list_destroy(&aclp->z_acl); 507eda14cbcSMatt Macy kmem_free(aclp, sizeof (zfs_acl_t)); 508eda14cbcSMatt Macy } 509eda14cbcSMatt Macy 510eda14cbcSMatt Macy static boolean_t 511eda14cbcSMatt Macy zfs_acl_valid_ace_type(uint_t type, uint_t flags) 512eda14cbcSMatt Macy { 513eda14cbcSMatt Macy uint16_t entry_type; 514eda14cbcSMatt Macy 515eda14cbcSMatt Macy switch (type) { 516eda14cbcSMatt Macy case ALLOW: 517eda14cbcSMatt Macy case DENY: 518eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_ACE_TYPE: 519eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_ACE_TYPE: 520eda14cbcSMatt Macy entry_type = flags & ACE_TYPE_FLAGS; 521eda14cbcSMatt Macy return (entry_type == ACE_OWNER || 522eda14cbcSMatt Macy entry_type == OWNING_GROUP || 523eda14cbcSMatt Macy entry_type == ACE_EVERYONE || entry_type == 0 || 524eda14cbcSMatt Macy entry_type == ACE_IDENTIFIER_GROUP); 525eda14cbcSMatt Macy default: 526be181ee2SMartin Matuska if (type <= MAX_ACE_TYPE) 527eda14cbcSMatt Macy return (B_TRUE); 528eda14cbcSMatt Macy } 529eda14cbcSMatt Macy return (B_FALSE); 530eda14cbcSMatt Macy } 531eda14cbcSMatt Macy 532eda14cbcSMatt Macy static boolean_t 533eda14cbcSMatt Macy zfs_ace_valid(umode_t obj_mode, zfs_acl_t *aclp, uint16_t type, uint16_t iflags) 534eda14cbcSMatt Macy { 535eda14cbcSMatt Macy /* 536eda14cbcSMatt Macy * first check type of entry 537eda14cbcSMatt Macy */ 538eda14cbcSMatt Macy 539eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 540eda14cbcSMatt Macy return (B_FALSE); 541eda14cbcSMatt Macy 542eda14cbcSMatt Macy switch (type) { 543eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 544eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 545eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 546eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 547eda14cbcSMatt Macy if (aclp->z_version < ZFS_ACL_VERSION_FUID) 548eda14cbcSMatt Macy return (B_FALSE); 549eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_OBJ_ACE; 550eda14cbcSMatt Macy } 551eda14cbcSMatt Macy 552eda14cbcSMatt Macy /* 553eda14cbcSMatt Macy * next check inheritance level flags 554eda14cbcSMatt Macy */ 555eda14cbcSMatt Macy 556eda14cbcSMatt Macy if (S_ISDIR(obj_mode) && 557eda14cbcSMatt Macy (iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 558eda14cbcSMatt Macy aclp->z_hints |= ZFS_INHERIT_ACE; 559eda14cbcSMatt Macy 560eda14cbcSMatt Macy if (iflags & (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 561eda14cbcSMatt Macy if ((iflags & (ACE_FILE_INHERIT_ACE| 562eda14cbcSMatt Macy ACE_DIRECTORY_INHERIT_ACE)) == 0) { 563eda14cbcSMatt Macy return (B_FALSE); 564eda14cbcSMatt Macy } 565eda14cbcSMatt Macy } 566eda14cbcSMatt Macy 567eda14cbcSMatt Macy return (B_TRUE); 568eda14cbcSMatt Macy } 569eda14cbcSMatt Macy 570eda14cbcSMatt Macy static void * 571eda14cbcSMatt Macy zfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who, 572eda14cbcSMatt Macy uint32_t *access_mask, uint16_t *iflags, uint16_t *type) 573eda14cbcSMatt Macy { 574eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 575eda14cbcSMatt Macy 576eda14cbcSMatt Macy ASSERT(aclp); 577eda14cbcSMatt Macy 578eda14cbcSMatt Macy if (start == NULL) { 579eda14cbcSMatt Macy aclnode = list_head(&aclp->z_acl); 580eda14cbcSMatt Macy if (aclnode == NULL) 581eda14cbcSMatt Macy return (NULL); 582eda14cbcSMatt Macy 583eda14cbcSMatt Macy aclp->z_next_ace = aclnode->z_acldata; 584eda14cbcSMatt Macy aclp->z_curr_node = aclnode; 585eda14cbcSMatt Macy aclnode->z_ace_idx = 0; 586eda14cbcSMatt Macy } 587eda14cbcSMatt Macy 588eda14cbcSMatt Macy aclnode = aclp->z_curr_node; 589eda14cbcSMatt Macy 590eda14cbcSMatt Macy if (aclnode == NULL) 591eda14cbcSMatt Macy return (NULL); 592eda14cbcSMatt Macy 593eda14cbcSMatt Macy if (aclnode->z_ace_idx >= aclnode->z_ace_count) { 594eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode); 595eda14cbcSMatt Macy if (aclnode == NULL) 596eda14cbcSMatt Macy return (NULL); 597eda14cbcSMatt Macy else { 598eda14cbcSMatt Macy aclp->z_curr_node = aclnode; 599eda14cbcSMatt Macy aclnode->z_ace_idx = 0; 600eda14cbcSMatt Macy aclp->z_next_ace = aclnode->z_acldata; 601eda14cbcSMatt Macy } 602eda14cbcSMatt Macy } 603eda14cbcSMatt Macy 604eda14cbcSMatt Macy if (aclnode->z_ace_idx < aclnode->z_ace_count) { 605eda14cbcSMatt Macy void *acep = aclp->z_next_ace; 606eda14cbcSMatt Macy size_t ace_size; 607eda14cbcSMatt Macy 608eda14cbcSMatt Macy /* 609eda14cbcSMatt Macy * Make sure we don't overstep our bounds 610eda14cbcSMatt Macy */ 611eda14cbcSMatt Macy ace_size = aclp->z_ops->ace_size(acep); 612eda14cbcSMatt Macy 613eda14cbcSMatt Macy if (((caddr_t)acep + ace_size) > 614eda14cbcSMatt Macy ((caddr_t)aclnode->z_acldata + aclnode->z_size)) { 615eda14cbcSMatt Macy return (NULL); 616eda14cbcSMatt Macy } 617eda14cbcSMatt Macy 618eda14cbcSMatt Macy *iflags = aclp->z_ops->ace_flags_get(acep); 619eda14cbcSMatt Macy *type = aclp->z_ops->ace_type_get(acep); 620eda14cbcSMatt Macy *access_mask = aclp->z_ops->ace_mask_get(acep); 621eda14cbcSMatt Macy *who = aclp->z_ops->ace_who_get(acep); 622eda14cbcSMatt Macy aclp->z_next_ace = (caddr_t)aclp->z_next_ace + ace_size; 623eda14cbcSMatt Macy aclnode->z_ace_idx++; 624eda14cbcSMatt Macy 625eda14cbcSMatt Macy return ((void *)acep); 626eda14cbcSMatt Macy } 627eda14cbcSMatt Macy return (NULL); 628eda14cbcSMatt Macy } 629eda14cbcSMatt Macy 630dbd5678dSMartin Matuska static uintptr_t 631dbd5678dSMartin Matuska zfs_ace_walk(void *datap, uintptr_t cookie, int aclcnt, 632eda14cbcSMatt Macy uint16_t *flags, uint16_t *type, uint32_t *mask) 633eda14cbcSMatt Macy { 634c03c5b1cSMartin Matuska (void) aclcnt; 635eda14cbcSMatt Macy zfs_acl_t *aclp = datap; 636dbd5678dSMartin Matuska zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)cookie; 637eda14cbcSMatt Macy uint64_t who; 638eda14cbcSMatt Macy 639eda14cbcSMatt Macy acep = zfs_acl_next_ace(aclp, acep, &who, mask, 640eda14cbcSMatt Macy flags, type); 641dbd5678dSMartin Matuska return ((uintptr_t)acep); 642eda14cbcSMatt Macy } 643eda14cbcSMatt Macy 644eda14cbcSMatt Macy /* 645eda14cbcSMatt Macy * Copy ACE to internal ZFS format. 646eda14cbcSMatt Macy * While processing the ACL each ACE will be validated for correctness. 647eda14cbcSMatt Macy * ACE FUIDs will be created later. 648eda14cbcSMatt Macy */ 649eda14cbcSMatt Macy static int 650eda14cbcSMatt Macy zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, umode_t obj_mode, zfs_acl_t *aclp, 651eda14cbcSMatt Macy void *datap, zfs_ace_t *z_acl, uint64_t aclcnt, size_t *size, 652eda14cbcSMatt Macy zfs_fuid_info_t **fuidp, cred_t *cr) 653eda14cbcSMatt Macy { 654eda14cbcSMatt Macy int i; 655eda14cbcSMatt Macy uint16_t entry_type; 656eda14cbcSMatt Macy zfs_ace_t *aceptr = z_acl; 657eda14cbcSMatt Macy ace_t *acep = datap; 658eda14cbcSMatt Macy zfs_object_ace_t *zobjacep; 659eda14cbcSMatt Macy ace_object_t *aceobjp; 660eda14cbcSMatt Macy 661eda14cbcSMatt Macy for (i = 0; i != aclcnt; i++) { 662eda14cbcSMatt Macy aceptr->z_hdr.z_access_mask = acep->a_access_mask; 663eda14cbcSMatt Macy aceptr->z_hdr.z_flags = acep->a_flags; 664eda14cbcSMatt Macy aceptr->z_hdr.z_type = acep->a_type; 665eda14cbcSMatt Macy entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS; 666eda14cbcSMatt Macy if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP && 667eda14cbcSMatt Macy entry_type != ACE_EVERYONE) { 668eda14cbcSMatt Macy aceptr->z_fuid = zfs_fuid_create(zfsvfs, acep->a_who, 669eda14cbcSMatt Macy cr, (entry_type == 0) ? 670eda14cbcSMatt Macy ZFS_ACE_USER : ZFS_ACE_GROUP, fuidp); 671eda14cbcSMatt Macy } 672eda14cbcSMatt Macy 673eda14cbcSMatt Macy /* 674eda14cbcSMatt Macy * Make sure ACE is valid 675eda14cbcSMatt Macy */ 676eda14cbcSMatt Macy if (zfs_ace_valid(obj_mode, aclp, aceptr->z_hdr.z_type, 677eda14cbcSMatt Macy aceptr->z_hdr.z_flags) != B_TRUE) 678eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 679eda14cbcSMatt Macy 680eda14cbcSMatt Macy switch (acep->a_type) { 681eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 682eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 683eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 684eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 685eda14cbcSMatt Macy zobjacep = (zfs_object_ace_t *)aceptr; 686eda14cbcSMatt Macy aceobjp = (ace_object_t *)acep; 687eda14cbcSMatt Macy 688da5137abSMartin Matuska memcpy(zobjacep->z_object_type, aceobjp->a_obj_type, 689eda14cbcSMatt Macy sizeof (aceobjp->a_obj_type)); 690da5137abSMartin Matuska memcpy(zobjacep->z_inherit_type, 691da5137abSMartin Matuska aceobjp->a_inherit_obj_type, 692eda14cbcSMatt Macy sizeof (aceobjp->a_inherit_obj_type)); 693eda14cbcSMatt Macy acep = (ace_t *)((caddr_t)acep + sizeof (ace_object_t)); 694eda14cbcSMatt Macy break; 695eda14cbcSMatt Macy default: 696eda14cbcSMatt Macy acep = (ace_t *)((caddr_t)acep + sizeof (ace_t)); 697eda14cbcSMatt Macy } 698eda14cbcSMatt Macy 699eda14cbcSMatt Macy aceptr = (zfs_ace_t *)((caddr_t)aceptr + 700eda14cbcSMatt Macy aclp->z_ops->ace_size(aceptr)); 701eda14cbcSMatt Macy } 702eda14cbcSMatt Macy 703eda14cbcSMatt Macy *size = (caddr_t)aceptr - (caddr_t)z_acl; 704eda14cbcSMatt Macy 705eda14cbcSMatt Macy return (0); 706eda14cbcSMatt Macy } 707eda14cbcSMatt Macy 708eda14cbcSMatt Macy /* 709eda14cbcSMatt Macy * Copy ZFS ACEs to fixed size ace_t layout 710eda14cbcSMatt Macy */ 711eda14cbcSMatt Macy static void 712eda14cbcSMatt Macy zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr, 713eda14cbcSMatt Macy void *datap, int filter) 714eda14cbcSMatt Macy { 715eda14cbcSMatt Macy uint64_t who; 716eda14cbcSMatt Macy uint32_t access_mask; 717eda14cbcSMatt Macy uint16_t iflags, type; 718eda14cbcSMatt Macy zfs_ace_hdr_t *zacep = NULL; 719eda14cbcSMatt Macy ace_t *acep = datap; 720eda14cbcSMatt Macy ace_object_t *objacep; 721eda14cbcSMatt Macy zfs_object_ace_t *zobjacep; 722eda14cbcSMatt Macy size_t ace_size; 723eda14cbcSMatt Macy uint16_t entry_type; 724eda14cbcSMatt Macy 725eda14cbcSMatt Macy while ((zacep = zfs_acl_next_ace(aclp, zacep, 726eda14cbcSMatt Macy &who, &access_mask, &iflags, &type))) { 727eda14cbcSMatt Macy 728eda14cbcSMatt Macy switch (type) { 729eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 730eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 731eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 732eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 733eda14cbcSMatt Macy if (filter) { 734eda14cbcSMatt Macy continue; 735eda14cbcSMatt Macy } 736eda14cbcSMatt Macy zobjacep = (zfs_object_ace_t *)zacep; 737eda14cbcSMatt Macy objacep = (ace_object_t *)acep; 738da5137abSMartin Matuska memcpy(objacep->a_obj_type, 739da5137abSMartin Matuska zobjacep->z_object_type, 740eda14cbcSMatt Macy sizeof (zobjacep->z_object_type)); 741da5137abSMartin Matuska memcpy(objacep->a_inherit_obj_type, 742da5137abSMartin Matuska zobjacep->z_inherit_type, 743eda14cbcSMatt Macy sizeof (zobjacep->z_inherit_type)); 744eda14cbcSMatt Macy ace_size = sizeof (ace_object_t); 745eda14cbcSMatt Macy break; 746eda14cbcSMatt Macy default: 747eda14cbcSMatt Macy ace_size = sizeof (ace_t); 748eda14cbcSMatt Macy break; 749eda14cbcSMatt Macy } 750eda14cbcSMatt Macy 751eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 752eda14cbcSMatt Macy if ((entry_type != ACE_OWNER && 753eda14cbcSMatt Macy entry_type != OWNING_GROUP && 754eda14cbcSMatt Macy entry_type != ACE_EVERYONE)) { 755eda14cbcSMatt Macy acep->a_who = zfs_fuid_map_id(zfsvfs, who, 756eda14cbcSMatt Macy cr, (entry_type & ACE_IDENTIFIER_GROUP) ? 757eda14cbcSMatt Macy ZFS_ACE_GROUP : ZFS_ACE_USER); 758eda14cbcSMatt Macy } else { 759eda14cbcSMatt Macy acep->a_who = (uid_t)(int64_t)who; 760eda14cbcSMatt Macy } 761eda14cbcSMatt Macy acep->a_access_mask = access_mask; 762eda14cbcSMatt Macy acep->a_flags = iflags; 763eda14cbcSMatt Macy acep->a_type = type; 764eda14cbcSMatt Macy acep = (ace_t *)((caddr_t)acep + ace_size); 765eda14cbcSMatt Macy } 766eda14cbcSMatt Macy } 767eda14cbcSMatt Macy 768eda14cbcSMatt Macy static int 769eda14cbcSMatt Macy zfs_copy_ace_2_oldace(umode_t obj_mode, zfs_acl_t *aclp, ace_t *acep, 770eda14cbcSMatt Macy zfs_oldace_t *z_acl, int aclcnt, size_t *size) 771eda14cbcSMatt Macy { 772eda14cbcSMatt Macy int i; 773eda14cbcSMatt Macy zfs_oldace_t *aceptr = z_acl; 774eda14cbcSMatt Macy 775eda14cbcSMatt Macy for (i = 0; i != aclcnt; i++, aceptr++) { 776eda14cbcSMatt Macy aceptr->z_access_mask = acep[i].a_access_mask; 777eda14cbcSMatt Macy aceptr->z_type = acep[i].a_type; 778eda14cbcSMatt Macy aceptr->z_flags = acep[i].a_flags; 779eda14cbcSMatt Macy aceptr->z_fuid = acep[i].a_who; 780eda14cbcSMatt Macy /* 781eda14cbcSMatt Macy * Make sure ACE is valid 782eda14cbcSMatt Macy */ 783eda14cbcSMatt Macy if (zfs_ace_valid(obj_mode, aclp, aceptr->z_type, 784eda14cbcSMatt Macy aceptr->z_flags) != B_TRUE) 785eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 786eda14cbcSMatt Macy } 787eda14cbcSMatt Macy *size = (caddr_t)aceptr - (caddr_t)z_acl; 788eda14cbcSMatt Macy return (0); 789eda14cbcSMatt Macy } 790eda14cbcSMatt Macy 791eda14cbcSMatt Macy /* 792eda14cbcSMatt Macy * convert old ACL format to new 793eda14cbcSMatt Macy */ 794eda14cbcSMatt Macy void 795eda14cbcSMatt Macy zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr) 796eda14cbcSMatt Macy { 797eda14cbcSMatt Macy zfs_oldace_t *oldaclp; 798eda14cbcSMatt Macy int i; 799eda14cbcSMatt Macy uint16_t type, iflags; 800eda14cbcSMatt Macy uint32_t access_mask; 801eda14cbcSMatt Macy uint64_t who; 802eda14cbcSMatt Macy void *cookie = NULL; 803eda14cbcSMatt Macy zfs_acl_node_t *newaclnode; 804eda14cbcSMatt Macy 805eda14cbcSMatt Macy ASSERT(aclp->z_version == ZFS_ACL_VERSION_INITIAL); 806eda14cbcSMatt Macy /* 807eda14cbcSMatt Macy * First create the ACE in a contiguous piece of memory 808eda14cbcSMatt Macy * for zfs_copy_ace_2_fuid(). 809eda14cbcSMatt Macy * 810eda14cbcSMatt Macy * We only convert an ACL once, so this won't happen 811eda14cbcSMatt Macy * every time. 812eda14cbcSMatt Macy */ 813eda14cbcSMatt Macy oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count, 814eda14cbcSMatt Macy KM_SLEEP); 815eda14cbcSMatt Macy i = 0; 816eda14cbcSMatt Macy while ((cookie = zfs_acl_next_ace(aclp, cookie, &who, 817eda14cbcSMatt Macy &access_mask, &iflags, &type))) { 818eda14cbcSMatt Macy oldaclp[i].z_flags = iflags; 819eda14cbcSMatt Macy oldaclp[i].z_type = type; 820eda14cbcSMatt Macy oldaclp[i].z_fuid = who; 821eda14cbcSMatt Macy oldaclp[i++].z_access_mask = access_mask; 822eda14cbcSMatt Macy } 823eda14cbcSMatt Macy 824eda14cbcSMatt Macy newaclnode = zfs_acl_node_alloc(aclp->z_acl_count * 825eda14cbcSMatt Macy sizeof (zfs_object_ace_t)); 826eda14cbcSMatt Macy aclp->z_ops = &zfs_acl_fuid_ops; 827eda14cbcSMatt Macy VERIFY(zfs_copy_ace_2_fuid(ZTOZSB(zp), ZTOI(zp)->i_mode, 828eda14cbcSMatt Macy aclp, oldaclp, newaclnode->z_acldata, aclp->z_acl_count, 829eda14cbcSMatt Macy &newaclnode->z_size, NULL, cr) == 0); 830eda14cbcSMatt Macy newaclnode->z_ace_count = aclp->z_acl_count; 831eda14cbcSMatt Macy aclp->z_version = ZFS_ACL_VERSION; 832eda14cbcSMatt Macy kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t)); 833eda14cbcSMatt Macy 834eda14cbcSMatt Macy /* 835eda14cbcSMatt Macy * Release all previous ACL nodes 836eda14cbcSMatt Macy */ 837eda14cbcSMatt Macy 838eda14cbcSMatt Macy zfs_acl_release_nodes(aclp); 839eda14cbcSMatt Macy 840eda14cbcSMatt Macy list_insert_head(&aclp->z_acl, newaclnode); 841eda14cbcSMatt Macy 842eda14cbcSMatt Macy aclp->z_acl_bytes = newaclnode->z_size; 843eda14cbcSMatt Macy aclp->z_acl_count = newaclnode->z_ace_count; 844eda14cbcSMatt Macy 845eda14cbcSMatt Macy } 846eda14cbcSMatt Macy 847eda14cbcSMatt Macy /* 848eda14cbcSMatt Macy * Convert unix access mask to v4 access mask 849eda14cbcSMatt Macy */ 850eda14cbcSMatt Macy static uint32_t 851eda14cbcSMatt Macy zfs_unix_to_v4(uint32_t access_mask) 852eda14cbcSMatt Macy { 853eda14cbcSMatt Macy uint32_t new_mask = 0; 854eda14cbcSMatt Macy 855eda14cbcSMatt Macy if (access_mask & S_IXOTH) 856eda14cbcSMatt Macy new_mask |= ACE_EXECUTE; 857eda14cbcSMatt Macy if (access_mask & S_IWOTH) 858eda14cbcSMatt Macy new_mask |= ACE_WRITE_DATA; 859eda14cbcSMatt Macy if (access_mask & S_IROTH) 860eda14cbcSMatt Macy new_mask |= ACE_READ_DATA; 861eda14cbcSMatt Macy return (new_mask); 862eda14cbcSMatt Macy } 863eda14cbcSMatt Macy 864716fd348SMartin Matuska 865716fd348SMartin Matuska static int 866716fd348SMartin Matuska zfs_v4_to_unix(uint32_t access_mask, int *unmapped) 867716fd348SMartin Matuska { 868716fd348SMartin Matuska int new_mask = 0; 869716fd348SMartin Matuska 870716fd348SMartin Matuska *unmapped = access_mask & 871716fd348SMartin Matuska (ACE_WRITE_OWNER | ACE_WRITE_ACL | ACE_DELETE); 872716fd348SMartin Matuska 873716fd348SMartin Matuska if (access_mask & WRITE_MASK) 874716fd348SMartin Matuska new_mask |= S_IWOTH; 875716fd348SMartin Matuska if (access_mask & ACE_READ_DATA) 876716fd348SMartin Matuska new_mask |= S_IROTH; 877716fd348SMartin Matuska if (access_mask & ACE_EXECUTE) 878716fd348SMartin Matuska new_mask |= S_IXOTH; 879716fd348SMartin Matuska 880716fd348SMartin Matuska return (new_mask); 881716fd348SMartin Matuska } 882716fd348SMartin Matuska 883716fd348SMartin Matuska 884eda14cbcSMatt Macy static void 885eda14cbcSMatt Macy zfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask, 886eda14cbcSMatt Macy uint16_t access_type, uint64_t fuid, uint16_t entry_type) 887eda14cbcSMatt Macy { 888eda14cbcSMatt Macy uint16_t type = entry_type & ACE_TYPE_FLAGS; 889eda14cbcSMatt Macy 890eda14cbcSMatt Macy aclp->z_ops->ace_mask_set(acep, access_mask); 891eda14cbcSMatt Macy aclp->z_ops->ace_type_set(acep, access_type); 892eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, entry_type); 893eda14cbcSMatt Macy if ((type != ACE_OWNER && type != OWNING_GROUP && 894eda14cbcSMatt Macy type != ACE_EVERYONE)) 895eda14cbcSMatt Macy aclp->z_ops->ace_who_set(acep, fuid); 896eda14cbcSMatt Macy } 897eda14cbcSMatt Macy 898eda14cbcSMatt Macy /* 899eda14cbcSMatt Macy * Determine mode of file based on ACL. 900eda14cbcSMatt Macy */ 901eda14cbcSMatt Macy uint64_t 902eda14cbcSMatt Macy zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, 903eda14cbcSMatt Macy uint64_t *pflags, uint64_t fuid, uint64_t fgid) 904eda14cbcSMatt Macy { 905eda14cbcSMatt Macy int entry_type; 906eda14cbcSMatt Macy mode_t mode; 907eda14cbcSMatt Macy mode_t seen = 0; 908eda14cbcSMatt Macy zfs_ace_hdr_t *acep = NULL; 909eda14cbcSMatt Macy uint64_t who; 910eda14cbcSMatt Macy uint16_t iflags, type; 911eda14cbcSMatt Macy uint32_t access_mask; 912eda14cbcSMatt Macy boolean_t an_exec_denied = B_FALSE; 913eda14cbcSMatt Macy 914eda14cbcSMatt Macy mode = (fmode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 915eda14cbcSMatt Macy 916eda14cbcSMatt Macy while ((acep = zfs_acl_next_ace(aclp, acep, &who, 917eda14cbcSMatt Macy &access_mask, &iflags, &type))) { 918eda14cbcSMatt Macy 919eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 920eda14cbcSMatt Macy continue; 921eda14cbcSMatt Macy 922eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 923eda14cbcSMatt Macy 924eda14cbcSMatt Macy /* 925eda14cbcSMatt Macy * Skip over any inherit_only ACEs 926eda14cbcSMatt Macy */ 927eda14cbcSMatt Macy if (iflags & ACE_INHERIT_ONLY_ACE) 928eda14cbcSMatt Macy continue; 929eda14cbcSMatt Macy 930eda14cbcSMatt Macy if (entry_type == ACE_OWNER || (entry_type == 0 && 931eda14cbcSMatt Macy who == fuid)) { 932eda14cbcSMatt Macy if ((access_mask & ACE_READ_DATA) && 933eda14cbcSMatt Macy (!(seen & S_IRUSR))) { 934eda14cbcSMatt Macy seen |= S_IRUSR; 935eda14cbcSMatt Macy if (type == ALLOW) { 936eda14cbcSMatt Macy mode |= S_IRUSR; 937eda14cbcSMatt Macy } 938eda14cbcSMatt Macy } 939eda14cbcSMatt Macy if ((access_mask & ACE_WRITE_DATA) && 940eda14cbcSMatt Macy (!(seen & S_IWUSR))) { 941eda14cbcSMatt Macy seen |= S_IWUSR; 942eda14cbcSMatt Macy if (type == ALLOW) { 943eda14cbcSMatt Macy mode |= S_IWUSR; 944eda14cbcSMatt Macy } 945eda14cbcSMatt Macy } 946eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE) && 947eda14cbcSMatt Macy (!(seen & S_IXUSR))) { 948eda14cbcSMatt Macy seen |= S_IXUSR; 949eda14cbcSMatt Macy if (type == ALLOW) { 950eda14cbcSMatt Macy mode |= S_IXUSR; 951eda14cbcSMatt Macy } 952eda14cbcSMatt Macy } 953eda14cbcSMatt Macy } else if (entry_type == OWNING_GROUP || 954eda14cbcSMatt Macy (entry_type == ACE_IDENTIFIER_GROUP && who == fgid)) { 955eda14cbcSMatt Macy if ((access_mask & ACE_READ_DATA) && 956eda14cbcSMatt Macy (!(seen & S_IRGRP))) { 957eda14cbcSMatt Macy seen |= S_IRGRP; 958eda14cbcSMatt Macy if (type == ALLOW) { 959eda14cbcSMatt Macy mode |= S_IRGRP; 960eda14cbcSMatt Macy } 961eda14cbcSMatt Macy } 962eda14cbcSMatt Macy if ((access_mask & ACE_WRITE_DATA) && 963eda14cbcSMatt Macy (!(seen & S_IWGRP))) { 964eda14cbcSMatt Macy seen |= S_IWGRP; 965eda14cbcSMatt Macy if (type == ALLOW) { 966eda14cbcSMatt Macy mode |= S_IWGRP; 967eda14cbcSMatt Macy } 968eda14cbcSMatt Macy } 969eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE) && 970eda14cbcSMatt Macy (!(seen & S_IXGRP))) { 971eda14cbcSMatt Macy seen |= S_IXGRP; 972eda14cbcSMatt Macy if (type == ALLOW) { 973eda14cbcSMatt Macy mode |= S_IXGRP; 974eda14cbcSMatt Macy } 975eda14cbcSMatt Macy } 976eda14cbcSMatt Macy } else if (entry_type == ACE_EVERYONE) { 977eda14cbcSMatt Macy if ((access_mask & ACE_READ_DATA)) { 978eda14cbcSMatt Macy if (!(seen & S_IRUSR)) { 979eda14cbcSMatt Macy seen |= S_IRUSR; 980eda14cbcSMatt Macy if (type == ALLOW) { 981eda14cbcSMatt Macy mode |= S_IRUSR; 982eda14cbcSMatt Macy } 983eda14cbcSMatt Macy } 984eda14cbcSMatt Macy if (!(seen & S_IRGRP)) { 985eda14cbcSMatt Macy seen |= S_IRGRP; 986eda14cbcSMatt Macy if (type == ALLOW) { 987eda14cbcSMatt Macy mode |= S_IRGRP; 988eda14cbcSMatt Macy } 989eda14cbcSMatt Macy } 990eda14cbcSMatt Macy if (!(seen & S_IROTH)) { 991eda14cbcSMatt Macy seen |= S_IROTH; 992eda14cbcSMatt Macy if (type == ALLOW) { 993eda14cbcSMatt Macy mode |= S_IROTH; 994eda14cbcSMatt Macy } 995eda14cbcSMatt Macy } 996eda14cbcSMatt Macy } 997eda14cbcSMatt Macy if ((access_mask & ACE_WRITE_DATA)) { 998eda14cbcSMatt Macy if (!(seen & S_IWUSR)) { 999eda14cbcSMatt Macy seen |= S_IWUSR; 1000eda14cbcSMatt Macy if (type == ALLOW) { 1001eda14cbcSMatt Macy mode |= S_IWUSR; 1002eda14cbcSMatt Macy } 1003eda14cbcSMatt Macy } 1004eda14cbcSMatt Macy if (!(seen & S_IWGRP)) { 1005eda14cbcSMatt Macy seen |= S_IWGRP; 1006eda14cbcSMatt Macy if (type == ALLOW) { 1007eda14cbcSMatt Macy mode |= S_IWGRP; 1008eda14cbcSMatt Macy } 1009eda14cbcSMatt Macy } 1010eda14cbcSMatt Macy if (!(seen & S_IWOTH)) { 1011eda14cbcSMatt Macy seen |= S_IWOTH; 1012eda14cbcSMatt Macy if (type == ALLOW) { 1013eda14cbcSMatt Macy mode |= S_IWOTH; 1014eda14cbcSMatt Macy } 1015eda14cbcSMatt Macy } 1016eda14cbcSMatt Macy } 1017eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE)) { 1018eda14cbcSMatt Macy if (!(seen & S_IXUSR)) { 1019eda14cbcSMatt Macy seen |= S_IXUSR; 1020eda14cbcSMatt Macy if (type == ALLOW) { 1021eda14cbcSMatt Macy mode |= S_IXUSR; 1022eda14cbcSMatt Macy } 1023eda14cbcSMatt Macy } 1024eda14cbcSMatt Macy if (!(seen & S_IXGRP)) { 1025eda14cbcSMatt Macy seen |= S_IXGRP; 1026eda14cbcSMatt Macy if (type == ALLOW) { 1027eda14cbcSMatt Macy mode |= S_IXGRP; 1028eda14cbcSMatt Macy } 1029eda14cbcSMatt Macy } 1030eda14cbcSMatt Macy if (!(seen & S_IXOTH)) { 1031eda14cbcSMatt Macy seen |= S_IXOTH; 1032eda14cbcSMatt Macy if (type == ALLOW) { 1033eda14cbcSMatt Macy mode |= S_IXOTH; 1034eda14cbcSMatt Macy } 1035eda14cbcSMatt Macy } 1036eda14cbcSMatt Macy } 1037eda14cbcSMatt Macy } else { 1038eda14cbcSMatt Macy /* 1039eda14cbcSMatt Macy * Only care if this IDENTIFIER_GROUP or 1040eda14cbcSMatt Macy * USER ACE denies execute access to someone, 1041eda14cbcSMatt Macy * mode is not affected 1042eda14cbcSMatt Macy */ 1043eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE) && type == DENY) 1044eda14cbcSMatt Macy an_exec_denied = B_TRUE; 1045eda14cbcSMatt Macy } 1046eda14cbcSMatt Macy } 1047eda14cbcSMatt Macy 1048eda14cbcSMatt Macy /* 1049eda14cbcSMatt Macy * Failure to allow is effectively a deny, so execute permission 1050eda14cbcSMatt Macy * is denied if it was never mentioned or if we explicitly 1051eda14cbcSMatt Macy * weren't allowed it. 1052eda14cbcSMatt Macy */ 1053eda14cbcSMatt Macy if (!an_exec_denied && 1054eda14cbcSMatt Macy ((seen & ALL_MODE_EXECS) != ALL_MODE_EXECS || 1055eda14cbcSMatt Macy (mode & ALL_MODE_EXECS) != ALL_MODE_EXECS)) 1056eda14cbcSMatt Macy an_exec_denied = B_TRUE; 1057eda14cbcSMatt Macy 1058eda14cbcSMatt Macy if (an_exec_denied) 1059eda14cbcSMatt Macy *pflags &= ~ZFS_NO_EXECS_DENIED; 1060eda14cbcSMatt Macy else 1061eda14cbcSMatt Macy *pflags |= ZFS_NO_EXECS_DENIED; 1062eda14cbcSMatt Macy 1063eda14cbcSMatt Macy return (mode); 1064eda14cbcSMatt Macy } 1065eda14cbcSMatt Macy 1066eda14cbcSMatt Macy /* 1067eda14cbcSMatt Macy * Read an external acl object. If the intent is to modify, always 1068eda14cbcSMatt Macy * create a new acl and leave any cached acl in place. 1069eda14cbcSMatt Macy */ 1070eda14cbcSMatt Macy int 1071eda14cbcSMatt Macy zfs_acl_node_read(struct znode *zp, boolean_t have_lock, zfs_acl_t **aclpp, 1072eda14cbcSMatt Macy boolean_t will_modify) 1073eda14cbcSMatt Macy { 1074eda14cbcSMatt Macy zfs_acl_t *aclp; 1075eda14cbcSMatt Macy int aclsize = 0; 1076eda14cbcSMatt Macy int acl_count = 0; 1077eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1078eda14cbcSMatt Macy zfs_acl_phys_t znode_acl; 1079eda14cbcSMatt Macy int version; 1080eda14cbcSMatt Macy int error; 1081eda14cbcSMatt Macy boolean_t drop_lock = B_FALSE; 1082eda14cbcSMatt Macy 1083eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1084eda14cbcSMatt Macy 1085eda14cbcSMatt Macy if (zp->z_acl_cached && !will_modify) { 1086eda14cbcSMatt Macy *aclpp = zp->z_acl_cached; 1087eda14cbcSMatt Macy return (0); 1088eda14cbcSMatt Macy } 1089eda14cbcSMatt Macy 1090eda14cbcSMatt Macy /* 1091eda14cbcSMatt Macy * close race where znode could be upgrade while trying to 1092eda14cbcSMatt Macy * read the znode attributes. 1093eda14cbcSMatt Macy * 1094eda14cbcSMatt Macy * But this could only happen if the file isn't already an SA 1095eda14cbcSMatt Macy * znode 1096eda14cbcSMatt Macy */ 1097eda14cbcSMatt Macy if (!zp->z_is_sa && !have_lock) { 1098eda14cbcSMatt Macy mutex_enter(&zp->z_lock); 1099eda14cbcSMatt Macy drop_lock = B_TRUE; 1100eda14cbcSMatt Macy } 1101eda14cbcSMatt Macy version = zfs_znode_acl_version(zp); 1102eda14cbcSMatt Macy 1103eda14cbcSMatt Macy if ((error = zfs_acl_znode_info(zp, &aclsize, 1104eda14cbcSMatt Macy &acl_count, &znode_acl)) != 0) { 1105eda14cbcSMatt Macy goto done; 1106eda14cbcSMatt Macy } 1107eda14cbcSMatt Macy 1108eda14cbcSMatt Macy aclp = zfs_acl_alloc(version); 1109eda14cbcSMatt Macy 1110eda14cbcSMatt Macy aclp->z_acl_count = acl_count; 1111eda14cbcSMatt Macy aclp->z_acl_bytes = aclsize; 1112eda14cbcSMatt Macy 1113eda14cbcSMatt Macy aclnode = zfs_acl_node_alloc(aclsize); 1114eda14cbcSMatt Macy aclnode->z_ace_count = aclp->z_acl_count; 1115eda14cbcSMatt Macy aclnode->z_size = aclsize; 1116eda14cbcSMatt Macy 1117eda14cbcSMatt Macy if (!zp->z_is_sa) { 1118eda14cbcSMatt Macy if (znode_acl.z_acl_extern_obj) { 1119eda14cbcSMatt Macy error = dmu_read(ZTOZSB(zp)->z_os, 1120eda14cbcSMatt Macy znode_acl.z_acl_extern_obj, 0, aclnode->z_size, 1121eda14cbcSMatt Macy aclnode->z_acldata, DMU_READ_PREFETCH); 1122eda14cbcSMatt Macy } else { 1123da5137abSMartin Matuska memcpy(aclnode->z_acldata, znode_acl.z_ace_data, 1124eda14cbcSMatt Macy aclnode->z_size); 1125eda14cbcSMatt Macy } 1126eda14cbcSMatt Macy } else { 1127eda14cbcSMatt Macy error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_ACES(ZTOZSB(zp)), 1128eda14cbcSMatt Macy aclnode->z_acldata, aclnode->z_size); 1129eda14cbcSMatt Macy } 1130eda14cbcSMatt Macy 1131eda14cbcSMatt Macy if (error != 0) { 1132eda14cbcSMatt Macy zfs_acl_free(aclp); 1133eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 1134eda14cbcSMatt Macy /* convert checksum errors into IO errors */ 1135eda14cbcSMatt Macy if (error == ECKSUM) 1136eda14cbcSMatt Macy error = SET_ERROR(EIO); 1137eda14cbcSMatt Macy goto done; 1138eda14cbcSMatt Macy } 1139eda14cbcSMatt Macy 1140eda14cbcSMatt Macy list_insert_head(&aclp->z_acl, aclnode); 1141eda14cbcSMatt Macy 1142eda14cbcSMatt Macy *aclpp = aclp; 1143eda14cbcSMatt Macy if (!will_modify) 1144eda14cbcSMatt Macy zp->z_acl_cached = aclp; 1145eda14cbcSMatt Macy done: 1146eda14cbcSMatt Macy if (drop_lock) 1147eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 1148eda14cbcSMatt Macy return (error); 1149eda14cbcSMatt Macy } 1150eda14cbcSMatt Macy 1151eda14cbcSMatt Macy void 1152eda14cbcSMatt Macy zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen, 1153eda14cbcSMatt Macy boolean_t start, void *userdata) 1154eda14cbcSMatt Macy { 1155c03c5b1cSMartin Matuska (void) buflen; 1156eda14cbcSMatt Macy zfs_acl_locator_cb_t *cb = (zfs_acl_locator_cb_t *)userdata; 1157eda14cbcSMatt Macy 1158eda14cbcSMatt Macy if (start) { 1159eda14cbcSMatt Macy cb->cb_acl_node = list_head(&cb->cb_aclp->z_acl); 1160eda14cbcSMatt Macy } else { 1161eda14cbcSMatt Macy cb->cb_acl_node = list_next(&cb->cb_aclp->z_acl, 1162eda14cbcSMatt Macy cb->cb_acl_node); 1163eda14cbcSMatt Macy } 1164dbd5678dSMartin Matuska ASSERT3P(cb->cb_acl_node, !=, NULL); 1165eda14cbcSMatt Macy *dataptr = cb->cb_acl_node->z_acldata; 1166eda14cbcSMatt Macy *length = cb->cb_acl_node->z_size; 1167eda14cbcSMatt Macy } 1168eda14cbcSMatt Macy 1169eda14cbcSMatt Macy int 1170eda14cbcSMatt Macy zfs_acl_chown_setattr(znode_t *zp) 1171eda14cbcSMatt Macy { 1172eda14cbcSMatt Macy int error; 1173eda14cbcSMatt Macy zfs_acl_t *aclp; 1174eda14cbcSMatt Macy 11752c48331dSMatt Macy if (ZTOZSB(zp)->z_acl_type == ZFS_ACLTYPE_POSIX) 1176eda14cbcSMatt Macy return (0); 1177eda14cbcSMatt Macy 1178eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&zp->z_lock)); 1179eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1180eda14cbcSMatt Macy 1181eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE); 1182eda14cbcSMatt Macy if (error == 0 && aclp->z_acl_count > 0) 1183eda14cbcSMatt Macy zp->z_mode = ZTOI(zp)->i_mode = 1184eda14cbcSMatt Macy zfs_mode_compute(zp->z_mode, aclp, 1185eda14cbcSMatt Macy &zp->z_pflags, KUID_TO_SUID(ZTOI(zp)->i_uid), 1186eda14cbcSMatt Macy KGID_TO_SGID(ZTOI(zp)->i_gid)); 1187eda14cbcSMatt Macy 1188eda14cbcSMatt Macy /* 1189eda14cbcSMatt Macy * Some ZFS implementations (ZEVO) create neither a ZNODE_ACL 1190eda14cbcSMatt Macy * nor a DACL_ACES SA in which case ENOENT is returned from 1191eda14cbcSMatt Macy * zfs_acl_node_read() when the SA can't be located. 1192eda14cbcSMatt Macy * Allow chown/chgrp to succeed in these cases rather than 1193eda14cbcSMatt Macy * returning an error that makes no sense in the context of 1194eda14cbcSMatt Macy * the caller. 1195eda14cbcSMatt Macy */ 1196eda14cbcSMatt Macy if (error == ENOENT) 1197eda14cbcSMatt Macy return (0); 1198eda14cbcSMatt Macy 1199eda14cbcSMatt Macy return (error); 1200eda14cbcSMatt Macy } 1201eda14cbcSMatt Macy 1202eda14cbcSMatt Macy typedef struct trivial_acl { 1203eda14cbcSMatt Macy uint32_t allow0; /* allow mask for bits only in owner */ 1204eda14cbcSMatt Macy uint32_t deny1; /* deny mask for bits not in owner */ 1205eda14cbcSMatt Macy uint32_t deny2; /* deny mask for bits not in group */ 1206eda14cbcSMatt Macy uint32_t owner; /* allow mask matching mode */ 1207eda14cbcSMatt Macy uint32_t group; /* allow mask matching mode */ 1208eda14cbcSMatt Macy uint32_t everyone; /* allow mask matching mode */ 1209eda14cbcSMatt Macy } trivial_acl_t; 1210eda14cbcSMatt Macy 1211eda14cbcSMatt Macy static void 1212eda14cbcSMatt Macy acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks) 1213eda14cbcSMatt Macy { 1214eda14cbcSMatt Macy uint32_t read_mask = ACE_READ_DATA; 1215eda14cbcSMatt Macy uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA; 1216eda14cbcSMatt Macy uint32_t execute_mask = ACE_EXECUTE; 1217eda14cbcSMatt Macy 1218eda14cbcSMatt Macy if (isdir) 1219eda14cbcSMatt Macy write_mask |= ACE_DELETE_CHILD; 1220eda14cbcSMatt Macy 1221eda14cbcSMatt Macy masks->deny1 = 0; 1222eda14cbcSMatt Macy 1223eda14cbcSMatt Macy if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) 1224eda14cbcSMatt Macy masks->deny1 |= read_mask; 1225eda14cbcSMatt Macy if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) 1226eda14cbcSMatt Macy masks->deny1 |= write_mask; 1227eda14cbcSMatt Macy if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))) 1228eda14cbcSMatt Macy masks->deny1 |= execute_mask; 1229eda14cbcSMatt Macy 1230eda14cbcSMatt Macy masks->deny2 = 0; 1231eda14cbcSMatt Macy if (!(mode & S_IRGRP) && (mode & S_IROTH)) 1232eda14cbcSMatt Macy masks->deny2 |= read_mask; 1233eda14cbcSMatt Macy if (!(mode & S_IWGRP) && (mode & S_IWOTH)) 1234eda14cbcSMatt Macy masks->deny2 |= write_mask; 1235eda14cbcSMatt Macy if (!(mode & S_IXGRP) && (mode & S_IXOTH)) 1236eda14cbcSMatt Macy masks->deny2 |= execute_mask; 1237eda14cbcSMatt Macy 1238eda14cbcSMatt Macy masks->allow0 = 0; 1239eda14cbcSMatt Macy if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH))) 1240eda14cbcSMatt Macy masks->allow0 |= read_mask; 1241eda14cbcSMatt Macy if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH))) 1242eda14cbcSMatt Macy masks->allow0 |= write_mask; 1243eda14cbcSMatt Macy if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH))) 1244eda14cbcSMatt Macy masks->allow0 |= execute_mask; 1245eda14cbcSMatt Macy 1246eda14cbcSMatt Macy masks->owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL| 1247eda14cbcSMatt Macy ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES| 1248eda14cbcSMatt Macy ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE; 1249eda14cbcSMatt Macy if (mode & S_IRUSR) 1250eda14cbcSMatt Macy masks->owner |= read_mask; 1251eda14cbcSMatt Macy if (mode & S_IWUSR) 1252eda14cbcSMatt Macy masks->owner |= write_mask; 1253eda14cbcSMatt Macy if (mode & S_IXUSR) 1254eda14cbcSMatt Macy masks->owner |= execute_mask; 1255eda14cbcSMatt Macy 1256eda14cbcSMatt Macy masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS| 1257eda14cbcSMatt Macy ACE_SYNCHRONIZE; 1258eda14cbcSMatt Macy if (mode & S_IRGRP) 1259eda14cbcSMatt Macy masks->group |= read_mask; 1260eda14cbcSMatt Macy if (mode & S_IWGRP) 1261eda14cbcSMatt Macy masks->group |= write_mask; 1262eda14cbcSMatt Macy if (mode & S_IXGRP) 1263eda14cbcSMatt Macy masks->group |= execute_mask; 1264eda14cbcSMatt Macy 1265eda14cbcSMatt Macy masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS| 1266eda14cbcSMatt Macy ACE_SYNCHRONIZE; 1267eda14cbcSMatt Macy if (mode & S_IROTH) 1268eda14cbcSMatt Macy masks->everyone |= read_mask; 1269eda14cbcSMatt Macy if (mode & S_IWOTH) 1270eda14cbcSMatt Macy masks->everyone |= write_mask; 1271eda14cbcSMatt Macy if (mode & S_IXOTH) 1272eda14cbcSMatt Macy masks->everyone |= execute_mask; 1273eda14cbcSMatt Macy } 1274eda14cbcSMatt Macy 1275eda14cbcSMatt Macy /* 1276eda14cbcSMatt Macy * ace_trivial: 1277eda14cbcSMatt Macy * determine whether an ace_t acl is trivial 1278eda14cbcSMatt Macy * 1279eda14cbcSMatt Macy * Trivialness implies that the acl is composed of only 1280eda14cbcSMatt Macy * owner, group, everyone entries. ACL can't 1281eda14cbcSMatt Macy * have read_acl denied, and write_owner/write_acl/write_attributes 1282eda14cbcSMatt Macy * can only be owner@ entry. 1283eda14cbcSMatt Macy */ 1284eda14cbcSMatt Macy static int 1285eda14cbcSMatt Macy ace_trivial_common(void *acep, int aclcnt, 1286dbd5678dSMartin Matuska uintptr_t (*walk)(void *, uintptr_t, int, 1287eda14cbcSMatt Macy uint16_t *, uint16_t *, uint32_t *)) 1288eda14cbcSMatt Macy { 1289eda14cbcSMatt Macy uint16_t flags; 1290eda14cbcSMatt Macy uint32_t mask; 1291eda14cbcSMatt Macy uint16_t type; 1292eda14cbcSMatt Macy uint64_t cookie = 0; 1293eda14cbcSMatt Macy 1294eda14cbcSMatt Macy while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) { 1295eda14cbcSMatt Macy switch (flags & ACE_TYPE_FLAGS) { 1296eda14cbcSMatt Macy case ACE_OWNER: 1297eda14cbcSMatt Macy case ACE_GROUP|ACE_IDENTIFIER_GROUP: 1298eda14cbcSMatt Macy case ACE_EVERYONE: 1299eda14cbcSMatt Macy break; 1300eda14cbcSMatt Macy default: 1301eda14cbcSMatt Macy return (1); 1302eda14cbcSMatt Macy } 1303eda14cbcSMatt Macy 1304eda14cbcSMatt Macy if (flags & (ACE_FILE_INHERIT_ACE| 1305eda14cbcSMatt Macy ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE| 1306eda14cbcSMatt Macy ACE_INHERIT_ONLY_ACE)) 1307eda14cbcSMatt Macy return (1); 1308eda14cbcSMatt Macy 1309eda14cbcSMatt Macy /* 1310eda14cbcSMatt Macy * Special check for some special bits 1311eda14cbcSMatt Macy * 1312eda14cbcSMatt Macy * Don't allow anybody to deny reading basic 1313eda14cbcSMatt Macy * attributes or a files ACL. 1314eda14cbcSMatt Macy */ 1315eda14cbcSMatt Macy if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) && 1316eda14cbcSMatt Macy (type == ACE_ACCESS_DENIED_ACE_TYPE)) 1317eda14cbcSMatt Macy return (1); 1318eda14cbcSMatt Macy 1319eda14cbcSMatt Macy /* 1320eda14cbcSMatt Macy * Delete permission is never set by default 1321eda14cbcSMatt Macy */ 1322eda14cbcSMatt Macy if (mask & ACE_DELETE) 1323eda14cbcSMatt Macy return (1); 1324eda14cbcSMatt Macy 1325eda14cbcSMatt Macy /* 1326eda14cbcSMatt Macy * Child delete permission should be accompanied by write 1327eda14cbcSMatt Macy */ 1328eda14cbcSMatt Macy if ((mask & ACE_DELETE_CHILD) && !(mask & ACE_WRITE_DATA)) 1329eda14cbcSMatt Macy return (1); 1330eda14cbcSMatt Macy 1331eda14cbcSMatt Macy /* 1332eda14cbcSMatt Macy * only allow owner@ to have 1333eda14cbcSMatt Macy * write_acl/write_owner/write_attributes/write_xattr/ 1334eda14cbcSMatt Macy */ 1335eda14cbcSMatt Macy if (type == ACE_ACCESS_ALLOWED_ACE_TYPE && 1336eda14cbcSMatt Macy (!(flags & ACE_OWNER) && (mask & 1337eda14cbcSMatt Macy (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES| 1338eda14cbcSMatt Macy ACE_WRITE_NAMED_ATTRS)))) 1339eda14cbcSMatt Macy return (1); 1340eda14cbcSMatt Macy 1341eda14cbcSMatt Macy } 1342eda14cbcSMatt Macy 1343eda14cbcSMatt Macy return (0); 1344eda14cbcSMatt Macy } 1345eda14cbcSMatt Macy 1346eda14cbcSMatt Macy /* 1347eda14cbcSMatt Macy * common code for setting ACLs. 1348eda14cbcSMatt Macy * 1349eda14cbcSMatt Macy * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 1350eda14cbcSMatt Macy * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 1351eda14cbcSMatt Macy * already checked the acl and knows whether to inherit. 1352eda14cbcSMatt Macy */ 1353eda14cbcSMatt Macy int 1354eda14cbcSMatt Macy zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx) 1355eda14cbcSMatt Macy { 1356eda14cbcSMatt Macy int error; 1357eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 1358eda14cbcSMatt Macy dmu_object_type_t otype; 1359eda14cbcSMatt Macy zfs_acl_locator_cb_t locate = { 0 }; 1360eda14cbcSMatt Macy uint64_t mode; 1361eda14cbcSMatt Macy sa_bulk_attr_t bulk[5]; 1362eda14cbcSMatt Macy uint64_t ctime[2]; 1363eda14cbcSMatt Macy int count = 0; 1364eda14cbcSMatt Macy zfs_acl_phys_t acl_phys; 1365eda14cbcSMatt Macy 1366eda14cbcSMatt Macy mode = zp->z_mode; 1367eda14cbcSMatt Macy 1368eda14cbcSMatt Macy mode = zfs_mode_compute(mode, aclp, &zp->z_pflags, 1369eda14cbcSMatt Macy KUID_TO_SUID(ZTOI(zp)->i_uid), KGID_TO_SGID(ZTOI(zp)->i_gid)); 1370eda14cbcSMatt Macy 1371eda14cbcSMatt Macy zp->z_mode = ZTOI(zp)->i_mode = mode; 1372eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, 1373eda14cbcSMatt Macy &mode, sizeof (mode)); 1374eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 1375eda14cbcSMatt Macy &zp->z_pflags, sizeof (zp->z_pflags)); 1376eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, 1377eda14cbcSMatt Macy &ctime, sizeof (ctime)); 1378eda14cbcSMatt Macy 1379eda14cbcSMatt Macy if (zp->z_acl_cached) { 1380eda14cbcSMatt Macy zfs_acl_free(zp->z_acl_cached); 1381eda14cbcSMatt Macy zp->z_acl_cached = NULL; 1382eda14cbcSMatt Macy } 1383eda14cbcSMatt Macy 1384eda14cbcSMatt Macy /* 1385eda14cbcSMatt Macy * Upgrade needed? 1386eda14cbcSMatt Macy */ 1387eda14cbcSMatt Macy if (!zfsvfs->z_use_fuids) { 1388eda14cbcSMatt Macy otype = DMU_OT_OLDACL; 1389eda14cbcSMatt Macy } else { 1390eda14cbcSMatt Macy if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) && 1391eda14cbcSMatt Macy (zfsvfs->z_version >= ZPL_VERSION_FUID)) 1392eda14cbcSMatt Macy zfs_acl_xform(zp, aclp, cr); 1393eda14cbcSMatt Macy ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID); 1394eda14cbcSMatt Macy otype = DMU_OT_ACL; 1395eda14cbcSMatt Macy } 1396eda14cbcSMatt Macy 1397eda14cbcSMatt Macy /* 1398eda14cbcSMatt Macy * Arrgh, we have to handle old on disk format 1399eda14cbcSMatt Macy * as well as newer (preferred) SA format. 1400eda14cbcSMatt Macy */ 1401eda14cbcSMatt Macy 1402eda14cbcSMatt Macy if (zp->z_is_sa) { /* the easy case, just update the ACL attribute */ 1403eda14cbcSMatt Macy locate.cb_aclp = aclp; 1404eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_ACES(zfsvfs), 1405eda14cbcSMatt Macy zfs_acl_data_locator, &locate, aclp->z_acl_bytes); 1406eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_COUNT(zfsvfs), 1407eda14cbcSMatt Macy NULL, &aclp->z_acl_count, sizeof (uint64_t)); 1408eda14cbcSMatt Macy } else { /* Painful legacy way */ 1409eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1410eda14cbcSMatt Macy uint64_t off = 0; 1411eda14cbcSMatt Macy uint64_t aoid; 1412eda14cbcSMatt Macy 1413eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), 1414eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys))) != 0) 1415eda14cbcSMatt Macy return (error); 1416eda14cbcSMatt Macy 1417eda14cbcSMatt Macy aoid = acl_phys.z_acl_extern_obj; 1418eda14cbcSMatt Macy 1419eda14cbcSMatt Macy if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 1420eda14cbcSMatt Macy /* 1421eda14cbcSMatt Macy * If ACL was previously external and we are now 1422eda14cbcSMatt Macy * converting to new ACL format then release old 1423eda14cbcSMatt Macy * ACL object and create a new one. 1424eda14cbcSMatt Macy */ 1425eda14cbcSMatt Macy if (aoid && 1426eda14cbcSMatt Macy aclp->z_version != acl_phys.z_acl_version) { 1427eda14cbcSMatt Macy error = dmu_object_free(zfsvfs->z_os, aoid, tx); 1428eda14cbcSMatt Macy if (error) 1429eda14cbcSMatt Macy return (error); 1430eda14cbcSMatt Macy aoid = 0; 1431eda14cbcSMatt Macy } 1432eda14cbcSMatt Macy if (aoid == 0) { 1433eda14cbcSMatt Macy aoid = dmu_object_alloc(zfsvfs->z_os, 1434eda14cbcSMatt Macy otype, aclp->z_acl_bytes, 1435eda14cbcSMatt Macy otype == DMU_OT_ACL ? 1436eda14cbcSMatt Macy DMU_OT_SYSACL : DMU_OT_NONE, 1437eda14cbcSMatt Macy otype == DMU_OT_ACL ? 1438eda14cbcSMatt Macy DN_OLD_MAX_BONUSLEN : 0, tx); 1439eda14cbcSMatt Macy } else { 1440eda14cbcSMatt Macy (void) dmu_object_set_blocksize(zfsvfs->z_os, 1441eda14cbcSMatt Macy aoid, aclp->z_acl_bytes, 0, tx); 1442eda14cbcSMatt Macy } 1443eda14cbcSMatt Macy acl_phys.z_acl_extern_obj = aoid; 1444eda14cbcSMatt Macy for (aclnode = list_head(&aclp->z_acl); aclnode; 1445eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode)) { 1446eda14cbcSMatt Macy if (aclnode->z_ace_count == 0) 1447eda14cbcSMatt Macy continue; 1448eda14cbcSMatt Macy dmu_write(zfsvfs->z_os, aoid, off, 1449eda14cbcSMatt Macy aclnode->z_size, aclnode->z_acldata, tx); 1450eda14cbcSMatt Macy off += aclnode->z_size; 1451eda14cbcSMatt Macy } 1452eda14cbcSMatt Macy } else { 1453eda14cbcSMatt Macy void *start = acl_phys.z_ace_data; 1454eda14cbcSMatt Macy /* 1455eda14cbcSMatt Macy * Migrating back embedded? 1456eda14cbcSMatt Macy */ 1457eda14cbcSMatt Macy if (acl_phys.z_acl_extern_obj) { 1458eda14cbcSMatt Macy error = dmu_object_free(zfsvfs->z_os, 1459eda14cbcSMatt Macy acl_phys.z_acl_extern_obj, tx); 1460eda14cbcSMatt Macy if (error) 1461eda14cbcSMatt Macy return (error); 1462eda14cbcSMatt Macy acl_phys.z_acl_extern_obj = 0; 1463eda14cbcSMatt Macy } 1464eda14cbcSMatt Macy 1465eda14cbcSMatt Macy for (aclnode = list_head(&aclp->z_acl); aclnode; 1466eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode)) { 1467eda14cbcSMatt Macy if (aclnode->z_ace_count == 0) 1468eda14cbcSMatt Macy continue; 1469da5137abSMartin Matuska memcpy(start, aclnode->z_acldata, 1470eda14cbcSMatt Macy aclnode->z_size); 1471eda14cbcSMatt Macy start = (caddr_t)start + aclnode->z_size; 1472eda14cbcSMatt Macy } 1473eda14cbcSMatt Macy } 1474eda14cbcSMatt Macy /* 1475eda14cbcSMatt Macy * If Old version then swap count/bytes to match old 1476eda14cbcSMatt Macy * layout of znode_acl_phys_t. 1477eda14cbcSMatt Macy */ 1478eda14cbcSMatt Macy if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 1479eda14cbcSMatt Macy acl_phys.z_acl_size = aclp->z_acl_count; 1480eda14cbcSMatt Macy acl_phys.z_acl_count = aclp->z_acl_bytes; 1481eda14cbcSMatt Macy } else { 1482eda14cbcSMatt Macy acl_phys.z_acl_size = aclp->z_acl_bytes; 1483eda14cbcSMatt Macy acl_phys.z_acl_count = aclp->z_acl_count; 1484eda14cbcSMatt Macy } 1485eda14cbcSMatt Macy acl_phys.z_acl_version = aclp->z_version; 1486eda14cbcSMatt Macy 1487eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL, 1488eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys)); 1489eda14cbcSMatt Macy } 1490eda14cbcSMatt Macy 1491eda14cbcSMatt Macy /* 1492eda14cbcSMatt Macy * Replace ACL wide bits, but first clear them. 1493eda14cbcSMatt Macy */ 1494eda14cbcSMatt Macy zp->z_pflags &= ~ZFS_ACL_WIDE_FLAGS; 1495eda14cbcSMatt Macy 1496eda14cbcSMatt Macy zp->z_pflags |= aclp->z_hints; 1497eda14cbcSMatt Macy 1498eda14cbcSMatt Macy if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0) 1499eda14cbcSMatt Macy zp->z_pflags |= ZFS_ACL_TRIVIAL; 1500eda14cbcSMatt Macy 1501eda14cbcSMatt Macy zfs_tstamp_update_setup(zp, STATE_CHANGED, NULL, ctime); 1502eda14cbcSMatt Macy return (sa_bulk_update(zp->z_sa_hdl, bulk, count, tx)); 1503eda14cbcSMatt Macy } 1504eda14cbcSMatt Macy 1505eda14cbcSMatt Macy static void 1506eda14cbcSMatt Macy zfs_acl_chmod(boolean_t isdir, uint64_t mode, boolean_t split, boolean_t trim, 1507eda14cbcSMatt Macy zfs_acl_t *aclp) 1508eda14cbcSMatt Macy { 1509eda14cbcSMatt Macy void *acep = NULL; 1510eda14cbcSMatt Macy uint64_t who; 1511eda14cbcSMatt Macy int new_count, new_bytes; 1512eda14cbcSMatt Macy int ace_size; 1513eda14cbcSMatt Macy int entry_type; 1514eda14cbcSMatt Macy uint16_t iflags, type; 1515eda14cbcSMatt Macy uint32_t access_mask; 1516eda14cbcSMatt Macy zfs_acl_node_t *newnode; 1517eda14cbcSMatt Macy size_t abstract_size = aclp->z_ops->ace_abstract_size(); 1518eda14cbcSMatt Macy void *zacep; 1519eda14cbcSMatt Macy trivial_acl_t masks; 1520eda14cbcSMatt Macy 1521eda14cbcSMatt Macy new_count = new_bytes = 0; 1522eda14cbcSMatt Macy 1523eda14cbcSMatt Macy acl_trivial_access_masks((mode_t)mode, isdir, &masks); 1524eda14cbcSMatt Macy 1525eda14cbcSMatt Macy newnode = zfs_acl_node_alloc((abstract_size * 6) + aclp->z_acl_bytes); 1526eda14cbcSMatt Macy 1527eda14cbcSMatt Macy zacep = newnode->z_acldata; 1528eda14cbcSMatt Macy if (masks.allow0) { 1529eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.allow0, ALLOW, -1, ACE_OWNER); 1530eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1531eda14cbcSMatt Macy new_count++; 1532eda14cbcSMatt Macy new_bytes += abstract_size; 1533eda14cbcSMatt Macy } 1534eda14cbcSMatt Macy if (masks.deny1) { 1535eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.deny1, DENY, -1, ACE_OWNER); 1536eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1537eda14cbcSMatt Macy new_count++; 1538eda14cbcSMatt Macy new_bytes += abstract_size; 1539eda14cbcSMatt Macy } 1540eda14cbcSMatt Macy if (masks.deny2) { 1541eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.deny2, DENY, -1, OWNING_GROUP); 1542eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1543eda14cbcSMatt Macy new_count++; 1544eda14cbcSMatt Macy new_bytes += abstract_size; 1545eda14cbcSMatt Macy } 1546eda14cbcSMatt Macy 1547eda14cbcSMatt Macy while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 1548eda14cbcSMatt Macy &iflags, &type))) { 1549eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 1550eda14cbcSMatt Macy /* 1551eda14cbcSMatt Macy * ACEs used to represent the file mode may be divided 1552eda14cbcSMatt Macy * into an equivalent pair of inherit-only and regular 1553eda14cbcSMatt Macy * ACEs, if they are inheritable. 1554eda14cbcSMatt Macy * Skip regular ACEs, which are replaced by the new mode. 1555eda14cbcSMatt Macy */ 1556eda14cbcSMatt Macy if (split && (entry_type == ACE_OWNER || 1557eda14cbcSMatt Macy entry_type == OWNING_GROUP || 1558eda14cbcSMatt Macy entry_type == ACE_EVERYONE)) { 1559eda14cbcSMatt Macy if (!isdir || !(iflags & 1560eda14cbcSMatt Macy (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 1561eda14cbcSMatt Macy continue; 1562eda14cbcSMatt Macy /* 1563eda14cbcSMatt Macy * We preserve owner@, group@, or @everyone 1564eda14cbcSMatt Macy * permissions, if they are inheritable, by 1565eda14cbcSMatt Macy * copying them to inherit_only ACEs. This 1566eda14cbcSMatt Macy * prevents inheritable permissions from being 1567eda14cbcSMatt Macy * altered along with the file mode. 1568eda14cbcSMatt Macy */ 1569eda14cbcSMatt Macy iflags |= ACE_INHERIT_ONLY_ACE; 1570eda14cbcSMatt Macy } 1571eda14cbcSMatt Macy 1572eda14cbcSMatt Macy /* 1573eda14cbcSMatt Macy * If this ACL has any inheritable ACEs, mark that in 1574eda14cbcSMatt Macy * the hints (which are later masked into the pflags) 1575eda14cbcSMatt Macy * so create knows to do inheritance. 1576eda14cbcSMatt Macy */ 1577eda14cbcSMatt Macy if (isdir && (iflags & 1578eda14cbcSMatt Macy (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 1579eda14cbcSMatt Macy aclp->z_hints |= ZFS_INHERIT_ACE; 1580eda14cbcSMatt Macy 1581eda14cbcSMatt Macy if ((type != ALLOW && type != DENY) || 1582eda14cbcSMatt Macy (iflags & ACE_INHERIT_ONLY_ACE)) { 1583eda14cbcSMatt Macy switch (type) { 1584eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1585eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1586eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1587eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1588eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_OBJ_ACE; 1589eda14cbcSMatt Macy break; 1590eda14cbcSMatt Macy } 1591eda14cbcSMatt Macy } else { 1592eda14cbcSMatt Macy /* 1593eda14cbcSMatt Macy * Limit permissions to be no greater than 1594eda14cbcSMatt Macy * group permissions. 1595eda14cbcSMatt Macy * The "aclinherit" and "aclmode" properties 1596eda14cbcSMatt Macy * affect policy for create and chmod(2), 1597eda14cbcSMatt Macy * respectively. 1598eda14cbcSMatt Macy */ 1599eda14cbcSMatt Macy if ((type == ALLOW) && trim) 1600eda14cbcSMatt Macy access_mask &= masks.group; 1601eda14cbcSMatt Macy } 1602eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, access_mask, type, who, iflags); 1603eda14cbcSMatt Macy ace_size = aclp->z_ops->ace_size(acep); 1604eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + ace_size); 1605eda14cbcSMatt Macy new_count++; 1606eda14cbcSMatt Macy new_bytes += ace_size; 1607eda14cbcSMatt Macy } 1608eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.owner, ALLOW, -1, ACE_OWNER); 1609eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1610eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.group, ALLOW, -1, OWNING_GROUP); 1611eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1612eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.everyone, ALLOW, -1, ACE_EVERYONE); 1613eda14cbcSMatt Macy 1614eda14cbcSMatt Macy new_count += 3; 1615eda14cbcSMatt Macy new_bytes += abstract_size * 3; 1616eda14cbcSMatt Macy zfs_acl_release_nodes(aclp); 1617eda14cbcSMatt Macy aclp->z_acl_count = new_count; 1618eda14cbcSMatt Macy aclp->z_acl_bytes = new_bytes; 1619eda14cbcSMatt Macy newnode->z_ace_count = new_count; 1620eda14cbcSMatt Macy newnode->z_size = new_bytes; 1621eda14cbcSMatt Macy list_insert_tail(&aclp->z_acl, newnode); 1622eda14cbcSMatt Macy } 1623eda14cbcSMatt Macy 1624eda14cbcSMatt Macy int 1625eda14cbcSMatt Macy zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) 1626eda14cbcSMatt Macy { 1627eda14cbcSMatt Macy int error = 0; 1628eda14cbcSMatt Macy 1629eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 1630eda14cbcSMatt Macy mutex_enter(&zp->z_lock); 1631eda14cbcSMatt Macy if (ZTOZSB(zp)->z_acl_mode == ZFS_ACL_DISCARD) 1632eda14cbcSMatt Macy *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); 1633eda14cbcSMatt Macy else 1634eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_TRUE, aclp, B_TRUE); 1635eda14cbcSMatt Macy 1636eda14cbcSMatt Macy if (error == 0) { 1637eda14cbcSMatt Macy (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS; 1638eda14cbcSMatt Macy zfs_acl_chmod(S_ISDIR(ZTOI(zp)->i_mode), mode, B_TRUE, 1639eda14cbcSMatt Macy (ZTOZSB(zp)->z_acl_mode == ZFS_ACL_GROUPMASK), *aclp); 1640eda14cbcSMatt Macy } 1641eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 1642eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 1643eda14cbcSMatt Macy 1644eda14cbcSMatt Macy return (error); 1645eda14cbcSMatt Macy } 1646eda14cbcSMatt Macy 1647eda14cbcSMatt Macy /* 1648eda14cbcSMatt Macy * Should ACE be inherited? 1649eda14cbcSMatt Macy */ 1650eda14cbcSMatt Macy static int 1651eda14cbcSMatt Macy zfs_ace_can_use(umode_t obj_mode, uint16_t acep_flags) 1652eda14cbcSMatt Macy { 1653eda14cbcSMatt Macy int iflags = (acep_flags & 0xf); 1654eda14cbcSMatt Macy 1655eda14cbcSMatt Macy if (S_ISDIR(obj_mode) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1656eda14cbcSMatt Macy return (1); 1657eda14cbcSMatt Macy else if (iflags & ACE_FILE_INHERIT_ACE) 1658eda14cbcSMatt Macy return (!(S_ISDIR(obj_mode) && 1659eda14cbcSMatt Macy (iflags & ACE_NO_PROPAGATE_INHERIT_ACE))); 1660eda14cbcSMatt Macy return (0); 1661eda14cbcSMatt Macy } 1662eda14cbcSMatt Macy 1663eda14cbcSMatt Macy /* 1664eda14cbcSMatt Macy * inherit inheritable ACEs from parent 1665eda14cbcSMatt Macy */ 1666eda14cbcSMatt Macy static zfs_acl_t * 1667eda14cbcSMatt Macy zfs_acl_inherit(zfsvfs_t *zfsvfs, umode_t va_mode, zfs_acl_t *paclp, 1668eda14cbcSMatt Macy uint64_t mode, boolean_t *need_chmod) 1669eda14cbcSMatt Macy { 1670eda14cbcSMatt Macy void *pacep = NULL; 1671eda14cbcSMatt Macy void *acep; 1672eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1673eda14cbcSMatt Macy zfs_acl_t *aclp = NULL; 1674eda14cbcSMatt Macy uint64_t who; 1675eda14cbcSMatt Macy uint32_t access_mask; 1676eda14cbcSMatt Macy uint16_t iflags, newflags, type; 1677eda14cbcSMatt Macy size_t ace_size; 1678eda14cbcSMatt Macy void *data1, *data2; 1679eda14cbcSMatt Macy size_t data1sz, data2sz; 1680eda14cbcSMatt Macy uint_t aclinherit; 1681eda14cbcSMatt Macy boolean_t isdir = S_ISDIR(va_mode); 1682eda14cbcSMatt Macy boolean_t isreg = S_ISREG(va_mode); 1683eda14cbcSMatt Macy 1684eda14cbcSMatt Macy *need_chmod = B_TRUE; 1685eda14cbcSMatt Macy 1686eda14cbcSMatt Macy aclp = zfs_acl_alloc(paclp->z_version); 1687eda14cbcSMatt Macy aclinherit = zfsvfs->z_acl_inherit; 1688eda14cbcSMatt Macy if (aclinherit == ZFS_ACL_DISCARD || S_ISLNK(va_mode)) 1689eda14cbcSMatt Macy return (aclp); 1690eda14cbcSMatt Macy 1691eda14cbcSMatt Macy while ((pacep = zfs_acl_next_ace(paclp, pacep, &who, 1692eda14cbcSMatt Macy &access_mask, &iflags, &type))) { 1693eda14cbcSMatt Macy 1694eda14cbcSMatt Macy /* 1695eda14cbcSMatt Macy * don't inherit bogus ACEs 1696eda14cbcSMatt Macy */ 1697eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 1698eda14cbcSMatt Macy continue; 1699eda14cbcSMatt Macy 1700eda14cbcSMatt Macy /* 1701eda14cbcSMatt Macy * Check if ACE is inheritable by this vnode 1702eda14cbcSMatt Macy */ 1703eda14cbcSMatt Macy if ((aclinherit == ZFS_ACL_NOALLOW && type == ALLOW) || 1704eda14cbcSMatt Macy !zfs_ace_can_use(va_mode, iflags)) 1705eda14cbcSMatt Macy continue; 1706eda14cbcSMatt Macy 1707eda14cbcSMatt Macy /* 1708eda14cbcSMatt Macy * If owner@, group@, or everyone@ inheritable 1709eda14cbcSMatt Macy * then zfs_acl_chmod() isn't needed. 1710eda14cbcSMatt Macy */ 1711eda14cbcSMatt Macy if ((aclinherit == ZFS_ACL_PASSTHROUGH || 1712eda14cbcSMatt Macy aclinherit == ZFS_ACL_PASSTHROUGH_X) && 1713eda14cbcSMatt Macy ((iflags & (ACE_OWNER|ACE_EVERYONE)) || 1714eda14cbcSMatt Macy ((iflags & OWNING_GROUP) == OWNING_GROUP)) && 1715eda14cbcSMatt Macy (isreg || (isdir && (iflags & ACE_DIRECTORY_INHERIT_ACE)))) 1716eda14cbcSMatt Macy *need_chmod = B_FALSE; 1717eda14cbcSMatt Macy 1718eda14cbcSMatt Macy /* 1719eda14cbcSMatt Macy * Strip inherited execute permission from file if 1720eda14cbcSMatt Macy * not in mode 1721eda14cbcSMatt Macy */ 1722eda14cbcSMatt Macy if (aclinherit == ZFS_ACL_PASSTHROUGH_X && type == ALLOW && 1723eda14cbcSMatt Macy !isdir && ((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)) { 1724eda14cbcSMatt Macy access_mask &= ~ACE_EXECUTE; 1725eda14cbcSMatt Macy } 1726eda14cbcSMatt Macy 1727eda14cbcSMatt Macy /* 1728eda14cbcSMatt Macy * Strip write_acl and write_owner from permissions 1729eda14cbcSMatt Macy * when inheriting an ACE 1730eda14cbcSMatt Macy */ 1731eda14cbcSMatt Macy if (aclinherit == ZFS_ACL_RESTRICTED && type == ALLOW) { 1732eda14cbcSMatt Macy access_mask &= ~RESTRICTED_CLEAR; 1733eda14cbcSMatt Macy } 1734eda14cbcSMatt Macy 1735eda14cbcSMatt Macy ace_size = aclp->z_ops->ace_size(pacep); 1736eda14cbcSMatt Macy aclnode = zfs_acl_node_alloc(ace_size); 1737eda14cbcSMatt Macy list_insert_tail(&aclp->z_acl, aclnode); 1738eda14cbcSMatt Macy acep = aclnode->z_acldata; 1739eda14cbcSMatt Macy 1740eda14cbcSMatt Macy zfs_set_ace(aclp, acep, access_mask, type, 1741eda14cbcSMatt Macy who, iflags|ACE_INHERITED_ACE); 1742eda14cbcSMatt Macy 1743eda14cbcSMatt Macy /* 1744eda14cbcSMatt Macy * Copy special opaque data if any 1745eda14cbcSMatt Macy */ 1746eda14cbcSMatt Macy if ((data1sz = paclp->z_ops->ace_data(pacep, &data1)) != 0) { 1747eda14cbcSMatt Macy VERIFY((data2sz = aclp->z_ops->ace_data(acep, 1748eda14cbcSMatt Macy &data2)) == data1sz); 1749da5137abSMartin Matuska memcpy(data2, data1, data2sz); 1750eda14cbcSMatt Macy } 1751eda14cbcSMatt Macy 1752eda14cbcSMatt Macy aclp->z_acl_count++; 1753eda14cbcSMatt Macy aclnode->z_ace_count++; 1754eda14cbcSMatt Macy aclp->z_acl_bytes += aclnode->z_size; 1755eda14cbcSMatt Macy newflags = aclp->z_ops->ace_flags_get(acep); 1756eda14cbcSMatt Macy 1757eda14cbcSMatt Macy /* 1758eda14cbcSMatt Macy * If ACE is not to be inherited further, or if the vnode is 1759eda14cbcSMatt Macy * not a directory, remove all inheritance flags 1760eda14cbcSMatt Macy */ 1761eda14cbcSMatt Macy if (!isdir || (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) { 1762eda14cbcSMatt Macy newflags &= ~ALL_INHERIT; 1763eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, 1764eda14cbcSMatt Macy newflags|ACE_INHERITED_ACE); 1765eda14cbcSMatt Macy continue; 1766eda14cbcSMatt Macy } 1767eda14cbcSMatt Macy 1768eda14cbcSMatt Macy /* 1769eda14cbcSMatt Macy * This directory has an inheritable ACE 1770eda14cbcSMatt Macy */ 1771eda14cbcSMatt Macy aclp->z_hints |= ZFS_INHERIT_ACE; 1772eda14cbcSMatt Macy 1773eda14cbcSMatt Macy /* 1774eda14cbcSMatt Macy * If only FILE_INHERIT is set then turn on 1775eda14cbcSMatt Macy * inherit_only 1776eda14cbcSMatt Macy */ 1777eda14cbcSMatt Macy if ((iflags & (ACE_FILE_INHERIT_ACE | 1778eda14cbcSMatt Macy ACE_DIRECTORY_INHERIT_ACE)) == ACE_FILE_INHERIT_ACE) { 1779eda14cbcSMatt Macy newflags |= ACE_INHERIT_ONLY_ACE; 1780eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, 1781eda14cbcSMatt Macy newflags|ACE_INHERITED_ACE); 1782eda14cbcSMatt Macy } else { 1783eda14cbcSMatt Macy newflags &= ~ACE_INHERIT_ONLY_ACE; 1784eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, 1785eda14cbcSMatt Macy newflags|ACE_INHERITED_ACE); 1786eda14cbcSMatt Macy } 1787eda14cbcSMatt Macy } 1788eda14cbcSMatt Macy if (zfsvfs->z_acl_mode == ZFS_ACL_RESTRICTED && 1789eda14cbcSMatt Macy aclp->z_acl_count != 0) { 1790eda14cbcSMatt Macy *need_chmod = B_FALSE; 1791eda14cbcSMatt Macy } 1792eda14cbcSMatt Macy 1793eda14cbcSMatt Macy return (aclp); 1794eda14cbcSMatt Macy } 1795eda14cbcSMatt Macy 1796eda14cbcSMatt Macy /* 1797eda14cbcSMatt Macy * Create file system object initial permissions 1798eda14cbcSMatt Macy * including inheritable ACEs. 1799eda14cbcSMatt Macy * Also, create FUIDs for owner and group. 1800eda14cbcSMatt Macy */ 1801eda14cbcSMatt Macy int 1802eda14cbcSMatt Macy zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, 1803d411c1d6SMartin Matuska vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns) 1804eda14cbcSMatt Macy { 1805eda14cbcSMatt Macy int error; 1806eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(dzp); 1807eda14cbcSMatt Macy zfs_acl_t *paclp; 1808eda14cbcSMatt Macy gid_t gid = vap->va_gid; 1809eda14cbcSMatt Macy boolean_t need_chmod = B_TRUE; 1810eda14cbcSMatt Macy boolean_t trim = B_FALSE; 1811eda14cbcSMatt Macy boolean_t inherited = B_FALSE; 1812eda14cbcSMatt Macy 1813da5137abSMartin Matuska memset(acl_ids, 0, sizeof (zfs_acl_ids_t)); 1814eda14cbcSMatt Macy acl_ids->z_mode = vap->va_mode; 1815eda14cbcSMatt Macy 1816eda14cbcSMatt Macy if (vsecp) 1817eda14cbcSMatt Macy if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_mode, vsecp, 1818eda14cbcSMatt Macy cr, &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0) 1819eda14cbcSMatt Macy return (error); 1820eda14cbcSMatt Macy 1821eda14cbcSMatt Macy acl_ids->z_fuid = vap->va_uid; 1822eda14cbcSMatt Macy acl_ids->z_fgid = vap->va_gid; 1823eda14cbcSMatt Macy #ifdef HAVE_KSID 1824eda14cbcSMatt Macy /* 1825eda14cbcSMatt Macy * Determine uid and gid. 1826eda14cbcSMatt Macy */ 1827eda14cbcSMatt Macy if ((flag & IS_ROOT_NODE) || zfsvfs->z_replay || 1828eda14cbcSMatt Macy ((flag & IS_XATTR) && (S_ISDIR(vap->va_mode)))) { 1829eda14cbcSMatt Macy acl_ids->z_fuid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_uid, 1830eda14cbcSMatt Macy cr, ZFS_OWNER, &acl_ids->z_fuidp); 1831eda14cbcSMatt Macy acl_ids->z_fgid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_gid, 1832eda14cbcSMatt Macy cr, ZFS_GROUP, &acl_ids->z_fuidp); 1833eda14cbcSMatt Macy gid = vap->va_gid; 1834eda14cbcSMatt Macy } else { 1835eda14cbcSMatt Macy acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, 1836eda14cbcSMatt Macy cr, &acl_ids->z_fuidp); 1837eda14cbcSMatt Macy acl_ids->z_fgid = 0; 1838eda14cbcSMatt Macy if (vap->va_mask & AT_GID) { 1839eda14cbcSMatt Macy acl_ids->z_fgid = zfs_fuid_create(zfsvfs, 1840eda14cbcSMatt Macy (uint64_t)vap->va_gid, 1841eda14cbcSMatt Macy cr, ZFS_GROUP, &acl_ids->z_fuidp); 1842eda14cbcSMatt Macy gid = vap->va_gid; 1843eda14cbcSMatt Macy if (acl_ids->z_fgid != KGID_TO_SGID(ZTOI(dzp)->i_gid) && 1844eda14cbcSMatt Macy !groupmember(vap->va_gid, cr) && 1845eda14cbcSMatt Macy secpolicy_vnode_create_gid(cr) != 0) 1846eda14cbcSMatt Macy acl_ids->z_fgid = 0; 1847eda14cbcSMatt Macy } 1848eda14cbcSMatt Macy if (acl_ids->z_fgid == 0) { 1849eda14cbcSMatt Macy if (dzp->z_mode & S_ISGID) { 1850eda14cbcSMatt Macy char *domain; 1851eda14cbcSMatt Macy uint32_t rid; 1852eda14cbcSMatt Macy 1853eda14cbcSMatt Macy acl_ids->z_fgid = KGID_TO_SGID( 1854eda14cbcSMatt Macy ZTOI(dzp)->i_gid); 1855eda14cbcSMatt Macy gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid, 1856eda14cbcSMatt Macy cr, ZFS_GROUP); 1857eda14cbcSMatt Macy 1858eda14cbcSMatt Macy if (zfsvfs->z_use_fuids && 1859eda14cbcSMatt Macy IS_EPHEMERAL(acl_ids->z_fgid)) { 1860eda14cbcSMatt Macy domain = zfs_fuid_idx_domain( 1861eda14cbcSMatt Macy &zfsvfs->z_fuid_idx, 1862eda14cbcSMatt Macy FUID_INDEX(acl_ids->z_fgid)); 1863eda14cbcSMatt Macy rid = FUID_RID(acl_ids->z_fgid); 1864eda14cbcSMatt Macy zfs_fuid_node_add(&acl_ids->z_fuidp, 1865eda14cbcSMatt Macy domain, rid, 1866eda14cbcSMatt Macy FUID_INDEX(acl_ids->z_fgid), 1867eda14cbcSMatt Macy acl_ids->z_fgid, ZFS_GROUP); 1868eda14cbcSMatt Macy } 1869eda14cbcSMatt Macy } else { 1870eda14cbcSMatt Macy acl_ids->z_fgid = zfs_fuid_create_cred(zfsvfs, 1871eda14cbcSMatt Macy ZFS_GROUP, cr, &acl_ids->z_fuidp); 1872eda14cbcSMatt Macy gid = crgetgid(cr); 1873eda14cbcSMatt Macy } 1874eda14cbcSMatt Macy } 1875eda14cbcSMatt Macy } 1876eda14cbcSMatt Macy #endif /* HAVE_KSID */ 1877eda14cbcSMatt Macy 1878eda14cbcSMatt Macy /* 1879eda14cbcSMatt Macy * If we're creating a directory, and the parent directory has the 1880eda14cbcSMatt Macy * set-GID bit set, set in on the new directory. 1881eda14cbcSMatt Macy * Otherwise, if the user is neither privileged nor a member of the 1882eda14cbcSMatt Macy * file's new group, clear the file's set-GID bit. 1883eda14cbcSMatt Macy */ 1884eda14cbcSMatt Macy 1885eda14cbcSMatt Macy if (!(flag & IS_ROOT_NODE) && (dzp->z_mode & S_ISGID) && 1886eda14cbcSMatt Macy (S_ISDIR(vap->va_mode))) { 1887eda14cbcSMatt Macy acl_ids->z_mode |= S_ISGID; 1888eda14cbcSMatt Macy } else { 1889eda14cbcSMatt Macy if ((acl_ids->z_mode & S_ISGID) && 1890dbd5678dSMartin Matuska secpolicy_vnode_setids_setgids(cr, gid, mnt_ns, 1891dbd5678dSMartin Matuska zfs_i_user_ns(ZTOI(dzp))) != 0) { 1892eda14cbcSMatt Macy acl_ids->z_mode &= ~S_ISGID; 1893eda14cbcSMatt Macy } 1894dbd5678dSMartin Matuska } 1895eda14cbcSMatt Macy 1896eda14cbcSMatt Macy if (acl_ids->z_aclp == NULL) { 1897eda14cbcSMatt Macy mutex_enter(&dzp->z_acl_lock); 1898eda14cbcSMatt Macy mutex_enter(&dzp->z_lock); 1899eda14cbcSMatt Macy if (!(flag & IS_ROOT_NODE) && 1900eda14cbcSMatt Macy (dzp->z_pflags & ZFS_INHERIT_ACE) && 1901eda14cbcSMatt Macy !(dzp->z_pflags & ZFS_XATTR)) { 1902eda14cbcSMatt Macy VERIFY(0 == zfs_acl_node_read(dzp, B_TRUE, 1903eda14cbcSMatt Macy &paclp, B_FALSE)); 1904eda14cbcSMatt Macy acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, 1905eda14cbcSMatt Macy vap->va_mode, paclp, acl_ids->z_mode, &need_chmod); 1906eda14cbcSMatt Macy inherited = B_TRUE; 1907eda14cbcSMatt Macy } else { 1908eda14cbcSMatt Macy acl_ids->z_aclp = 1909eda14cbcSMatt Macy zfs_acl_alloc(zfs_acl_version_zp(dzp)); 1910eda14cbcSMatt Macy acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; 1911eda14cbcSMatt Macy } 1912eda14cbcSMatt Macy mutex_exit(&dzp->z_lock); 1913eda14cbcSMatt Macy mutex_exit(&dzp->z_acl_lock); 1914eda14cbcSMatt Macy 1915eda14cbcSMatt Macy if (need_chmod) { 1916eda14cbcSMatt Macy if (S_ISDIR(vap->va_mode)) 1917eda14cbcSMatt Macy acl_ids->z_aclp->z_hints |= 1918eda14cbcSMatt Macy ZFS_ACL_AUTO_INHERIT; 1919eda14cbcSMatt Macy 1920eda14cbcSMatt Macy if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK && 1921eda14cbcSMatt Macy zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH && 1922eda14cbcSMatt Macy zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X) 1923eda14cbcSMatt Macy trim = B_TRUE; 19244fefe1b7SMartin Matuska zfs_acl_chmod(S_ISDIR(vap->va_mode), acl_ids->z_mode, 19254fefe1b7SMartin Matuska B_FALSE, trim, acl_ids->z_aclp); 1926eda14cbcSMatt Macy } 1927eda14cbcSMatt Macy } 1928eda14cbcSMatt Macy 1929eda14cbcSMatt Macy if (inherited || vsecp) { 1930eda14cbcSMatt Macy acl_ids->z_mode = zfs_mode_compute(acl_ids->z_mode, 1931eda14cbcSMatt Macy acl_ids->z_aclp, &acl_ids->z_aclp->z_hints, 1932eda14cbcSMatt Macy acl_ids->z_fuid, acl_ids->z_fgid); 1933eda14cbcSMatt Macy if (ace_trivial_common(acl_ids->z_aclp, 0, zfs_ace_walk) == 0) 1934eda14cbcSMatt Macy acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; 1935eda14cbcSMatt Macy } 1936eda14cbcSMatt Macy 1937eda14cbcSMatt Macy return (0); 1938eda14cbcSMatt Macy } 1939eda14cbcSMatt Macy 1940eda14cbcSMatt Macy /* 1941eda14cbcSMatt Macy * Free ACL and fuid_infop, but not the acl_ids structure 1942eda14cbcSMatt Macy */ 1943eda14cbcSMatt Macy void 1944eda14cbcSMatt Macy zfs_acl_ids_free(zfs_acl_ids_t *acl_ids) 1945eda14cbcSMatt Macy { 1946eda14cbcSMatt Macy if (acl_ids->z_aclp) 1947eda14cbcSMatt Macy zfs_acl_free(acl_ids->z_aclp); 1948eda14cbcSMatt Macy if (acl_ids->z_fuidp) 1949eda14cbcSMatt Macy zfs_fuid_info_free(acl_ids->z_fuidp); 1950eda14cbcSMatt Macy acl_ids->z_aclp = NULL; 1951eda14cbcSMatt Macy acl_ids->z_fuidp = NULL; 1952eda14cbcSMatt Macy } 1953eda14cbcSMatt Macy 1954eda14cbcSMatt Macy boolean_t 1955eda14cbcSMatt Macy zfs_acl_ids_overquota(zfsvfs_t *zv, zfs_acl_ids_t *acl_ids, uint64_t projid) 1956eda14cbcSMatt Macy { 1957eda14cbcSMatt Macy return (zfs_id_overquota(zv, DMU_USERUSED_OBJECT, acl_ids->z_fuid) || 1958eda14cbcSMatt Macy zfs_id_overquota(zv, DMU_GROUPUSED_OBJECT, acl_ids->z_fgid) || 1959eda14cbcSMatt Macy (projid != ZFS_DEFAULT_PROJID && projid != ZFS_INVALID_PROJID && 1960eda14cbcSMatt Macy zfs_id_overquota(zv, DMU_PROJECTUSED_OBJECT, projid))); 1961eda14cbcSMatt Macy } 1962eda14cbcSMatt Macy 1963eda14cbcSMatt Macy /* 1964eda14cbcSMatt Macy * Retrieve a file's ACL 1965eda14cbcSMatt Macy */ 1966eda14cbcSMatt Macy int 1967eda14cbcSMatt Macy zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1968eda14cbcSMatt Macy { 1969eda14cbcSMatt Macy zfs_acl_t *aclp; 1970eda14cbcSMatt Macy ulong_t mask; 1971eda14cbcSMatt Macy int error; 1972eda14cbcSMatt Macy int count = 0; 1973eda14cbcSMatt Macy int largeace = 0; 1974eda14cbcSMatt Macy 1975eda14cbcSMatt Macy mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT | 1976eda14cbcSMatt Macy VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 1977eda14cbcSMatt Macy 1978eda14cbcSMatt Macy if (mask == 0) 1979eda14cbcSMatt Macy return (SET_ERROR(ENOSYS)); 1980eda14cbcSMatt Macy 1981dbd5678dSMartin Matuska if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, 1982d411c1d6SMartin Matuska zfs_init_idmap))) 1983eda14cbcSMatt Macy return (error); 1984eda14cbcSMatt Macy 1985eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 1986eda14cbcSMatt Macy 1987eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); 1988eda14cbcSMatt Macy if (error != 0) { 1989eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 1990eda14cbcSMatt Macy return (error); 1991eda14cbcSMatt Macy } 1992eda14cbcSMatt Macy 1993eda14cbcSMatt Macy /* 1994eda14cbcSMatt Macy * Scan ACL to determine number of ACEs 1995eda14cbcSMatt Macy */ 1996eda14cbcSMatt Macy if ((zp->z_pflags & ZFS_ACL_OBJ_ACE) && !(mask & VSA_ACE_ALLTYPES)) { 1997eda14cbcSMatt Macy void *zacep = NULL; 1998eda14cbcSMatt Macy uint64_t who; 1999eda14cbcSMatt Macy uint32_t access_mask; 2000eda14cbcSMatt Macy uint16_t type, iflags; 2001eda14cbcSMatt Macy 2002eda14cbcSMatt Macy while ((zacep = zfs_acl_next_ace(aclp, zacep, 2003eda14cbcSMatt Macy &who, &access_mask, &iflags, &type))) { 2004eda14cbcSMatt Macy switch (type) { 2005eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 2006eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 2007eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 2008eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 2009eda14cbcSMatt Macy largeace++; 2010eda14cbcSMatt Macy continue; 2011eda14cbcSMatt Macy default: 2012eda14cbcSMatt Macy count++; 2013eda14cbcSMatt Macy } 2014eda14cbcSMatt Macy } 2015eda14cbcSMatt Macy vsecp->vsa_aclcnt = count; 2016eda14cbcSMatt Macy } else 2017eda14cbcSMatt Macy count = (int)aclp->z_acl_count; 2018eda14cbcSMatt Macy 2019eda14cbcSMatt Macy if (mask & VSA_ACECNT) { 2020eda14cbcSMatt Macy vsecp->vsa_aclcnt = count; 2021eda14cbcSMatt Macy } 2022eda14cbcSMatt Macy 2023eda14cbcSMatt Macy if (mask & VSA_ACE) { 2024eda14cbcSMatt Macy size_t aclsz; 2025eda14cbcSMatt Macy 2026eda14cbcSMatt Macy aclsz = count * sizeof (ace_t) + 2027eda14cbcSMatt Macy sizeof (ace_object_t) * largeace; 2028eda14cbcSMatt Macy 2029eda14cbcSMatt Macy vsecp->vsa_aclentp = kmem_alloc(aclsz, KM_SLEEP); 2030eda14cbcSMatt Macy vsecp->vsa_aclentsz = aclsz; 2031eda14cbcSMatt Macy 2032eda14cbcSMatt Macy if (aclp->z_version == ZFS_ACL_VERSION_FUID) 2033eda14cbcSMatt Macy zfs_copy_fuid_2_ace(ZTOZSB(zp), aclp, cr, 2034eda14cbcSMatt Macy vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES)); 2035eda14cbcSMatt Macy else { 2036eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 2037eda14cbcSMatt Macy void *start = vsecp->vsa_aclentp; 2038eda14cbcSMatt Macy 2039eda14cbcSMatt Macy for (aclnode = list_head(&aclp->z_acl); aclnode; 2040eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode)) { 2041da5137abSMartin Matuska memcpy(start, aclnode->z_acldata, 2042eda14cbcSMatt Macy aclnode->z_size); 2043eda14cbcSMatt Macy start = (caddr_t)start + aclnode->z_size; 2044eda14cbcSMatt Macy } 2045eda14cbcSMatt Macy ASSERT((caddr_t)start - (caddr_t)vsecp->vsa_aclentp == 2046eda14cbcSMatt Macy aclp->z_acl_bytes); 2047eda14cbcSMatt Macy } 2048eda14cbcSMatt Macy } 2049eda14cbcSMatt Macy if (mask & VSA_ACE_ACLFLAGS) { 2050eda14cbcSMatt Macy vsecp->vsa_aclflags = 0; 2051eda14cbcSMatt Macy if (zp->z_pflags & ZFS_ACL_DEFAULTED) 2052eda14cbcSMatt Macy vsecp->vsa_aclflags |= ACL_DEFAULTED; 2053eda14cbcSMatt Macy if (zp->z_pflags & ZFS_ACL_PROTECTED) 2054eda14cbcSMatt Macy vsecp->vsa_aclflags |= ACL_PROTECTED; 2055eda14cbcSMatt Macy if (zp->z_pflags & ZFS_ACL_AUTO_INHERIT) 2056eda14cbcSMatt Macy vsecp->vsa_aclflags |= ACL_AUTO_INHERIT; 2057eda14cbcSMatt Macy } 2058eda14cbcSMatt Macy 2059eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2060eda14cbcSMatt Macy 2061eda14cbcSMatt Macy return (0); 2062eda14cbcSMatt Macy } 2063eda14cbcSMatt Macy 2064eda14cbcSMatt Macy int 2065eda14cbcSMatt Macy zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, umode_t obj_mode, 2066eda14cbcSMatt Macy vsecattr_t *vsecp, cred_t *cr, zfs_fuid_info_t **fuidp, zfs_acl_t **zaclp) 2067eda14cbcSMatt Macy { 2068eda14cbcSMatt Macy zfs_acl_t *aclp; 2069eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 2070eda14cbcSMatt Macy int aclcnt = vsecp->vsa_aclcnt; 2071eda14cbcSMatt Macy int error; 2072eda14cbcSMatt Macy 2073eda14cbcSMatt Macy if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0) 2074eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 2075eda14cbcSMatt Macy 2076eda14cbcSMatt Macy aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version)); 2077eda14cbcSMatt Macy 2078eda14cbcSMatt Macy aclp->z_hints = 0; 2079eda14cbcSMatt Macy aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t)); 2080eda14cbcSMatt Macy if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 2081eda14cbcSMatt Macy if ((error = zfs_copy_ace_2_oldace(obj_mode, aclp, 2082eda14cbcSMatt Macy (ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata, 2083eda14cbcSMatt Macy aclcnt, &aclnode->z_size)) != 0) { 2084eda14cbcSMatt Macy zfs_acl_free(aclp); 2085eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 2086eda14cbcSMatt Macy return (error); 2087eda14cbcSMatt Macy } 2088eda14cbcSMatt Macy } else { 2089eda14cbcSMatt Macy if ((error = zfs_copy_ace_2_fuid(zfsvfs, obj_mode, aclp, 2090eda14cbcSMatt Macy vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt, 2091eda14cbcSMatt Macy &aclnode->z_size, fuidp, cr)) != 0) { 2092eda14cbcSMatt Macy zfs_acl_free(aclp); 2093eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 2094eda14cbcSMatt Macy return (error); 2095eda14cbcSMatt Macy } 2096eda14cbcSMatt Macy } 2097eda14cbcSMatt Macy aclp->z_acl_bytes = aclnode->z_size; 2098eda14cbcSMatt Macy aclnode->z_ace_count = aclcnt; 2099eda14cbcSMatt Macy aclp->z_acl_count = aclcnt; 2100eda14cbcSMatt Macy list_insert_head(&aclp->z_acl, aclnode); 2101eda14cbcSMatt Macy 2102eda14cbcSMatt Macy /* 2103eda14cbcSMatt Macy * If flags are being set then add them to z_hints 2104eda14cbcSMatt Macy */ 2105eda14cbcSMatt Macy if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) { 2106eda14cbcSMatt Macy if (vsecp->vsa_aclflags & ACL_PROTECTED) 2107eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_PROTECTED; 2108eda14cbcSMatt Macy if (vsecp->vsa_aclflags & ACL_DEFAULTED) 2109eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_DEFAULTED; 2110eda14cbcSMatt Macy if (vsecp->vsa_aclflags & ACL_AUTO_INHERIT) 2111eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 2112eda14cbcSMatt Macy } 2113eda14cbcSMatt Macy 2114eda14cbcSMatt Macy *zaclp = aclp; 2115eda14cbcSMatt Macy 2116eda14cbcSMatt Macy return (0); 2117eda14cbcSMatt Macy } 2118eda14cbcSMatt Macy 2119eda14cbcSMatt Macy /* 2120eda14cbcSMatt Macy * Set a file's ACL 2121eda14cbcSMatt Macy */ 2122eda14cbcSMatt Macy int 2123eda14cbcSMatt Macy zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 2124eda14cbcSMatt Macy { 2125eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 2126eda14cbcSMatt Macy zilog_t *zilog = zfsvfs->z_log; 2127eda14cbcSMatt Macy ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 2128eda14cbcSMatt Macy dmu_tx_t *tx; 2129eda14cbcSMatt Macy int error; 2130eda14cbcSMatt Macy zfs_acl_t *aclp; 2131eda14cbcSMatt Macy zfs_fuid_info_t *fuidp = NULL; 2132eda14cbcSMatt Macy boolean_t fuid_dirtied; 2133eda14cbcSMatt Macy uint64_t acl_obj; 2134eda14cbcSMatt Macy 2135eda14cbcSMatt Macy if (mask == 0) 2136eda14cbcSMatt Macy return (SET_ERROR(ENOSYS)); 2137eda14cbcSMatt Macy 2138eda14cbcSMatt Macy if (zp->z_pflags & ZFS_IMMUTABLE) 2139eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2140eda14cbcSMatt Macy 2141dbd5678dSMartin Matuska if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, 2142d411c1d6SMartin Matuska zfs_init_idmap))) 2143eda14cbcSMatt Macy return (error); 2144eda14cbcSMatt Macy 2145eda14cbcSMatt Macy error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, 2146eda14cbcSMatt Macy &aclp); 2147eda14cbcSMatt Macy if (error) 2148eda14cbcSMatt Macy return (error); 2149eda14cbcSMatt Macy 2150eda14cbcSMatt Macy /* 2151eda14cbcSMatt Macy * If ACL wide flags aren't being set then preserve any 2152eda14cbcSMatt Macy * existing flags. 2153eda14cbcSMatt Macy */ 2154eda14cbcSMatt Macy if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { 2155eda14cbcSMatt Macy aclp->z_hints |= 2156eda14cbcSMatt Macy (zp->z_pflags & V4_ACL_WIDE_FLAGS); 2157eda14cbcSMatt Macy } 2158eda14cbcSMatt Macy top: 2159eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 2160eda14cbcSMatt Macy mutex_enter(&zp->z_lock); 2161eda14cbcSMatt Macy 2162eda14cbcSMatt Macy tx = dmu_tx_create(zfsvfs->z_os); 2163eda14cbcSMatt Macy 2164eda14cbcSMatt Macy dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); 2165eda14cbcSMatt Macy 2166eda14cbcSMatt Macy fuid_dirtied = zfsvfs->z_fuid_dirty; 2167eda14cbcSMatt Macy if (fuid_dirtied) 2168eda14cbcSMatt Macy zfs_fuid_txhold(zfsvfs, tx); 2169eda14cbcSMatt Macy 2170eda14cbcSMatt Macy /* 2171eda14cbcSMatt Macy * If old version and ACL won't fit in bonus and we aren't 2172eda14cbcSMatt Macy * upgrading then take out necessary DMU holds 2173eda14cbcSMatt Macy */ 2174eda14cbcSMatt Macy 2175eda14cbcSMatt Macy if ((acl_obj = zfs_external_acl(zp)) != 0) { 2176eda14cbcSMatt Macy if (zfsvfs->z_version >= ZPL_VERSION_FUID && 2177eda14cbcSMatt Macy zfs_znode_acl_version(zp) <= ZFS_ACL_VERSION_INITIAL) { 2178eda14cbcSMatt Macy dmu_tx_hold_free(tx, acl_obj, 0, 2179eda14cbcSMatt Macy DMU_OBJECT_END); 2180eda14cbcSMatt Macy dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 2181eda14cbcSMatt Macy aclp->z_acl_bytes); 2182eda14cbcSMatt Macy } else { 2183eda14cbcSMatt Macy dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes); 2184eda14cbcSMatt Macy } 2185eda14cbcSMatt Macy } else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { 2186eda14cbcSMatt Macy dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); 2187eda14cbcSMatt Macy } 2188eda14cbcSMatt Macy 2189eda14cbcSMatt Macy zfs_sa_upgrade_txholds(tx, zp); 2190eda14cbcSMatt Macy error = dmu_tx_assign(tx, TXG_NOWAIT); 2191eda14cbcSMatt Macy if (error) { 2192eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2193eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 2194eda14cbcSMatt Macy 2195eda14cbcSMatt Macy if (error == ERESTART) { 2196eda14cbcSMatt Macy dmu_tx_wait(tx); 2197eda14cbcSMatt Macy dmu_tx_abort(tx); 2198eda14cbcSMatt Macy goto top; 2199eda14cbcSMatt Macy } 2200eda14cbcSMatt Macy dmu_tx_abort(tx); 2201eda14cbcSMatt Macy zfs_acl_free(aclp); 2202eda14cbcSMatt Macy return (error); 2203eda14cbcSMatt Macy } 2204eda14cbcSMatt Macy 2205eda14cbcSMatt Macy error = zfs_aclset_common(zp, aclp, cr, tx); 2206eda14cbcSMatt Macy ASSERT(error == 0); 2207eda14cbcSMatt Macy ASSERT(zp->z_acl_cached == NULL); 2208eda14cbcSMatt Macy zp->z_acl_cached = aclp; 2209eda14cbcSMatt Macy 2210eda14cbcSMatt Macy if (fuid_dirtied) 2211eda14cbcSMatt Macy zfs_fuid_sync(zfsvfs, tx); 2212eda14cbcSMatt Macy 2213eda14cbcSMatt Macy zfs_log_acl(zilog, tx, zp, vsecp, fuidp); 2214eda14cbcSMatt Macy 2215eda14cbcSMatt Macy if (fuidp) 2216eda14cbcSMatt Macy zfs_fuid_info_free(fuidp); 2217eda14cbcSMatt Macy dmu_tx_commit(tx); 2218eda14cbcSMatt Macy 2219eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 2220eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2221eda14cbcSMatt Macy 2222eda14cbcSMatt Macy return (error); 2223eda14cbcSMatt Macy } 2224eda14cbcSMatt Macy 2225eda14cbcSMatt Macy /* 2226eda14cbcSMatt Macy * Check accesses of interest (AoI) against attributes of the dataset 2227eda14cbcSMatt Macy * such as read-only. Returns zero if no AoI conflict with dataset 2228eda14cbcSMatt Macy * attributes, otherwise an appropriate errno is returned. 2229eda14cbcSMatt Macy */ 2230eda14cbcSMatt Macy static int 2231eda14cbcSMatt Macy zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) 2232eda14cbcSMatt Macy { 2233eda14cbcSMatt Macy if ((v4_mode & WRITE_MASK) && (zfs_is_readonly(ZTOZSB(zp))) && 223415f0b8c3SMartin Matuska (!Z_ISDEV(ZTOI(zp)->i_mode) || (v4_mode & WRITE_MASK_ATTRS))) { 2235eda14cbcSMatt Macy return (SET_ERROR(EROFS)); 2236eda14cbcSMatt Macy } 2237eda14cbcSMatt Macy 2238eda14cbcSMatt Macy /* 22399db44a8eSMartin Matuska * Intentionally allow ZFS_READONLY through here. 22409db44a8eSMartin Matuska * See zfs_zaccess_common(). 2241eda14cbcSMatt Macy */ 2242eda14cbcSMatt Macy if ((v4_mode & WRITE_MASK_DATA) && 22439db44a8eSMartin Matuska (zp->z_pflags & ZFS_IMMUTABLE)) { 2244eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2245eda14cbcSMatt Macy } 2246eda14cbcSMatt Macy 2247eda14cbcSMatt Macy if ((v4_mode & (ACE_DELETE | ACE_DELETE_CHILD)) && 2248eda14cbcSMatt Macy (zp->z_pflags & ZFS_NOUNLINK)) { 2249eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2250eda14cbcSMatt Macy } 2251eda14cbcSMatt Macy 2252eda14cbcSMatt Macy if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) && 2253eda14cbcSMatt Macy (zp->z_pflags & ZFS_AV_QUARANTINED))) { 2254eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2255eda14cbcSMatt Macy } 2256eda14cbcSMatt Macy 2257eda14cbcSMatt Macy return (0); 2258eda14cbcSMatt Macy } 2259eda14cbcSMatt Macy 2260eda14cbcSMatt Macy /* 2261eda14cbcSMatt Macy * The primary usage of this function is to loop through all of the 2262eda14cbcSMatt Macy * ACEs in the znode, determining what accesses of interest (AoI) to 2263eda14cbcSMatt Macy * the caller are allowed or denied. The AoI are expressed as bits in 2264eda14cbcSMatt Macy * the working_mode parameter. As each ACE is processed, bits covered 2265eda14cbcSMatt Macy * by that ACE are removed from the working_mode. This removal 2266eda14cbcSMatt Macy * facilitates two things. The first is that when the working mode is 2267eda14cbcSMatt Macy * empty (= 0), we know we've looked at all the AoI. The second is 2268eda14cbcSMatt Macy * that the ACE interpretation rules don't allow a later ACE to undo 2269eda14cbcSMatt Macy * something granted or denied by an earlier ACE. Removing the 2270eda14cbcSMatt Macy * discovered access or denial enforces this rule. At the end of 2271eda14cbcSMatt Macy * processing the ACEs, all AoI that were found to be denied are 2272eda14cbcSMatt Macy * placed into the working_mode, giving the caller a mask of denied 2273eda14cbcSMatt Macy * accesses. Returns: 2274eda14cbcSMatt Macy * 0 if all AoI granted 2275eda14cbcSMatt Macy * EACCES if the denied mask is non-zero 2276eda14cbcSMatt Macy * other error if abnormal failure (e.g., IO error) 2277eda14cbcSMatt Macy * 2278eda14cbcSMatt Macy * A secondary usage of the function is to determine if any of the 2279eda14cbcSMatt Macy * AoI are granted. If an ACE grants any access in 2280eda14cbcSMatt Macy * the working_mode, we immediately short circuit out of the function. 2281eda14cbcSMatt Macy * This mode is chosen by setting anyaccess to B_TRUE. The 2282eda14cbcSMatt Macy * working_mode is not a denied access mask upon exit if the function 2283eda14cbcSMatt Macy * is used in this manner. 2284eda14cbcSMatt Macy */ 2285eda14cbcSMatt Macy static int 2286eda14cbcSMatt Macy zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, 2287d411c1d6SMartin Matuska boolean_t anyaccess, cred_t *cr, zidmap_t *mnt_ns) 2288eda14cbcSMatt Macy { 2289eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 2290eda14cbcSMatt Macy zfs_acl_t *aclp; 2291eda14cbcSMatt Macy int error; 2292eda14cbcSMatt Macy uid_t uid = crgetuid(cr); 2293eda14cbcSMatt Macy uint64_t who; 2294eda14cbcSMatt Macy uint16_t type, iflags; 2295eda14cbcSMatt Macy uint16_t entry_type; 2296eda14cbcSMatt Macy uint32_t access_mask; 2297eda14cbcSMatt Macy uint32_t deny_mask = 0; 2298eda14cbcSMatt Macy zfs_ace_hdr_t *acep = NULL; 2299eda14cbcSMatt Macy boolean_t checkit; 2300eda14cbcSMatt Macy uid_t gowner; 2301eda14cbcSMatt Macy uid_t fowner; 2302eda14cbcSMatt Macy 2303dbd5678dSMartin Matuska if (mnt_ns) { 2304dbd5678dSMartin Matuska fowner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), 2305dbd5678dSMartin Matuska KUID_TO_SUID(ZTOI(zp)->i_uid)); 2306dbd5678dSMartin Matuska gowner = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), 2307dbd5678dSMartin Matuska KGID_TO_SGID(ZTOI(zp)->i_gid)); 2308dbd5678dSMartin Matuska } else 2309eda14cbcSMatt Macy zfs_fuid_map_ids(zp, cr, &fowner, &gowner); 2310eda14cbcSMatt Macy 2311eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 2312eda14cbcSMatt Macy 2313eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_FALSE, &aclp, B_FALSE); 2314eda14cbcSMatt Macy if (error != 0) { 2315eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2316eda14cbcSMatt Macy return (error); 2317eda14cbcSMatt Macy } 2318eda14cbcSMatt Macy 2319eda14cbcSMatt Macy ASSERT(zp->z_acl_cached); 2320eda14cbcSMatt Macy 2321eda14cbcSMatt Macy while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 2322eda14cbcSMatt Macy &iflags, &type))) { 2323eda14cbcSMatt Macy uint32_t mask_matched; 2324eda14cbcSMatt Macy 2325eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 2326eda14cbcSMatt Macy continue; 2327eda14cbcSMatt Macy 2328eda14cbcSMatt Macy if (S_ISDIR(ZTOI(zp)->i_mode) && 2329eda14cbcSMatt Macy (iflags & ACE_INHERIT_ONLY_ACE)) 2330eda14cbcSMatt Macy continue; 2331eda14cbcSMatt Macy 2332eda14cbcSMatt Macy /* Skip ACE if it does not affect any AoI */ 2333eda14cbcSMatt Macy mask_matched = (access_mask & *working_mode); 2334eda14cbcSMatt Macy if (!mask_matched) 2335eda14cbcSMatt Macy continue; 2336eda14cbcSMatt Macy 2337eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 2338eda14cbcSMatt Macy 2339eda14cbcSMatt Macy checkit = B_FALSE; 2340eda14cbcSMatt Macy 2341eda14cbcSMatt Macy switch (entry_type) { 2342eda14cbcSMatt Macy case ACE_OWNER: 2343eda14cbcSMatt Macy if (uid == fowner) 2344eda14cbcSMatt Macy checkit = B_TRUE; 2345eda14cbcSMatt Macy break; 2346eda14cbcSMatt Macy case OWNING_GROUP: 2347eda14cbcSMatt Macy who = gowner; 2348c03c5b1cSMartin Matuska zfs_fallthrough; 2349eda14cbcSMatt Macy case ACE_IDENTIFIER_GROUP: 2350eda14cbcSMatt Macy checkit = zfs_groupmember(zfsvfs, who, cr); 2351eda14cbcSMatt Macy break; 2352eda14cbcSMatt Macy case ACE_EVERYONE: 2353eda14cbcSMatt Macy checkit = B_TRUE; 2354eda14cbcSMatt Macy break; 2355eda14cbcSMatt Macy 2356eda14cbcSMatt Macy /* USER Entry */ 2357eda14cbcSMatt Macy default: 2358eda14cbcSMatt Macy if (entry_type == 0) { 2359eda14cbcSMatt Macy uid_t newid; 2360eda14cbcSMatt Macy 2361eda14cbcSMatt Macy newid = zfs_fuid_map_id(zfsvfs, who, cr, 2362eda14cbcSMatt Macy ZFS_ACE_USER); 2363eda14cbcSMatt Macy if (newid != IDMAP_WK_CREATOR_OWNER_UID && 2364eda14cbcSMatt Macy uid == newid) 2365eda14cbcSMatt Macy checkit = B_TRUE; 2366eda14cbcSMatt Macy break; 2367eda14cbcSMatt Macy } else { 2368eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2369eda14cbcSMatt Macy return (SET_ERROR(EIO)); 2370eda14cbcSMatt Macy } 2371eda14cbcSMatt Macy } 2372eda14cbcSMatt Macy 2373eda14cbcSMatt Macy if (checkit) { 2374eda14cbcSMatt Macy if (type == DENY) { 2375eda14cbcSMatt Macy DTRACE_PROBE3(zfs__ace__denies, 2376eda14cbcSMatt Macy znode_t *, zp, 2377eda14cbcSMatt Macy zfs_ace_hdr_t *, acep, 2378eda14cbcSMatt Macy uint32_t, mask_matched); 2379eda14cbcSMatt Macy deny_mask |= mask_matched; 2380eda14cbcSMatt Macy } else { 2381eda14cbcSMatt Macy DTRACE_PROBE3(zfs__ace__allows, 2382eda14cbcSMatt Macy znode_t *, zp, 2383eda14cbcSMatt Macy zfs_ace_hdr_t *, acep, 2384eda14cbcSMatt Macy uint32_t, mask_matched); 2385eda14cbcSMatt Macy if (anyaccess) { 2386eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2387eda14cbcSMatt Macy return (0); 2388eda14cbcSMatt Macy } 2389eda14cbcSMatt Macy } 2390eda14cbcSMatt Macy *working_mode &= ~mask_matched; 2391eda14cbcSMatt Macy } 2392eda14cbcSMatt Macy 2393eda14cbcSMatt Macy /* Are we done? */ 2394eda14cbcSMatt Macy if (*working_mode == 0) 2395eda14cbcSMatt Macy break; 2396eda14cbcSMatt Macy } 2397eda14cbcSMatt Macy 2398eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2399eda14cbcSMatt Macy 2400eda14cbcSMatt Macy /* Put the found 'denies' back on the working mode */ 2401eda14cbcSMatt Macy if (deny_mask) { 2402eda14cbcSMatt Macy *working_mode |= deny_mask; 2403eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2404eda14cbcSMatt Macy } else if (*working_mode) { 2405eda14cbcSMatt Macy return (-1); 2406eda14cbcSMatt Macy } 2407eda14cbcSMatt Macy 2408eda14cbcSMatt Macy return (0); 2409eda14cbcSMatt Macy } 2410eda14cbcSMatt Macy 2411eda14cbcSMatt Macy /* 2412eda14cbcSMatt Macy * Return true if any access whatsoever granted, we don't actually 2413eda14cbcSMatt Macy * care what access is granted. 2414eda14cbcSMatt Macy */ 2415eda14cbcSMatt Macy boolean_t 2416eda14cbcSMatt Macy zfs_has_access(znode_t *zp, cred_t *cr) 2417eda14cbcSMatt Macy { 2418eda14cbcSMatt Macy uint32_t have = ACE_ALL_PERMS; 2419eda14cbcSMatt Macy 2420dbd5678dSMartin Matuska if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, 2421d411c1d6SMartin Matuska zfs_init_idmap) != 0) { 2422eda14cbcSMatt Macy uid_t owner; 2423eda14cbcSMatt Macy 2424eda14cbcSMatt Macy owner = zfs_fuid_map_id(ZTOZSB(zp), 2425eda14cbcSMatt Macy KUID_TO_SUID(ZTOI(zp)->i_uid), cr, ZFS_OWNER); 2426eda14cbcSMatt Macy return (secpolicy_vnode_any_access(cr, ZTOI(zp), owner) == 0); 2427eda14cbcSMatt Macy } 2428eda14cbcSMatt Macy return (B_TRUE); 2429eda14cbcSMatt Macy } 2430eda14cbcSMatt Macy 2431716fd348SMartin Matuska /* 2432716fd348SMartin Matuska * Simplified access check for case where ACL is known to not contain 2433716fd348SMartin Matuska * information beyond what is defined in the mode. In this case, we 2434716fd348SMartin Matuska * can pass along to the kernel / vfs generic_permission() check, which 2435716fd348SMartin Matuska * evaluates the mode and POSIX ACL. 2436716fd348SMartin Matuska * 2437716fd348SMartin Matuska * NFSv4 ACLs allow granting permissions that are usually relegated only 2438716fd348SMartin Matuska * to the file owner or superuser. Examples are ACE_WRITE_OWNER (chown), 2439716fd348SMartin Matuska * ACE_WRITE_ACL(chmod), and ACE_DELETE. ACE_DELETE requests must fail 2440716fd348SMartin Matuska * because with conventional posix permissions, right to delete file 2441716fd348SMartin Matuska * is determined by write bit on the parent dir. 2442716fd348SMartin Matuska * 2443716fd348SMartin Matuska * If unmappable perms are requested, then we must return EPERM 2444716fd348SMartin Matuska * and include those bits in the working_mode so that the caller of 2445716fd348SMartin Matuska * zfs_zaccess_common() can decide whether to perform additional 2446716fd348SMartin Matuska * policy / capability checks. EACCES is used in zfs_zaccess_aces_check() 2447716fd348SMartin Matuska * to indicate access check failed due to explicit DENY entry, and so 2448716fd348SMartin Matuska * we want to avoid that here. 2449716fd348SMartin Matuska */ 2450716fd348SMartin Matuska static int 2451dbd5678dSMartin Matuska zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr, 2452d411c1d6SMartin Matuska zidmap_t *mnt_ns) 2453716fd348SMartin Matuska { 2454716fd348SMartin Matuska int err, mask; 2455716fd348SMartin Matuska int unmapped = 0; 2456716fd348SMartin Matuska 2457716fd348SMartin Matuska ASSERT(zp->z_pflags & ZFS_ACL_TRIVIAL); 2458716fd348SMartin Matuska 2459716fd348SMartin Matuska mask = zfs_v4_to_unix(*working_mode, &unmapped); 2460716fd348SMartin Matuska if (mask == 0 || unmapped) { 2461716fd348SMartin Matuska *working_mode = unmapped; 2462716fd348SMartin Matuska return (unmapped ? SET_ERROR(EPERM) : 0); 2463716fd348SMartin Matuska } 2464716fd348SMartin Matuska 2465d411c1d6SMartin Matuska #if (defined(HAVE_IOPS_PERMISSION_USERNS) || \ 2466d411c1d6SMartin Matuska defined(HAVE_IOPS_PERMISSION_IDMAP)) 2467dbd5678dSMartin Matuska err = generic_permission(mnt_ns, ZTOI(zp), mask); 2468716fd348SMartin Matuska #else 2469716fd348SMartin Matuska err = generic_permission(ZTOI(zp), mask); 2470716fd348SMartin Matuska #endif 2471716fd348SMartin Matuska if (err != 0) { 2472716fd348SMartin Matuska return (SET_ERROR(EPERM)); 2473716fd348SMartin Matuska } 2474716fd348SMartin Matuska 2475716fd348SMartin Matuska *working_mode = unmapped; 2476716fd348SMartin Matuska 2477716fd348SMartin Matuska return (0); 2478716fd348SMartin Matuska } 2479716fd348SMartin Matuska 2480eda14cbcSMatt Macy static int 2481eda14cbcSMatt Macy zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, 2482d411c1d6SMartin Matuska boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zidmap_t *mnt_ns) 2483eda14cbcSMatt Macy { 2484eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 2485eda14cbcSMatt Macy int err; 2486eda14cbcSMatt Macy 2487eda14cbcSMatt Macy *working_mode = v4_mode; 2488eda14cbcSMatt Macy *check_privs = B_TRUE; 2489eda14cbcSMatt Macy 2490eda14cbcSMatt Macy /* 2491eda14cbcSMatt Macy * Short circuit empty requests 2492eda14cbcSMatt Macy */ 2493eda14cbcSMatt Macy if (v4_mode == 0 || zfsvfs->z_replay) { 2494eda14cbcSMatt Macy *working_mode = 0; 2495eda14cbcSMatt Macy return (0); 2496eda14cbcSMatt Macy } 2497eda14cbcSMatt Macy 2498eda14cbcSMatt Macy if ((err = zfs_zaccess_dataset_check(zp, v4_mode)) != 0) { 2499eda14cbcSMatt Macy *check_privs = B_FALSE; 2500eda14cbcSMatt Macy return (err); 2501eda14cbcSMatt Macy } 2502eda14cbcSMatt Macy 2503eda14cbcSMatt Macy /* 2504eda14cbcSMatt Macy * The caller requested that the ACL check be skipped. This 2505eda14cbcSMatt Macy * would only happen if the caller checked VOP_ACCESS() with a 2506eda14cbcSMatt Macy * 32 bit ACE mask and already had the appropriate permissions. 2507eda14cbcSMatt Macy */ 2508eda14cbcSMatt Macy if (skipaclchk) { 2509eda14cbcSMatt Macy *working_mode = 0; 2510eda14cbcSMatt Macy return (0); 2511eda14cbcSMatt Macy } 2512eda14cbcSMatt Macy 25139db44a8eSMartin Matuska /* 25149db44a8eSMartin Matuska * Note: ZFS_READONLY represents the "DOS R/O" attribute. 25159db44a8eSMartin Matuska * When that flag is set, we should behave as if write access 25169db44a8eSMartin Matuska * were not granted by anything in the ACL. In particular: 25179db44a8eSMartin Matuska * We _must_ allow writes after opening the file r/w, then 25189db44a8eSMartin Matuska * setting the DOS R/O attribute, and writing some more. 25199db44a8eSMartin Matuska * (Similar to how you can write after fchmod(fd, 0444).) 25209db44a8eSMartin Matuska * 25219db44a8eSMartin Matuska * Therefore ZFS_READONLY is ignored in the dataset check 25229db44a8eSMartin Matuska * above, and checked here as if part of the ACL check. 25239db44a8eSMartin Matuska * Also note: DOS R/O is ignored for directories. 25249db44a8eSMartin Matuska */ 25259db44a8eSMartin Matuska if ((v4_mode & WRITE_MASK_DATA) && 25269db44a8eSMartin Matuska S_ISDIR(ZTOI(zp)->i_mode) && 25279db44a8eSMartin Matuska (zp->z_pflags & ZFS_READONLY)) { 25289db44a8eSMartin Matuska return (SET_ERROR(EPERM)); 25299db44a8eSMartin Matuska } 25309db44a8eSMartin Matuska 2531716fd348SMartin Matuska if (zp->z_pflags & ZFS_ACL_TRIVIAL) 2532dbd5678dSMartin Matuska return (zfs_zaccess_trivial(zp, working_mode, cr, mnt_ns)); 2533716fd348SMartin Matuska 2534dbd5678dSMartin Matuska return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr, mnt_ns)); 2535eda14cbcSMatt Macy } 2536eda14cbcSMatt Macy 2537eda14cbcSMatt Macy static int 2538eda14cbcSMatt Macy zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, 2539d411c1d6SMartin Matuska cred_t *cr, zidmap_t *mnt_ns) 2540eda14cbcSMatt Macy { 2541eda14cbcSMatt Macy if (*working_mode != ACE_WRITE_DATA) 2542eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2543eda14cbcSMatt Macy 2544eda14cbcSMatt Macy return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, 2545dbd5678dSMartin Matuska check_privs, B_FALSE, cr, mnt_ns)); 2546eda14cbcSMatt Macy } 2547eda14cbcSMatt Macy 2548eda14cbcSMatt Macy int 2549eda14cbcSMatt Macy zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) 2550eda14cbcSMatt Macy { 2551eda14cbcSMatt Macy boolean_t owner = B_FALSE; 2552eda14cbcSMatt Macy boolean_t groupmbr = B_FALSE; 2553eda14cbcSMatt Macy boolean_t is_attr; 2554eda14cbcSMatt Macy uid_t uid = crgetuid(cr); 2555eda14cbcSMatt Macy int error; 2556eda14cbcSMatt Macy 2557eda14cbcSMatt Macy if (zdp->z_pflags & ZFS_AV_QUARANTINED) 2558eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2559eda14cbcSMatt Macy 2560eda14cbcSMatt Macy is_attr = ((zdp->z_pflags & ZFS_XATTR) && 2561eda14cbcSMatt Macy (S_ISDIR(ZTOI(zdp)->i_mode))); 2562eda14cbcSMatt Macy if (is_attr) 2563eda14cbcSMatt Macy goto slow; 2564eda14cbcSMatt Macy 2565eda14cbcSMatt Macy 2566eda14cbcSMatt Macy mutex_enter(&zdp->z_acl_lock); 2567eda14cbcSMatt Macy 2568eda14cbcSMatt Macy if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) { 2569eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2570eda14cbcSMatt Macy return (0); 2571eda14cbcSMatt Macy } 2572eda14cbcSMatt Macy 2573eda14cbcSMatt Macy if (KUID_TO_SUID(ZTOI(zdp)->i_uid) != 0 || 2574eda14cbcSMatt Macy KGID_TO_SGID(ZTOI(zdp)->i_gid) != 0) { 2575eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2576eda14cbcSMatt Macy goto slow; 2577eda14cbcSMatt Macy } 2578eda14cbcSMatt Macy 2579eda14cbcSMatt Macy if (uid == KUID_TO_SUID(ZTOI(zdp)->i_uid)) { 2580eda14cbcSMatt Macy if (zdp->z_mode & S_IXUSR) { 2581eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2582eda14cbcSMatt Macy return (0); 2583eda14cbcSMatt Macy } else { 2584eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2585eda14cbcSMatt Macy goto slow; 2586eda14cbcSMatt Macy } 2587eda14cbcSMatt Macy } 2588eda14cbcSMatt Macy if (groupmember(KGID_TO_SGID(ZTOI(zdp)->i_gid), cr)) { 2589eda14cbcSMatt Macy if (zdp->z_mode & S_IXGRP) { 2590eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2591eda14cbcSMatt Macy return (0); 2592eda14cbcSMatt Macy } else { 2593eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2594eda14cbcSMatt Macy goto slow; 2595eda14cbcSMatt Macy } 2596eda14cbcSMatt Macy } 2597eda14cbcSMatt Macy if (!owner && !groupmbr) { 2598eda14cbcSMatt Macy if (zdp->z_mode & S_IXOTH) { 2599eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2600eda14cbcSMatt Macy return (0); 2601eda14cbcSMatt Macy } 2602eda14cbcSMatt Macy } 2603eda14cbcSMatt Macy 2604eda14cbcSMatt Macy mutex_exit(&zdp->z_acl_lock); 2605eda14cbcSMatt Macy 2606eda14cbcSMatt Macy slow: 2607eda14cbcSMatt Macy DTRACE_PROBE(zfs__fastpath__execute__access__miss); 2608c7046f76SMartin Matuska if ((error = zfs_enter(ZTOZSB(zdp), FTAG)) != 0) 2609c7046f76SMartin Matuska return (error); 2610dbd5678dSMartin Matuska error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, 2611d411c1d6SMartin Matuska zfs_init_idmap); 2612c7046f76SMartin Matuska zfs_exit(ZTOZSB(zdp), FTAG); 2613eda14cbcSMatt Macy return (error); 2614eda14cbcSMatt Macy } 2615eda14cbcSMatt Macy 2616eda14cbcSMatt Macy /* 2617eda14cbcSMatt Macy * Determine whether Access should be granted/denied. 2618eda14cbcSMatt Macy * 2619eda14cbcSMatt Macy * The least priv subsystem is always consulted as a basic privilege 2620eda14cbcSMatt Macy * can define any form of access. 2621eda14cbcSMatt Macy */ 2622eda14cbcSMatt Macy int 2623dbd5678dSMartin Matuska zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, 2624d411c1d6SMartin Matuska zidmap_t *mnt_ns) 2625eda14cbcSMatt Macy { 2626eda14cbcSMatt Macy uint32_t working_mode; 2627eda14cbcSMatt Macy int error; 2628eda14cbcSMatt Macy int is_attr; 2629eda14cbcSMatt Macy boolean_t check_privs; 2630eda14cbcSMatt Macy znode_t *xzp; 2631eda14cbcSMatt Macy znode_t *check_zp = zp; 2632eda14cbcSMatt Macy mode_t needed_bits; 2633eda14cbcSMatt Macy uid_t owner; 2634eda14cbcSMatt Macy 2635eda14cbcSMatt Macy is_attr = ((zp->z_pflags & ZFS_XATTR) && S_ISDIR(ZTOI(zp)->i_mode)); 2636eda14cbcSMatt Macy 2637eda14cbcSMatt Macy /* 2638eda14cbcSMatt Macy * If attribute then validate against base file 2639eda14cbcSMatt Macy */ 2640eda14cbcSMatt Macy if (is_attr) { 2641eda14cbcSMatt Macy if ((error = zfs_zget(ZTOZSB(zp), 2642eda14cbcSMatt Macy zp->z_xattr_parent, &xzp)) != 0) { 2643eda14cbcSMatt Macy return (error); 2644eda14cbcSMatt Macy } 2645eda14cbcSMatt Macy 2646eda14cbcSMatt Macy check_zp = xzp; 2647eda14cbcSMatt Macy 2648eda14cbcSMatt Macy /* 2649eda14cbcSMatt Macy * fixup mode to map to xattr perms 2650eda14cbcSMatt Macy */ 2651eda14cbcSMatt Macy 2652eda14cbcSMatt Macy if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) { 2653eda14cbcSMatt Macy mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA); 2654eda14cbcSMatt Macy mode |= ACE_WRITE_NAMED_ATTRS; 2655eda14cbcSMatt Macy } 2656eda14cbcSMatt Macy 2657eda14cbcSMatt Macy if (mode & (ACE_READ_DATA|ACE_EXECUTE)) { 2658eda14cbcSMatt Macy mode &= ~(ACE_READ_DATA|ACE_EXECUTE); 2659eda14cbcSMatt Macy mode |= ACE_READ_NAMED_ATTRS; 2660eda14cbcSMatt Macy } 2661eda14cbcSMatt Macy } 2662eda14cbcSMatt Macy 2663dbd5678dSMartin Matuska owner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), 2664dbd5678dSMartin Matuska KUID_TO_SUID(ZTOI(zp)->i_uid)); 2665dbd5678dSMartin Matuska owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER); 2666dbd5678dSMartin Matuska 2667eda14cbcSMatt Macy /* 2668eda14cbcSMatt Macy * Map the bits required to the standard inode flags 2669eda14cbcSMatt Macy * S_IRUSR|S_IWUSR|S_IXUSR in the needed_bits. Map the bits 2670eda14cbcSMatt Macy * mapped by working_mode (currently missing) in missing_bits. 2671eda14cbcSMatt Macy * Call secpolicy_vnode_access2() with (needed_bits & ~checkmode), 2672eda14cbcSMatt Macy * needed_bits. 2673eda14cbcSMatt Macy */ 2674eda14cbcSMatt Macy needed_bits = 0; 2675eda14cbcSMatt Macy 2676eda14cbcSMatt Macy working_mode = mode; 2677eda14cbcSMatt Macy if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) && 2678eda14cbcSMatt Macy owner == crgetuid(cr)) 2679eda14cbcSMatt Macy working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2680eda14cbcSMatt Macy 2681eda14cbcSMatt Macy if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2682eda14cbcSMatt Macy ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2683eda14cbcSMatt Macy needed_bits |= S_IRUSR; 2684eda14cbcSMatt Macy if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2685eda14cbcSMatt Macy ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2686eda14cbcSMatt Macy needed_bits |= S_IWUSR; 2687eda14cbcSMatt Macy if (working_mode & ACE_EXECUTE) 2688eda14cbcSMatt Macy needed_bits |= S_IXUSR; 2689eda14cbcSMatt Macy 2690eda14cbcSMatt Macy if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, 2691dbd5678dSMartin Matuska &check_privs, skipaclchk, cr, mnt_ns)) == 0) { 2692eda14cbcSMatt Macy if (is_attr) 2693eda14cbcSMatt Macy zrele(xzp); 2694eda14cbcSMatt Macy return (secpolicy_vnode_access2(cr, ZTOI(zp), owner, 2695eda14cbcSMatt Macy needed_bits, needed_bits)); 2696eda14cbcSMatt Macy } 2697eda14cbcSMatt Macy 2698eda14cbcSMatt Macy if (error && !check_privs) { 2699eda14cbcSMatt Macy if (is_attr) 2700eda14cbcSMatt Macy zrele(xzp); 2701eda14cbcSMatt Macy return (error); 2702eda14cbcSMatt Macy } 2703eda14cbcSMatt Macy 2704eda14cbcSMatt Macy if (error && (flags & V_APPEND)) { 2705dbd5678dSMartin Matuska error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr, 2706dbd5678dSMartin Matuska mnt_ns); 2707eda14cbcSMatt Macy } 2708eda14cbcSMatt Macy 2709eda14cbcSMatt Macy if (error && check_privs) { 2710eda14cbcSMatt Macy mode_t checkmode = 0; 2711eda14cbcSMatt Macy 2712eda14cbcSMatt Macy /* 2713eda14cbcSMatt Macy * First check for implicit owner permission on 2714eda14cbcSMatt Macy * read_acl/read_attributes 2715eda14cbcSMatt Macy */ 2716eda14cbcSMatt Macy 2717eda14cbcSMatt Macy ASSERT(working_mode != 0); 2718eda14cbcSMatt Macy 2719eda14cbcSMatt Macy if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) && 2720eda14cbcSMatt Macy owner == crgetuid(cr))) 2721eda14cbcSMatt Macy working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2722eda14cbcSMatt Macy 2723eda14cbcSMatt Macy if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2724eda14cbcSMatt Macy ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2725eda14cbcSMatt Macy checkmode |= S_IRUSR; 2726eda14cbcSMatt Macy if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2727eda14cbcSMatt Macy ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2728eda14cbcSMatt Macy checkmode |= S_IWUSR; 2729eda14cbcSMatt Macy if (working_mode & ACE_EXECUTE) 2730eda14cbcSMatt Macy checkmode |= S_IXUSR; 2731eda14cbcSMatt Macy 2732eda14cbcSMatt Macy error = secpolicy_vnode_access2(cr, ZTOI(check_zp), owner, 2733eda14cbcSMatt Macy needed_bits & ~checkmode, needed_bits); 2734eda14cbcSMatt Macy 2735eda14cbcSMatt Macy if (error == 0 && (working_mode & ACE_WRITE_OWNER)) 2736eda14cbcSMatt Macy error = secpolicy_vnode_chown(cr, owner); 2737eda14cbcSMatt Macy if (error == 0 && (working_mode & ACE_WRITE_ACL)) 2738eda14cbcSMatt Macy error = secpolicy_vnode_setdac(cr, owner); 2739eda14cbcSMatt Macy 2740eda14cbcSMatt Macy if (error == 0 && (working_mode & 2741eda14cbcSMatt Macy (ACE_DELETE|ACE_DELETE_CHILD))) 2742eda14cbcSMatt Macy error = secpolicy_vnode_remove(cr); 2743eda14cbcSMatt Macy 2744eda14cbcSMatt Macy if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) { 2745eda14cbcSMatt Macy error = secpolicy_vnode_chown(cr, owner); 2746eda14cbcSMatt Macy } 2747eda14cbcSMatt Macy if (error == 0) { 2748eda14cbcSMatt Macy /* 2749eda14cbcSMatt Macy * See if any bits other than those already checked 2750eda14cbcSMatt Macy * for are still present. If so then return EACCES 2751eda14cbcSMatt Macy */ 2752eda14cbcSMatt Macy if (working_mode & ~(ZFS_CHECKED_MASKS)) { 2753eda14cbcSMatt Macy error = SET_ERROR(EACCES); 2754eda14cbcSMatt Macy } 2755eda14cbcSMatt Macy } 2756eda14cbcSMatt Macy } else if (error == 0) { 2757eda14cbcSMatt Macy error = secpolicy_vnode_access2(cr, ZTOI(zp), owner, 2758eda14cbcSMatt Macy needed_bits, needed_bits); 2759eda14cbcSMatt Macy } 2760eda14cbcSMatt Macy 2761eda14cbcSMatt Macy if (is_attr) 2762eda14cbcSMatt Macy zrele(xzp); 2763eda14cbcSMatt Macy 2764eda14cbcSMatt Macy return (error); 2765eda14cbcSMatt Macy } 2766eda14cbcSMatt Macy 2767eda14cbcSMatt Macy /* 2768eda14cbcSMatt Macy * Translate traditional unix S_IRUSR/S_IWUSR/S_IXUSR mode into 2769180f8225SMatt Macy * NFSv4-style ZFS ACL format and call zfs_zaccess() 2770eda14cbcSMatt Macy */ 2771eda14cbcSMatt Macy int 2772dbd5678dSMartin Matuska zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, 2773d411c1d6SMartin Matuska zidmap_t *mnt_ns) 2774eda14cbcSMatt Macy { 2775dbd5678dSMartin Matuska return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, 2776dbd5678dSMartin Matuska mnt_ns)); 2777eda14cbcSMatt Macy } 2778eda14cbcSMatt Macy 2779eda14cbcSMatt Macy /* 2780eda14cbcSMatt Macy * Access function for secpolicy_vnode_setattr 2781eda14cbcSMatt Macy */ 2782eda14cbcSMatt Macy int 2783bb2d13b6SMartin Matuska zfs_zaccess_unix(void *zp, int mode, cred_t *cr) 2784eda14cbcSMatt Macy { 2785eda14cbcSMatt Macy int v4_mode = zfs_unix_to_v4(mode >> 6); 2786eda14cbcSMatt Macy 2787d411c1d6SMartin Matuska return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, zfs_init_idmap)); 2788eda14cbcSMatt Macy } 2789eda14cbcSMatt Macy 2790eda14cbcSMatt Macy /* See zfs_zaccess_delete() */ 2791e92ffd9bSMartin Matuska static const boolean_t zfs_write_implies_delete_child = B_TRUE; 2792eda14cbcSMatt Macy 2793eda14cbcSMatt Macy /* 2794eda14cbcSMatt Macy * Determine whether delete access should be granted. 2795eda14cbcSMatt Macy * 2796eda14cbcSMatt Macy * The following chart outlines how we handle delete permissions which is 2797eda14cbcSMatt Macy * how recent versions of windows (Windows 2008) handles it. The efficiency 2798eda14cbcSMatt Macy * comes from not having to check the parent ACL where the object itself grants 2799eda14cbcSMatt Macy * delete: 2800eda14cbcSMatt Macy * 2801eda14cbcSMatt Macy * ------------------------------------------------------- 2802eda14cbcSMatt Macy * | Parent Dir | Target Object Permissions | 2803eda14cbcSMatt Macy * | permissions | | 2804eda14cbcSMatt Macy * ------------------------------------------------------- 2805eda14cbcSMatt Macy * | | ACL Allows | ACL Denies| Delete | 2806eda14cbcSMatt Macy * | | Delete | Delete | unspecified| 2807eda14cbcSMatt Macy * ------------------------------------------------------- 2808eda14cbcSMatt Macy * | ACL Allows | Permit | Deny * | Permit | 2809eda14cbcSMatt Macy * | DELETE_CHILD | | | | 2810eda14cbcSMatt Macy * ------------------------------------------------------- 2811eda14cbcSMatt Macy * | ACL Denies | Permit | Deny | Deny | 2812eda14cbcSMatt Macy * | DELETE_CHILD | | | | 2813eda14cbcSMatt Macy * ------------------------------------------------------- 2814eda14cbcSMatt Macy * | ACL specifies | | | | 2815eda14cbcSMatt Macy * | only allow | Permit | Deny * | Permit | 2816eda14cbcSMatt Macy * | write and | | | | 2817eda14cbcSMatt Macy * | execute | | | | 2818eda14cbcSMatt Macy * ------------------------------------------------------- 2819eda14cbcSMatt Macy * | ACL denies | | | | 2820eda14cbcSMatt Macy * | write and | Permit | Deny | Deny | 2821eda14cbcSMatt Macy * | execute | | | | 2822eda14cbcSMatt Macy * ------------------------------------------------------- 2823eda14cbcSMatt Macy * ^ 2824eda14cbcSMatt Macy * | 2825eda14cbcSMatt Macy * Re. execute permission on the directory: if that's missing, 2826eda14cbcSMatt Macy * the vnode lookup of the target will fail before we get here. 2827eda14cbcSMatt Macy * 2828eda14cbcSMatt Macy * Re [*] in the table above: NFSv4 would normally Permit delete for 2829eda14cbcSMatt Macy * these two cells of the matrix. 2830eda14cbcSMatt Macy * See acl.h for notes on which ACE_... flags should be checked for which 2831eda14cbcSMatt Macy * operations. Specifically, the NFSv4 committee recommendation is in 2832eda14cbcSMatt Macy * conflict with the Windows interpretation of DENY ACEs, where DENY ACEs 2833eda14cbcSMatt Macy * should take precedence ahead of ALLOW ACEs. 2834eda14cbcSMatt Macy * 2835eda14cbcSMatt Macy * This implementation always consults the target object's ACL first. 2836eda14cbcSMatt Macy * If a DENY ACE is present on the target object that specifies ACE_DELETE, 2837eda14cbcSMatt Macy * delete access is denied. If an ALLOW ACE with ACE_DELETE is present on 2838eda14cbcSMatt Macy * the target object, access is allowed. If and only if no entries with 2839eda14cbcSMatt Macy * ACE_DELETE are present in the object's ACL, check the container's ACL 2840eda14cbcSMatt Macy * for entries with ACE_DELETE_CHILD. 2841eda14cbcSMatt Macy * 2842eda14cbcSMatt Macy * A summary of the logic implemented from the table above is as follows: 2843eda14cbcSMatt Macy * 2844eda14cbcSMatt Macy * First check for DENY ACEs that apply. 2845eda14cbcSMatt Macy * If either target or container has a deny, EACCES. 2846eda14cbcSMatt Macy * 2847eda14cbcSMatt Macy * Delete access can then be summarized as follows: 2848eda14cbcSMatt Macy * 1: The object to be deleted grants ACE_DELETE, or 2849eda14cbcSMatt Macy * 2: The containing directory grants ACE_DELETE_CHILD. 2850eda14cbcSMatt Macy * In a Windows system, that would be the end of the story. 2851eda14cbcSMatt Macy * In this system, (2) has some complications... 2852eda14cbcSMatt Macy * 2a: "sticky" bit on a directory adds restrictions, and 2853eda14cbcSMatt Macy * 2b: existing ACEs from previous versions of ZFS may 2854eda14cbcSMatt Macy * not carry ACE_DELETE_CHILD where they should, so we 2855eda14cbcSMatt Macy * also allow delete when ACE_WRITE_DATA is granted. 2856eda14cbcSMatt Macy * 2857eda14cbcSMatt Macy * Note: 2b is technically a work-around for a prior bug, 2858eda14cbcSMatt Macy * which hopefully can go away some day. For those who 2859eda14cbcSMatt Macy * no longer need the work around, and for testing, this 2860eda14cbcSMatt Macy * work-around is made conditional via the tunable: 2861eda14cbcSMatt Macy * zfs_write_implies_delete_child 2862eda14cbcSMatt Macy */ 2863eda14cbcSMatt Macy int 2864d411c1d6SMartin Matuska zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns) 2865eda14cbcSMatt Macy { 2866eda14cbcSMatt Macy uint32_t wanted_dirperms; 2867eda14cbcSMatt Macy uint32_t dzp_working_mode = 0; 2868eda14cbcSMatt Macy uint32_t zp_working_mode = 0; 2869eda14cbcSMatt Macy int dzp_error, zp_error; 2870eda14cbcSMatt Macy boolean_t dzpcheck_privs; 2871eda14cbcSMatt Macy boolean_t zpcheck_privs; 2872eda14cbcSMatt Macy 2873eda14cbcSMatt Macy if (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_NOUNLINK)) 2874eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2875eda14cbcSMatt Macy 2876eda14cbcSMatt Macy /* 2877eda14cbcSMatt Macy * Case 1: 2878eda14cbcSMatt Macy * If target object grants ACE_DELETE then we are done. This is 2879eda14cbcSMatt Macy * indicated by a return value of 0. For this case we don't worry 2880eda14cbcSMatt Macy * about the sticky bit because sticky only applies to the parent 2881eda14cbcSMatt Macy * directory and this is the child access result. 2882eda14cbcSMatt Macy * 2883eda14cbcSMatt Macy * If we encounter a DENY ACE here, we're also done (EACCES). 2884eda14cbcSMatt Macy * Note that if we hit a DENY ACE here (on the target) it should 2885eda14cbcSMatt Macy * take precedence over a DENY ACE on the container, so that when 2886eda14cbcSMatt Macy * we have more complete auditing support we will be able to 2887eda14cbcSMatt Macy * report an access failure against the specific target. 2888eda14cbcSMatt Macy * (This is part of why we're checking the target first.) 2889eda14cbcSMatt Macy */ 2890eda14cbcSMatt Macy zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, 2891dbd5678dSMartin Matuska &zpcheck_privs, B_FALSE, cr, mnt_ns); 2892eda14cbcSMatt Macy if (zp_error == EACCES) { 2893eda14cbcSMatt Macy /* We hit a DENY ACE. */ 2894eda14cbcSMatt Macy if (!zpcheck_privs) 2895eda14cbcSMatt Macy return (SET_ERROR(zp_error)); 2896eda14cbcSMatt Macy return (secpolicy_vnode_remove(cr)); 2897eda14cbcSMatt Macy 2898eda14cbcSMatt Macy } 2899eda14cbcSMatt Macy if (zp_error == 0) 2900eda14cbcSMatt Macy return (0); 2901eda14cbcSMatt Macy 2902eda14cbcSMatt Macy /* 2903eda14cbcSMatt Macy * Case 2: 2904eda14cbcSMatt Macy * If the containing directory grants ACE_DELETE_CHILD, 2905eda14cbcSMatt Macy * or we're in backward compatibility mode and the 2906eda14cbcSMatt Macy * containing directory has ACE_WRITE_DATA, allow. 2907eda14cbcSMatt Macy * Case 2b is handled with wanted_dirperms. 2908eda14cbcSMatt Macy */ 2909eda14cbcSMatt Macy wanted_dirperms = ACE_DELETE_CHILD; 2910eda14cbcSMatt Macy if (zfs_write_implies_delete_child) 2911eda14cbcSMatt Macy wanted_dirperms |= ACE_WRITE_DATA; 2912eda14cbcSMatt Macy dzp_error = zfs_zaccess_common(dzp, wanted_dirperms, 2913dbd5678dSMartin Matuska &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr, mnt_ns); 2914eda14cbcSMatt Macy if (dzp_error == EACCES) { 2915eda14cbcSMatt Macy /* We hit a DENY ACE. */ 2916eda14cbcSMatt Macy if (!dzpcheck_privs) 2917eda14cbcSMatt Macy return (SET_ERROR(dzp_error)); 2918eda14cbcSMatt Macy return (secpolicy_vnode_remove(cr)); 2919eda14cbcSMatt Macy } 2920eda14cbcSMatt Macy 2921eda14cbcSMatt Macy /* 2922eda14cbcSMatt Macy * Cases 2a, 2b (continued) 2923eda14cbcSMatt Macy * 2924eda14cbcSMatt Macy * Note: dzp_working_mode now contains any permissions 2925eda14cbcSMatt Macy * that were NOT granted. Therefore, if any of the 2926eda14cbcSMatt Macy * wanted_dirperms WERE granted, we will have: 2927eda14cbcSMatt Macy * dzp_working_mode != wanted_dirperms 2928eda14cbcSMatt Macy * We're really asking if ANY of those permissions 2929eda14cbcSMatt Macy * were granted, and if so, grant delete access. 2930eda14cbcSMatt Macy */ 2931eda14cbcSMatt Macy if (dzp_working_mode != wanted_dirperms) 2932eda14cbcSMatt Macy dzp_error = 0; 2933eda14cbcSMatt Macy 2934eda14cbcSMatt Macy /* 2935eda14cbcSMatt Macy * dzp_error is 0 if the container granted us permissions to "modify". 2936eda14cbcSMatt Macy * If we do not have permission via one or more ACEs, our current 2937eda14cbcSMatt Macy * privileges may still permit us to modify the container. 2938eda14cbcSMatt Macy * 2939eda14cbcSMatt Macy * dzpcheck_privs is false when i.e. the FS is read-only. 2940eda14cbcSMatt Macy * Otherwise, do privilege checks for the container. 2941eda14cbcSMatt Macy */ 2942eda14cbcSMatt Macy if (dzp_error != 0 && dzpcheck_privs) { 2943eda14cbcSMatt Macy uid_t owner; 2944eda14cbcSMatt Macy 2945eda14cbcSMatt Macy /* 2946eda14cbcSMatt Macy * The secpolicy call needs the requested access and 2947eda14cbcSMatt Macy * the current access mode of the container, but it 2948eda14cbcSMatt Macy * only knows about Unix-style modes (VEXEC, VWRITE), 2949eda14cbcSMatt Macy * so this must condense the fine-grained ACE bits into 2950eda14cbcSMatt Macy * Unix modes. 2951eda14cbcSMatt Macy * 2952eda14cbcSMatt Macy * The VEXEC flag is easy, because we know that has 2953eda14cbcSMatt Macy * always been checked before we get here (during the 2954eda14cbcSMatt Macy * lookup of the target vnode). The container has not 2955eda14cbcSMatt Macy * granted us permissions to "modify", so we do not set 2956eda14cbcSMatt Macy * the VWRITE flag in the current access mode. 2957eda14cbcSMatt Macy */ 2958eda14cbcSMatt Macy owner = zfs_fuid_map_id(ZTOZSB(dzp), 2959eda14cbcSMatt Macy KUID_TO_SUID(ZTOI(dzp)->i_uid), cr, ZFS_OWNER); 2960eda14cbcSMatt Macy dzp_error = secpolicy_vnode_access2(cr, ZTOI(dzp), 2961eda14cbcSMatt Macy owner, S_IXUSR, S_IWUSR|S_IXUSR); 2962eda14cbcSMatt Macy } 2963eda14cbcSMatt Macy if (dzp_error != 0) { 2964eda14cbcSMatt Macy /* 2965eda14cbcSMatt Macy * Note: We may have dzp_error = -1 here (from 2966eda14cbcSMatt Macy * zfs_zacess_common). Don't return that. 2967eda14cbcSMatt Macy */ 2968eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2969eda14cbcSMatt Macy } 2970eda14cbcSMatt Macy 2971eda14cbcSMatt Macy 2972eda14cbcSMatt Macy /* 2973eda14cbcSMatt Macy * At this point, we know that the directory permissions allow 2974eda14cbcSMatt Macy * us to modify, but we still need to check for the additional 2975eda14cbcSMatt Macy * restrictions that apply when the "sticky bit" is set. 2976eda14cbcSMatt Macy * 2977eda14cbcSMatt Macy * Yes, zfs_sticky_remove_access() also checks this bit, but 2978eda14cbcSMatt Macy * checking it here and skipping the call below is nice when 2979eda14cbcSMatt Macy * you're watching all of this with dtrace. 2980eda14cbcSMatt Macy */ 2981eda14cbcSMatt Macy if ((dzp->z_mode & S_ISVTX) == 0) 2982eda14cbcSMatt Macy return (0); 2983eda14cbcSMatt Macy 2984eda14cbcSMatt Macy /* 2985eda14cbcSMatt Macy * zfs_sticky_remove_access will succeed if: 2986eda14cbcSMatt Macy * 1. The sticky bit is absent. 2987eda14cbcSMatt Macy * 2. We pass the sticky bit restrictions. 2988eda14cbcSMatt Macy * 3. We have privileges that always allow file removal. 2989eda14cbcSMatt Macy */ 2990eda14cbcSMatt Macy return (zfs_sticky_remove_access(dzp, zp, cr)); 2991eda14cbcSMatt Macy } 2992eda14cbcSMatt Macy 2993eda14cbcSMatt Macy int 2994eda14cbcSMatt Macy zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 2995d411c1d6SMartin Matuska znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns) 2996eda14cbcSMatt Macy { 2997eda14cbcSMatt Macy int add_perm; 2998eda14cbcSMatt Macy int error; 2999eda14cbcSMatt Macy 3000eda14cbcSMatt Macy if (szp->z_pflags & ZFS_AV_QUARANTINED) 3001eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 3002eda14cbcSMatt Macy 3003eda14cbcSMatt Macy add_perm = S_ISDIR(ZTOI(szp)->i_mode) ? 3004eda14cbcSMatt Macy ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 3005eda14cbcSMatt Macy 3006eda14cbcSMatt Macy /* 3007eda14cbcSMatt Macy * Rename permissions are combination of delete permission + 3008eda14cbcSMatt Macy * add file/subdir permission. 3009eda14cbcSMatt Macy */ 3010eda14cbcSMatt Macy 3011eda14cbcSMatt Macy /* 3012eda14cbcSMatt Macy * first make sure we do the delete portion. 3013eda14cbcSMatt Macy * 3014eda14cbcSMatt Macy * If that succeeds then check for add_file/add_subdir permissions 3015eda14cbcSMatt Macy */ 3016eda14cbcSMatt Macy 3017dbd5678dSMartin Matuska if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns))) 3018eda14cbcSMatt Macy return (error); 3019eda14cbcSMatt Macy 3020eda14cbcSMatt Macy /* 3021eda14cbcSMatt Macy * If we have a tzp, see if we can delete it? 3022eda14cbcSMatt Macy */ 3023eda14cbcSMatt Macy if (tzp) { 3024dbd5678dSMartin Matuska if ((error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns))) 3025eda14cbcSMatt Macy return (error); 3026eda14cbcSMatt Macy } 3027eda14cbcSMatt Macy 3028eda14cbcSMatt Macy /* 3029eda14cbcSMatt Macy * Now check for add permissions 3030eda14cbcSMatt Macy */ 3031dbd5678dSMartin Matuska error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns); 3032eda14cbcSMatt Macy 3033eda14cbcSMatt Macy return (error); 3034eda14cbcSMatt Macy } 3035