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