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