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 2017 Nexenta Systems, Inc. All rights reserved. 25eda14cbcSMatt Macy */ 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy #include <sys/types.h> 28eda14cbcSMatt Macy #include <sys/param.h> 29eda14cbcSMatt Macy #include <sys/time.h> 30eda14cbcSMatt Macy #include <sys/systm.h> 31eda14cbcSMatt Macy #include <sys/sysmacros.h> 32eda14cbcSMatt Macy #include <sys/resource.h> 33eda14cbcSMatt Macy #include <sys/vfs.h> 34eda14cbcSMatt Macy #include <sys/vnode.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/unistd.h> 41eda14cbcSMatt Macy #include <sys/sdt.h> 42eda14cbcSMatt Macy #include <sys/fs/zfs.h> 43eda14cbcSMatt Macy #include <sys/policy.h> 44eda14cbcSMatt Macy #include <sys/zfs_znode.h> 45eda14cbcSMatt Macy #include <sys/zfs_fuid.h> 46eda14cbcSMatt Macy #include <sys/zfs_acl.h> 47eda14cbcSMatt Macy #include <sys/zfs_dir.h> 48eda14cbcSMatt Macy #include <sys/zfs_quota.h> 49eda14cbcSMatt Macy #include <sys/zfs_vfsops.h> 50eda14cbcSMatt Macy #include <sys/dmu.h> 51eda14cbcSMatt Macy #include <sys/dnode.h> 52eda14cbcSMatt Macy #include <sys/zap.h> 53eda14cbcSMatt Macy #include <sys/sa.h> 54eda14cbcSMatt Macy #include <acl/acl_common.h> 55eda14cbcSMatt Macy 56eda14cbcSMatt Macy 57eda14cbcSMatt Macy #define ALLOW ACE_ACCESS_ALLOWED_ACE_TYPE 58eda14cbcSMatt Macy #define DENY ACE_ACCESS_DENIED_ACE_TYPE 59eda14cbcSMatt Macy #define MAX_ACE_TYPE ACE_SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 60eda14cbcSMatt Macy #define MIN_ACE_TYPE ALLOW 61eda14cbcSMatt Macy 62eda14cbcSMatt Macy #define OWNING_GROUP (ACE_GROUP|ACE_IDENTIFIER_GROUP) 63eda14cbcSMatt Macy #define EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \ 64eda14cbcSMatt Macy ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE) 65eda14cbcSMatt Macy #define EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \ 66eda14cbcSMatt Macy ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 67eda14cbcSMatt Macy #define OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \ 68eda14cbcSMatt Macy ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS) 69eda14cbcSMatt Macy 70eda14cbcSMatt Macy #define ZFS_CHECKED_MASKS (ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_DATA| \ 71eda14cbcSMatt Macy ACE_READ_NAMED_ATTRS|ACE_WRITE_DATA|ACE_WRITE_ATTRIBUTES| \ 72eda14cbcSMatt Macy ACE_WRITE_NAMED_ATTRS|ACE_APPEND_DATA|ACE_EXECUTE|ACE_WRITE_OWNER| \ 73eda14cbcSMatt Macy ACE_WRITE_ACL|ACE_DELETE|ACE_DELETE_CHILD|ACE_SYNCHRONIZE) 74eda14cbcSMatt Macy 75eda14cbcSMatt Macy #define WRITE_MASK_DATA (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS) 76eda14cbcSMatt Macy #define WRITE_MASK_ATTRS (ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES| \ 77eda14cbcSMatt Macy ACE_DELETE|ACE_DELETE_CHILD) 78eda14cbcSMatt Macy #define WRITE_MASK (WRITE_MASK_DATA|WRITE_MASK_ATTRS) 79eda14cbcSMatt Macy 80eda14cbcSMatt Macy #define OGE_CLEAR (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 81eda14cbcSMatt Macy ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 82eda14cbcSMatt Macy 83eda14cbcSMatt Macy #define OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \ 84eda14cbcSMatt Macy ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE) 85eda14cbcSMatt Macy 86eda14cbcSMatt Macy #define ALL_INHERIT (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \ 87eda14cbcSMatt Macy ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE|ACE_INHERITED_ACE) 88eda14cbcSMatt Macy 89eda14cbcSMatt Macy #define RESTRICTED_CLEAR (ACE_WRITE_ACL|ACE_WRITE_OWNER) 90eda14cbcSMatt Macy 91eda14cbcSMatt Macy #define V4_ACL_WIDE_FLAGS (ZFS_ACL_AUTO_INHERIT|ZFS_ACL_DEFAULTED|\ 92eda14cbcSMatt Macy ZFS_ACL_PROTECTED) 93eda14cbcSMatt Macy 94eda14cbcSMatt Macy #define ZFS_ACL_WIDE_FLAGS (V4_ACL_WIDE_FLAGS|ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE|\ 95eda14cbcSMatt Macy ZFS_ACL_OBJ_ACE) 96eda14cbcSMatt Macy 97eda14cbcSMatt Macy #define ALL_MODE_EXECS (S_IXUSR | S_IXGRP | S_IXOTH) 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 zfs_ace_v0_get_mask, 176eda14cbcSMatt Macy zfs_ace_v0_set_mask, 177eda14cbcSMatt Macy zfs_ace_v0_get_flags, 178eda14cbcSMatt Macy zfs_ace_v0_set_flags, 179eda14cbcSMatt Macy zfs_ace_v0_get_type, 180eda14cbcSMatt Macy zfs_ace_v0_set_type, 181eda14cbcSMatt Macy zfs_ace_v0_get_who, 182eda14cbcSMatt Macy zfs_ace_v0_set_who, 183eda14cbcSMatt Macy zfs_ace_v0_size, 184eda14cbcSMatt Macy zfs_ace_v0_abstract_size, 185eda14cbcSMatt Macy zfs_ace_v0_mask_off, 186eda14cbcSMatt Macy 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 zfs_ace_fuid_get_mask, 312eda14cbcSMatt Macy zfs_ace_fuid_set_mask, 313eda14cbcSMatt Macy zfs_ace_fuid_get_flags, 314eda14cbcSMatt Macy zfs_ace_fuid_set_flags, 315eda14cbcSMatt Macy zfs_ace_fuid_get_type, 316eda14cbcSMatt Macy zfs_ace_fuid_set_type, 317eda14cbcSMatt Macy zfs_ace_fuid_get_who, 318eda14cbcSMatt Macy zfs_ace_fuid_set_who, 319eda14cbcSMatt Macy zfs_ace_fuid_size, 320eda14cbcSMatt Macy zfs_ace_fuid_abstract_size, 321eda14cbcSMatt Macy zfs_ace_fuid_mask_off, 322eda14cbcSMatt Macy 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(zp->z_zfsvfs), 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 */ 35716038816SMartin Matuska VERIFY(zp->z_is_sa); 35816038816SMartin Matuska VERIFY3S(error, ==, ENOENT); 359eda14cbcSMatt Macy return (0); 360eda14cbcSMatt Macy } 361eda14cbcSMatt Macy } 362eda14cbcSMatt Macy 363eda14cbcSMatt Macy /* 364eda14cbcSMatt Macy * Determine size of ACL in bytes 365eda14cbcSMatt Macy * 366eda14cbcSMatt Macy * This is more complicated than it should be since we have to deal 367eda14cbcSMatt Macy * with old external ACLs. 368eda14cbcSMatt Macy */ 369eda14cbcSMatt Macy static int 370eda14cbcSMatt Macy zfs_acl_znode_info(znode_t *zp, int *aclsize, int *aclcount, 371eda14cbcSMatt Macy zfs_acl_phys_t *aclphys) 372eda14cbcSMatt Macy { 373eda14cbcSMatt Macy zfsvfs_t *zfsvfs = zp->z_zfsvfs; 374eda14cbcSMatt Macy uint64_t acl_count; 375eda14cbcSMatt Macy int size; 376eda14cbcSMatt Macy int error; 377eda14cbcSMatt Macy 378eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 379eda14cbcSMatt Macy if (zp->z_is_sa) { 380eda14cbcSMatt Macy if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zfsvfs), 381eda14cbcSMatt Macy &size)) != 0) 382eda14cbcSMatt Macy return (error); 383eda14cbcSMatt Macy *aclsize = size; 384eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_COUNT(zfsvfs), 385eda14cbcSMatt Macy &acl_count, sizeof (acl_count))) != 0) 386eda14cbcSMatt Macy return (error); 387eda14cbcSMatt Macy *aclcount = acl_count; 388eda14cbcSMatt Macy } else { 389eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), 390eda14cbcSMatt Macy aclphys, sizeof (*aclphys))) != 0) 391eda14cbcSMatt Macy return (error); 392eda14cbcSMatt Macy 393eda14cbcSMatt Macy if (aclphys->z_acl_version == ZFS_ACL_VERSION_INITIAL) { 394eda14cbcSMatt Macy *aclsize = ZFS_ACL_SIZE(aclphys->z_acl_size); 395eda14cbcSMatt Macy *aclcount = aclphys->z_acl_size; 396eda14cbcSMatt Macy } else { 397eda14cbcSMatt Macy *aclsize = aclphys->z_acl_size; 398eda14cbcSMatt Macy *aclcount = aclphys->z_acl_count; 399eda14cbcSMatt Macy } 400eda14cbcSMatt Macy } 401eda14cbcSMatt Macy return (0); 402eda14cbcSMatt Macy } 403eda14cbcSMatt Macy 404eda14cbcSMatt Macy int 405eda14cbcSMatt Macy zfs_znode_acl_version(znode_t *zp) 406eda14cbcSMatt Macy { 407eda14cbcSMatt Macy zfs_acl_phys_t acl_phys; 408eda14cbcSMatt Macy 409eda14cbcSMatt Macy if (zp->z_is_sa) 410eda14cbcSMatt Macy return (ZFS_ACL_VERSION_FUID); 411eda14cbcSMatt Macy else { 412eda14cbcSMatt Macy int error; 413eda14cbcSMatt Macy 414eda14cbcSMatt Macy /* 415eda14cbcSMatt Macy * Need to deal with a potential 416eda14cbcSMatt Macy * race where zfs_sa_upgrade could cause 417eda14cbcSMatt Macy * z_isa_sa to change. 418eda14cbcSMatt Macy * 419eda14cbcSMatt Macy * If the lookup fails then the state of z_is_sa should have 420eda14cbcSMatt Macy * changed. 421eda14cbcSMatt Macy */ 422eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, 423eda14cbcSMatt Macy SA_ZPL_ZNODE_ACL(zp->z_zfsvfs), 424eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys))) == 0) 425eda14cbcSMatt Macy return (acl_phys.z_acl_version); 426eda14cbcSMatt Macy else { 427eda14cbcSMatt Macy /* 428eda14cbcSMatt Macy * After upgrade SA_ZPL_ZNODE_ACL should have 429eda14cbcSMatt Macy * been removed. 430eda14cbcSMatt Macy */ 43116038816SMartin Matuska VERIFY(zp->z_is_sa); 43216038816SMartin Matuska VERIFY3S(error, ==, ENOENT); 433eda14cbcSMatt Macy return (ZFS_ACL_VERSION_FUID); 434eda14cbcSMatt Macy } 435eda14cbcSMatt Macy } 436eda14cbcSMatt Macy } 437eda14cbcSMatt Macy 438eda14cbcSMatt Macy static int 439eda14cbcSMatt Macy zfs_acl_version(int version) 440eda14cbcSMatt Macy { 441eda14cbcSMatt Macy if (version < ZPL_VERSION_FUID) 442eda14cbcSMatt Macy return (ZFS_ACL_VERSION_INITIAL); 443eda14cbcSMatt Macy else 444eda14cbcSMatt Macy return (ZFS_ACL_VERSION_FUID); 445eda14cbcSMatt Macy } 446eda14cbcSMatt Macy 447eda14cbcSMatt Macy static int 448eda14cbcSMatt Macy zfs_acl_version_zp(znode_t *zp) 449eda14cbcSMatt Macy { 450eda14cbcSMatt Macy return (zfs_acl_version(zp->z_zfsvfs->z_version)); 451eda14cbcSMatt Macy } 452eda14cbcSMatt Macy 453eda14cbcSMatt Macy zfs_acl_t * 454eda14cbcSMatt Macy zfs_acl_alloc(int vers) 455eda14cbcSMatt Macy { 456eda14cbcSMatt Macy zfs_acl_t *aclp; 457eda14cbcSMatt Macy 458eda14cbcSMatt Macy aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP); 459eda14cbcSMatt Macy list_create(&aclp->z_acl, sizeof (zfs_acl_node_t), 460eda14cbcSMatt Macy offsetof(zfs_acl_node_t, z_next)); 461eda14cbcSMatt Macy aclp->z_version = vers; 462eda14cbcSMatt Macy if (vers == ZFS_ACL_VERSION_FUID) 463eda14cbcSMatt Macy aclp->z_ops = &zfs_acl_fuid_ops; 464eda14cbcSMatt Macy else 465eda14cbcSMatt Macy aclp->z_ops = &zfs_acl_v0_ops; 466eda14cbcSMatt Macy return (aclp); 467eda14cbcSMatt Macy } 468eda14cbcSMatt Macy 469eda14cbcSMatt Macy zfs_acl_node_t * 470eda14cbcSMatt Macy zfs_acl_node_alloc(size_t bytes) 471eda14cbcSMatt Macy { 472eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 473eda14cbcSMatt Macy 474eda14cbcSMatt Macy aclnode = kmem_zalloc(sizeof (zfs_acl_node_t), KM_SLEEP); 475eda14cbcSMatt Macy if (bytes) { 476*7a7741afSMartin Matuska aclnode->z_acldata = kmem_zalloc(bytes, KM_SLEEP); 477eda14cbcSMatt Macy aclnode->z_allocdata = aclnode->z_acldata; 478eda14cbcSMatt Macy aclnode->z_allocsize = bytes; 479eda14cbcSMatt Macy aclnode->z_size = bytes; 480eda14cbcSMatt Macy } 481eda14cbcSMatt Macy 482eda14cbcSMatt Macy return (aclnode); 483eda14cbcSMatt Macy } 484eda14cbcSMatt Macy 485eda14cbcSMatt Macy static void 486eda14cbcSMatt Macy zfs_acl_node_free(zfs_acl_node_t *aclnode) 487eda14cbcSMatt Macy { 488eda14cbcSMatt Macy if (aclnode->z_allocsize) 489eda14cbcSMatt Macy kmem_free(aclnode->z_allocdata, aclnode->z_allocsize); 490eda14cbcSMatt Macy kmem_free(aclnode, sizeof (zfs_acl_node_t)); 491eda14cbcSMatt Macy } 492eda14cbcSMatt Macy 493eda14cbcSMatt Macy static void 494eda14cbcSMatt Macy zfs_acl_release_nodes(zfs_acl_t *aclp) 495eda14cbcSMatt Macy { 496eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 497eda14cbcSMatt Macy 4984e8d558cSMartin Matuska while ((aclnode = list_remove_head(&aclp->z_acl))) 499eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 500eda14cbcSMatt Macy aclp->z_acl_count = 0; 501eda14cbcSMatt Macy aclp->z_acl_bytes = 0; 502eda14cbcSMatt Macy } 503eda14cbcSMatt Macy 504eda14cbcSMatt Macy void 505eda14cbcSMatt Macy zfs_acl_free(zfs_acl_t *aclp) 506eda14cbcSMatt Macy { 507eda14cbcSMatt Macy zfs_acl_release_nodes(aclp); 508eda14cbcSMatt Macy list_destroy(&aclp->z_acl); 509eda14cbcSMatt Macy kmem_free(aclp, sizeof (zfs_acl_t)); 510eda14cbcSMatt Macy } 511eda14cbcSMatt Macy 512eda14cbcSMatt Macy static boolean_t 513eda14cbcSMatt Macy zfs_acl_valid_ace_type(uint_t type, uint_t flags) 514eda14cbcSMatt Macy { 515eda14cbcSMatt Macy uint16_t entry_type; 516eda14cbcSMatt Macy 517eda14cbcSMatt Macy switch (type) { 518eda14cbcSMatt Macy case ALLOW: 519eda14cbcSMatt Macy case DENY: 520eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_ACE_TYPE: 521eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_ACE_TYPE: 522eda14cbcSMatt Macy entry_type = flags & ACE_TYPE_FLAGS; 523eda14cbcSMatt Macy return (entry_type == ACE_OWNER || 524eda14cbcSMatt Macy entry_type == OWNING_GROUP || 525eda14cbcSMatt Macy entry_type == ACE_EVERYONE || entry_type == 0 || 526eda14cbcSMatt Macy entry_type == ACE_IDENTIFIER_GROUP); 527eda14cbcSMatt Macy default: 528be181ee2SMartin Matuska if (type <= MAX_ACE_TYPE) 529eda14cbcSMatt Macy return (B_TRUE); 530eda14cbcSMatt Macy } 531eda14cbcSMatt Macy return (B_FALSE); 532eda14cbcSMatt Macy } 533eda14cbcSMatt Macy 534eda14cbcSMatt Macy static boolean_t 535eda14cbcSMatt Macy zfs_ace_valid(vtype_t obj_type, zfs_acl_t *aclp, uint16_t type, uint16_t iflags) 536eda14cbcSMatt Macy { 537eda14cbcSMatt Macy /* 538eda14cbcSMatt Macy * first check type of entry 539eda14cbcSMatt Macy */ 540eda14cbcSMatt Macy 541eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 542eda14cbcSMatt Macy return (B_FALSE); 543eda14cbcSMatt Macy 544eda14cbcSMatt Macy switch (type) { 545eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 546eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 547eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 548eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 549eda14cbcSMatt Macy if (aclp->z_version < ZFS_ACL_VERSION_FUID) 550eda14cbcSMatt Macy return (B_FALSE); 551eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_OBJ_ACE; 552eda14cbcSMatt Macy } 553eda14cbcSMatt Macy 554eda14cbcSMatt Macy /* 555eda14cbcSMatt Macy * next check inheritance level flags 556eda14cbcSMatt Macy */ 557eda14cbcSMatt Macy 558eda14cbcSMatt Macy if (obj_type == VDIR && 559eda14cbcSMatt Macy (iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 560eda14cbcSMatt Macy aclp->z_hints |= ZFS_INHERIT_ACE; 561eda14cbcSMatt Macy 562eda14cbcSMatt Macy if (iflags & (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) { 563eda14cbcSMatt Macy if ((iflags & (ACE_FILE_INHERIT_ACE| 564eda14cbcSMatt Macy ACE_DIRECTORY_INHERIT_ACE)) == 0) { 565eda14cbcSMatt Macy return (B_FALSE); 566eda14cbcSMatt Macy } 567eda14cbcSMatt Macy } 568eda14cbcSMatt Macy 569eda14cbcSMatt Macy return (B_TRUE); 570eda14cbcSMatt Macy } 571eda14cbcSMatt Macy 572eda14cbcSMatt Macy static void * 573eda14cbcSMatt Macy zfs_acl_next_ace(zfs_acl_t *aclp, void *start, uint64_t *who, 574eda14cbcSMatt Macy uint32_t *access_mask, uint16_t *iflags, uint16_t *type) 575eda14cbcSMatt Macy { 576eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 577eda14cbcSMatt Macy 57816038816SMartin Matuska ASSERT3P(aclp, !=, NULL); 579eda14cbcSMatt Macy 580eda14cbcSMatt Macy if (start == NULL) { 581eda14cbcSMatt Macy aclnode = list_head(&aclp->z_acl); 582eda14cbcSMatt Macy if (aclnode == NULL) 583eda14cbcSMatt Macy return (NULL); 584eda14cbcSMatt Macy 585eda14cbcSMatt Macy aclp->z_next_ace = aclnode->z_acldata; 586eda14cbcSMatt Macy aclp->z_curr_node = aclnode; 587eda14cbcSMatt Macy aclnode->z_ace_idx = 0; 588eda14cbcSMatt Macy } 589eda14cbcSMatt Macy 590eda14cbcSMatt Macy aclnode = aclp->z_curr_node; 591eda14cbcSMatt Macy 592eda14cbcSMatt Macy if (aclnode == NULL) 593eda14cbcSMatt Macy return (NULL); 594eda14cbcSMatt Macy 595eda14cbcSMatt Macy if (aclnode->z_ace_idx >= aclnode->z_ace_count) { 596eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode); 597eda14cbcSMatt Macy if (aclnode == NULL) 598eda14cbcSMatt Macy return (NULL); 599eda14cbcSMatt Macy else { 600eda14cbcSMatt Macy aclp->z_curr_node = aclnode; 601eda14cbcSMatt Macy aclnode->z_ace_idx = 0; 602eda14cbcSMatt Macy aclp->z_next_ace = aclnode->z_acldata; 603eda14cbcSMatt Macy } 604eda14cbcSMatt Macy } 605eda14cbcSMatt Macy 606eda14cbcSMatt Macy if (aclnode->z_ace_idx < aclnode->z_ace_count) { 607eda14cbcSMatt Macy void *acep = aclp->z_next_ace; 608eda14cbcSMatt Macy size_t ace_size; 609eda14cbcSMatt Macy 610eda14cbcSMatt Macy /* 611eda14cbcSMatt Macy * Make sure we don't overstep our bounds 612eda14cbcSMatt Macy */ 613eda14cbcSMatt Macy ace_size = aclp->z_ops->ace_size(acep); 614eda14cbcSMatt Macy 615eda14cbcSMatt Macy if (((caddr_t)acep + ace_size) > 616eda14cbcSMatt Macy ((caddr_t)aclnode->z_acldata + aclnode->z_size)) { 617eda14cbcSMatt Macy return (NULL); 618eda14cbcSMatt Macy } 619eda14cbcSMatt Macy 620eda14cbcSMatt Macy *iflags = aclp->z_ops->ace_flags_get(acep); 621eda14cbcSMatt Macy *type = aclp->z_ops->ace_type_get(acep); 622eda14cbcSMatt Macy *access_mask = aclp->z_ops->ace_mask_get(acep); 623eda14cbcSMatt Macy *who = aclp->z_ops->ace_who_get(acep); 624eda14cbcSMatt Macy aclp->z_next_ace = (caddr_t)aclp->z_next_ace + ace_size; 625eda14cbcSMatt Macy aclnode->z_ace_idx++; 626eda14cbcSMatt Macy 627eda14cbcSMatt Macy return ((void *)acep); 628eda14cbcSMatt Macy } 629eda14cbcSMatt Macy return (NULL); 630eda14cbcSMatt Macy } 631eda14cbcSMatt Macy 632dbd5678dSMartin Matuska static uintptr_t 633dbd5678dSMartin Matuska zfs_ace_walk(void *datap, uintptr_t cookie, int aclcnt, 634eda14cbcSMatt Macy uint16_t *flags, uint16_t *type, uint32_t *mask) 635eda14cbcSMatt Macy { 636c03c5b1cSMartin Matuska (void) aclcnt; 637eda14cbcSMatt Macy zfs_acl_t *aclp = datap; 638eda14cbcSMatt Macy zfs_ace_hdr_t *acep = (zfs_ace_hdr_t *)(uintptr_t)cookie; 639eda14cbcSMatt Macy uint64_t who; 640eda14cbcSMatt Macy 641eda14cbcSMatt Macy acep = zfs_acl_next_ace(aclp, acep, &who, mask, 642eda14cbcSMatt Macy flags, type); 643dbd5678dSMartin Matuska return ((uintptr_t)acep); 644eda14cbcSMatt Macy } 645eda14cbcSMatt Macy 646eda14cbcSMatt Macy /* 647eda14cbcSMatt Macy * Copy ACE to internal ZFS format. 648eda14cbcSMatt Macy * While processing the ACL each ACE will be validated for correctness. 649eda14cbcSMatt Macy * ACE FUIDs will be created later. 650eda14cbcSMatt Macy */ 651eda14cbcSMatt Macy static int 652eda14cbcSMatt Macy zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp, 653eda14cbcSMatt Macy void *datap, zfs_ace_t *z_acl, uint64_t aclcnt, size_t *size, 654eda14cbcSMatt Macy zfs_fuid_info_t **fuidp, cred_t *cr) 655eda14cbcSMatt Macy { 656eda14cbcSMatt Macy int i; 657eda14cbcSMatt Macy uint16_t entry_type; 658eda14cbcSMatt Macy zfs_ace_t *aceptr = z_acl; 659eda14cbcSMatt Macy ace_t *acep = datap; 660eda14cbcSMatt Macy zfs_object_ace_t *zobjacep; 661eda14cbcSMatt Macy ace_object_t *aceobjp; 662eda14cbcSMatt Macy 663eda14cbcSMatt Macy for (i = 0; i != aclcnt; i++) { 664eda14cbcSMatt Macy aceptr->z_hdr.z_access_mask = acep->a_access_mask; 665eda14cbcSMatt Macy aceptr->z_hdr.z_flags = acep->a_flags; 666eda14cbcSMatt Macy aceptr->z_hdr.z_type = acep->a_type; 667eda14cbcSMatt Macy entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS; 668eda14cbcSMatt Macy if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP && 669eda14cbcSMatt Macy entry_type != ACE_EVERYONE) { 670eda14cbcSMatt Macy aceptr->z_fuid = zfs_fuid_create(zfsvfs, acep->a_who, 671eda14cbcSMatt Macy cr, (entry_type == 0) ? 672eda14cbcSMatt Macy ZFS_ACE_USER : ZFS_ACE_GROUP, fuidp); 673eda14cbcSMatt Macy } 674eda14cbcSMatt Macy 675eda14cbcSMatt Macy /* 676eda14cbcSMatt Macy * Make sure ACE is valid 677eda14cbcSMatt Macy */ 678eda14cbcSMatt Macy if (zfs_ace_valid(obj_type, aclp, aceptr->z_hdr.z_type, 679eda14cbcSMatt Macy aceptr->z_hdr.z_flags) != B_TRUE) 680eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 681eda14cbcSMatt Macy 682eda14cbcSMatt Macy switch (acep->a_type) { 683eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 684eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 685eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 686eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 687eda14cbcSMatt Macy zobjacep = (zfs_object_ace_t *)aceptr; 688eda14cbcSMatt Macy aceobjp = (ace_object_t *)acep; 689eda14cbcSMatt Macy 690da5137abSMartin Matuska memcpy(zobjacep->z_object_type, aceobjp->a_obj_type, 691eda14cbcSMatt Macy sizeof (aceobjp->a_obj_type)); 692da5137abSMartin Matuska memcpy(zobjacep->z_inherit_type, 693da5137abSMartin Matuska aceobjp->a_inherit_obj_type, 694eda14cbcSMatt Macy sizeof (aceobjp->a_inherit_obj_type)); 695eda14cbcSMatt Macy acep = (ace_t *)((caddr_t)acep + sizeof (ace_object_t)); 696eda14cbcSMatt Macy break; 697eda14cbcSMatt Macy default: 698eda14cbcSMatt Macy acep = (ace_t *)((caddr_t)acep + sizeof (ace_t)); 699eda14cbcSMatt Macy } 700eda14cbcSMatt Macy 701eda14cbcSMatt Macy aceptr = (zfs_ace_t *)((caddr_t)aceptr + 702eda14cbcSMatt Macy aclp->z_ops->ace_size(aceptr)); 703eda14cbcSMatt Macy } 704eda14cbcSMatt Macy 705eda14cbcSMatt Macy *size = (caddr_t)aceptr - (caddr_t)z_acl; 706eda14cbcSMatt Macy 707eda14cbcSMatt Macy return (0); 708eda14cbcSMatt Macy } 709eda14cbcSMatt Macy 710eda14cbcSMatt Macy /* 711eda14cbcSMatt Macy * Copy ZFS ACEs to fixed size ace_t layout 712eda14cbcSMatt Macy */ 713eda14cbcSMatt Macy static void 714eda14cbcSMatt Macy zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr, 715eda14cbcSMatt Macy void *datap, int filter) 716eda14cbcSMatt Macy { 717eda14cbcSMatt Macy uint64_t who; 718eda14cbcSMatt Macy uint32_t access_mask; 719eda14cbcSMatt Macy uint16_t iflags, type; 720eda14cbcSMatt Macy zfs_ace_hdr_t *zacep = NULL; 721eda14cbcSMatt Macy ace_t *acep = datap; 722eda14cbcSMatt Macy ace_object_t *objacep; 723eda14cbcSMatt Macy zfs_object_ace_t *zobjacep; 724eda14cbcSMatt Macy size_t ace_size; 725eda14cbcSMatt Macy uint16_t entry_type; 726eda14cbcSMatt Macy 727eda14cbcSMatt Macy while ((zacep = zfs_acl_next_ace(aclp, zacep, 728eda14cbcSMatt Macy &who, &access_mask, &iflags, &type))) { 729eda14cbcSMatt Macy 730eda14cbcSMatt Macy switch (type) { 731eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 732eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 733eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 734eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 735eda14cbcSMatt Macy if (filter) { 736eda14cbcSMatt Macy continue; 737eda14cbcSMatt Macy } 738eda14cbcSMatt Macy zobjacep = (zfs_object_ace_t *)zacep; 739eda14cbcSMatt Macy objacep = (ace_object_t *)acep; 740da5137abSMartin Matuska memcpy(objacep->a_obj_type, 741da5137abSMartin Matuska zobjacep->z_object_type, 742eda14cbcSMatt Macy sizeof (zobjacep->z_object_type)); 743da5137abSMartin Matuska memcpy(objacep->a_inherit_obj_type, 744da5137abSMartin Matuska zobjacep->z_inherit_type, 745eda14cbcSMatt Macy sizeof (zobjacep->z_inherit_type)); 746eda14cbcSMatt Macy ace_size = sizeof (ace_object_t); 747eda14cbcSMatt Macy break; 748eda14cbcSMatt Macy default: 749eda14cbcSMatt Macy ace_size = sizeof (ace_t); 750eda14cbcSMatt Macy break; 751eda14cbcSMatt Macy } 752eda14cbcSMatt Macy 753eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 754eda14cbcSMatt Macy if ((entry_type != ACE_OWNER && 755eda14cbcSMatt Macy entry_type != OWNING_GROUP && 756eda14cbcSMatt Macy entry_type != ACE_EVERYONE)) { 757eda14cbcSMatt Macy acep->a_who = zfs_fuid_map_id(zfsvfs, who, 758eda14cbcSMatt Macy cr, (entry_type & ACE_IDENTIFIER_GROUP) ? 759eda14cbcSMatt Macy ZFS_ACE_GROUP : ZFS_ACE_USER); 760eda14cbcSMatt Macy } else { 761eda14cbcSMatt Macy acep->a_who = (uid_t)(int64_t)who; 762eda14cbcSMatt Macy } 763eda14cbcSMatt Macy acep->a_access_mask = access_mask; 764eda14cbcSMatt Macy acep->a_flags = iflags; 765eda14cbcSMatt Macy acep->a_type = type; 766eda14cbcSMatt Macy acep = (ace_t *)((caddr_t)acep + ace_size); 767eda14cbcSMatt Macy } 768eda14cbcSMatt Macy } 769eda14cbcSMatt Macy 770eda14cbcSMatt Macy static int 771eda14cbcSMatt Macy zfs_copy_ace_2_oldace(vtype_t obj_type, zfs_acl_t *aclp, ace_t *acep, 772eda14cbcSMatt Macy zfs_oldace_t *z_acl, int aclcnt, size_t *size) 773eda14cbcSMatt Macy { 774eda14cbcSMatt Macy int i; 775eda14cbcSMatt Macy zfs_oldace_t *aceptr = z_acl; 776eda14cbcSMatt Macy 777eda14cbcSMatt Macy for (i = 0; i != aclcnt; i++, aceptr++) { 778eda14cbcSMatt Macy aceptr->z_access_mask = acep[i].a_access_mask; 779eda14cbcSMatt Macy aceptr->z_type = acep[i].a_type; 780eda14cbcSMatt Macy aceptr->z_flags = acep[i].a_flags; 781eda14cbcSMatt Macy aceptr->z_fuid = acep[i].a_who; 782eda14cbcSMatt Macy /* 783eda14cbcSMatt Macy * Make sure ACE is valid 784eda14cbcSMatt Macy */ 785eda14cbcSMatt Macy if (zfs_ace_valid(obj_type, aclp, aceptr->z_type, 786eda14cbcSMatt Macy aceptr->z_flags) != B_TRUE) 787eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 788eda14cbcSMatt Macy } 789eda14cbcSMatt Macy *size = (caddr_t)aceptr - (caddr_t)z_acl; 790eda14cbcSMatt Macy return (0); 791eda14cbcSMatt Macy } 792eda14cbcSMatt Macy 793eda14cbcSMatt Macy /* 794eda14cbcSMatt Macy * convert old ACL format to new 795eda14cbcSMatt Macy */ 796eda14cbcSMatt Macy void 797eda14cbcSMatt Macy zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr) 798eda14cbcSMatt Macy { 799eda14cbcSMatt Macy zfs_oldace_t *oldaclp; 800eda14cbcSMatt Macy int i; 801eda14cbcSMatt Macy uint16_t type, iflags; 802eda14cbcSMatt Macy uint32_t access_mask; 803eda14cbcSMatt Macy uint64_t who; 804eda14cbcSMatt Macy void *cookie = NULL; 805eda14cbcSMatt Macy zfs_acl_node_t *newaclnode; 806eda14cbcSMatt Macy 80716038816SMartin Matuska ASSERT3U(aclp->z_version, ==, ZFS_ACL_VERSION_INITIAL); 808eda14cbcSMatt Macy /* 809eda14cbcSMatt Macy * First create the ACE in a contiguous piece of memory 810eda14cbcSMatt Macy * for zfs_copy_ace_2_fuid(). 811eda14cbcSMatt Macy * 812eda14cbcSMatt Macy * We only convert an ACL once, so this won't happen 813eda14cbcSMatt Macy * everytime. 814eda14cbcSMatt Macy */ 815eda14cbcSMatt Macy oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count, 816eda14cbcSMatt Macy KM_SLEEP); 817eda14cbcSMatt Macy i = 0; 818eda14cbcSMatt Macy while ((cookie = zfs_acl_next_ace(aclp, cookie, &who, 819eda14cbcSMatt Macy &access_mask, &iflags, &type))) { 820eda14cbcSMatt Macy oldaclp[i].z_flags = iflags; 821eda14cbcSMatt Macy oldaclp[i].z_type = type; 822eda14cbcSMatt Macy oldaclp[i].z_fuid = who; 823eda14cbcSMatt Macy oldaclp[i++].z_access_mask = access_mask; 824eda14cbcSMatt Macy } 825eda14cbcSMatt Macy 826eda14cbcSMatt Macy newaclnode = zfs_acl_node_alloc(aclp->z_acl_count * 827eda14cbcSMatt Macy sizeof (zfs_object_ace_t)); 828eda14cbcSMatt Macy aclp->z_ops = &zfs_acl_fuid_ops; 82916038816SMartin Matuska VERIFY0(zfs_copy_ace_2_fuid(zp->z_zfsvfs, ZTOV(zp)->v_type, aclp, 830eda14cbcSMatt Macy oldaclp, newaclnode->z_acldata, aclp->z_acl_count, 83116038816SMartin Matuska &newaclnode->z_size, NULL, cr)); 832eda14cbcSMatt Macy newaclnode->z_ace_count = aclp->z_acl_count; 833eda14cbcSMatt Macy aclp->z_version = ZFS_ACL_VERSION; 834eda14cbcSMatt Macy kmem_free(oldaclp, aclp->z_acl_count * sizeof (zfs_oldace_t)); 835eda14cbcSMatt Macy 836eda14cbcSMatt Macy /* 837eda14cbcSMatt Macy * Release all previous ACL nodes 838eda14cbcSMatt Macy */ 839eda14cbcSMatt Macy 840eda14cbcSMatt Macy zfs_acl_release_nodes(aclp); 841eda14cbcSMatt Macy 842eda14cbcSMatt Macy list_insert_head(&aclp->z_acl, newaclnode); 843eda14cbcSMatt Macy 844eda14cbcSMatt Macy aclp->z_acl_bytes = newaclnode->z_size; 845eda14cbcSMatt Macy aclp->z_acl_count = newaclnode->z_ace_count; 846eda14cbcSMatt Macy 847eda14cbcSMatt Macy } 848eda14cbcSMatt Macy 849eda14cbcSMatt Macy /* 850eda14cbcSMatt Macy * Convert unix access mask to v4 access mask 851eda14cbcSMatt Macy */ 852eda14cbcSMatt Macy static uint32_t 853eda14cbcSMatt Macy zfs_unix_to_v4(uint32_t access_mask) 854eda14cbcSMatt Macy { 855eda14cbcSMatt Macy uint32_t new_mask = 0; 856eda14cbcSMatt Macy 857eda14cbcSMatt Macy if (access_mask & S_IXOTH) 858eda14cbcSMatt Macy new_mask |= ACE_EXECUTE; 859eda14cbcSMatt Macy if (access_mask & S_IWOTH) 860eda14cbcSMatt Macy new_mask |= ACE_WRITE_DATA; 861eda14cbcSMatt Macy if (access_mask & S_IROTH) 862eda14cbcSMatt Macy new_mask |= ACE_READ_DATA; 863eda14cbcSMatt Macy return (new_mask); 864eda14cbcSMatt Macy } 865eda14cbcSMatt Macy 866eda14cbcSMatt Macy static void 867eda14cbcSMatt Macy zfs_set_ace(zfs_acl_t *aclp, void *acep, uint32_t access_mask, 868eda14cbcSMatt Macy uint16_t access_type, uint64_t fuid, uint16_t entry_type) 869eda14cbcSMatt Macy { 870eda14cbcSMatt Macy uint16_t type = entry_type & ACE_TYPE_FLAGS; 871eda14cbcSMatt Macy 872eda14cbcSMatt Macy aclp->z_ops->ace_mask_set(acep, access_mask); 873eda14cbcSMatt Macy aclp->z_ops->ace_type_set(acep, access_type); 874eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, entry_type); 875eda14cbcSMatt Macy if ((type != ACE_OWNER && type != OWNING_GROUP && 876eda14cbcSMatt Macy type != ACE_EVERYONE)) 877eda14cbcSMatt Macy aclp->z_ops->ace_who_set(acep, fuid); 878eda14cbcSMatt Macy } 879eda14cbcSMatt Macy 880eda14cbcSMatt Macy /* 881eda14cbcSMatt Macy * Determine mode of file based on ACL. 882eda14cbcSMatt Macy */ 883eda14cbcSMatt Macy uint64_t 884eda14cbcSMatt Macy zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp, 885eda14cbcSMatt Macy uint64_t *pflags, uint64_t fuid, uint64_t fgid) 886eda14cbcSMatt Macy { 887eda14cbcSMatt Macy int entry_type; 888eda14cbcSMatt Macy mode_t mode; 889eda14cbcSMatt Macy mode_t seen = 0; 890eda14cbcSMatt Macy zfs_ace_hdr_t *acep = NULL; 891eda14cbcSMatt Macy uint64_t who; 892eda14cbcSMatt Macy uint16_t iflags, type; 893eda14cbcSMatt Macy uint32_t access_mask; 894eda14cbcSMatt Macy boolean_t an_exec_denied = B_FALSE; 895eda14cbcSMatt Macy 896eda14cbcSMatt Macy mode = (fmode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX)); 897eda14cbcSMatt Macy 898eda14cbcSMatt Macy while ((acep = zfs_acl_next_ace(aclp, acep, &who, 899eda14cbcSMatt Macy &access_mask, &iflags, &type))) { 900eda14cbcSMatt Macy 901eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 902eda14cbcSMatt Macy continue; 903eda14cbcSMatt Macy 904eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 905eda14cbcSMatt Macy 906eda14cbcSMatt Macy /* 907eda14cbcSMatt Macy * Skip over any inherit_only ACEs 908eda14cbcSMatt Macy */ 909eda14cbcSMatt Macy if (iflags & ACE_INHERIT_ONLY_ACE) 910eda14cbcSMatt Macy continue; 911eda14cbcSMatt Macy 912eda14cbcSMatt Macy if (entry_type == ACE_OWNER || (entry_type == 0 && 913eda14cbcSMatt Macy who == fuid)) { 914eda14cbcSMatt Macy if ((access_mask & ACE_READ_DATA) && 915eda14cbcSMatt Macy (!(seen & S_IRUSR))) { 916eda14cbcSMatt Macy seen |= S_IRUSR; 917eda14cbcSMatt Macy if (type == ALLOW) { 918eda14cbcSMatt Macy mode |= S_IRUSR; 919eda14cbcSMatt Macy } 920eda14cbcSMatt Macy } 921eda14cbcSMatt Macy if ((access_mask & ACE_WRITE_DATA) && 922eda14cbcSMatt Macy (!(seen & S_IWUSR))) { 923eda14cbcSMatt Macy seen |= S_IWUSR; 924eda14cbcSMatt Macy if (type == ALLOW) { 925eda14cbcSMatt Macy mode |= S_IWUSR; 926eda14cbcSMatt Macy } 927eda14cbcSMatt Macy } 928eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE) && 929eda14cbcSMatt Macy (!(seen & S_IXUSR))) { 930eda14cbcSMatt Macy seen |= S_IXUSR; 931eda14cbcSMatt Macy if (type == ALLOW) { 932eda14cbcSMatt Macy mode |= S_IXUSR; 933eda14cbcSMatt Macy } 934eda14cbcSMatt Macy } 935eda14cbcSMatt Macy } else if (entry_type == OWNING_GROUP || 936eda14cbcSMatt Macy (entry_type == ACE_IDENTIFIER_GROUP && who == fgid)) { 937eda14cbcSMatt Macy if ((access_mask & ACE_READ_DATA) && 938eda14cbcSMatt Macy (!(seen & S_IRGRP))) { 939eda14cbcSMatt Macy seen |= S_IRGRP; 940eda14cbcSMatt Macy if (type == ALLOW) { 941eda14cbcSMatt Macy mode |= S_IRGRP; 942eda14cbcSMatt Macy } 943eda14cbcSMatt Macy } 944eda14cbcSMatt Macy if ((access_mask & ACE_WRITE_DATA) && 945eda14cbcSMatt Macy (!(seen & S_IWGRP))) { 946eda14cbcSMatt Macy seen |= S_IWGRP; 947eda14cbcSMatt Macy if (type == ALLOW) { 948eda14cbcSMatt Macy mode |= S_IWGRP; 949eda14cbcSMatt Macy } 950eda14cbcSMatt Macy } 951eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE) && 952eda14cbcSMatt Macy (!(seen & S_IXGRP))) { 953eda14cbcSMatt Macy seen |= S_IXGRP; 954eda14cbcSMatt Macy if (type == ALLOW) { 955eda14cbcSMatt Macy mode |= S_IXGRP; 956eda14cbcSMatt Macy } 957eda14cbcSMatt Macy } 958eda14cbcSMatt Macy } else if (entry_type == ACE_EVERYONE) { 959eda14cbcSMatt Macy if ((access_mask & ACE_READ_DATA)) { 960eda14cbcSMatt Macy if (!(seen & S_IRUSR)) { 961eda14cbcSMatt Macy seen |= S_IRUSR; 962eda14cbcSMatt Macy if (type == ALLOW) { 963eda14cbcSMatt Macy mode |= S_IRUSR; 964eda14cbcSMatt Macy } 965eda14cbcSMatt Macy } 966eda14cbcSMatt Macy if (!(seen & S_IRGRP)) { 967eda14cbcSMatt Macy seen |= S_IRGRP; 968eda14cbcSMatt Macy if (type == ALLOW) { 969eda14cbcSMatt Macy mode |= S_IRGRP; 970eda14cbcSMatt Macy } 971eda14cbcSMatt Macy } 972eda14cbcSMatt Macy if (!(seen & S_IROTH)) { 973eda14cbcSMatt Macy seen |= S_IROTH; 974eda14cbcSMatt Macy if (type == ALLOW) { 975eda14cbcSMatt Macy mode |= S_IROTH; 976eda14cbcSMatt Macy } 977eda14cbcSMatt Macy } 978eda14cbcSMatt Macy } 979eda14cbcSMatt Macy if ((access_mask & ACE_WRITE_DATA)) { 980eda14cbcSMatt Macy if (!(seen & S_IWUSR)) { 981eda14cbcSMatt Macy seen |= S_IWUSR; 982eda14cbcSMatt Macy if (type == ALLOW) { 983eda14cbcSMatt Macy mode |= S_IWUSR; 984eda14cbcSMatt Macy } 985eda14cbcSMatt Macy } 986eda14cbcSMatt Macy if (!(seen & S_IWGRP)) { 987eda14cbcSMatt Macy seen |= S_IWGRP; 988eda14cbcSMatt Macy if (type == ALLOW) { 989eda14cbcSMatt Macy mode |= S_IWGRP; 990eda14cbcSMatt Macy } 991eda14cbcSMatt Macy } 992eda14cbcSMatt Macy if (!(seen & S_IWOTH)) { 993eda14cbcSMatt Macy seen |= S_IWOTH; 994eda14cbcSMatt Macy if (type == ALLOW) { 995eda14cbcSMatt Macy mode |= S_IWOTH; 996eda14cbcSMatt Macy } 997eda14cbcSMatt Macy } 998eda14cbcSMatt Macy } 999eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE)) { 1000eda14cbcSMatt Macy if (!(seen & S_IXUSR)) { 1001eda14cbcSMatt Macy seen |= S_IXUSR; 1002eda14cbcSMatt Macy if (type == ALLOW) { 1003eda14cbcSMatt Macy mode |= S_IXUSR; 1004eda14cbcSMatt Macy } 1005eda14cbcSMatt Macy } 1006eda14cbcSMatt Macy if (!(seen & S_IXGRP)) { 1007eda14cbcSMatt Macy seen |= S_IXGRP; 1008eda14cbcSMatt Macy if (type == ALLOW) { 1009eda14cbcSMatt Macy mode |= S_IXGRP; 1010eda14cbcSMatt Macy } 1011eda14cbcSMatt Macy } 1012eda14cbcSMatt Macy if (!(seen & S_IXOTH)) { 1013eda14cbcSMatt Macy seen |= S_IXOTH; 1014eda14cbcSMatt Macy if (type == ALLOW) { 1015eda14cbcSMatt Macy mode |= S_IXOTH; 1016eda14cbcSMatt Macy } 1017eda14cbcSMatt Macy } 1018eda14cbcSMatt Macy } 1019eda14cbcSMatt Macy } else { 1020eda14cbcSMatt Macy /* 1021eda14cbcSMatt Macy * Only care if this IDENTIFIER_GROUP or 1022eda14cbcSMatt Macy * USER ACE denies execute access to someone, 1023eda14cbcSMatt Macy * mode is not affected 1024eda14cbcSMatt Macy */ 1025eda14cbcSMatt Macy if ((access_mask & ACE_EXECUTE) && type == DENY) 1026eda14cbcSMatt Macy an_exec_denied = B_TRUE; 1027eda14cbcSMatt Macy } 1028eda14cbcSMatt Macy } 1029eda14cbcSMatt Macy 1030eda14cbcSMatt Macy /* 1031eda14cbcSMatt Macy * Failure to allow is effectively a deny, so execute permission 1032eda14cbcSMatt Macy * is denied if it was never mentioned or if we explicitly 1033eda14cbcSMatt Macy * weren't allowed it. 1034eda14cbcSMatt Macy */ 1035eda14cbcSMatt Macy if (!an_exec_denied && 1036eda14cbcSMatt Macy ((seen & ALL_MODE_EXECS) != ALL_MODE_EXECS || 1037eda14cbcSMatt Macy (mode & ALL_MODE_EXECS) != ALL_MODE_EXECS)) 1038eda14cbcSMatt Macy an_exec_denied = B_TRUE; 1039eda14cbcSMatt Macy 1040eda14cbcSMatt Macy if (an_exec_denied) 1041eda14cbcSMatt Macy *pflags &= ~ZFS_NO_EXECS_DENIED; 1042eda14cbcSMatt Macy else 1043eda14cbcSMatt Macy *pflags |= ZFS_NO_EXECS_DENIED; 1044eda14cbcSMatt Macy 1045eda14cbcSMatt Macy return (mode); 1046eda14cbcSMatt Macy } 1047eda14cbcSMatt Macy 1048eda14cbcSMatt Macy /* 1049eda14cbcSMatt Macy * Read an external acl object. If the intent is to modify, always 1050eda14cbcSMatt Macy * create a new acl and leave any cached acl in place. 1051eda14cbcSMatt Macy */ 1052eda14cbcSMatt Macy int 1053eda14cbcSMatt Macy zfs_acl_node_read(znode_t *zp, boolean_t have_lock, zfs_acl_t **aclpp, 1054eda14cbcSMatt Macy boolean_t will_modify) 1055eda14cbcSMatt Macy { 1056eda14cbcSMatt Macy zfs_acl_t *aclp; 1057eda14cbcSMatt Macy int aclsize; 1058eda14cbcSMatt Macy int acl_count; 1059eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1060eda14cbcSMatt Macy zfs_acl_phys_t znode_acl; 1061eda14cbcSMatt Macy int version; 1062eda14cbcSMatt Macy int error; 1063eda14cbcSMatt Macy 1064eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1065eda14cbcSMatt Macy if (zp->z_zfsvfs->z_replay == B_FALSE) 1066eda14cbcSMatt Macy ASSERT_VOP_LOCKED(ZTOV(zp), __func__); 1067eda14cbcSMatt Macy 1068eda14cbcSMatt Macy if (zp->z_acl_cached && !will_modify) { 1069eda14cbcSMatt Macy *aclpp = zp->z_acl_cached; 1070eda14cbcSMatt Macy return (0); 1071eda14cbcSMatt Macy } 1072eda14cbcSMatt Macy 1073eda14cbcSMatt Macy version = zfs_znode_acl_version(zp); 1074eda14cbcSMatt Macy 1075eda14cbcSMatt Macy if ((error = zfs_acl_znode_info(zp, &aclsize, 1076eda14cbcSMatt Macy &acl_count, &znode_acl)) != 0) { 1077eda14cbcSMatt Macy goto done; 1078eda14cbcSMatt Macy } 1079eda14cbcSMatt Macy 1080eda14cbcSMatt Macy aclp = zfs_acl_alloc(version); 1081eda14cbcSMatt Macy 1082eda14cbcSMatt Macy aclp->z_acl_count = acl_count; 1083eda14cbcSMatt Macy aclp->z_acl_bytes = aclsize; 1084eda14cbcSMatt Macy 1085eda14cbcSMatt Macy aclnode = zfs_acl_node_alloc(aclsize); 1086eda14cbcSMatt Macy aclnode->z_ace_count = aclp->z_acl_count; 1087eda14cbcSMatt Macy aclnode->z_size = aclsize; 1088eda14cbcSMatt Macy 1089eda14cbcSMatt Macy if (!zp->z_is_sa) { 1090eda14cbcSMatt Macy if (znode_acl.z_acl_extern_obj) { 1091eda14cbcSMatt Macy error = dmu_read(zp->z_zfsvfs->z_os, 1092eda14cbcSMatt Macy znode_acl.z_acl_extern_obj, 0, aclnode->z_size, 1093eda14cbcSMatt Macy aclnode->z_acldata, DMU_READ_PREFETCH); 1094eda14cbcSMatt Macy } else { 1095da5137abSMartin Matuska memcpy(aclnode->z_acldata, znode_acl.z_ace_data, 1096eda14cbcSMatt Macy aclnode->z_size); 1097eda14cbcSMatt Macy } 1098eda14cbcSMatt Macy } else { 1099eda14cbcSMatt Macy error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zp->z_zfsvfs), 1100eda14cbcSMatt Macy aclnode->z_acldata, aclnode->z_size); 1101eda14cbcSMatt Macy } 1102eda14cbcSMatt Macy 1103eda14cbcSMatt Macy if (error != 0) { 1104eda14cbcSMatt Macy zfs_acl_free(aclp); 1105eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 1106eda14cbcSMatt Macy /* convert checksum errors into IO errors */ 1107eda14cbcSMatt Macy if (error == ECKSUM) 1108eda14cbcSMatt Macy error = SET_ERROR(EIO); 1109eda14cbcSMatt Macy goto done; 1110eda14cbcSMatt Macy } 1111eda14cbcSMatt Macy 1112eda14cbcSMatt Macy list_insert_head(&aclp->z_acl, aclnode); 1113eda14cbcSMatt Macy 1114eda14cbcSMatt Macy *aclpp = aclp; 1115eda14cbcSMatt Macy if (!will_modify) 1116eda14cbcSMatt Macy zp->z_acl_cached = aclp; 1117eda14cbcSMatt Macy done: 1118eda14cbcSMatt Macy return (error); 1119eda14cbcSMatt Macy } 1120eda14cbcSMatt Macy 1121eda14cbcSMatt Macy void 1122eda14cbcSMatt Macy zfs_acl_data_locator(void **dataptr, uint32_t *length, uint32_t buflen, 1123eda14cbcSMatt Macy boolean_t start, void *userdata) 1124eda14cbcSMatt Macy { 1125c03c5b1cSMartin Matuska (void) buflen; 1126eda14cbcSMatt Macy zfs_acl_locator_cb_t *cb = (zfs_acl_locator_cb_t *)userdata; 1127eda14cbcSMatt Macy 1128eda14cbcSMatt Macy if (start) { 1129eda14cbcSMatt Macy cb->cb_acl_node = list_head(&cb->cb_aclp->z_acl); 1130eda14cbcSMatt Macy } else { 1131eda14cbcSMatt Macy cb->cb_acl_node = list_next(&cb->cb_aclp->z_acl, 1132eda14cbcSMatt Macy cb->cb_acl_node); 1133eda14cbcSMatt Macy } 1134dbd5678dSMartin Matuska ASSERT3P(cb->cb_acl_node, !=, NULL); 1135eda14cbcSMatt Macy *dataptr = cb->cb_acl_node->z_acldata; 1136eda14cbcSMatt Macy *length = cb->cb_acl_node->z_size; 1137eda14cbcSMatt Macy } 1138eda14cbcSMatt Macy 1139eda14cbcSMatt Macy int 1140eda14cbcSMatt Macy zfs_acl_chown_setattr(znode_t *zp) 1141eda14cbcSMatt Macy { 1142eda14cbcSMatt Macy int error; 1143eda14cbcSMatt Macy zfs_acl_t *aclp; 1144eda14cbcSMatt Macy 114559146a69SMateusz Guzik if (zp->z_zfsvfs->z_replay == B_FALSE) { 1146eda14cbcSMatt Macy ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); 1147eda14cbcSMatt Macy ASSERT_VOP_IN_SEQC(ZTOV(zp)); 114859146a69SMateusz Guzik } 114959146a69SMateusz Guzik ASSERT(MUTEX_HELD(&zp->z_acl_lock)); 1150eda14cbcSMatt Macy 1151eda14cbcSMatt Macy if ((error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE)) == 0) 1152eda14cbcSMatt Macy zp->z_mode = zfs_mode_compute(zp->z_mode, aclp, 1153eda14cbcSMatt Macy &zp->z_pflags, zp->z_uid, zp->z_gid); 1154eda14cbcSMatt Macy return (error); 1155eda14cbcSMatt Macy } 1156eda14cbcSMatt Macy 1157eda14cbcSMatt Macy /* 1158eda14cbcSMatt Macy * common code for setting ACLs. 1159eda14cbcSMatt Macy * 1160eda14cbcSMatt Macy * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl. 1161eda14cbcSMatt Macy * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's 1162eda14cbcSMatt Macy * already checked the acl and knows whether to inherit. 1163eda14cbcSMatt Macy */ 1164eda14cbcSMatt Macy int 1165eda14cbcSMatt Macy zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx) 1166eda14cbcSMatt Macy { 1167eda14cbcSMatt Macy int error; 1168eda14cbcSMatt Macy zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1169eda14cbcSMatt Macy dmu_object_type_t otype; 1170eda14cbcSMatt Macy zfs_acl_locator_cb_t locate = { 0 }; 1171eda14cbcSMatt Macy uint64_t mode; 1172eda14cbcSMatt Macy sa_bulk_attr_t bulk[5]; 1173eda14cbcSMatt Macy uint64_t ctime[2]; 1174eda14cbcSMatt Macy int count = 0; 1175eda14cbcSMatt Macy zfs_acl_phys_t acl_phys; 1176eda14cbcSMatt Macy 117759146a69SMateusz Guzik if (zp->z_zfsvfs->z_replay == B_FALSE) { 1178eda14cbcSMatt Macy ASSERT_VOP_IN_SEQC(ZTOV(zp)); 117959146a69SMateusz Guzik } 1180eda14cbcSMatt Macy 1181eda14cbcSMatt Macy mode = zp->z_mode; 1182eda14cbcSMatt Macy 1183eda14cbcSMatt Macy mode = zfs_mode_compute(mode, aclp, &zp->z_pflags, 1184eda14cbcSMatt Macy zp->z_uid, zp->z_gid); 1185eda14cbcSMatt Macy 1186eda14cbcSMatt Macy zp->z_mode = mode; 1187eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, 1188eda14cbcSMatt Macy &mode, sizeof (mode)); 1189eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, 1190eda14cbcSMatt Macy &zp->z_pflags, sizeof (zp->z_pflags)); 1191eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, 1192eda14cbcSMatt Macy &ctime, sizeof (ctime)); 1193eda14cbcSMatt Macy 1194eda14cbcSMatt Macy if (zp->z_acl_cached) { 1195eda14cbcSMatt Macy zfs_acl_free(zp->z_acl_cached); 1196eda14cbcSMatt Macy zp->z_acl_cached = NULL; 1197eda14cbcSMatt Macy } 1198eda14cbcSMatt Macy 1199eda14cbcSMatt Macy /* 1200eda14cbcSMatt Macy * Upgrade needed? 1201eda14cbcSMatt Macy */ 1202eda14cbcSMatt Macy if (!zfsvfs->z_use_fuids) { 1203eda14cbcSMatt Macy otype = DMU_OT_OLDACL; 1204eda14cbcSMatt Macy } else { 1205eda14cbcSMatt Macy if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) && 1206eda14cbcSMatt Macy (zfsvfs->z_version >= ZPL_VERSION_FUID)) 1207eda14cbcSMatt Macy zfs_acl_xform(zp, aclp, cr); 120816038816SMartin Matuska ASSERT3U(aclp->z_version, >=, ZFS_ACL_VERSION_FUID); 1209eda14cbcSMatt Macy otype = DMU_OT_ACL; 1210eda14cbcSMatt Macy } 1211eda14cbcSMatt Macy 1212eda14cbcSMatt Macy /* 1213eda14cbcSMatt Macy * Arrgh, we have to handle old on disk format 1214eda14cbcSMatt Macy * as well as newer (preferred) SA format. 1215eda14cbcSMatt Macy */ 1216eda14cbcSMatt Macy 1217eda14cbcSMatt Macy if (zp->z_is_sa) { /* the easy case, just update the ACL attribute */ 1218eda14cbcSMatt Macy locate.cb_aclp = aclp; 1219eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_ACES(zfsvfs), 1220eda14cbcSMatt Macy zfs_acl_data_locator, &locate, aclp->z_acl_bytes); 1221eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_COUNT(zfsvfs), 1222eda14cbcSMatt Macy NULL, &aclp->z_acl_count, sizeof (uint64_t)); 1223eda14cbcSMatt Macy } else { /* Painful legacy way */ 1224eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1225eda14cbcSMatt Macy uint64_t off = 0; 1226eda14cbcSMatt Macy uint64_t aoid; 1227eda14cbcSMatt Macy 1228eda14cbcSMatt Macy if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), 1229eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys))) != 0) 1230eda14cbcSMatt Macy return (error); 1231eda14cbcSMatt Macy 1232eda14cbcSMatt Macy aoid = acl_phys.z_acl_extern_obj; 1233eda14cbcSMatt Macy 1234eda14cbcSMatt Macy if (aclp->z_acl_bytes > ZFS_ACE_SPACE) { 1235eda14cbcSMatt Macy /* 1236eda14cbcSMatt Macy * If ACL was previously external and we are now 1237eda14cbcSMatt Macy * converting to new ACL format then release old 1238eda14cbcSMatt Macy * ACL object and create a new one. 1239eda14cbcSMatt Macy */ 1240eda14cbcSMatt Macy if (aoid && 1241eda14cbcSMatt Macy aclp->z_version != acl_phys.z_acl_version) { 1242eda14cbcSMatt Macy error = dmu_object_free(zfsvfs->z_os, aoid, tx); 1243eda14cbcSMatt Macy if (error) 1244eda14cbcSMatt Macy return (error); 1245eda14cbcSMatt Macy aoid = 0; 1246eda14cbcSMatt Macy } 1247eda14cbcSMatt Macy if (aoid == 0) { 1248eda14cbcSMatt Macy aoid = dmu_object_alloc(zfsvfs->z_os, 1249eda14cbcSMatt Macy otype, aclp->z_acl_bytes, 1250eda14cbcSMatt Macy otype == DMU_OT_ACL ? 1251eda14cbcSMatt Macy DMU_OT_SYSACL : DMU_OT_NONE, 1252eda14cbcSMatt Macy otype == DMU_OT_ACL ? 1253eda14cbcSMatt Macy DN_OLD_MAX_BONUSLEN : 0, tx); 1254eda14cbcSMatt Macy } else { 1255eda14cbcSMatt Macy (void) dmu_object_set_blocksize(zfsvfs->z_os, 1256eda14cbcSMatt Macy aoid, aclp->z_acl_bytes, 0, tx); 1257eda14cbcSMatt Macy } 1258eda14cbcSMatt Macy acl_phys.z_acl_extern_obj = aoid; 1259eda14cbcSMatt Macy for (aclnode = list_head(&aclp->z_acl); aclnode; 1260eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode)) { 1261eda14cbcSMatt Macy if (aclnode->z_ace_count == 0) 1262eda14cbcSMatt Macy continue; 1263eda14cbcSMatt Macy dmu_write(zfsvfs->z_os, aoid, off, 1264eda14cbcSMatt Macy aclnode->z_size, aclnode->z_acldata, tx); 1265eda14cbcSMatt Macy off += aclnode->z_size; 1266eda14cbcSMatt Macy } 1267eda14cbcSMatt Macy } else { 1268eda14cbcSMatt Macy void *start = acl_phys.z_ace_data; 1269eda14cbcSMatt Macy /* 1270eda14cbcSMatt Macy * Migrating back embedded? 1271eda14cbcSMatt Macy */ 1272eda14cbcSMatt Macy if (acl_phys.z_acl_extern_obj) { 1273eda14cbcSMatt Macy error = dmu_object_free(zfsvfs->z_os, 1274eda14cbcSMatt Macy acl_phys.z_acl_extern_obj, tx); 1275eda14cbcSMatt Macy if (error) 1276eda14cbcSMatt Macy return (error); 1277eda14cbcSMatt Macy acl_phys.z_acl_extern_obj = 0; 1278eda14cbcSMatt Macy } 1279eda14cbcSMatt Macy 1280eda14cbcSMatt Macy for (aclnode = list_head(&aclp->z_acl); aclnode; 1281eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode)) { 1282eda14cbcSMatt Macy if (aclnode->z_ace_count == 0) 1283eda14cbcSMatt Macy continue; 1284da5137abSMartin Matuska memcpy(start, aclnode->z_acldata, 1285eda14cbcSMatt Macy aclnode->z_size); 1286eda14cbcSMatt Macy start = (caddr_t)start + aclnode->z_size; 1287eda14cbcSMatt Macy } 1288eda14cbcSMatt Macy } 1289eda14cbcSMatt Macy /* 1290eda14cbcSMatt Macy * If Old version then swap count/bytes to match old 1291eda14cbcSMatt Macy * layout of znode_acl_phys_t. 1292eda14cbcSMatt Macy */ 1293eda14cbcSMatt Macy if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 1294eda14cbcSMatt Macy acl_phys.z_acl_size = aclp->z_acl_count; 1295eda14cbcSMatt Macy acl_phys.z_acl_count = aclp->z_acl_bytes; 1296eda14cbcSMatt Macy } else { 1297eda14cbcSMatt Macy acl_phys.z_acl_size = aclp->z_acl_bytes; 1298eda14cbcSMatt Macy acl_phys.z_acl_count = aclp->z_acl_count; 1299eda14cbcSMatt Macy } 1300eda14cbcSMatt Macy acl_phys.z_acl_version = aclp->z_version; 1301eda14cbcSMatt Macy 1302eda14cbcSMatt Macy SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL, 1303eda14cbcSMatt Macy &acl_phys, sizeof (acl_phys)); 1304eda14cbcSMatt Macy } 1305eda14cbcSMatt Macy 1306eda14cbcSMatt Macy /* 1307eda14cbcSMatt Macy * Replace ACL wide bits, but first clear them. 1308eda14cbcSMatt Macy */ 1309eda14cbcSMatt Macy zp->z_pflags &= ~ZFS_ACL_WIDE_FLAGS; 1310eda14cbcSMatt Macy 1311eda14cbcSMatt Macy zp->z_pflags |= aclp->z_hints; 1312eda14cbcSMatt Macy 1313eda14cbcSMatt Macy if (ace_trivial_common(aclp, 0, zfs_ace_walk) == 0) 1314eda14cbcSMatt Macy zp->z_pflags |= ZFS_ACL_TRIVIAL; 1315eda14cbcSMatt Macy 1316eda14cbcSMatt Macy zfs_tstamp_update_setup(zp, STATE_CHANGED, NULL, ctime); 1317eda14cbcSMatt Macy return (sa_bulk_update(zp->z_sa_hdl, bulk, count, tx)); 1318eda14cbcSMatt Macy } 1319eda14cbcSMatt Macy 1320eda14cbcSMatt Macy static void 1321eda14cbcSMatt Macy zfs_acl_chmod(vtype_t vtype, uint64_t mode, boolean_t split, boolean_t trim, 1322eda14cbcSMatt Macy zfs_acl_t *aclp) 1323eda14cbcSMatt Macy { 1324eda14cbcSMatt Macy void *acep = NULL; 1325eda14cbcSMatt Macy uint64_t who; 1326eda14cbcSMatt Macy int new_count, new_bytes; 1327eda14cbcSMatt Macy int ace_size; 1328eda14cbcSMatt Macy int entry_type; 1329eda14cbcSMatt Macy uint16_t iflags, type; 1330eda14cbcSMatt Macy uint32_t access_mask; 1331eda14cbcSMatt Macy zfs_acl_node_t *newnode; 1332eda14cbcSMatt Macy size_t abstract_size = aclp->z_ops->ace_abstract_size(); 1333eda14cbcSMatt Macy void *zacep; 1334eda14cbcSMatt Macy boolean_t isdir; 1335eda14cbcSMatt Macy trivial_acl_t masks; 1336eda14cbcSMatt Macy 1337eda14cbcSMatt Macy new_count = new_bytes = 0; 1338eda14cbcSMatt Macy 1339eda14cbcSMatt Macy isdir = (vtype == VDIR); 1340eda14cbcSMatt Macy 1341eda14cbcSMatt Macy acl_trivial_access_masks((mode_t)mode, isdir, &masks); 1342eda14cbcSMatt Macy 1343eda14cbcSMatt Macy newnode = zfs_acl_node_alloc((abstract_size * 6) + aclp->z_acl_bytes); 1344eda14cbcSMatt Macy 1345eda14cbcSMatt Macy zacep = newnode->z_acldata; 1346eda14cbcSMatt Macy if (masks.allow0) { 1347eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.allow0, ALLOW, -1, ACE_OWNER); 1348eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1349eda14cbcSMatt Macy new_count++; 1350eda14cbcSMatt Macy new_bytes += abstract_size; 1351eda14cbcSMatt Macy } 1352eda14cbcSMatt Macy if (masks.deny1) { 1353eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.deny1, DENY, -1, ACE_OWNER); 1354eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1355eda14cbcSMatt Macy new_count++; 1356eda14cbcSMatt Macy new_bytes += abstract_size; 1357eda14cbcSMatt Macy } 1358eda14cbcSMatt Macy if (masks.deny2) { 1359eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.deny2, DENY, -1, OWNING_GROUP); 1360eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1361eda14cbcSMatt Macy new_count++; 1362eda14cbcSMatt Macy new_bytes += abstract_size; 1363eda14cbcSMatt Macy } 1364eda14cbcSMatt Macy 1365eda14cbcSMatt Macy while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 1366eda14cbcSMatt Macy &iflags, &type))) { 1367eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 1368eda14cbcSMatt Macy /* 1369eda14cbcSMatt Macy * ACEs used to represent the file mode may be divided 1370eda14cbcSMatt Macy * into an equivalent pair of inherit-only and regular 1371eda14cbcSMatt Macy * ACEs, if they are inheritable. 1372eda14cbcSMatt Macy * Skip regular ACEs, which are replaced by the new mode. 1373eda14cbcSMatt Macy */ 1374eda14cbcSMatt Macy if (split && (entry_type == ACE_OWNER || 1375eda14cbcSMatt Macy entry_type == OWNING_GROUP || 1376eda14cbcSMatt Macy entry_type == ACE_EVERYONE)) { 1377eda14cbcSMatt Macy if (!isdir || !(iflags & 1378eda14cbcSMatt Macy (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 1379eda14cbcSMatt Macy continue; 1380eda14cbcSMatt Macy /* 1381eda14cbcSMatt Macy * We preserve owner@, group@, or @everyone 1382eda14cbcSMatt Macy * permissions, if they are inheritable, by 1383eda14cbcSMatt Macy * copying them to inherit_only ACEs. This 1384eda14cbcSMatt Macy * prevents inheritable permissions from being 1385eda14cbcSMatt Macy * altered along with the file mode. 1386eda14cbcSMatt Macy */ 1387eda14cbcSMatt Macy iflags |= ACE_INHERIT_ONLY_ACE; 1388eda14cbcSMatt Macy } 1389eda14cbcSMatt Macy 1390eda14cbcSMatt Macy /* 1391eda14cbcSMatt Macy * If this ACL has any inheritable ACEs, mark that in 1392eda14cbcSMatt Macy * the hints (which are later masked into the pflags) 1393eda14cbcSMatt Macy * so create knows to do inheritance. 1394eda14cbcSMatt Macy */ 1395eda14cbcSMatt Macy if (isdir && (iflags & 1396eda14cbcSMatt Macy (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))) 1397eda14cbcSMatt Macy aclp->z_hints |= ZFS_INHERIT_ACE; 1398eda14cbcSMatt Macy 1399eda14cbcSMatt Macy if ((type != ALLOW && type != DENY) || 1400eda14cbcSMatt Macy (iflags & ACE_INHERIT_ONLY_ACE)) { 1401eda14cbcSMatt Macy switch (type) { 1402eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1403eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1404eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1405eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1406eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_OBJ_ACE; 1407eda14cbcSMatt Macy break; 1408eda14cbcSMatt Macy } 1409eda14cbcSMatt Macy } else { 1410eda14cbcSMatt Macy /* 1411eda14cbcSMatt Macy * Limit permissions granted by ACEs to be no greater 1412eda14cbcSMatt Macy * than permissions of the requested group mode. 1413eda14cbcSMatt Macy * Applies when the "aclmode" property is set to 1414eda14cbcSMatt Macy * "groupmask". 1415eda14cbcSMatt Macy */ 1416eda14cbcSMatt Macy if ((type == ALLOW) && trim) 1417eda14cbcSMatt Macy access_mask &= masks.group; 1418eda14cbcSMatt Macy } 1419eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, access_mask, type, who, iflags); 1420eda14cbcSMatt Macy ace_size = aclp->z_ops->ace_size(acep); 1421eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + ace_size); 1422eda14cbcSMatt Macy new_count++; 1423eda14cbcSMatt Macy new_bytes += ace_size; 1424eda14cbcSMatt Macy } 1425eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.owner, ALLOW, -1, ACE_OWNER); 1426eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1427eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.group, ALLOW, -1, OWNING_GROUP); 1428eda14cbcSMatt Macy zacep = (void *)((uintptr_t)zacep + abstract_size); 1429eda14cbcSMatt Macy zfs_set_ace(aclp, zacep, masks.everyone, ALLOW, -1, ACE_EVERYONE); 1430eda14cbcSMatt Macy 1431eda14cbcSMatt Macy new_count += 3; 1432eda14cbcSMatt Macy new_bytes += abstract_size * 3; 1433eda14cbcSMatt Macy zfs_acl_release_nodes(aclp); 1434eda14cbcSMatt Macy aclp->z_acl_count = new_count; 1435eda14cbcSMatt Macy aclp->z_acl_bytes = new_bytes; 1436eda14cbcSMatt Macy newnode->z_ace_count = new_count; 1437eda14cbcSMatt Macy newnode->z_size = new_bytes; 1438eda14cbcSMatt Macy list_insert_tail(&aclp->z_acl, newnode); 1439eda14cbcSMatt Macy } 1440eda14cbcSMatt Macy 1441eda14cbcSMatt Macy int 1442eda14cbcSMatt Macy zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode) 1443eda14cbcSMatt Macy { 1444eda14cbcSMatt Macy int error = 0; 1445eda14cbcSMatt Macy 1446eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 1447eda14cbcSMatt Macy if (zp->z_zfsvfs->z_replay == B_FALSE) 1448eda14cbcSMatt Macy ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); 1449eda14cbcSMatt Macy if (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_DISCARD) 1450eda14cbcSMatt Macy *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp)); 1451eda14cbcSMatt Macy else 1452eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_TRUE, aclp, B_TRUE); 1453eda14cbcSMatt Macy 1454eda14cbcSMatt Macy if (error == 0) { 1455eda14cbcSMatt Macy (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS; 1456eda14cbcSMatt Macy zfs_acl_chmod(ZTOV(zp)->v_type, mode, B_TRUE, 1457eda14cbcSMatt Macy (zp->z_zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK), *aclp); 1458eda14cbcSMatt Macy } 1459eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 1460eda14cbcSMatt Macy 1461eda14cbcSMatt Macy return (error); 1462eda14cbcSMatt Macy } 1463eda14cbcSMatt Macy 1464eda14cbcSMatt Macy /* 1465eda14cbcSMatt Macy * Should ACE be inherited? 1466eda14cbcSMatt Macy */ 1467eda14cbcSMatt Macy static int 1468eda14cbcSMatt Macy zfs_ace_can_use(vtype_t vtype, uint16_t acep_flags) 1469eda14cbcSMatt Macy { 1470eda14cbcSMatt Macy int iflags = (acep_flags & 0xf); 1471eda14cbcSMatt Macy 1472eda14cbcSMatt Macy if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE)) 1473eda14cbcSMatt Macy return (1); 1474eda14cbcSMatt Macy else if (iflags & ACE_FILE_INHERIT_ACE) 1475eda14cbcSMatt Macy return (!((vtype == VDIR) && 1476eda14cbcSMatt Macy (iflags & ACE_NO_PROPAGATE_INHERIT_ACE))); 1477eda14cbcSMatt Macy return (0); 1478eda14cbcSMatt Macy } 1479eda14cbcSMatt Macy 1480eda14cbcSMatt Macy /* 1481eda14cbcSMatt Macy * inherit inheritable ACEs from parent 1482eda14cbcSMatt Macy */ 1483eda14cbcSMatt Macy static zfs_acl_t * 1484eda14cbcSMatt Macy zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp, 1485eda14cbcSMatt Macy uint64_t mode, boolean_t *need_chmod) 1486eda14cbcSMatt Macy { 1487eda14cbcSMatt Macy void *pacep = NULL; 1488eda14cbcSMatt Macy void *acep; 1489eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1490eda14cbcSMatt Macy zfs_acl_t *aclp = NULL; 1491eda14cbcSMatt Macy uint64_t who; 1492eda14cbcSMatt Macy uint32_t access_mask; 1493eda14cbcSMatt Macy uint16_t iflags, newflags, type; 1494eda14cbcSMatt Macy size_t ace_size; 1495eda14cbcSMatt Macy void *data1, *data2; 1496eda14cbcSMatt Macy size_t data1sz, data2sz; 1497eda14cbcSMatt Macy uint_t aclinherit; 1498eda14cbcSMatt Macy boolean_t isdir = (vtype == VDIR); 1499eda14cbcSMatt Macy boolean_t isreg = (vtype == VREG); 1500eda14cbcSMatt Macy 1501eda14cbcSMatt Macy *need_chmod = B_TRUE; 1502eda14cbcSMatt Macy 1503eda14cbcSMatt Macy aclp = zfs_acl_alloc(paclp->z_version); 1504eda14cbcSMatt Macy aclinherit = zfsvfs->z_acl_inherit; 1505eda14cbcSMatt Macy if (aclinherit == ZFS_ACL_DISCARD || vtype == VLNK) 1506eda14cbcSMatt Macy return (aclp); 1507eda14cbcSMatt Macy 1508eda14cbcSMatt Macy while ((pacep = zfs_acl_next_ace(paclp, pacep, &who, 1509eda14cbcSMatt Macy &access_mask, &iflags, &type))) { 1510eda14cbcSMatt Macy 1511eda14cbcSMatt Macy /* 1512eda14cbcSMatt Macy * don't inherit bogus ACEs 1513eda14cbcSMatt Macy */ 1514eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 1515eda14cbcSMatt Macy continue; 1516eda14cbcSMatt Macy 1517eda14cbcSMatt Macy /* 1518eda14cbcSMatt Macy * Check if ACE is inheritable by this vnode 1519eda14cbcSMatt Macy */ 1520eda14cbcSMatt Macy if ((aclinherit == ZFS_ACL_NOALLOW && type == ALLOW) || 1521eda14cbcSMatt Macy !zfs_ace_can_use(vtype, iflags)) 1522eda14cbcSMatt Macy continue; 1523eda14cbcSMatt Macy 1524eda14cbcSMatt Macy /* 1525eda14cbcSMatt Macy * If owner@, group@, or everyone@ inheritable 1526eda14cbcSMatt Macy * then zfs_acl_chmod() isn't needed. 1527eda14cbcSMatt Macy */ 1528eda14cbcSMatt Macy if ((aclinherit == ZFS_ACL_PASSTHROUGH || 1529eda14cbcSMatt Macy aclinherit == ZFS_ACL_PASSTHROUGH_X) && 1530eda14cbcSMatt Macy ((iflags & (ACE_OWNER|ACE_EVERYONE)) || 1531eda14cbcSMatt Macy ((iflags & OWNING_GROUP) == OWNING_GROUP)) && 1532eda14cbcSMatt Macy (isreg || (isdir && (iflags & ACE_DIRECTORY_INHERIT_ACE)))) 1533eda14cbcSMatt Macy *need_chmod = B_FALSE; 1534eda14cbcSMatt Macy 1535eda14cbcSMatt Macy /* 1536eda14cbcSMatt Macy * Strip inherited execute permission from file if 1537eda14cbcSMatt Macy * not in mode 1538eda14cbcSMatt Macy */ 1539eda14cbcSMatt Macy if (aclinherit == ZFS_ACL_PASSTHROUGH_X && type == ALLOW && 1540eda14cbcSMatt Macy !isdir && ((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)) { 1541eda14cbcSMatt Macy access_mask &= ~ACE_EXECUTE; 1542eda14cbcSMatt Macy } 1543eda14cbcSMatt Macy 1544eda14cbcSMatt Macy /* 1545eda14cbcSMatt Macy * Strip write_acl and write_owner from permissions 1546eda14cbcSMatt Macy * when inheriting an ACE 1547eda14cbcSMatt Macy */ 1548eda14cbcSMatt Macy if (aclinherit == ZFS_ACL_RESTRICTED && type == ALLOW) { 1549eda14cbcSMatt Macy access_mask &= ~RESTRICTED_CLEAR; 1550eda14cbcSMatt Macy } 1551eda14cbcSMatt Macy 1552eda14cbcSMatt Macy ace_size = aclp->z_ops->ace_size(pacep); 1553eda14cbcSMatt Macy aclnode = zfs_acl_node_alloc(ace_size); 1554eda14cbcSMatt Macy list_insert_tail(&aclp->z_acl, aclnode); 1555eda14cbcSMatt Macy acep = aclnode->z_acldata; 1556eda14cbcSMatt Macy 1557eda14cbcSMatt Macy zfs_set_ace(aclp, acep, access_mask, type, 1558eda14cbcSMatt Macy who, iflags|ACE_INHERITED_ACE); 1559eda14cbcSMatt Macy 1560eda14cbcSMatt Macy /* 1561eda14cbcSMatt Macy * Copy special opaque data if any 1562eda14cbcSMatt Macy */ 1563eda14cbcSMatt Macy if ((data1sz = paclp->z_ops->ace_data(pacep, &data1)) != 0) { 156416038816SMartin Matuska data2sz = aclp->z_ops->ace_data(acep, &data2); 156516038816SMartin Matuska VERIFY3U(data2sz, ==, data1sz); 1566da5137abSMartin Matuska memcpy(data2, data1, data2sz); 1567eda14cbcSMatt Macy } 1568eda14cbcSMatt Macy 1569eda14cbcSMatt Macy aclp->z_acl_count++; 1570eda14cbcSMatt Macy aclnode->z_ace_count++; 1571eda14cbcSMatt Macy aclp->z_acl_bytes += aclnode->z_size; 1572eda14cbcSMatt Macy newflags = aclp->z_ops->ace_flags_get(acep); 1573eda14cbcSMatt Macy 1574eda14cbcSMatt Macy /* 1575eda14cbcSMatt Macy * If ACE is not to be inherited further, or if the vnode is 1576eda14cbcSMatt Macy * not a directory, remove all inheritance flags 1577eda14cbcSMatt Macy */ 1578eda14cbcSMatt Macy if (!isdir || (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)) { 1579eda14cbcSMatt Macy newflags &= ~ALL_INHERIT; 1580eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, 1581eda14cbcSMatt Macy newflags|ACE_INHERITED_ACE); 1582eda14cbcSMatt Macy continue; 1583eda14cbcSMatt Macy } 1584eda14cbcSMatt Macy 1585eda14cbcSMatt Macy /* 1586eda14cbcSMatt Macy * This directory has an inheritable ACE 1587eda14cbcSMatt Macy */ 1588eda14cbcSMatt Macy aclp->z_hints |= ZFS_INHERIT_ACE; 1589eda14cbcSMatt Macy 1590eda14cbcSMatt Macy /* 1591eda14cbcSMatt Macy * If only FILE_INHERIT is set then turn on 1592eda14cbcSMatt Macy * inherit_only 1593eda14cbcSMatt Macy */ 1594eda14cbcSMatt Macy if ((iflags & (ACE_FILE_INHERIT_ACE | 1595eda14cbcSMatt Macy ACE_DIRECTORY_INHERIT_ACE)) == ACE_FILE_INHERIT_ACE) { 1596eda14cbcSMatt Macy newflags |= ACE_INHERIT_ONLY_ACE; 1597eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, 1598eda14cbcSMatt Macy newflags|ACE_INHERITED_ACE); 1599eda14cbcSMatt Macy } else { 1600eda14cbcSMatt Macy newflags &= ~ACE_INHERIT_ONLY_ACE; 1601eda14cbcSMatt Macy aclp->z_ops->ace_flags_set(acep, 1602eda14cbcSMatt Macy newflags|ACE_INHERITED_ACE); 1603eda14cbcSMatt Macy } 1604eda14cbcSMatt Macy } 1605eda14cbcSMatt Macy if (zfsvfs->z_acl_mode == ZFS_ACL_RESTRICTED && 1606eda14cbcSMatt Macy aclp->z_acl_count != 0) { 1607eda14cbcSMatt Macy *need_chmod = B_FALSE; 1608eda14cbcSMatt Macy } 1609eda14cbcSMatt Macy 1610eda14cbcSMatt Macy return (aclp); 1611eda14cbcSMatt Macy } 1612eda14cbcSMatt Macy 1613eda14cbcSMatt Macy /* 1614eda14cbcSMatt Macy * Create file system object initial permissions 1615eda14cbcSMatt Macy * including inheritable ACEs. 1616eda14cbcSMatt Macy * Also, create FUIDs for owner and group. 1617eda14cbcSMatt Macy */ 1618eda14cbcSMatt Macy int 1619eda14cbcSMatt Macy zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, 1620d411c1d6SMartin Matuska vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zidmap_t *mnt_ns) 1621eda14cbcSMatt Macy { 1622eda14cbcSMatt Macy int error; 1623eda14cbcSMatt Macy zfsvfs_t *zfsvfs = dzp->z_zfsvfs; 1624eda14cbcSMatt Macy zfs_acl_t *paclp; 1625eda14cbcSMatt Macy gid_t gid; 1626eda14cbcSMatt Macy boolean_t need_chmod = B_TRUE; 1627eda14cbcSMatt Macy boolean_t trim = B_FALSE; 1628eda14cbcSMatt Macy boolean_t inherited = B_FALSE; 1629eda14cbcSMatt Macy 1630eda14cbcSMatt Macy if ((flag & IS_ROOT_NODE) == 0) { 1631eda14cbcSMatt Macy if (zfsvfs->z_replay == B_FALSE) 1632eda14cbcSMatt Macy ASSERT_VOP_ELOCKED(ZTOV(dzp), __func__); 1633eda14cbcSMatt Macy } else 163416038816SMartin Matuska ASSERT3P(dzp->z_vnode, ==, NULL); 1635da5137abSMartin Matuska memset(acl_ids, 0, sizeof (zfs_acl_ids_t)); 1636eda14cbcSMatt Macy acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1637eda14cbcSMatt Macy 1638eda14cbcSMatt Macy if (vsecp) 1639eda14cbcSMatt Macy if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr, 1640eda14cbcSMatt Macy &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0) 1641eda14cbcSMatt Macy return (error); 1642eda14cbcSMatt Macy /* 1643eda14cbcSMatt Macy * Determine uid and gid. 1644eda14cbcSMatt Macy */ 1645eda14cbcSMatt Macy if ((flag & IS_ROOT_NODE) || zfsvfs->z_replay || 1646eda14cbcSMatt Macy ((flag & IS_XATTR) && (vap->va_type == VDIR))) { 1647eda14cbcSMatt Macy acl_ids->z_fuid = zfs_fuid_create(zfsvfs, 1648eda14cbcSMatt Macy (uint64_t)vap->va_uid, cr, 1649eda14cbcSMatt Macy ZFS_OWNER, &acl_ids->z_fuidp); 1650eda14cbcSMatt Macy acl_ids->z_fgid = zfs_fuid_create(zfsvfs, 1651eda14cbcSMatt Macy (uint64_t)vap->va_gid, cr, 1652eda14cbcSMatt Macy ZFS_GROUP, &acl_ids->z_fuidp); 1653eda14cbcSMatt Macy gid = vap->va_gid; 1654eda14cbcSMatt Macy } else { 1655da5137abSMartin Matuska uid_t id = crgetuid(cr); 1656da5137abSMartin Matuska if (IS_EPHEMERAL(id)) 1657da5137abSMartin Matuska id = UID_NOBODY; 1658da5137abSMartin Matuska acl_ids->z_fuid = (uint64_t)id; 1659eda14cbcSMatt Macy acl_ids->z_fgid = 0; 1660eda14cbcSMatt Macy if (vap->va_mask & AT_GID) { 1661eda14cbcSMatt Macy acl_ids->z_fgid = zfs_fuid_create(zfsvfs, 1662eda14cbcSMatt Macy (uint64_t)vap->va_gid, 1663eda14cbcSMatt Macy cr, ZFS_GROUP, &acl_ids->z_fuidp); 1664eda14cbcSMatt Macy gid = vap->va_gid; 1665eda14cbcSMatt Macy if (acl_ids->z_fgid != dzp->z_gid && 1666eda14cbcSMatt Macy !groupmember(vap->va_gid, cr) && 1667eda14cbcSMatt Macy secpolicy_vnode_create_gid(cr) != 0) 1668eda14cbcSMatt Macy acl_ids->z_fgid = 0; 1669eda14cbcSMatt Macy } 1670eda14cbcSMatt Macy if (acl_ids->z_fgid == 0) { 1671a0b956f5SMartin Matuska const char *domain; 1672eda14cbcSMatt Macy uint32_t rid; 1673eda14cbcSMatt Macy 1674eda14cbcSMatt Macy acl_ids->z_fgid = dzp->z_gid; 1675eda14cbcSMatt Macy gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid, 1676eda14cbcSMatt Macy cr, ZFS_GROUP); 1677eda14cbcSMatt Macy 1678eda14cbcSMatt Macy if (zfsvfs->z_use_fuids && 1679eda14cbcSMatt Macy IS_EPHEMERAL(acl_ids->z_fgid)) { 1680eda14cbcSMatt Macy domain = 1681eda14cbcSMatt Macy zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, 1682eda14cbcSMatt Macy FUID_INDEX(acl_ids->z_fgid)); 1683eda14cbcSMatt Macy rid = FUID_RID(acl_ids->z_fgid); 1684eda14cbcSMatt Macy zfs_fuid_node_add(&acl_ids->z_fuidp, 1685eda14cbcSMatt Macy domain, rid, FUID_INDEX(acl_ids->z_fgid), 1686eda14cbcSMatt Macy acl_ids->z_fgid, ZFS_GROUP); 1687eda14cbcSMatt Macy } 1688eda14cbcSMatt Macy } 1689eda14cbcSMatt Macy } 1690eda14cbcSMatt Macy 1691eda14cbcSMatt Macy /* 1692eda14cbcSMatt Macy * If we're creating a directory, and the parent directory has the 1693eda14cbcSMatt Macy * set-GID bit set, set in on the new directory. 1694eda14cbcSMatt Macy * Otherwise, if the user is neither privileged nor a member of the 1695eda14cbcSMatt Macy * file's new group, clear the file's set-GID bit. 1696eda14cbcSMatt Macy */ 1697eda14cbcSMatt Macy 1698eda14cbcSMatt Macy if (!(flag & IS_ROOT_NODE) && (dzp->z_mode & S_ISGID) && 1699eda14cbcSMatt Macy (vap->va_type == VDIR)) { 1700eda14cbcSMatt Macy acl_ids->z_mode |= S_ISGID; 1701eda14cbcSMatt Macy } else { 1702eda14cbcSMatt Macy if ((acl_ids->z_mode & S_ISGID) && 1703eda14cbcSMatt Macy secpolicy_vnode_setids_setgids(ZTOV(dzp), cr, gid) != 0) 1704eda14cbcSMatt Macy acl_ids->z_mode &= ~S_ISGID; 1705eda14cbcSMatt Macy } 1706eda14cbcSMatt Macy 1707eda14cbcSMatt Macy if (acl_ids->z_aclp == NULL) { 1708eda14cbcSMatt Macy mutex_enter(&dzp->z_acl_lock); 1709eda14cbcSMatt Macy if (!(flag & IS_ROOT_NODE) && 1710eda14cbcSMatt Macy (dzp->z_pflags & ZFS_INHERIT_ACE) && 1711eda14cbcSMatt Macy !(dzp->z_pflags & ZFS_XATTR)) { 1712eda14cbcSMatt Macy VERIFY0(zfs_acl_node_read(dzp, B_TRUE, 1713eda14cbcSMatt Macy &paclp, B_FALSE)); 1714eda14cbcSMatt Macy acl_ids->z_aclp = zfs_acl_inherit(zfsvfs, 1715eda14cbcSMatt Macy vap->va_type, paclp, acl_ids->z_mode, &need_chmod); 1716eda14cbcSMatt Macy inherited = B_TRUE; 1717eda14cbcSMatt Macy } else { 1718eda14cbcSMatt Macy acl_ids->z_aclp = 1719eda14cbcSMatt Macy zfs_acl_alloc(zfs_acl_version_zp(dzp)); 1720eda14cbcSMatt Macy acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; 1721eda14cbcSMatt Macy } 1722eda14cbcSMatt Macy mutex_exit(&dzp->z_acl_lock); 1723eda14cbcSMatt Macy 1724eda14cbcSMatt Macy if (need_chmod) { 1725eda14cbcSMatt Macy if (vap->va_type == VDIR) 1726eda14cbcSMatt Macy acl_ids->z_aclp->z_hints |= 1727eda14cbcSMatt Macy ZFS_ACL_AUTO_INHERIT; 1728eda14cbcSMatt Macy 1729eda14cbcSMatt Macy if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK && 1730eda14cbcSMatt Macy zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH && 1731eda14cbcSMatt Macy zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X) 1732eda14cbcSMatt Macy trim = B_TRUE; 1733eda14cbcSMatt Macy zfs_acl_chmod(vap->va_type, acl_ids->z_mode, B_FALSE, 1734eda14cbcSMatt Macy trim, acl_ids->z_aclp); 1735eda14cbcSMatt Macy } 1736eda14cbcSMatt Macy } 1737eda14cbcSMatt Macy 1738eda14cbcSMatt Macy if (inherited || vsecp) { 1739eda14cbcSMatt Macy acl_ids->z_mode = zfs_mode_compute(acl_ids->z_mode, 1740eda14cbcSMatt Macy acl_ids->z_aclp, &acl_ids->z_aclp->z_hints, 1741eda14cbcSMatt Macy acl_ids->z_fuid, acl_ids->z_fgid); 1742eda14cbcSMatt Macy if (ace_trivial_common(acl_ids->z_aclp, 0, zfs_ace_walk) == 0) 1743eda14cbcSMatt Macy acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL; 1744eda14cbcSMatt Macy } 1745eda14cbcSMatt Macy 1746eda14cbcSMatt Macy return (0); 1747eda14cbcSMatt Macy } 1748eda14cbcSMatt Macy 1749eda14cbcSMatt Macy /* 1750eda14cbcSMatt Macy * Free ACL and fuid_infop, but not the acl_ids structure 1751eda14cbcSMatt Macy */ 1752eda14cbcSMatt Macy void 1753eda14cbcSMatt Macy zfs_acl_ids_free(zfs_acl_ids_t *acl_ids) 1754eda14cbcSMatt Macy { 1755eda14cbcSMatt Macy if (acl_ids->z_aclp) 1756eda14cbcSMatt Macy zfs_acl_free(acl_ids->z_aclp); 1757eda14cbcSMatt Macy if (acl_ids->z_fuidp) 1758eda14cbcSMatt Macy zfs_fuid_info_free(acl_ids->z_fuidp); 1759eda14cbcSMatt Macy acl_ids->z_aclp = NULL; 1760eda14cbcSMatt Macy acl_ids->z_fuidp = NULL; 1761eda14cbcSMatt Macy } 1762eda14cbcSMatt Macy 1763eda14cbcSMatt Macy boolean_t 1764eda14cbcSMatt Macy zfs_acl_ids_overquota(zfsvfs_t *zv, zfs_acl_ids_t *acl_ids, uint64_t projid) 1765eda14cbcSMatt Macy { 1766eda14cbcSMatt Macy return (zfs_id_overquota(zv, DMU_USERUSED_OBJECT, acl_ids->z_fuid) || 1767eda14cbcSMatt Macy zfs_id_overquota(zv, DMU_GROUPUSED_OBJECT, acl_ids->z_fgid) || 1768eda14cbcSMatt Macy (projid != ZFS_DEFAULT_PROJID && projid != ZFS_INVALID_PROJID && 1769eda14cbcSMatt Macy zfs_id_overquota(zv, DMU_PROJECTUSED_OBJECT, projid))); 1770eda14cbcSMatt Macy } 1771eda14cbcSMatt Macy 1772eda14cbcSMatt Macy /* 1773eda14cbcSMatt Macy * Retrieve a file's ACL 1774eda14cbcSMatt Macy */ 1775eda14cbcSMatt Macy int 1776eda14cbcSMatt Macy zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1777eda14cbcSMatt Macy { 1778eda14cbcSMatt Macy zfs_acl_t *aclp; 1779eda14cbcSMatt Macy ulong_t mask; 1780eda14cbcSMatt Macy int error; 1781eda14cbcSMatt Macy int count = 0; 1782eda14cbcSMatt Macy int largeace = 0; 1783eda14cbcSMatt Macy 1784eda14cbcSMatt Macy mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT | 1785eda14cbcSMatt Macy VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 1786eda14cbcSMatt Macy 1787eda14cbcSMatt Macy if (mask == 0) 1788eda14cbcSMatt Macy return (SET_ERROR(ENOSYS)); 1789eda14cbcSMatt Macy 1790dbd5678dSMartin Matuska if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) 1791eda14cbcSMatt Macy return (error); 1792eda14cbcSMatt Macy 1793eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 1794eda14cbcSMatt Macy 1795eda14cbcSMatt Macy if (zp->z_zfsvfs->z_replay == B_FALSE) 1796eda14cbcSMatt Macy ASSERT_VOP_LOCKED(ZTOV(zp), __func__); 1797eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE); 1798eda14cbcSMatt Macy if (error != 0) { 1799eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 1800eda14cbcSMatt Macy return (error); 1801eda14cbcSMatt Macy } 1802eda14cbcSMatt Macy 1803eda14cbcSMatt Macy /* 1804eda14cbcSMatt Macy * Scan ACL to determine number of ACEs 1805eda14cbcSMatt Macy */ 1806eda14cbcSMatt Macy if ((zp->z_pflags & ZFS_ACL_OBJ_ACE) && !(mask & VSA_ACE_ALLTYPES)) { 1807eda14cbcSMatt Macy void *zacep = NULL; 1808eda14cbcSMatt Macy uint64_t who; 1809eda14cbcSMatt Macy uint32_t access_mask; 1810eda14cbcSMatt Macy uint16_t type, iflags; 1811eda14cbcSMatt Macy 1812eda14cbcSMatt Macy while ((zacep = zfs_acl_next_ace(aclp, zacep, 1813eda14cbcSMatt Macy &who, &access_mask, &iflags, &type))) { 1814eda14cbcSMatt Macy switch (type) { 1815eda14cbcSMatt Macy case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE: 1816eda14cbcSMatt Macy case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE: 1817eda14cbcSMatt Macy case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE: 1818eda14cbcSMatt Macy case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE: 1819eda14cbcSMatt Macy largeace++; 1820eda14cbcSMatt Macy continue; 1821eda14cbcSMatt Macy default: 1822eda14cbcSMatt Macy count++; 1823eda14cbcSMatt Macy } 1824eda14cbcSMatt Macy } 1825eda14cbcSMatt Macy vsecp->vsa_aclcnt = count; 1826eda14cbcSMatt Macy } else 1827eda14cbcSMatt Macy count = (int)aclp->z_acl_count; 1828eda14cbcSMatt Macy 1829eda14cbcSMatt Macy if (mask & VSA_ACECNT) { 1830eda14cbcSMatt Macy vsecp->vsa_aclcnt = count; 1831eda14cbcSMatt Macy } 1832eda14cbcSMatt Macy 1833eda14cbcSMatt Macy if (mask & VSA_ACE) { 1834eda14cbcSMatt Macy size_t aclsz; 1835eda14cbcSMatt Macy 1836eda14cbcSMatt Macy aclsz = count * sizeof (ace_t) + 1837eda14cbcSMatt Macy sizeof (ace_object_t) * largeace; 1838eda14cbcSMatt Macy 1839eda14cbcSMatt Macy vsecp->vsa_aclentp = kmem_alloc(aclsz, KM_SLEEP); 1840eda14cbcSMatt Macy vsecp->vsa_aclentsz = aclsz; 1841eda14cbcSMatt Macy 1842eda14cbcSMatt Macy if (aclp->z_version == ZFS_ACL_VERSION_FUID) 1843eda14cbcSMatt Macy zfs_copy_fuid_2_ace(zp->z_zfsvfs, aclp, cr, 1844eda14cbcSMatt Macy vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES)); 1845eda14cbcSMatt Macy else { 1846eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1847eda14cbcSMatt Macy void *start = vsecp->vsa_aclentp; 1848eda14cbcSMatt Macy 1849eda14cbcSMatt Macy for (aclnode = list_head(&aclp->z_acl); aclnode; 1850eda14cbcSMatt Macy aclnode = list_next(&aclp->z_acl, aclnode)) { 1851da5137abSMartin Matuska memcpy(start, aclnode->z_acldata, 1852eda14cbcSMatt Macy aclnode->z_size); 1853eda14cbcSMatt Macy start = (caddr_t)start + aclnode->z_size; 1854eda14cbcSMatt Macy } 185516038816SMartin Matuska ASSERT3U((caddr_t)start - (caddr_t)vsecp->vsa_aclentp, 185616038816SMartin Matuska ==, aclp->z_acl_bytes); 1857eda14cbcSMatt Macy } 1858eda14cbcSMatt Macy } 1859eda14cbcSMatt Macy if (mask & VSA_ACE_ACLFLAGS) { 1860eda14cbcSMatt Macy vsecp->vsa_aclflags = 0; 1861eda14cbcSMatt Macy if (zp->z_pflags & ZFS_ACL_DEFAULTED) 1862eda14cbcSMatt Macy vsecp->vsa_aclflags |= ACL_DEFAULTED; 1863eda14cbcSMatt Macy if (zp->z_pflags & ZFS_ACL_PROTECTED) 1864eda14cbcSMatt Macy vsecp->vsa_aclflags |= ACL_PROTECTED; 1865eda14cbcSMatt Macy if (zp->z_pflags & ZFS_ACL_AUTO_INHERIT) 1866eda14cbcSMatt Macy vsecp->vsa_aclflags |= ACL_AUTO_INHERIT; 1867eda14cbcSMatt Macy } 1868eda14cbcSMatt Macy 1869eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 1870eda14cbcSMatt Macy 1871eda14cbcSMatt Macy return (0); 1872eda14cbcSMatt Macy } 1873eda14cbcSMatt Macy 1874eda14cbcSMatt Macy int 1875eda14cbcSMatt Macy zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, umode_t obj_type, 1876eda14cbcSMatt Macy vsecattr_t *vsecp, cred_t *cr, zfs_fuid_info_t **fuidp, zfs_acl_t **zaclp) 1877eda14cbcSMatt Macy { 1878eda14cbcSMatt Macy zfs_acl_t *aclp; 1879eda14cbcSMatt Macy zfs_acl_node_t *aclnode; 1880eda14cbcSMatt Macy int aclcnt = vsecp->vsa_aclcnt; 1881eda14cbcSMatt Macy int error; 1882eda14cbcSMatt Macy 1883eda14cbcSMatt Macy if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0) 1884eda14cbcSMatt Macy return (SET_ERROR(EINVAL)); 1885eda14cbcSMatt Macy 1886eda14cbcSMatt Macy aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version)); 1887eda14cbcSMatt Macy 1888eda14cbcSMatt Macy aclp->z_hints = 0; 1889eda14cbcSMatt Macy aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t)); 1890eda14cbcSMatt Macy if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) { 1891eda14cbcSMatt Macy if ((error = zfs_copy_ace_2_oldace(obj_type, aclp, 1892eda14cbcSMatt Macy (ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata, 1893eda14cbcSMatt Macy aclcnt, &aclnode->z_size)) != 0) { 1894eda14cbcSMatt Macy zfs_acl_free(aclp); 1895eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 1896eda14cbcSMatt Macy return (error); 1897eda14cbcSMatt Macy } 1898eda14cbcSMatt Macy } else { 1899eda14cbcSMatt Macy if ((error = zfs_copy_ace_2_fuid(zfsvfs, obj_type, aclp, 1900eda14cbcSMatt Macy vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt, 1901eda14cbcSMatt Macy &aclnode->z_size, fuidp, cr)) != 0) { 1902eda14cbcSMatt Macy zfs_acl_free(aclp); 1903eda14cbcSMatt Macy zfs_acl_node_free(aclnode); 1904eda14cbcSMatt Macy return (error); 1905eda14cbcSMatt Macy } 1906eda14cbcSMatt Macy } 1907eda14cbcSMatt Macy aclp->z_acl_bytes = aclnode->z_size; 1908eda14cbcSMatt Macy aclnode->z_ace_count = aclcnt; 1909eda14cbcSMatt Macy aclp->z_acl_count = aclcnt; 1910eda14cbcSMatt Macy list_insert_head(&aclp->z_acl, aclnode); 1911eda14cbcSMatt Macy 1912eda14cbcSMatt Macy /* 1913eda14cbcSMatt Macy * If flags are being set then add them to z_hints 1914eda14cbcSMatt Macy */ 1915eda14cbcSMatt Macy if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) { 1916eda14cbcSMatt Macy if (vsecp->vsa_aclflags & ACL_PROTECTED) 1917eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_PROTECTED; 1918eda14cbcSMatt Macy if (vsecp->vsa_aclflags & ACL_DEFAULTED) 1919eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_DEFAULTED; 1920eda14cbcSMatt Macy if (vsecp->vsa_aclflags & ACL_AUTO_INHERIT) 1921eda14cbcSMatt Macy aclp->z_hints |= ZFS_ACL_AUTO_INHERIT; 1922eda14cbcSMatt Macy } 1923eda14cbcSMatt Macy 1924eda14cbcSMatt Macy *zaclp = aclp; 1925eda14cbcSMatt Macy 1926eda14cbcSMatt Macy return (0); 1927eda14cbcSMatt Macy } 1928eda14cbcSMatt Macy 1929eda14cbcSMatt Macy /* 1930eda14cbcSMatt Macy * Set a file's ACL 1931eda14cbcSMatt Macy */ 1932eda14cbcSMatt Macy int 1933eda14cbcSMatt Macy zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) 1934eda14cbcSMatt Macy { 1935eda14cbcSMatt Macy zfsvfs_t *zfsvfs = zp->z_zfsvfs; 1936eda14cbcSMatt Macy zilog_t *zilog = zfsvfs->z_log; 1937eda14cbcSMatt Macy ulong_t mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT); 1938eda14cbcSMatt Macy dmu_tx_t *tx; 1939eda14cbcSMatt Macy int error; 1940eda14cbcSMatt Macy zfs_acl_t *aclp; 1941eda14cbcSMatt Macy zfs_fuid_info_t *fuidp = NULL; 1942eda14cbcSMatt Macy boolean_t fuid_dirtied; 1943eda14cbcSMatt Macy uint64_t acl_obj; 1944eda14cbcSMatt Macy 1945eda14cbcSMatt Macy if (zp->z_zfsvfs->z_replay == B_FALSE) 1946eda14cbcSMatt Macy ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); 1947eda14cbcSMatt Macy if (mask == 0) 1948eda14cbcSMatt Macy return (SET_ERROR(ENOSYS)); 1949eda14cbcSMatt Macy 1950eda14cbcSMatt Macy if (zp->z_pflags & ZFS_IMMUTABLE) 1951eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 1952eda14cbcSMatt Macy 1953dbd5678dSMartin Matuska if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) 1954eda14cbcSMatt Macy return (error); 1955eda14cbcSMatt Macy 1956eda14cbcSMatt Macy error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, 1957eda14cbcSMatt Macy &aclp); 1958eda14cbcSMatt Macy if (error) 1959eda14cbcSMatt Macy return (error); 1960eda14cbcSMatt Macy 1961eda14cbcSMatt Macy /* 1962eda14cbcSMatt Macy * If ACL wide flags aren't being set then preserve any 1963eda14cbcSMatt Macy * existing flags. 1964eda14cbcSMatt Macy */ 1965eda14cbcSMatt Macy if (!(vsecp->vsa_mask & VSA_ACE_ACLFLAGS)) { 1966eda14cbcSMatt Macy aclp->z_hints |= 1967eda14cbcSMatt Macy (zp->z_pflags & V4_ACL_WIDE_FLAGS); 1968eda14cbcSMatt Macy } 1969eda14cbcSMatt Macy top: 1970eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 1971eda14cbcSMatt Macy 1972eda14cbcSMatt Macy tx = dmu_tx_create(zfsvfs->z_os); 1973eda14cbcSMatt Macy 1974eda14cbcSMatt Macy dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); 1975eda14cbcSMatt Macy 1976eda14cbcSMatt Macy fuid_dirtied = zfsvfs->z_fuid_dirty; 1977eda14cbcSMatt Macy if (fuid_dirtied) 1978eda14cbcSMatt Macy zfs_fuid_txhold(zfsvfs, tx); 1979eda14cbcSMatt Macy 1980eda14cbcSMatt Macy /* 1981eda14cbcSMatt Macy * If old version and ACL won't fit in bonus and we aren't 1982eda14cbcSMatt Macy * upgrading then take out necessary DMU holds 1983eda14cbcSMatt Macy */ 1984eda14cbcSMatt Macy 1985eda14cbcSMatt Macy if ((acl_obj = zfs_external_acl(zp)) != 0) { 1986eda14cbcSMatt Macy if (zfsvfs->z_version >= ZPL_VERSION_FUID && 1987eda14cbcSMatt Macy zfs_znode_acl_version(zp) <= ZFS_ACL_VERSION_INITIAL) { 1988eda14cbcSMatt Macy dmu_tx_hold_free(tx, acl_obj, 0, 1989eda14cbcSMatt Macy DMU_OBJECT_END); 1990eda14cbcSMatt Macy dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 1991eda14cbcSMatt Macy aclp->z_acl_bytes); 1992eda14cbcSMatt Macy } else { 1993eda14cbcSMatt Macy dmu_tx_hold_write(tx, acl_obj, 0, aclp->z_acl_bytes); 1994eda14cbcSMatt Macy } 1995eda14cbcSMatt Macy } else if (!zp->z_is_sa && aclp->z_acl_bytes > ZFS_ACE_SPACE) { 1996eda14cbcSMatt Macy dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, aclp->z_acl_bytes); 1997eda14cbcSMatt Macy } 1998eda14cbcSMatt Macy 1999eda14cbcSMatt Macy zfs_sa_upgrade_txholds(tx, zp); 2000eda14cbcSMatt Macy error = dmu_tx_assign(tx, TXG_NOWAIT); 2001eda14cbcSMatt Macy if (error) { 2002eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2003eda14cbcSMatt Macy 2004eda14cbcSMatt Macy if (error == ERESTART) { 2005eda14cbcSMatt Macy dmu_tx_wait(tx); 2006eda14cbcSMatt Macy dmu_tx_abort(tx); 2007eda14cbcSMatt Macy goto top; 2008eda14cbcSMatt Macy } 2009eda14cbcSMatt Macy dmu_tx_abort(tx); 2010eda14cbcSMatt Macy zfs_acl_free(aclp); 2011eda14cbcSMatt Macy return (error); 2012eda14cbcSMatt Macy } 2013eda14cbcSMatt Macy 2014eda14cbcSMatt Macy error = zfs_aclset_common(zp, aclp, cr, tx); 201516038816SMartin Matuska ASSERT0(error); 201616038816SMartin Matuska ASSERT3P(zp->z_acl_cached, ==, NULL); 2017eda14cbcSMatt Macy zp->z_acl_cached = aclp; 2018eda14cbcSMatt Macy 2019eda14cbcSMatt Macy if (fuid_dirtied) 2020eda14cbcSMatt Macy zfs_fuid_sync(zfsvfs, tx); 2021eda14cbcSMatt Macy 2022eda14cbcSMatt Macy zfs_log_acl(zilog, tx, zp, vsecp, fuidp); 2023eda14cbcSMatt Macy 2024eda14cbcSMatt Macy if (fuidp) 2025eda14cbcSMatt Macy zfs_fuid_info_free(fuidp); 2026eda14cbcSMatt Macy dmu_tx_commit(tx); 2027eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2028eda14cbcSMatt Macy 2029eda14cbcSMatt Macy return (error); 2030eda14cbcSMatt Macy } 2031eda14cbcSMatt Macy 2032eda14cbcSMatt Macy /* 2033eda14cbcSMatt Macy * Check accesses of interest (AoI) against attributes of the dataset 2034eda14cbcSMatt Macy * such as read-only. Returns zero if no AoI conflict with dataset 2035eda14cbcSMatt Macy * attributes, otherwise an appropriate errno is returned. 2036eda14cbcSMatt Macy */ 2037eda14cbcSMatt Macy static int 2038eda14cbcSMatt Macy zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) 2039eda14cbcSMatt Macy { 2040eda14cbcSMatt Macy if ((v4_mode & WRITE_MASK) && 2041eda14cbcSMatt Macy (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) && 204215f0b8c3SMartin Matuska (!IS_DEVVP(ZTOV(zp)) || (v4_mode & WRITE_MASK_ATTRS))) { 2043eda14cbcSMatt Macy return (SET_ERROR(EROFS)); 2044eda14cbcSMatt Macy } 2045eda14cbcSMatt Macy 2046eda14cbcSMatt Macy /* 2047eda14cbcSMatt Macy * Intentionally allow ZFS_READONLY through here. 2048eda14cbcSMatt Macy * See zfs_zaccess_common(). 2049eda14cbcSMatt Macy */ 2050eda14cbcSMatt Macy if ((v4_mode & WRITE_MASK_DATA) && 2051eda14cbcSMatt Macy (zp->z_pflags & ZFS_IMMUTABLE)) { 2052eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2053eda14cbcSMatt Macy } 2054eda14cbcSMatt Macy 2055eda14cbcSMatt Macy /* 2056eda14cbcSMatt Macy * In FreeBSD we allow to modify directory's content is ZFS_NOUNLINK 2057eda14cbcSMatt Macy * (sunlnk) is set. We just don't allow directory removal, which is 2058eda14cbcSMatt Macy * handled in zfs_zaccess_delete(). 2059eda14cbcSMatt Macy */ 2060eda14cbcSMatt Macy if ((v4_mode & ACE_DELETE) && 2061eda14cbcSMatt Macy (zp->z_pflags & ZFS_NOUNLINK)) { 2062eda14cbcSMatt Macy return (EPERM); 2063eda14cbcSMatt Macy } 2064eda14cbcSMatt Macy 2065eda14cbcSMatt Macy if (((v4_mode & (ACE_READ_DATA|ACE_EXECUTE)) && 2066eda14cbcSMatt Macy (zp->z_pflags & ZFS_AV_QUARANTINED))) { 2067eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2068eda14cbcSMatt Macy } 2069eda14cbcSMatt Macy 2070eda14cbcSMatt Macy return (0); 2071eda14cbcSMatt Macy } 2072eda14cbcSMatt Macy 2073eda14cbcSMatt Macy /* 2074eda14cbcSMatt Macy * The primary usage of this function is to loop through all of the 2075eda14cbcSMatt Macy * ACEs in the znode, determining what accesses of interest (AoI) to 2076eda14cbcSMatt Macy * the caller are allowed or denied. The AoI are expressed as bits in 2077eda14cbcSMatt Macy * the working_mode parameter. As each ACE is processed, bits covered 2078eda14cbcSMatt Macy * by that ACE are removed from the working_mode. This removal 2079eda14cbcSMatt Macy * facilitates two things. The first is that when the working mode is 2080eda14cbcSMatt Macy * empty (= 0), we know we've looked at all the AoI. The second is 2081eda14cbcSMatt Macy * that the ACE interpretation rules don't allow a later ACE to undo 2082eda14cbcSMatt Macy * something granted or denied by an earlier ACE. Removing the 2083eda14cbcSMatt Macy * discovered access or denial enforces this rule. At the end of 2084eda14cbcSMatt Macy * processing the ACEs, all AoI that were found to be denied are 2085eda14cbcSMatt Macy * placed into the working_mode, giving the caller a mask of denied 2086eda14cbcSMatt Macy * accesses. Returns: 2087eda14cbcSMatt Macy * 0 if all AoI granted 2088eda14cbcSMatt Macy * EACCESS if the denied mask is non-zero 2089eda14cbcSMatt Macy * other error if abnormal failure (e.g., IO error) 2090eda14cbcSMatt Macy * 2091eda14cbcSMatt Macy * A secondary usage of the function is to determine if any of the 2092eda14cbcSMatt Macy * AoI are granted. If an ACE grants any access in 2093eda14cbcSMatt Macy * the working_mode, we immediately short circuit out of the function. 2094eda14cbcSMatt Macy * This mode is chosen by setting anyaccess to B_TRUE. The 2095eda14cbcSMatt Macy * working_mode is not a denied access mask upon exit if the function 2096eda14cbcSMatt Macy * is used in this manner. 2097eda14cbcSMatt Macy */ 2098eda14cbcSMatt Macy static int 2099eda14cbcSMatt Macy zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, 2100eda14cbcSMatt Macy boolean_t anyaccess, cred_t *cr) 2101eda14cbcSMatt Macy { 2102eda14cbcSMatt Macy zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2103eda14cbcSMatt Macy zfs_acl_t *aclp; 2104eda14cbcSMatt Macy int error; 2105eda14cbcSMatt Macy uid_t uid = crgetuid(cr); 2106eda14cbcSMatt Macy uint64_t who; 2107eda14cbcSMatt Macy uint16_t type, iflags; 2108eda14cbcSMatt Macy uint16_t entry_type; 2109eda14cbcSMatt Macy uint32_t access_mask; 2110eda14cbcSMatt Macy uint32_t deny_mask = 0; 2111eda14cbcSMatt Macy zfs_ace_hdr_t *acep = NULL; 2112eda14cbcSMatt Macy boolean_t checkit; 2113eda14cbcSMatt Macy uid_t gowner; 2114eda14cbcSMatt Macy uid_t fowner; 2115eda14cbcSMatt Macy 2116eda14cbcSMatt Macy zfs_fuid_map_ids(zp, cr, &fowner, &gowner); 2117eda14cbcSMatt Macy 2118eda14cbcSMatt Macy mutex_enter(&zp->z_acl_lock); 2119eda14cbcSMatt Macy 2120eda14cbcSMatt Macy if (zp->z_zfsvfs->z_replay == B_FALSE) 2121eda14cbcSMatt Macy ASSERT_VOP_LOCKED(ZTOV(zp), __func__); 2122eda14cbcSMatt Macy error = zfs_acl_node_read(zp, B_TRUE, &aclp, B_FALSE); 2123eda14cbcSMatt Macy if (error != 0) { 2124eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2125eda14cbcSMatt Macy return (error); 2126eda14cbcSMatt Macy } 2127eda14cbcSMatt Macy 212816038816SMartin Matuska ASSERT3P(zp->z_acl_cached, !=, NULL); 2129eda14cbcSMatt Macy 2130eda14cbcSMatt Macy while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask, 2131eda14cbcSMatt Macy &iflags, &type))) { 2132eda14cbcSMatt Macy uint32_t mask_matched; 2133eda14cbcSMatt Macy 2134eda14cbcSMatt Macy if (!zfs_acl_valid_ace_type(type, iflags)) 2135eda14cbcSMatt Macy continue; 2136eda14cbcSMatt Macy 2137eda14cbcSMatt Macy if (ZTOV(zp)->v_type == VDIR && (iflags & ACE_INHERIT_ONLY_ACE)) 2138eda14cbcSMatt Macy continue; 2139eda14cbcSMatt Macy 2140eda14cbcSMatt Macy /* Skip ACE if it does not affect any AoI */ 2141eda14cbcSMatt Macy mask_matched = (access_mask & *working_mode); 2142eda14cbcSMatt Macy if (!mask_matched) 2143eda14cbcSMatt Macy continue; 2144eda14cbcSMatt Macy 2145eda14cbcSMatt Macy entry_type = (iflags & ACE_TYPE_FLAGS); 2146eda14cbcSMatt Macy 2147eda14cbcSMatt Macy checkit = B_FALSE; 2148eda14cbcSMatt Macy 2149eda14cbcSMatt Macy switch (entry_type) { 2150eda14cbcSMatt Macy case ACE_OWNER: 2151eda14cbcSMatt Macy if (uid == fowner) 2152eda14cbcSMatt Macy checkit = B_TRUE; 2153eda14cbcSMatt Macy break; 2154eda14cbcSMatt Macy case OWNING_GROUP: 2155eda14cbcSMatt Macy who = gowner; 2156c03c5b1cSMartin Matuska zfs_fallthrough; 2157eda14cbcSMatt Macy case ACE_IDENTIFIER_GROUP: 2158eda14cbcSMatt Macy checkit = zfs_groupmember(zfsvfs, who, cr); 2159eda14cbcSMatt Macy break; 2160eda14cbcSMatt Macy case ACE_EVERYONE: 2161eda14cbcSMatt Macy checkit = B_TRUE; 2162eda14cbcSMatt Macy break; 2163eda14cbcSMatt Macy 2164eda14cbcSMatt Macy /* USER Entry */ 2165eda14cbcSMatt Macy default: 2166eda14cbcSMatt Macy if (entry_type == 0) { 2167eda14cbcSMatt Macy uid_t newid; 2168eda14cbcSMatt Macy 2169eda14cbcSMatt Macy newid = zfs_fuid_map_id(zfsvfs, who, cr, 2170eda14cbcSMatt Macy ZFS_ACE_USER); 2171eda14cbcSMatt Macy if (newid != UID_NOBODY && 2172eda14cbcSMatt Macy uid == newid) 2173eda14cbcSMatt Macy checkit = B_TRUE; 2174eda14cbcSMatt Macy break; 2175eda14cbcSMatt Macy } else { 2176eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2177eda14cbcSMatt Macy return (SET_ERROR(EIO)); 2178eda14cbcSMatt Macy } 2179eda14cbcSMatt Macy } 2180eda14cbcSMatt Macy 2181eda14cbcSMatt Macy if (checkit) { 2182eda14cbcSMatt Macy if (type == DENY) { 2183eda14cbcSMatt Macy DTRACE_PROBE3(zfs__ace__denies, 2184eda14cbcSMatt Macy znode_t *, zp, 2185eda14cbcSMatt Macy zfs_ace_hdr_t *, acep, 2186eda14cbcSMatt Macy uint32_t, mask_matched); 2187eda14cbcSMatt Macy deny_mask |= mask_matched; 2188eda14cbcSMatt Macy } else { 2189eda14cbcSMatt Macy DTRACE_PROBE3(zfs__ace__allows, 2190eda14cbcSMatt Macy znode_t *, zp, 2191eda14cbcSMatt Macy zfs_ace_hdr_t *, acep, 2192eda14cbcSMatt Macy uint32_t, mask_matched); 2193eda14cbcSMatt Macy if (anyaccess) { 2194eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2195eda14cbcSMatt Macy return (0); 2196eda14cbcSMatt Macy } 2197eda14cbcSMatt Macy } 2198eda14cbcSMatt Macy *working_mode &= ~mask_matched; 2199eda14cbcSMatt Macy } 2200eda14cbcSMatt Macy 2201eda14cbcSMatt Macy /* Are we done? */ 2202eda14cbcSMatt Macy if (*working_mode == 0) 2203eda14cbcSMatt Macy break; 2204eda14cbcSMatt Macy } 2205eda14cbcSMatt Macy 2206eda14cbcSMatt Macy mutex_exit(&zp->z_acl_lock); 2207eda14cbcSMatt Macy 2208eda14cbcSMatt Macy /* Put the found 'denies' back on the working mode */ 2209eda14cbcSMatt Macy if (deny_mask) { 2210eda14cbcSMatt Macy *working_mode |= deny_mask; 2211eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2212eda14cbcSMatt Macy } else if (*working_mode) { 2213eda14cbcSMatt Macy return (-1); 2214eda14cbcSMatt Macy } 2215eda14cbcSMatt Macy 2216eda14cbcSMatt Macy return (0); 2217eda14cbcSMatt Macy } 2218eda14cbcSMatt Macy 2219eda14cbcSMatt Macy /* 2220eda14cbcSMatt Macy * Return true if any access whatsoever granted, we don't actually 2221eda14cbcSMatt Macy * care what access is granted. 2222eda14cbcSMatt Macy */ 2223eda14cbcSMatt Macy boolean_t 2224eda14cbcSMatt Macy zfs_has_access(znode_t *zp, cred_t *cr) 2225eda14cbcSMatt Macy { 2226eda14cbcSMatt Macy uint32_t have = ACE_ALL_PERMS; 2227eda14cbcSMatt Macy 2228eda14cbcSMatt Macy if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) { 2229eda14cbcSMatt Macy uid_t owner; 2230eda14cbcSMatt Macy 2231eda14cbcSMatt Macy owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER); 2232eda14cbcSMatt Macy return (secpolicy_vnode_any_access(cr, ZTOV(zp), owner) == 0); 2233eda14cbcSMatt Macy } 2234eda14cbcSMatt Macy return (B_TRUE); 2235eda14cbcSMatt Macy } 2236eda14cbcSMatt Macy 2237eda14cbcSMatt Macy static int 2238eda14cbcSMatt Macy zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, 2239eda14cbcSMatt Macy boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) 2240eda14cbcSMatt Macy { 2241eda14cbcSMatt Macy zfsvfs_t *zfsvfs = zp->z_zfsvfs; 2242eda14cbcSMatt Macy int err; 2243eda14cbcSMatt Macy 2244eda14cbcSMatt Macy *working_mode = v4_mode; 2245eda14cbcSMatt Macy *check_privs = B_TRUE; 2246eda14cbcSMatt Macy 2247eda14cbcSMatt Macy /* 2248eda14cbcSMatt Macy * Short circuit empty requests 2249eda14cbcSMatt Macy */ 2250eda14cbcSMatt Macy if (v4_mode == 0 || zfsvfs->z_replay) { 2251eda14cbcSMatt Macy *working_mode = 0; 2252eda14cbcSMatt Macy return (0); 2253eda14cbcSMatt Macy } 2254eda14cbcSMatt Macy 2255eda14cbcSMatt Macy if ((err = zfs_zaccess_dataset_check(zp, v4_mode)) != 0) { 2256eda14cbcSMatt Macy *check_privs = B_FALSE; 2257eda14cbcSMatt Macy return (err); 2258eda14cbcSMatt Macy } 2259eda14cbcSMatt Macy 2260eda14cbcSMatt Macy /* 2261eda14cbcSMatt Macy * The caller requested that the ACL check be skipped. This 2262eda14cbcSMatt Macy * would only happen if the caller checked VOP_ACCESS() with a 2263eda14cbcSMatt Macy * 32 bit ACE mask and already had the appropriate permissions. 2264eda14cbcSMatt Macy */ 2265eda14cbcSMatt Macy if (skipaclchk) { 2266eda14cbcSMatt Macy *working_mode = 0; 2267eda14cbcSMatt Macy return (0); 2268eda14cbcSMatt Macy } 2269eda14cbcSMatt Macy 2270eda14cbcSMatt Macy /* 2271eda14cbcSMatt Macy * Note: ZFS_READONLY represents the "DOS R/O" attribute. 2272eda14cbcSMatt Macy * When that flag is set, we should behave as if write access 2273eda14cbcSMatt Macy * were not granted by anything in the ACL. In particular: 2274eda14cbcSMatt Macy * We _must_ allow writes after opening the file r/w, then 2275eda14cbcSMatt Macy * setting the DOS R/O attribute, and writing some more. 2276eda14cbcSMatt Macy * (Similar to how you can write after fchmod(fd, 0444).) 2277eda14cbcSMatt Macy * 2278eda14cbcSMatt Macy * Therefore ZFS_READONLY is ignored in the dataset check 2279eda14cbcSMatt Macy * above, and checked here as if part of the ACL check. 2280eda14cbcSMatt Macy * Also note: DOS R/O is ignored for directories. 2281eda14cbcSMatt Macy */ 2282eda14cbcSMatt Macy if ((v4_mode & WRITE_MASK_DATA) && 2283eda14cbcSMatt Macy (ZTOV(zp)->v_type != VDIR) && 2284eda14cbcSMatt Macy (zp->z_pflags & ZFS_READONLY)) { 2285eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2286eda14cbcSMatt Macy } 2287eda14cbcSMatt Macy 2288eda14cbcSMatt Macy return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr)); 2289eda14cbcSMatt Macy } 2290eda14cbcSMatt Macy 2291eda14cbcSMatt Macy static int 2292eda14cbcSMatt Macy zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, 2293eda14cbcSMatt Macy cred_t *cr) 2294eda14cbcSMatt Macy { 2295eda14cbcSMatt Macy if (*working_mode != ACE_WRITE_DATA) 2296eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2297eda14cbcSMatt Macy 2298eda14cbcSMatt Macy return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, 2299eda14cbcSMatt Macy check_privs, B_FALSE, cr)); 2300eda14cbcSMatt Macy } 2301eda14cbcSMatt Macy 2302eda14cbcSMatt Macy /* 2303eda14cbcSMatt Macy * Check if VEXEC is allowed. 2304eda14cbcSMatt Macy * 2305eda14cbcSMatt Macy * This routine is based on zfs_fastaccesschk_execute which has slowpath 2306eda14cbcSMatt Macy * calling zfs_zaccess. This would be incorrect on FreeBSD (see 2307eda14cbcSMatt Macy * zfs_freebsd_access for the difference). Thus this variant let's the 2308eda14cbcSMatt Macy * caller handle the slowpath (if necessary). 2309eda14cbcSMatt Macy * 2310eda14cbcSMatt Macy * On top of that we perform a lockless check for ZFS_NO_EXECS_DENIED. 2311eda14cbcSMatt Macy * 2312eda14cbcSMatt Macy * Safe access to znode_t is provided by the vnode lock. 2313eda14cbcSMatt Macy */ 2314eda14cbcSMatt Macy int 2315eda14cbcSMatt Macy zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) 2316eda14cbcSMatt Macy { 2317eda14cbcSMatt Macy boolean_t is_attr; 2318eda14cbcSMatt Macy 2319eda14cbcSMatt Macy if (zdp->z_pflags & ZFS_AV_QUARANTINED) 2320eda14cbcSMatt Macy return (1); 2321eda14cbcSMatt Macy 2322eda14cbcSMatt Macy is_attr = ((zdp->z_pflags & ZFS_XATTR) && 2323eda14cbcSMatt Macy (ZTOV(zdp)->v_type == VDIR)); 2324eda14cbcSMatt Macy if (is_attr) 2325eda14cbcSMatt Macy return (1); 2326eda14cbcSMatt Macy 2327eda14cbcSMatt Macy if (zdp->z_pflags & ZFS_NO_EXECS_DENIED) 2328eda14cbcSMatt Macy return (0); 2329eda14cbcSMatt Macy 2330eda14cbcSMatt Macy return (1); 2331eda14cbcSMatt Macy } 2332eda14cbcSMatt Macy 2333eda14cbcSMatt Macy 2334eda14cbcSMatt Macy /* 2335eda14cbcSMatt Macy * Determine whether Access should be granted/denied. 2336eda14cbcSMatt Macy * 2337eda14cbcSMatt Macy * The least priv subsystem is always consulted as a basic privilege 2338eda14cbcSMatt Macy * can define any form of access. 2339eda14cbcSMatt Macy */ 2340eda14cbcSMatt Macy int 2341dbd5678dSMartin Matuska zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, 2342d411c1d6SMartin Matuska zidmap_t *mnt_ns) 2343eda14cbcSMatt Macy { 2344eda14cbcSMatt Macy uint32_t working_mode; 2345eda14cbcSMatt Macy int error; 2346eda14cbcSMatt Macy int is_attr; 2347eda14cbcSMatt Macy boolean_t check_privs; 2348eda14cbcSMatt Macy znode_t *xzp = NULL; 2349eda14cbcSMatt Macy znode_t *check_zp = zp; 2350eda14cbcSMatt Macy mode_t needed_bits; 2351eda14cbcSMatt Macy uid_t owner; 2352eda14cbcSMatt Macy 2353eda14cbcSMatt Macy is_attr = ((zp->z_pflags & ZFS_XATTR) && (ZTOV(zp)->v_type == VDIR)); 2354eda14cbcSMatt Macy 2355eda14cbcSMatt Macy /* 2356eda14cbcSMatt Macy * In FreeBSD, we don't care about permissions of individual ADS. 2357eda14cbcSMatt Macy * Note that not checking them is not just an optimization - without 2358eda14cbcSMatt Macy * this shortcut, EA operations may bogusly fail with EACCES. 2359eda14cbcSMatt Macy */ 2360eda14cbcSMatt Macy if (zp->z_pflags & ZFS_XATTR) 2361eda14cbcSMatt Macy return (0); 2362eda14cbcSMatt Macy 2363eda14cbcSMatt Macy owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER); 236416038816SMartin Matuska 2365eda14cbcSMatt Macy /* 2366eda14cbcSMatt Macy * Map the bits required to the standard vnode flags VREAD|VWRITE|VEXEC 2367eda14cbcSMatt Macy * in needed_bits. Map the bits mapped by working_mode (currently 2368eda14cbcSMatt Macy * missing) in missing_bits. 2369eda14cbcSMatt Macy * Call secpolicy_vnode_access2() with (needed_bits & ~checkmode), 2370eda14cbcSMatt Macy * needed_bits. 2371eda14cbcSMatt Macy */ 2372eda14cbcSMatt Macy needed_bits = 0; 2373eda14cbcSMatt Macy 2374eda14cbcSMatt Macy working_mode = mode; 2375eda14cbcSMatt Macy if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) && 2376eda14cbcSMatt Macy owner == crgetuid(cr)) 2377eda14cbcSMatt Macy working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2378eda14cbcSMatt Macy 2379eda14cbcSMatt Macy if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2380eda14cbcSMatt Macy ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2381eda14cbcSMatt Macy needed_bits |= VREAD; 2382eda14cbcSMatt Macy if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2383eda14cbcSMatt Macy ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2384eda14cbcSMatt Macy needed_bits |= VWRITE; 2385eda14cbcSMatt Macy if (working_mode & ACE_EXECUTE) 2386eda14cbcSMatt Macy needed_bits |= VEXEC; 2387eda14cbcSMatt Macy 2388eda14cbcSMatt Macy if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, 2389eda14cbcSMatt Macy &check_privs, skipaclchk, cr)) == 0) { 2390eda14cbcSMatt Macy if (is_attr) 2391eda14cbcSMatt Macy VN_RELE(ZTOV(xzp)); 2392eda14cbcSMatt Macy return (secpolicy_vnode_access2(cr, ZTOV(zp), owner, 2393eda14cbcSMatt Macy needed_bits, needed_bits)); 2394eda14cbcSMatt Macy } 2395eda14cbcSMatt Macy 2396eda14cbcSMatt Macy if (error && !check_privs) { 2397eda14cbcSMatt Macy if (is_attr) 2398eda14cbcSMatt Macy VN_RELE(ZTOV(xzp)); 2399eda14cbcSMatt Macy return (error); 2400eda14cbcSMatt Macy } 2401eda14cbcSMatt Macy 2402eda14cbcSMatt Macy if (error && (flags & V_APPEND)) { 2403eda14cbcSMatt Macy error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr); 2404eda14cbcSMatt Macy } 2405eda14cbcSMatt Macy 2406eda14cbcSMatt Macy if (error && check_privs) { 2407eda14cbcSMatt Macy mode_t checkmode = 0; 2408eda14cbcSMatt Macy vnode_t *check_vp = ZTOV(check_zp); 2409eda14cbcSMatt Macy 2410eda14cbcSMatt Macy /* 2411eda14cbcSMatt Macy * First check for implicit owner permission on 2412eda14cbcSMatt Macy * read_acl/read_attributes 2413eda14cbcSMatt Macy */ 2414eda14cbcSMatt Macy 241516038816SMartin Matuska ASSERT3U(working_mode, !=, 0); 2416eda14cbcSMatt Macy 2417eda14cbcSMatt Macy if ((working_mode & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) && 2418eda14cbcSMatt Macy owner == crgetuid(cr))) 2419eda14cbcSMatt Macy working_mode &= ~(ACE_READ_ACL|ACE_READ_ATTRIBUTES); 2420eda14cbcSMatt Macy 2421eda14cbcSMatt Macy if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS| 2422eda14cbcSMatt Macy ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE)) 2423eda14cbcSMatt Macy checkmode |= VREAD; 2424eda14cbcSMatt Macy if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS| 2425eda14cbcSMatt Macy ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE)) 2426eda14cbcSMatt Macy checkmode |= VWRITE; 2427eda14cbcSMatt Macy if (working_mode & ACE_EXECUTE) 2428eda14cbcSMatt Macy checkmode |= VEXEC; 2429eda14cbcSMatt Macy 2430eda14cbcSMatt Macy error = secpolicy_vnode_access2(cr, check_vp, owner, 2431eda14cbcSMatt Macy needed_bits & ~checkmode, needed_bits); 2432eda14cbcSMatt Macy 2433eda14cbcSMatt Macy if (error == 0 && (working_mode & ACE_WRITE_OWNER)) 2434eda14cbcSMatt Macy error = secpolicy_vnode_chown(check_vp, cr, owner); 2435eda14cbcSMatt Macy if (error == 0 && (working_mode & ACE_WRITE_ACL)) 2436eda14cbcSMatt Macy error = secpolicy_vnode_setdac(check_vp, cr, owner); 2437eda14cbcSMatt Macy 2438eda14cbcSMatt Macy if (error == 0 && (working_mode & 2439eda14cbcSMatt Macy (ACE_DELETE|ACE_DELETE_CHILD))) 2440eda14cbcSMatt Macy error = secpolicy_vnode_remove(check_vp, cr); 2441eda14cbcSMatt Macy 2442eda14cbcSMatt Macy if (error == 0 && (working_mode & ACE_SYNCHRONIZE)) { 2443eda14cbcSMatt Macy error = secpolicy_vnode_chown(check_vp, cr, owner); 2444eda14cbcSMatt Macy } 2445eda14cbcSMatt Macy if (error == 0) { 2446eda14cbcSMatt Macy /* 2447eda14cbcSMatt Macy * See if any bits other than those already checked 2448eda14cbcSMatt Macy * for are still present. If so then return EACCES 2449eda14cbcSMatt Macy */ 2450eda14cbcSMatt Macy if (working_mode & ~(ZFS_CHECKED_MASKS)) { 2451eda14cbcSMatt Macy error = SET_ERROR(EACCES); 2452eda14cbcSMatt Macy } 2453eda14cbcSMatt Macy } 2454eda14cbcSMatt Macy } else if (error == 0) { 2455eda14cbcSMatt Macy error = secpolicy_vnode_access2(cr, ZTOV(zp), owner, 2456eda14cbcSMatt Macy needed_bits, needed_bits); 2457eda14cbcSMatt Macy } 2458eda14cbcSMatt Macy 2459eda14cbcSMatt Macy 2460eda14cbcSMatt Macy if (is_attr) 2461eda14cbcSMatt Macy VN_RELE(ZTOV(xzp)); 2462eda14cbcSMatt Macy 2463eda14cbcSMatt Macy return (error); 2464eda14cbcSMatt Macy } 2465eda14cbcSMatt Macy 2466eda14cbcSMatt Macy /* 2467eda14cbcSMatt Macy * Translate traditional unix VREAD/VWRITE/VEXEC mode into 2468180f8225SMatt Macy * NFSv4-style ZFS ACL format and call zfs_zaccess() 2469eda14cbcSMatt Macy */ 2470eda14cbcSMatt Macy int 2471dbd5678dSMartin Matuska zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, 2472d411c1d6SMartin Matuska zidmap_t *mnt_ns) 2473eda14cbcSMatt Macy { 2474dbd5678dSMartin Matuska return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, 2475dbd5678dSMartin Matuska mnt_ns)); 2476eda14cbcSMatt Macy } 2477eda14cbcSMatt Macy 2478eda14cbcSMatt Macy /* 2479eda14cbcSMatt Macy * Access function for secpolicy_vnode_setattr 2480eda14cbcSMatt Macy */ 2481eda14cbcSMatt Macy int 2482bb2d13b6SMartin Matuska zfs_zaccess_unix(void *zp, int mode, cred_t *cr) 2483eda14cbcSMatt Macy { 2484eda14cbcSMatt Macy int v4_mode = zfs_unix_to_v4(mode >> 6); 2485eda14cbcSMatt Macy 2486dbd5678dSMartin Matuska return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); 2487eda14cbcSMatt Macy } 2488eda14cbcSMatt Macy 2489eda14cbcSMatt Macy static int 2490eda14cbcSMatt Macy zfs_delete_final_check(znode_t *zp, znode_t *dzp, 2491eda14cbcSMatt Macy mode_t available_perms, cred_t *cr) 2492eda14cbcSMatt Macy { 2493eda14cbcSMatt Macy int error; 2494eda14cbcSMatt Macy uid_t downer; 2495eda14cbcSMatt Macy 2496eda14cbcSMatt Macy downer = zfs_fuid_map_id(dzp->z_zfsvfs, dzp->z_uid, cr, ZFS_OWNER); 2497eda14cbcSMatt Macy 2498eda14cbcSMatt Macy error = secpolicy_vnode_access2(cr, ZTOV(dzp), 2499eda14cbcSMatt Macy downer, available_perms, VWRITE|VEXEC); 2500eda14cbcSMatt Macy 2501eda14cbcSMatt Macy if (error == 0) 2502eda14cbcSMatt Macy error = zfs_sticky_remove_access(dzp, zp, cr); 2503eda14cbcSMatt Macy 2504eda14cbcSMatt Macy return (error); 2505eda14cbcSMatt Macy } 2506eda14cbcSMatt Macy 2507eda14cbcSMatt Macy /* 2508eda14cbcSMatt Macy * Determine whether Access should be granted/deny, without 2509eda14cbcSMatt Macy * consulting least priv subsystem. 2510eda14cbcSMatt Macy * 2511eda14cbcSMatt Macy * The following chart is the recommended NFSv4 enforcement for 2512eda14cbcSMatt Macy * ability to delete an object. 2513eda14cbcSMatt Macy * 2514eda14cbcSMatt Macy * ------------------------------------------------------- 2515eda14cbcSMatt Macy * | Parent Dir | Target Object Permissions | 2516eda14cbcSMatt Macy * | permissions | | 2517eda14cbcSMatt Macy * ------------------------------------------------------- 2518eda14cbcSMatt Macy * | | ACL Allows | ACL Denies| Delete | 2519eda14cbcSMatt Macy * | | Delete | Delete | unspecified| 2520eda14cbcSMatt Macy * ------------------------------------------------------- 2521eda14cbcSMatt Macy * | ACL Allows | Permit | Permit | Permit | 2522eda14cbcSMatt Macy * | DELETE_CHILD | | 2523eda14cbcSMatt Macy * ------------------------------------------------------- 2524eda14cbcSMatt Macy * | ACL Denies | Permit | Deny | Deny | 2525eda14cbcSMatt Macy * | DELETE_CHILD | | | | 2526eda14cbcSMatt Macy * ------------------------------------------------------- 2527eda14cbcSMatt Macy * | ACL specifies | | | | 2528eda14cbcSMatt Macy * | only allow | Permit | Permit | Permit | 2529eda14cbcSMatt Macy * | write and | | | | 2530eda14cbcSMatt Macy * | execute | | | | 2531eda14cbcSMatt Macy * ------------------------------------------------------- 2532eda14cbcSMatt Macy * | ACL denies | | | | 2533eda14cbcSMatt Macy * | write and | Permit | Deny | Deny | 2534eda14cbcSMatt Macy * | execute | | | | 2535eda14cbcSMatt Macy * ------------------------------------------------------- 2536eda14cbcSMatt Macy * ^ 2537eda14cbcSMatt Macy * | 2538eda14cbcSMatt Macy * No search privilege, can't even look up file? 2539eda14cbcSMatt Macy * 2540eda14cbcSMatt Macy */ 2541eda14cbcSMatt Macy int 2542d411c1d6SMartin Matuska zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zidmap_t *mnt_ns) 2543eda14cbcSMatt Macy { 2544eda14cbcSMatt Macy uint32_t dzp_working_mode = 0; 2545eda14cbcSMatt Macy uint32_t zp_working_mode = 0; 2546eda14cbcSMatt Macy int dzp_error, zp_error; 2547eda14cbcSMatt Macy mode_t available_perms; 2548eda14cbcSMatt Macy boolean_t dzpcheck_privs = B_TRUE; 2549eda14cbcSMatt Macy boolean_t zpcheck_privs = B_TRUE; 2550eda14cbcSMatt Macy 2551eda14cbcSMatt Macy /* 2552eda14cbcSMatt Macy * We want specific DELETE permissions to 2553eda14cbcSMatt Macy * take precedence over WRITE/EXECUTE. We don't 2554eda14cbcSMatt Macy * want an ACL such as this to mess us up. 2555eda14cbcSMatt Macy * user:joe:write_data:deny,user:joe:delete:allow 2556eda14cbcSMatt Macy * 2557eda14cbcSMatt Macy * However, deny permissions may ultimately be overridden 2558eda14cbcSMatt Macy * by secpolicy_vnode_access(). 2559eda14cbcSMatt Macy * 2560eda14cbcSMatt Macy * We will ask for all of the necessary permissions and then 2561eda14cbcSMatt Macy * look at the working modes from the directory and target object 2562eda14cbcSMatt Macy * to determine what was found. 2563eda14cbcSMatt Macy */ 2564eda14cbcSMatt Macy 2565eda14cbcSMatt Macy if (zp->z_pflags & (ZFS_IMMUTABLE | ZFS_NOUNLINK)) 2566eda14cbcSMatt Macy return (SET_ERROR(EPERM)); 2567eda14cbcSMatt Macy 2568eda14cbcSMatt Macy /* 2569eda14cbcSMatt Macy * First row 2570eda14cbcSMatt Macy * If the directory permissions allow the delete, we are done. 2571eda14cbcSMatt Macy */ 2572eda14cbcSMatt Macy if ((dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD, 2573eda14cbcSMatt Macy &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr)) == 0) 2574eda14cbcSMatt Macy return (0); 2575eda14cbcSMatt Macy 2576eda14cbcSMatt Macy /* 2577eda14cbcSMatt Macy * If target object has delete permission then we are done 2578eda14cbcSMatt Macy */ 2579eda14cbcSMatt Macy if ((zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, 2580eda14cbcSMatt Macy &zpcheck_privs, B_FALSE, cr)) == 0) 2581eda14cbcSMatt Macy return (0); 2582eda14cbcSMatt Macy 258316038816SMartin Matuska ASSERT(dzp_error); 258416038816SMartin Matuska ASSERT(zp_error); 2585eda14cbcSMatt Macy 2586eda14cbcSMatt Macy if (!dzpcheck_privs) 2587eda14cbcSMatt Macy return (dzp_error); 2588eda14cbcSMatt Macy if (!zpcheck_privs) 2589eda14cbcSMatt Macy return (zp_error); 2590eda14cbcSMatt Macy 2591eda14cbcSMatt Macy /* 2592eda14cbcSMatt Macy * Second row 2593eda14cbcSMatt Macy * 2594eda14cbcSMatt Macy * If directory returns EACCES then delete_child was denied 2595eda14cbcSMatt Macy * due to deny delete_child. In this case send the request through 2596eda14cbcSMatt Macy * secpolicy_vnode_remove(). We don't use zfs_delete_final_check() 2597eda14cbcSMatt Macy * since that *could* allow the delete based on write/execute permission 2598eda14cbcSMatt Macy * and we want delete permissions to override write/execute. 2599eda14cbcSMatt Macy */ 2600eda14cbcSMatt Macy 2601eda14cbcSMatt Macy if (dzp_error == EACCES) { 2602eda14cbcSMatt Macy /* XXXPJD: s/dzp/zp/ ? */ 2603eda14cbcSMatt Macy return (secpolicy_vnode_remove(ZTOV(dzp), cr)); 2604eda14cbcSMatt Macy } 2605eda14cbcSMatt Macy /* 2606eda14cbcSMatt Macy * Third Row 2607eda14cbcSMatt Macy * only need to see if we have write/execute on directory. 2608eda14cbcSMatt Macy */ 2609eda14cbcSMatt Macy 2610eda14cbcSMatt Macy dzp_error = zfs_zaccess_common(dzp, ACE_EXECUTE|ACE_WRITE_DATA, 2611eda14cbcSMatt Macy &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr); 2612eda14cbcSMatt Macy 2613eda14cbcSMatt Macy if (dzp_error != 0 && !dzpcheck_privs) 2614eda14cbcSMatt Macy return (dzp_error); 2615eda14cbcSMatt Macy 2616eda14cbcSMatt Macy /* 2617eda14cbcSMatt Macy * Fourth row 2618eda14cbcSMatt Macy */ 2619eda14cbcSMatt Macy 2620eda14cbcSMatt Macy available_perms = (dzp_working_mode & ACE_WRITE_DATA) ? 0 : VWRITE; 2621eda14cbcSMatt Macy available_perms |= (dzp_working_mode & ACE_EXECUTE) ? 0 : VEXEC; 2622eda14cbcSMatt Macy 2623eda14cbcSMatt Macy return (zfs_delete_final_check(zp, dzp, available_perms, cr)); 2624eda14cbcSMatt Macy 2625eda14cbcSMatt Macy } 2626eda14cbcSMatt Macy 2627eda14cbcSMatt Macy int 2628eda14cbcSMatt Macy zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, 2629d411c1d6SMartin Matuska znode_t *tzp, cred_t *cr, zidmap_t *mnt_ns) 2630eda14cbcSMatt Macy { 2631eda14cbcSMatt Macy int add_perm; 2632eda14cbcSMatt Macy int error; 2633eda14cbcSMatt Macy 2634eda14cbcSMatt Macy if (szp->z_pflags & ZFS_AV_QUARANTINED) 2635eda14cbcSMatt Macy return (SET_ERROR(EACCES)); 2636eda14cbcSMatt Macy 2637eda14cbcSMatt Macy add_perm = (ZTOV(szp)->v_type == VDIR) ? 2638eda14cbcSMatt Macy ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE; 2639eda14cbcSMatt Macy 2640eda14cbcSMatt Macy /* 2641eda14cbcSMatt Macy * Rename permissions are combination of delete permission + 2642eda14cbcSMatt Macy * add file/subdir permission. 2643eda14cbcSMatt Macy * 2644eda14cbcSMatt Macy * BSD operating systems also require write permission 2645eda14cbcSMatt Macy * on the directory being moved from one parent directory 2646eda14cbcSMatt Macy * to another. 2647eda14cbcSMatt Macy */ 2648eda14cbcSMatt Macy if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) { 2649dbd5678dSMartin Matuska if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr, 2650dbd5678dSMartin Matuska mnt_ns))) 2651eda14cbcSMatt Macy return (error); 2652eda14cbcSMatt Macy } 2653eda14cbcSMatt Macy 2654eda14cbcSMatt Macy /* 2655eda14cbcSMatt Macy * first make sure we do the delete portion. 2656eda14cbcSMatt Macy * 2657eda14cbcSMatt Macy * If that succeeds then check for add_file/add_subdir permissions 2658eda14cbcSMatt Macy */ 2659eda14cbcSMatt Macy 2660dbd5678dSMartin Matuska if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns))) 2661eda14cbcSMatt Macy return (error); 2662eda14cbcSMatt Macy 2663eda14cbcSMatt Macy /* 2664eda14cbcSMatt Macy * If we have a tzp, see if we can delete it? 2665eda14cbcSMatt Macy */ 2666dbd5678dSMartin Matuska if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns))) 2667eda14cbcSMatt Macy return (error); 2668eda14cbcSMatt Macy 2669eda14cbcSMatt Macy /* 2670eda14cbcSMatt Macy * Now check for add permissions 2671eda14cbcSMatt Macy */ 2672dbd5678dSMartin Matuska error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns); 2673eda14cbcSMatt Macy 2674eda14cbcSMatt Macy return (error); 2675eda14cbcSMatt Macy } 2676