xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_acl.c (revision 1576:0364d1928a7f)
1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
51544Seschrock  * Common Development and Distribution License (the "License").
61544Seschrock  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
21789Sahrens /*
221308Smarks  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27789Sahrens 
28789Sahrens #include <sys/types.h>
29789Sahrens #include <sys/param.h>
30789Sahrens #include <sys/time.h>
31789Sahrens #include <sys/systm.h>
32789Sahrens #include <sys/sysmacros.h>
33789Sahrens #include <sys/resource.h>
34789Sahrens #include <sys/vfs.h>
35789Sahrens #include <sys/vnode.h>
36789Sahrens #include <sys/file.h>
37789Sahrens #include <sys/stat.h>
38789Sahrens #include <sys/kmem.h>
39789Sahrens #include <sys/cmn_err.h>
40789Sahrens #include <sys/errno.h>
41789Sahrens #include <sys/unistd.h>
42*1576Smarks #include <sys/sdt.h>
43789Sahrens #include <sys/fs/zfs.h>
44789Sahrens #include <sys/mode.h>
45789Sahrens #include <sys/policy.h>
46789Sahrens #include <sys/zfs_znode.h>
47789Sahrens #include <sys/zfs_acl.h>
48789Sahrens #include <sys/zfs_dir.h>
49789Sahrens #include <sys/zfs_vfsops.h>
50789Sahrens #include <sys/dmu.h>
51789Sahrens #include <sys/zap.h>
52789Sahrens #include <util/qsort.h>
53789Sahrens #include "fs/fs_subr.h"
54789Sahrens #include <acl/acl_common.h>
55789Sahrens 
56789Sahrens #define	ALLOW	ACE_ACCESS_ALLOWED_ACE_TYPE
57789Sahrens #define	DENY	ACE_ACCESS_DENIED_ACE_TYPE
58789Sahrens 
59789Sahrens #define	OWNING_GROUP		(ACE_GROUP|ACE_IDENTIFIER_GROUP)
60789Sahrens #define	EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \
61789Sahrens     ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE)
62789Sahrens #define	EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \
63789Sahrens     ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS)
64789Sahrens #define	OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \
65789Sahrens     ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS)
66789Sahrens #define	WRITE_MASK (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS| \
67789Sahrens     ACE_WRITE_ATTRIBUTES|ACE_WRITE_ACL|ACE_WRITE_OWNER)
68789Sahrens 
69789Sahrens #define	OGE_CLEAR	(ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \
70789Sahrens     ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE)
71789Sahrens 
72789Sahrens #define	OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \
73789Sahrens     ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE)
74789Sahrens 
75789Sahrens #define	ALL_INHERIT	(ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \
76789Sahrens     ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE)
77789Sahrens 
78*1576Smarks #define	SECURE_CLEAR	(ACE_WRITE_ACL|ACE_WRITE_OWNER)
79789Sahrens 
80789Sahrens #define	OGE_PAD	6		/* traditional owner/group/everyone ACES */
81789Sahrens 
82789Sahrens static int zfs_ace_can_use(znode_t *zp, ace_t *);
83789Sahrens 
84789Sahrens static zfs_acl_t *
85789Sahrens zfs_acl_alloc(int slots)
86789Sahrens {
87789Sahrens 	zfs_acl_t *aclp;
88789Sahrens 
89789Sahrens 	aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP);
90789Sahrens 	if (slots != 0) {
91789Sahrens 		aclp->z_acl = kmem_alloc(ZFS_ACL_SIZE(slots), KM_SLEEP);
92789Sahrens 		aclp->z_acl_count = 0;
93789Sahrens 		aclp->z_state = ACL_DATA_ALLOCED;
94789Sahrens 	} else {
95789Sahrens 		aclp->z_state = 0;
96789Sahrens 	}
97789Sahrens 	aclp->z_slots = slots;
98789Sahrens 	return (aclp);
99789Sahrens }
100789Sahrens 
101789Sahrens void
102789Sahrens zfs_acl_free(zfs_acl_t *aclp)
103789Sahrens {
104789Sahrens 	if (aclp->z_state == ACL_DATA_ALLOCED) {
105789Sahrens 		kmem_free(aclp->z_acl, ZFS_ACL_SIZE(aclp->z_slots));
106789Sahrens 	}
107789Sahrens 	kmem_free(aclp, sizeof (zfs_acl_t));
108789Sahrens }
109789Sahrens 
110789Sahrens static uint32_t
111789Sahrens zfs_v4_to_unix(uint32_t access_mask)
112789Sahrens {
113789Sahrens 	uint32_t new_mask = 0;
114789Sahrens 
115*1576Smarks 	/*
116*1576Smarks 	 * This is used for mapping v4 permissions into permissions
117*1576Smarks 	 * that can be passed to secpolicy_vnode_access()
118*1576Smarks 	 */
119*1576Smarks 	if (access_mask & (ACE_READ_DATA | ACE_LIST_DIRECTORY |
120*1576Smarks 	    ACE_READ_ATTRIBUTES | ACE_READ_ACL))
121789Sahrens 		new_mask |= S_IROTH;
122*1576Smarks 	if (access_mask & (ACE_WRITE_DATA | ACE_APPEND_DATA |
123*1576Smarks 	    ACE_WRITE_ATTRIBUTES | ACE_ADD_FILE | ACE_WRITE_NAMED_ATTRS))
124789Sahrens 		new_mask |= S_IWOTH;
125*1576Smarks 	if (access_mask & (ACE_EXECUTE | ACE_READ_NAMED_ATTRS))
126789Sahrens 		new_mask |= S_IXOTH;
127789Sahrens 
128789Sahrens 	return (new_mask);
129789Sahrens }
130789Sahrens 
131789Sahrens /*
132789Sahrens  * Convert unix access mask to v4 access mask
133789Sahrens  */
134789Sahrens static uint32_t
135789Sahrens zfs_unix_to_v4(uint32_t access_mask)
136789Sahrens {
137789Sahrens 	uint32_t new_mask = 0;
138789Sahrens 
139789Sahrens 	if (access_mask & 01)
140789Sahrens 		new_mask |= (ACE_EXECUTE);
141789Sahrens 	if (access_mask & 02) {
142789Sahrens 		new_mask |= (ACE_WRITE_DATA);
143789Sahrens 	} if (access_mask & 04) {
144789Sahrens 		new_mask |= ACE_READ_DATA;
145789Sahrens 	}
146789Sahrens 	return (new_mask);
147789Sahrens }
148789Sahrens 
149789Sahrens static void
150789Sahrens zfs_set_ace(ace_t *zacep, uint32_t access_mask, int access_type,
151789Sahrens     uid_t uid, int entry_type)
152789Sahrens {
153789Sahrens 	zacep->a_access_mask = access_mask;
154789Sahrens 	zacep->a_type = access_type;
155789Sahrens 	zacep->a_who = uid;
156789Sahrens 	zacep->a_flags = entry_type;
157789Sahrens }
158789Sahrens 
159789Sahrens static uint64_t
160789Sahrens zfs_mode_compute(znode_t *zp, zfs_acl_t *aclp)
161789Sahrens {
162789Sahrens 	int 	i;
163789Sahrens 	int	entry_type;
164789Sahrens 	mode_t	mode = (zp->z_phys->zp_mode &
165789Sahrens 	    (S_IFMT | S_ISUID | S_ISGID | S_ISVTX));
166789Sahrens 	mode_t	 seen = 0;
167789Sahrens 	ace_t 	*acep;
168789Sahrens 
169789Sahrens 	for (i = 0, acep = aclp->z_acl;
170789Sahrens 	    i != aclp->z_acl_count; i++, acep++) {
171*1576Smarks 		entry_type = (acep->a_flags & ACE_TYPE_FLAGS);
172789Sahrens 		if (entry_type == ACE_OWNER) {
173789Sahrens 			if ((acep->a_access_mask & ACE_READ_DATA) &&
174789Sahrens 			    (!(seen & S_IRUSR))) {
175789Sahrens 				seen |= S_IRUSR;
176789Sahrens 				if (acep->a_type == ALLOW) {
177789Sahrens 					mode |= S_IRUSR;
178789Sahrens 				}
179789Sahrens 			}
180789Sahrens 			if ((acep->a_access_mask & ACE_WRITE_DATA) &&
181789Sahrens 			    (!(seen & S_IWUSR))) {
182789Sahrens 				seen |= S_IWUSR;
183789Sahrens 				if (acep->a_type == ALLOW) {
184789Sahrens 					mode |= S_IWUSR;
185789Sahrens 				}
186789Sahrens 			}
187789Sahrens 			if ((acep->a_access_mask & ACE_EXECUTE) &&
188789Sahrens 			    (!(seen & S_IXUSR))) {
189789Sahrens 				seen |= S_IXUSR;
190789Sahrens 				if (acep->a_type == ALLOW) {
191789Sahrens 					mode |= S_IXUSR;
192789Sahrens 				}
193789Sahrens 			}
194789Sahrens 		} else if (entry_type == OWNING_GROUP) {
195789Sahrens 			if ((acep->a_access_mask & ACE_READ_DATA) &&
196789Sahrens 			    (!(seen & S_IRGRP))) {
197789Sahrens 				seen |= S_IRGRP;
198789Sahrens 				if (acep->a_type == ALLOW) {
199789Sahrens 					mode |= S_IRGRP;
200789Sahrens 				}
201789Sahrens 			}
202789Sahrens 			if ((acep->a_access_mask & ACE_WRITE_DATA) &&
203789Sahrens 			    (!(seen & S_IWGRP))) {
204789Sahrens 				seen |= S_IWGRP;
205789Sahrens 				if (acep->a_type == ALLOW) {
206789Sahrens 					mode |= S_IWGRP;
207789Sahrens 				}
208789Sahrens 			}
209789Sahrens 			if ((acep->a_access_mask & ACE_EXECUTE) &&
210789Sahrens 			    (!(seen & S_IXGRP))) {
211789Sahrens 				seen |= S_IXGRP;
212789Sahrens 				if (acep->a_type == ALLOW) {
213789Sahrens 					mode |= S_IXGRP;
214789Sahrens 				}
215789Sahrens 			}
216789Sahrens 		} else if (entry_type == ACE_EVERYONE) {
217789Sahrens 			if ((acep->a_access_mask & ACE_READ_DATA)) {
218789Sahrens 				if (!(seen & S_IRUSR)) {
219789Sahrens 					seen |= S_IRUSR;
220789Sahrens 					if (acep->a_type == ALLOW) {
221789Sahrens 						mode |= S_IRUSR;
222789Sahrens 					}
223789Sahrens 				}
224789Sahrens 				if (!(seen & S_IRGRP)) {
225789Sahrens 					seen |= S_IRGRP;
226789Sahrens 					if (acep->a_type == ALLOW) {
227789Sahrens 						mode |= S_IRGRP;
228789Sahrens 					}
229789Sahrens 				}
230789Sahrens 				if (!(seen & S_IROTH)) {
231789Sahrens 					seen |= S_IROTH;
232789Sahrens 					if (acep->a_type == ALLOW) {
233789Sahrens 						mode |= S_IROTH;
234789Sahrens 					}
235789Sahrens 				}
236789Sahrens 			}
237789Sahrens 			if ((acep->a_access_mask & ACE_WRITE_DATA)) {
238789Sahrens 				if (!(seen & S_IWUSR)) {
239789Sahrens 					seen |= S_IWUSR;
240789Sahrens 					if (acep->a_type == ALLOW) {
241789Sahrens 						mode |= S_IWUSR;
242789Sahrens 					}
243789Sahrens 				}
244789Sahrens 				if (!(seen & S_IWGRP)) {
245789Sahrens 					seen |= S_IWGRP;
246789Sahrens 					if (acep->a_type == ALLOW) {
247789Sahrens 						mode |= S_IWGRP;
248789Sahrens 					}
249789Sahrens 				}
250789Sahrens 				if (!(seen & S_IWOTH)) {
251789Sahrens 					seen |= S_IWOTH;
252789Sahrens 					if (acep->a_type == ALLOW) {
253789Sahrens 						mode |= S_IWOTH;
254789Sahrens 					}
255789Sahrens 				}
256789Sahrens 			}
257789Sahrens 			if ((acep->a_access_mask & ACE_EXECUTE)) {
258789Sahrens 				if (!(seen & S_IXUSR)) {
259789Sahrens 					seen |= S_IXUSR;
260789Sahrens 					if (acep->a_type == ALLOW) {
261789Sahrens 						mode |= S_IXUSR;
262789Sahrens 					}
263789Sahrens 				}
264789Sahrens 				if (!(seen & S_IXGRP)) {
265789Sahrens 					seen |= S_IXGRP;
266789Sahrens 					if (acep->a_type == ALLOW) {
267789Sahrens 						mode |= S_IXGRP;
268789Sahrens 					}
269789Sahrens 				}
270789Sahrens 				if (!(seen & S_IXOTH)) {
271789Sahrens 					seen |= S_IXOTH;
272789Sahrens 					if (acep->a_type == ALLOW) {
273789Sahrens 						mode |= S_IXOTH;
274789Sahrens 					}
275789Sahrens 				}
276789Sahrens 			}
277789Sahrens 		}
278789Sahrens 	}
279789Sahrens 	return (mode);
280789Sahrens }
281789Sahrens 
282789Sahrens static zfs_acl_t *
283789Sahrens zfs_acl_node_read_internal(znode_t *zp)
284789Sahrens {
285789Sahrens 	zfs_acl_t	*aclp;
286789Sahrens 
287789Sahrens 	aclp = zfs_acl_alloc(0);
288789Sahrens 	aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count;
289789Sahrens 	aclp->z_acl = &zp->z_phys->zp_acl.z_ace_data[0];
290789Sahrens 
291789Sahrens 	return (aclp);
292789Sahrens }
293789Sahrens 
294789Sahrens /*
295789Sahrens  * Read an external acl object.
296789Sahrens  */
2971544Seschrock static int
2981544Seschrock zfs_acl_node_read(znode_t *zp, zfs_acl_t **aclpp)
299789Sahrens {
300789Sahrens 	uint64_t extacl = zp->z_phys->zp_acl.z_acl_extern_obj;
301789Sahrens 	zfs_acl_t	*aclp;
3021544Seschrock 	int error;
303789Sahrens 
304789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_acl_lock));
305789Sahrens 
3061544Seschrock 	if (zp->z_phys->zp_acl.z_acl_extern_obj == 0) {
3071544Seschrock 		*aclpp = zfs_acl_node_read_internal(zp);
3081544Seschrock 		return (0);
3091544Seschrock 	}
310789Sahrens 
311789Sahrens 	aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_count);
312789Sahrens 
3131544Seschrock 	error = dmu_read(zp->z_zfsvfs->z_os, extacl, 0,
314789Sahrens 	    ZFS_ACL_SIZE(zp->z_phys->zp_acl.z_acl_count), aclp->z_acl);
3151544Seschrock 	if (error != 0) {
3161544Seschrock 		zfs_acl_free(aclp);
3171544Seschrock 		return (error);
3181544Seschrock 	}
319789Sahrens 
320789Sahrens 	aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count;
321789Sahrens 
3221544Seschrock 	*aclpp = aclp;
3231544Seschrock 	return (0);
324789Sahrens }
325789Sahrens 
326789Sahrens static boolean_t
327789Sahrens zfs_acl_valid(znode_t *zp, ace_t *uace, int aclcnt, int *inherit)
328789Sahrens {
329789Sahrens 	ace_t 	*acep;
330789Sahrens 	int i;
331789Sahrens 
332789Sahrens 	*inherit = 0;
333789Sahrens 
334789Sahrens 	if (aclcnt > MAX_ACL_ENTRIES || aclcnt <= 0) {
335789Sahrens 		return (B_FALSE);
336789Sahrens 	}
337789Sahrens 
338789Sahrens 	for (i = 0, acep = uace; i != aclcnt; i++, acep++) {
339789Sahrens 
340789Sahrens 		/*
341789Sahrens 		 * first check type of entry
342789Sahrens 		 */
343789Sahrens 
344*1576Smarks 		switch (acep->a_flags & ACE_TYPE_FLAGS) {
345789Sahrens 		case ACE_OWNER:
346789Sahrens 			acep->a_who = -1;
347789Sahrens 			break;
348789Sahrens 		case (ACE_IDENTIFIER_GROUP | ACE_GROUP):
349789Sahrens 		case ACE_IDENTIFIER_GROUP:
350789Sahrens 			if (acep->a_flags & ACE_GROUP) {
351789Sahrens 				acep->a_who = -1;
352789Sahrens 			}
353789Sahrens 			break;
354789Sahrens 		case ACE_EVERYONE:
355789Sahrens 			acep->a_who = -1;
356789Sahrens 			break;
357789Sahrens 		}
358789Sahrens 
359789Sahrens 		/*
360789Sahrens 		 * next check inheritance level flags
361789Sahrens 		 */
362789Sahrens 
363789Sahrens 		if (acep->a_type != ALLOW && acep->a_type != DENY)
364789Sahrens 			return (B_FALSE);
365789Sahrens 
366789Sahrens 		/*
367789Sahrens 		 * Only directories should have inheritance flags.
368789Sahrens 		 */
369789Sahrens 		if (ZTOV(zp)->v_type != VDIR && (acep->a_flags &
370789Sahrens 		    (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE|
371789Sahrens 		    ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE))) {
372789Sahrens 			return (B_FALSE);
373789Sahrens 		}
374789Sahrens 
375789Sahrens 		if (acep->a_flags &
376789Sahrens 		    (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))
377789Sahrens 			*inherit = 1;
378789Sahrens 
379789Sahrens 		if (acep->a_flags &
380789Sahrens 		    (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) {
381789Sahrens 			if ((acep->a_flags & (ACE_FILE_INHERIT_ACE|
382789Sahrens 			    ACE_DIRECTORY_INHERIT_ACE)) == 0) {
383789Sahrens 				return (B_FALSE);
384789Sahrens 			}
385789Sahrens 		}
386789Sahrens 	}
387789Sahrens 
388789Sahrens 	return (B_TRUE);
389789Sahrens }
390789Sahrens /*
391789Sahrens  * common code for setting acl's.
392789Sahrens  *
393789Sahrens  * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl.
394789Sahrens  * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's
395789Sahrens  * already checked the acl and knows whether to inherit.
396789Sahrens  */
397789Sahrens int
398789Sahrens zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, dmu_tx_t *tx, int *ihp)
399789Sahrens {
400789Sahrens 	int 		inherit = 0;
401789Sahrens 	int		error;
402789Sahrens 	znode_phys_t	*zphys = zp->z_phys;
403789Sahrens 	zfs_znode_acl_t	*zacl = &zphys->zp_acl;
404789Sahrens 	uint32_t	acl_phys_size = ZFS_ACL_SIZE(aclp->z_acl_count);
405789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
406789Sahrens 	uint64_t	aoid = zphys->zp_acl.z_acl_extern_obj;
407789Sahrens 
408789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_lock));
409789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_acl_lock));
410789Sahrens 
411789Sahrens 	if (ihp)
412789Sahrens 		inherit = *ihp;		/* already determined by caller */
413789Sahrens 	else if (!zfs_acl_valid(zp, aclp->z_acl,
414789Sahrens 	    aclp->z_acl_count, &inherit)) {
415789Sahrens 		return (EINVAL);
416789Sahrens 	}
417789Sahrens 
418789Sahrens 	dmu_buf_will_dirty(zp->z_dbuf, tx);
419789Sahrens 
420789Sahrens 	/*
421789Sahrens 	 * Will ACL fit internally?
422789Sahrens 	 */
423789Sahrens 	if (aclp->z_acl_count > ACE_SLOT_CNT) {
424789Sahrens 		if (aoid == 0) {
425789Sahrens 			aoid = dmu_object_alloc(zfsvfs->z_os,
426789Sahrens 			    DMU_OT_ACL, acl_phys_size, DMU_OT_NONE, 0, tx);
427789Sahrens 		} else {
428789Sahrens 			(void) dmu_object_set_blocksize(zfsvfs->z_os, aoid,
429789Sahrens 			    acl_phys_size, 0, tx);
430789Sahrens 		}
431789Sahrens 		zphys->zp_acl.z_acl_extern_obj = aoid;
432789Sahrens 		zphys->zp_acl.z_acl_count = aclp->z_acl_count;
433789Sahrens 		dmu_write(zfsvfs->z_os, aoid, 0,
434789Sahrens 		    acl_phys_size, aclp->z_acl, tx);
435789Sahrens 	} else {
436789Sahrens 		/*
437789Sahrens 		 * Migrating back embedded?
438789Sahrens 		 */
439789Sahrens 		if (zphys->zp_acl.z_acl_extern_obj) {
440789Sahrens 			error = dmu_object_free(zfsvfs->z_os,
441789Sahrens 				zp->z_phys->zp_acl.z_acl_extern_obj, tx);
442789Sahrens 			if (error)
443789Sahrens 				return (error);
444789Sahrens 			zphys->zp_acl.z_acl_extern_obj = 0;
445789Sahrens 		}
446789Sahrens 		bcopy(aclp->z_acl, zacl->z_ace_data,
447789Sahrens 		    aclp->z_acl_count * sizeof (ace_t));
448789Sahrens 		zacl->z_acl_count = aclp->z_acl_count;
449789Sahrens 	}
450905Smarks 
451905Smarks 	zp->z_phys->zp_flags &= ~(ZFS_ACL_TRIVIAL|ZFS_INHERIT_ACE);
452905Smarks 	if (inherit) {
453789Sahrens 		zp->z_phys->zp_flags |= ZFS_INHERIT_ACE;
454905Smarks 	} else if (ace_trivial(zacl->z_ace_data, zacl->z_acl_count) == 0) {
455905Smarks 		zp->z_phys->zp_flags |= ZFS_ACL_TRIVIAL;
456905Smarks 	}
457789Sahrens 
458789Sahrens 	zphys->zp_mode = zfs_mode_compute(zp, aclp);
459789Sahrens 	zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
460789Sahrens 
461789Sahrens 	return (0);
462789Sahrens }
463789Sahrens 
464789Sahrens /*
465789Sahrens  * Create space for slots_needed ACEs to be append
466789Sahrens  * to aclp.
467789Sahrens  */
468789Sahrens static void
469789Sahrens zfs_acl_append(zfs_acl_t *aclp, int slots_needed)
470789Sahrens {
471789Sahrens 	ace_t	*newacep;
472789Sahrens 	ace_t	*oldaclp;
473789Sahrens 	int	slot_cnt;
474789Sahrens 	int 	slots_left = aclp->z_slots - aclp->z_acl_count;
475789Sahrens 
476789Sahrens 	if (aclp->z_state == ACL_DATA_ALLOCED)
477789Sahrens 		ASSERT(aclp->z_slots >= aclp->z_acl_count);
478789Sahrens 	if (slots_left < slots_needed || aclp->z_state != ACL_DATA_ALLOCED) {
479789Sahrens 		slot_cnt = aclp->z_slots +  1 + (slots_needed - slots_left);
480789Sahrens 		newacep = kmem_alloc(ZFS_ACL_SIZE(slot_cnt), KM_SLEEP);
481789Sahrens 		bcopy(aclp->z_acl, newacep,
482789Sahrens 		    ZFS_ACL_SIZE(aclp->z_acl_count));
483789Sahrens 		oldaclp = aclp->z_acl;
484789Sahrens 		if (aclp->z_state == ACL_DATA_ALLOCED)
485789Sahrens 			kmem_free(oldaclp, ZFS_ACL_SIZE(aclp->z_slots));
486789Sahrens 		aclp->z_acl = newacep;
487789Sahrens 		aclp->z_slots = slot_cnt;
488789Sahrens 		aclp->z_state = ACL_DATA_ALLOCED;
489789Sahrens 	}
490789Sahrens }
491789Sahrens 
492789Sahrens /*
493789Sahrens  * Remove "slot" ACE from aclp
494789Sahrens  */
495789Sahrens static void
496789Sahrens zfs_ace_remove(zfs_acl_t *aclp, int slot)
497789Sahrens {
498789Sahrens 	if (aclp->z_acl_count > 1) {
499789Sahrens 		(void) memmove(&aclp->z_acl[slot],
500789Sahrens 		    &aclp->z_acl[slot +1], sizeof (ace_t) *
501789Sahrens 		    (--aclp->z_acl_count - slot));
502789Sahrens 	} else
503789Sahrens 		aclp->z_acl_count--;
504789Sahrens }
505789Sahrens 
506789Sahrens /*
507789Sahrens  * Update access mask for prepended ACE
508789Sahrens  *
509789Sahrens  * This applies the "groupmask" value for aclmode property.
510789Sahrens  */
511789Sahrens static void
512789Sahrens zfs_acl_prepend_fixup(ace_t *acep, ace_t *origacep, mode_t mode, uid_t owner)
513789Sahrens {
514789Sahrens 
515789Sahrens 	int	rmask, wmask, xmask;
516789Sahrens 	int	user_ace;
517789Sahrens 
518789Sahrens 	user_ace = (!(acep->a_flags &
519789Sahrens 	    (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP)));
520789Sahrens 
521789Sahrens 	if (user_ace && (acep->a_who == owner)) {
522789Sahrens 		rmask = S_IRUSR;
523789Sahrens 		wmask = S_IWUSR;
524789Sahrens 		xmask = S_IXUSR;
525789Sahrens 	} else {
526789Sahrens 		rmask = S_IRGRP;
527789Sahrens 		wmask = S_IWGRP;
528789Sahrens 		xmask = S_IXGRP;
529789Sahrens 	}
530789Sahrens 
531789Sahrens 	if (origacep->a_access_mask & ACE_READ_DATA) {
532789Sahrens 		if (mode & rmask)
533789Sahrens 			acep->a_access_mask &= ~ACE_READ_DATA;
534789Sahrens 		else
535789Sahrens 			acep->a_access_mask |= ACE_READ_DATA;
536789Sahrens 	}
537789Sahrens 
538789Sahrens 	if (origacep->a_access_mask & ACE_WRITE_DATA) {
539789Sahrens 		if (mode & wmask)
540789Sahrens 			acep->a_access_mask &= ~ACE_WRITE_DATA;
541789Sahrens 		else
542789Sahrens 			acep->a_access_mask |= ACE_WRITE_DATA;
543789Sahrens 	}
544789Sahrens 
545789Sahrens 	if (origacep->a_access_mask & ACE_APPEND_DATA) {
546789Sahrens 		if (mode & wmask)
547789Sahrens 			acep->a_access_mask &= ~ACE_APPEND_DATA;
548789Sahrens 		else
549789Sahrens 			acep->a_access_mask |= ACE_APPEND_DATA;
550789Sahrens 	}
551789Sahrens 
552789Sahrens 	if (origacep->a_access_mask & ACE_EXECUTE) {
553789Sahrens 		if (mode & xmask)
554789Sahrens 			acep->a_access_mask &= ~ACE_EXECUTE;
555789Sahrens 		else
556789Sahrens 			acep->a_access_mask |= ACE_EXECUTE;
557789Sahrens 	}
558789Sahrens }
559789Sahrens 
560789Sahrens /*
561789Sahrens  * Apply mode to canonical six ACEs.
562789Sahrens  */
563789Sahrens static void
564789Sahrens zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode)
565789Sahrens {
566789Sahrens 	int	cnt;
567789Sahrens 	ace_t	*acep;
568789Sahrens 
569789Sahrens 	cnt = aclp->z_acl_count -1;
570789Sahrens 	acep = aclp->z_acl;
571789Sahrens 
572789Sahrens 	/*
573789Sahrens 	 * Fixup final ACEs to match the mode
574789Sahrens 	 */
575789Sahrens 
576789Sahrens 	ASSERT(cnt >= 5);
577789Sahrens 	adjust_ace_pair(&acep[cnt - 1], mode);	/* everyone@ */
578789Sahrens 	adjust_ace_pair(&acep[cnt - 3], (mode & 0070) >> 3);	/* group@ */
579789Sahrens 	adjust_ace_pair(&acep[cnt - 5], (mode & 0700) >> 6);	/* owner@ */
580789Sahrens }
581789Sahrens 
582789Sahrens 
583789Sahrens static int
584789Sahrens zfs_acl_ace_match(ace_t *acep, int allow_deny, int type, int mask)
585789Sahrens {
586789Sahrens 	return (acep->a_access_mask == mask && acep->a_type == allow_deny &&
587*1576Smarks 	    ((acep->a_flags & ACE_TYPE_FLAGS) == type));
588789Sahrens }
589789Sahrens 
590789Sahrens /*
591789Sahrens  * Can prepended ACE be reused?
592789Sahrens  */
593789Sahrens static int
594789Sahrens zfs_reuse_deny(ace_t *acep, int i)
595789Sahrens {
596789Sahrens 	int okay_masks;
597789Sahrens 
598789Sahrens 	if (i < 1)
599789Sahrens 		return (B_FALSE);
600789Sahrens 
601789Sahrens 	if (acep[i-1].a_type != DENY)
602789Sahrens 		return (B_FALSE);
603789Sahrens 
604789Sahrens 	if (acep[i-1].a_flags != (acep[i].a_flags & ACE_IDENTIFIER_GROUP))
605789Sahrens 		return (B_FALSE);
606789Sahrens 
607789Sahrens 	okay_masks = (acep[i].a_access_mask & OKAY_MASK_BITS);
608789Sahrens 
609789Sahrens 	if (acep[i-1].a_access_mask & ~okay_masks)
610789Sahrens 		return (B_FALSE);
611789Sahrens 
612789Sahrens 	return (B_TRUE);
613789Sahrens }
614789Sahrens 
615789Sahrens /*
616789Sahrens  * Create space to prepend an ACE
617789Sahrens  */
618789Sahrens static void
619789Sahrens zfs_acl_prepend(zfs_acl_t *aclp, int i)
620789Sahrens {
621789Sahrens 	ace_t	*oldaclp = NULL;
622789Sahrens 	ace_t	*to, *from;
623789Sahrens 	int	slots_left = aclp->z_slots - aclp->z_acl_count;
624789Sahrens 	int	oldslots;
625789Sahrens 	int	need_free = 0;
626789Sahrens 
627789Sahrens 	if (aclp->z_state == ACL_DATA_ALLOCED)
628789Sahrens 		ASSERT(aclp->z_slots >= aclp->z_acl_count);
629789Sahrens 
630789Sahrens 	if (slots_left == 0 || aclp->z_state != ACL_DATA_ALLOCED) {
631789Sahrens 
632789Sahrens 		to = kmem_alloc(ZFS_ACL_SIZE(aclp->z_acl_count +
633789Sahrens 		    OGE_PAD), KM_SLEEP);
634789Sahrens 		if (aclp->z_state == ACL_DATA_ALLOCED)
635789Sahrens 			need_free++;
636789Sahrens 		from = aclp->z_acl;
637789Sahrens 		oldaclp = aclp->z_acl;
638789Sahrens 		(void) memmove(to, from,
639789Sahrens 		    sizeof (ace_t) * aclp->z_acl_count);
640789Sahrens 		aclp->z_state = ACL_DATA_ALLOCED;
641789Sahrens 	} else {
642789Sahrens 		from = aclp->z_acl;
643789Sahrens 		to = aclp->z_acl;
644789Sahrens 	}
645789Sahrens 
646789Sahrens 
647789Sahrens 	(void) memmove(&to[i + 1], &from[i],
648789Sahrens 	    sizeof (ace_t) * (aclp->z_acl_count - i));
649789Sahrens 
650789Sahrens 	if (oldaclp) {
651789Sahrens 		aclp->z_acl = to;
652789Sahrens 		oldslots = aclp->z_slots;
653789Sahrens 		aclp->z_slots = aclp->z_acl_count + OGE_PAD;
654789Sahrens 		if (need_free)
655789Sahrens 			kmem_free(oldaclp, ZFS_ACL_SIZE(oldslots));
656789Sahrens 	}
657789Sahrens 
658789Sahrens }
659789Sahrens 
660789Sahrens /*
661789Sahrens  * Prepend deny ACE
662789Sahrens  */
663789Sahrens static void
664789Sahrens zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, int i,
665789Sahrens     mode_t mode)
666789Sahrens {
667789Sahrens 	ace_t	*acep;
668789Sahrens 
669789Sahrens 	zfs_acl_prepend(aclp, i);
670789Sahrens 
671789Sahrens 	acep = aclp->z_acl;
672789Sahrens 	zfs_set_ace(&acep[i], 0, DENY, acep[i + 1].a_who,
673*1576Smarks 	    (acep[i + 1].a_flags & ACE_TYPE_FLAGS));
674789Sahrens 	zfs_acl_prepend_fixup(&acep[i], &acep[i+1], mode, zp->z_phys->zp_uid);
675789Sahrens 	aclp->z_acl_count++;
676789Sahrens }
677789Sahrens 
678789Sahrens /*
679789Sahrens  * Split an inherited ACE into inherit_only ACE
680789Sahrens  * and original ACE with inheritance flags stripped off.
681789Sahrens  */
682789Sahrens static void
683789Sahrens zfs_acl_split_ace(zfs_acl_t *aclp, int i)
684789Sahrens {
685789Sahrens 	ace_t *acep = aclp->z_acl;
686789Sahrens 
687789Sahrens 	zfs_acl_prepend(aclp, i);
688789Sahrens 	acep = aclp->z_acl;
689789Sahrens 	acep[i] = acep[i + 1];
690789Sahrens 	acep[i].a_flags |= ACE_INHERIT_ONLY_ACE;
691789Sahrens 	acep[i + 1].a_flags &= ~ALL_INHERIT;
692789Sahrens 	aclp->z_acl_count++;
693789Sahrens }
694789Sahrens 
695789Sahrens /*
696789Sahrens  * Are ACES started at index i, the canonical six ACES?
697789Sahrens  */
698789Sahrens static int
699789Sahrens zfs_have_canonical_six(zfs_acl_t *aclp, int i)
700789Sahrens {
701789Sahrens 	ace_t *acep = aclp->z_acl;
702789Sahrens 
703789Sahrens 	if ((zfs_acl_ace_match(&acep[i],
704789Sahrens 	    DENY, ACE_OWNER, 0) &&
705789Sahrens 	    zfs_acl_ace_match(&acep[i + 1], ALLOW, ACE_OWNER,
706789Sahrens 	    OWNER_ALLOW_MASK) && zfs_acl_ace_match(&acep[i + 2],
707789Sahrens 	    DENY, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 3],
708789Sahrens 	    ALLOW, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 4],
709789Sahrens 	    DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) &&
710789Sahrens 	    zfs_acl_ace_match(&acep[i + 5], ALLOW, ACE_EVERYONE,
711789Sahrens 	    EVERYONE_ALLOW_MASK))) {
712789Sahrens 		return (1);
713789Sahrens 	} else {
714789Sahrens 		return (0);
715789Sahrens 	}
716789Sahrens }
717789Sahrens 
718789Sahrens /*
719789Sahrens  * Apply step 1g, to group entries
720789Sahrens  *
721789Sahrens  * Need to deal with corner case where group may have
722789Sahrens  * greater permissions than owner.  If so then limit
723789Sahrens  * group permissions, based on what extra permissions
724789Sahrens  * group has.
725789Sahrens  */
726789Sahrens static void
727789Sahrens zfs_fixup_group_entries(ace_t *acep, mode_t mode)
728789Sahrens {
729789Sahrens 	mode_t extramode = (mode >> 3) & 07;
730789Sahrens 	mode_t ownermode = (mode >> 6);
731789Sahrens 
732789Sahrens 	if (acep[0].a_flags & ACE_IDENTIFIER_GROUP) {
733789Sahrens 
734789Sahrens 		extramode &= ~ownermode;
735789Sahrens 
736789Sahrens 		if (extramode) {
737789Sahrens 			if (extramode & 04) {
738789Sahrens 				acep[0].a_access_mask &= ~ACE_READ_DATA;
739789Sahrens 				acep[1].a_access_mask &= ~ACE_READ_DATA;
740789Sahrens 			}
741789Sahrens 			if (extramode & 02) {
742789Sahrens 				acep[0].a_access_mask &=
743789Sahrens 				    ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
744789Sahrens 				acep[1].a_access_mask &=
745789Sahrens 				    ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
746789Sahrens 			}
747789Sahrens 			if (extramode & 01) {
748789Sahrens 				acep[0].a_access_mask &= ~ACE_EXECUTE;
749789Sahrens 				acep[1].a_access_mask &= ~ACE_EXECUTE;
750789Sahrens 			}
751789Sahrens 		}
752789Sahrens 	}
753789Sahrens }
754789Sahrens 
755789Sahrens /*
756789Sahrens  * Apply the chmod algorithm as described
757789Sahrens  * in PSARC/2002/240
758789Sahrens  */
759789Sahrens static int
760789Sahrens zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp,
761789Sahrens     dmu_tx_t *tx)
762789Sahrens {
763789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
764789Sahrens 	ace_t 		*acep;
765789Sahrens 	int 		i;
766789Sahrens 	int		error;
767789Sahrens 	int 		entry_type;
768789Sahrens 	int 		reuse_deny;
769789Sahrens 	int 		need_canonical_six = 1;
770905Smarks 	int		inherit = 0;
771905Smarks 	int		iflags;
772789Sahrens 
773789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_acl_lock));
774789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_lock));
775789Sahrens 
776789Sahrens 	i = 0;
777789Sahrens 	while (i < aclp->z_acl_count) {
778789Sahrens 		acep = aclp->z_acl;
779*1576Smarks 		entry_type = (acep[i].a_flags & ACE_TYPE_FLAGS);
780905Smarks 		iflags = (acep[i].a_flags & ALL_INHERIT);
781789Sahrens 
782789Sahrens 		if ((acep[i].a_type != ALLOW && acep[i].a_type != DENY) ||
783905Smarks 		    (iflags & ACE_INHERIT_ONLY_ACE)) {
784789Sahrens 			i++;
785905Smarks 			if (iflags)
786905Smarks 				inherit = 1;
787789Sahrens 			continue;
788789Sahrens 		}
789789Sahrens 
790789Sahrens 
791789Sahrens 		if (zfsvfs->z_acl_mode == DISCARD) {
792789Sahrens 			zfs_ace_remove(aclp, i);
793789Sahrens 			continue;
794789Sahrens 		}
795789Sahrens 
796789Sahrens 		/*
797789Sahrens 		 * Need to split ace into two?
798789Sahrens 		 */
799905Smarks 		if ((iflags & (ACE_FILE_INHERIT_ACE|
800789Sahrens 		    ACE_DIRECTORY_INHERIT_ACE)) &&
801905Smarks 		    (!(iflags & ACE_INHERIT_ONLY_ACE))) {
802789Sahrens 			zfs_acl_split_ace(aclp, i);
803789Sahrens 			i++;
804905Smarks 			inherit = 1;
805789Sahrens 			continue;
806789Sahrens 		}
807789Sahrens 
808789Sahrens 		if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE ||
809789Sahrens 		    (entry_type == OWNING_GROUP)) {
810789Sahrens 			acep[i].a_access_mask &= ~OGE_CLEAR;
811789Sahrens 			i++;
812789Sahrens 			continue;
813789Sahrens 
814789Sahrens 		} else {
815789Sahrens 			if (acep[i].a_type == ALLOW) {
816789Sahrens 
817789Sahrens 				/*
818789Sahrens 				 * Check preceding ACE if any, to see
819789Sahrens 				 * if we need to prepend a DENY ACE.
820789Sahrens 				 * This is only applicable when the acl_mode
821789Sahrens 				 * property == groupmask.
822789Sahrens 				 */
823789Sahrens 				if (zfsvfs->z_acl_mode == GROUPMASK) {
824789Sahrens 
825789Sahrens 					reuse_deny = zfs_reuse_deny(acep, i);
826789Sahrens 
827789Sahrens 					if (reuse_deny == B_FALSE) {
828789Sahrens 						zfs_acl_prepend_deny(zp, aclp,
829789Sahrens 						    i, mode);
830789Sahrens 						i++;
831789Sahrens 						acep = aclp->z_acl;
832789Sahrens 					} else {
833789Sahrens 						zfs_acl_prepend_fixup(
834789Sahrens 						    &acep[i - 1],
835789Sahrens 						    &acep[i], mode,
836789Sahrens 						    zp->z_phys->zp_uid);
837789Sahrens 					}
838789Sahrens 					zfs_fixup_group_entries(&acep[i - 1],
839789Sahrens 					    mode);
840789Sahrens 				}
841789Sahrens 			}
842789Sahrens 			i++;
843789Sahrens 		}
844789Sahrens 	}
845789Sahrens 
846789Sahrens 	/*
847789Sahrens 	 * Check out last six aces, if we have six.
848789Sahrens 	 */
849789Sahrens 
850789Sahrens 	if (aclp->z_acl_count >= 6) {
851789Sahrens 		i = aclp->z_acl_count - 6;
852789Sahrens 
853789Sahrens 		if (zfs_have_canonical_six(aclp, i)) {
854789Sahrens 			need_canonical_six = 0;
855789Sahrens 		}
856789Sahrens 	}
857789Sahrens 
858789Sahrens 	if (need_canonical_six) {
859789Sahrens 
860789Sahrens 		zfs_acl_append(aclp, 6);
861789Sahrens 		i = aclp->z_acl_count;
862789Sahrens 		acep = aclp->z_acl;
863789Sahrens 		zfs_set_ace(&acep[i++], 0, DENY, -1, ACE_OWNER);
864789Sahrens 		zfs_set_ace(&acep[i++], OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER);
865789Sahrens 		zfs_set_ace(&acep[i++], 0, DENY, -1, OWNING_GROUP);
866789Sahrens 		zfs_set_ace(&acep[i++], 0, ALLOW, -1, OWNING_GROUP);
867789Sahrens 		zfs_set_ace(&acep[i++], EVERYONE_DENY_MASK,
868789Sahrens 		    DENY, -1, ACE_EVERYONE);
869789Sahrens 		zfs_set_ace(&acep[i++], EVERYONE_ALLOW_MASK,
870789Sahrens 		    ALLOW, -1, ACE_EVERYONE);
871789Sahrens 		aclp->z_acl_count += 6;
872789Sahrens 	}
873789Sahrens 
874789Sahrens 	zfs_acl_fixup_canonical_six(aclp, mode);
875789Sahrens 
876789Sahrens 	zp->z_phys->zp_mode = mode;
877905Smarks 	error = zfs_aclset_common(zp, aclp, tx, &inherit);
878789Sahrens 	return (error);
879789Sahrens }
880789Sahrens 
881789Sahrens 
882789Sahrens int
883789Sahrens zfs_acl_chmod_setattr(znode_t *zp, uint64_t mode, dmu_tx_t *tx)
884789Sahrens {
8851544Seschrock 	zfs_acl_t *aclp = NULL;
886789Sahrens 	int error;
887789Sahrens 
888789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_lock));
889789Sahrens 	mutex_enter(&zp->z_acl_lock);
8901544Seschrock 	error = zfs_acl_node_read(zp, &aclp);
8911544Seschrock 	if (error == 0)
8921544Seschrock 		error = zfs_acl_chmod(zp, mode, aclp, tx);
893789Sahrens 	mutex_exit(&zp->z_acl_lock);
8941544Seschrock 	if (aclp)
8951544Seschrock 		zfs_acl_free(aclp);
896789Sahrens 	return (error);
897789Sahrens }
898789Sahrens 
899789Sahrens /*
900789Sahrens  * strip off write_owner and write_acl
901789Sahrens  */
902789Sahrens static void
903789Sahrens zfs_securemode_update(zfsvfs_t *zfsvfs, ace_t *acep)
904789Sahrens {
905789Sahrens 	if ((zfsvfs->z_acl_inherit == SECURE) &&
906*1576Smarks 	    (acep->a_type == ALLOW))
907*1576Smarks 		acep->a_access_mask &= ~SECURE_CLEAR;
908789Sahrens }
909789Sahrens 
910789Sahrens /*
911789Sahrens  * inherit inheritable ACEs from parent
912789Sahrens  */
913789Sahrens static zfs_acl_t *
914789Sahrens zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp)
915789Sahrens {
916789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
917789Sahrens 	ace_t 		*pacep;
918789Sahrens 	ace_t		*acep;
919789Sahrens 	int 		ace_cnt = 0;
920789Sahrens 	int		pace_cnt;
921789Sahrens 	int 		i, j;
922789Sahrens 	zfs_acl_t	*aclp = NULL;
923789Sahrens 
924789Sahrens 	i = j = 0;
925789Sahrens 	pace_cnt = paclp->z_acl_count;
926789Sahrens 	pacep = paclp->z_acl;
927789Sahrens 	if (zfsvfs->z_acl_inherit != DISCARD) {
928789Sahrens 		for (i = 0; i != pace_cnt; i++) {
929789Sahrens 
930789Sahrens 			if (zfsvfs->z_acl_inherit == NOALLOW &&
931789Sahrens 			    pacep[i].a_type == ALLOW)
932789Sahrens 				continue;
933789Sahrens 
934789Sahrens 			if (zfs_ace_can_use(zp, &pacep[i])) {
935789Sahrens 				ace_cnt++;
936789Sahrens 				if (!(pacep[i].a_flags &
937789Sahrens 				    ACE_NO_PROPAGATE_INHERIT_ACE))
938789Sahrens 					ace_cnt++;
939789Sahrens 			}
940789Sahrens 		}
941789Sahrens 	}
942789Sahrens 
943789Sahrens 	aclp = zfs_acl_alloc(ace_cnt + OGE_PAD);
944789Sahrens 	if (ace_cnt && zfsvfs->z_acl_inherit != DISCARD) {
945789Sahrens 		acep = aclp->z_acl;
946789Sahrens 		pacep = paclp->z_acl;
947789Sahrens 		for (i = 0; i != pace_cnt; i++) {
948789Sahrens 
949789Sahrens 			if (zfsvfs->z_acl_inherit == NOALLOW &&
950789Sahrens 			    pacep[i].a_type == ALLOW)
951789Sahrens 				continue;
952789Sahrens 
953789Sahrens 			if (zfs_ace_can_use(zp, &pacep[i])) {
954*1576Smarks 
955789Sahrens 				/*
956789Sahrens 				 * Now create entry for inherited ace
957789Sahrens 				 */
958*1576Smarks 
959789Sahrens 				acep[j] = pacep[i];
960789Sahrens 
961*1576Smarks 				/*
962*1576Smarks 				 * When AUDIT/ALARM a_types are supported
963*1576Smarks 				 * they should be inherited here.
964*1576Smarks 				 */
965789Sahrens 
966*1576Smarks 				if ((pacep[i].a_flags &
967*1576Smarks 				    ACE_NO_PROPAGATE_INHERIT_ACE) ||
968*1576Smarks 				    (ZTOV(zp)->v_type != VDIR)) {
969789Sahrens 					acep[j].a_flags &= ~ALL_INHERIT;
970789Sahrens 					zfs_securemode_update(zfsvfs, &acep[j]);
971789Sahrens 					j++;
972789Sahrens 					continue;
973789Sahrens 				}
974789Sahrens 
975789Sahrens 				ASSERT(ZTOV(zp)->v_type == VDIR);
976789Sahrens 
977789Sahrens 				/*
978789Sahrens 				 * If we are inheriting an ACE targeted for
979865Smarks 				 * only files, then make sure inherit_only
980865Smarks 				 * is on for future propagation.
981789Sahrens 				 */
982*1576Smarks 				if ((pacep[i].a_flags & (ACE_FILE_INHERIT_ACE |
983*1576Smarks 				    ACE_DIRECTORY_INHERIT_ACE)) !=
984865Smarks 				    ACE_FILE_INHERIT_ACE) {
985*1576Smarks 					j++;
986*1576Smarks 					acep[j] = acep[j-1];
987*1576Smarks 					acep[j-1].a_flags |=
988*1576Smarks 					    ACE_INHERIT_ONLY_ACE;
989*1576Smarks 					acep[j].a_flags &= ~ALL_INHERIT;
990865Smarks 				} else {
991*1576Smarks 					acep[j].a_flags |= ACE_INHERIT_ONLY_ACE;
992865Smarks 				}
993789Sahrens 				zfs_securemode_update(zfsvfs, &acep[j]);
994789Sahrens 				j++;
995789Sahrens 			}
996789Sahrens 		}
997789Sahrens 	}
998789Sahrens 	aclp->z_acl_count = j;
999789Sahrens 	ASSERT(aclp->z_slots >= aclp->z_acl_count);
1000789Sahrens 
1001789Sahrens 	return (aclp);
1002789Sahrens }
1003789Sahrens 
1004789Sahrens /*
1005789Sahrens  * Create file system object initial permissions
1006789Sahrens  * including inheritable ACEs.
1007789Sahrens  */
1008789Sahrens void
1009789Sahrens zfs_perm_init(znode_t *zp, znode_t *parent, int flag,
1010789Sahrens     vattr_t *vap, dmu_tx_t *tx, cred_t *cr)
1011789Sahrens {
1012789Sahrens 	uint64_t	mode;
1013789Sahrens 	uid_t		uid;
1014789Sahrens 	gid_t		gid;
1015789Sahrens 	int		error;
1016789Sahrens 	int		pull_down;
1017789Sahrens 	zfs_acl_t	*aclp, *paclp;
1018789Sahrens 
1019789Sahrens 	mode = MAKEIMODE(vap->va_type, vap->va_mode);
1020789Sahrens 
1021789Sahrens 	/*
1022789Sahrens 	 * Determine uid and gid.
1023789Sahrens 	 */
1024789Sahrens 	if ((flag & (IS_ROOT_NODE | IS_REPLAY)) ||
1025789Sahrens 	    ((flag & IS_XATTR) && (vap->va_type == VDIR))) {
1026789Sahrens 		uid = vap->va_uid;
1027789Sahrens 		gid = vap->va_gid;
1028789Sahrens 	} else {
1029789Sahrens 		uid = crgetuid(cr);
1030789Sahrens 		if ((vap->va_mask & AT_GID) &&
1031789Sahrens 		    ((vap->va_gid == parent->z_phys->zp_gid) ||
1032789Sahrens 		    groupmember(vap->va_gid, cr) ||
1033789Sahrens 		    secpolicy_vnode_create_gid(cr)))
1034789Sahrens 			gid = vap->va_gid;
1035789Sahrens 		else
1036789Sahrens 			gid = (parent->z_phys->zp_mode & S_ISGID) ?
1037789Sahrens 			    parent->z_phys->zp_gid : crgetgid(cr);
1038789Sahrens 	}
1039789Sahrens 
1040789Sahrens 	/*
1041789Sahrens 	 * If we're creating a directory, and the parent directory has the
1042789Sahrens 	 * set-GID bit set, set in on the new directory.
1043789Sahrens 	 * Otherwise, if the user is neither privileged nor a member of the
1044789Sahrens 	 * file's new group, clear the file's set-GID bit.
1045789Sahrens 	 */
1046789Sahrens 
1047789Sahrens 	if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR))
1048789Sahrens 		mode |= S_ISGID;
1049789Sahrens 	else {
1050789Sahrens 		if ((mode & S_ISGID) &&
1051789Sahrens 		    secpolicy_vnode_setids_setgids(cr, gid) != 0)
1052789Sahrens 			mode &= ~S_ISGID;
1053789Sahrens 	}
1054789Sahrens 
1055789Sahrens 	zp->z_phys->zp_uid = uid;
1056789Sahrens 	zp->z_phys->zp_gid = gid;
1057789Sahrens 	zp->z_phys->zp_mode = mode;
1058789Sahrens 
1059789Sahrens 	mutex_enter(&parent->z_lock);
1060789Sahrens 	pull_down = (parent->z_phys->zp_flags & ZFS_INHERIT_ACE);
1061789Sahrens 	if (pull_down) {
1062789Sahrens 		mutex_enter(&parent->z_acl_lock);
10631544Seschrock 		VERIFY(0 == zfs_acl_node_read(parent, &paclp));
1064789Sahrens 		mutex_exit(&parent->z_acl_lock);
1065789Sahrens 		aclp = zfs_acl_inherit(zp, paclp);
1066789Sahrens 		zfs_acl_free(paclp);
1067789Sahrens 	} else {
1068789Sahrens 		aclp = zfs_acl_alloc(6);
1069789Sahrens 	}
1070789Sahrens 	mutex_exit(&parent->z_lock);
1071789Sahrens 	mutex_enter(&zp->z_lock);
1072789Sahrens 	mutex_enter(&zp->z_acl_lock);
1073789Sahrens 	error = zfs_acl_chmod(zp, mode, aclp, tx);
1074789Sahrens 	mutex_exit(&zp->z_lock);
1075789Sahrens 	mutex_exit(&zp->z_acl_lock);
1076789Sahrens 	ASSERT3U(error, ==, 0);
1077789Sahrens 	zfs_acl_free(aclp);
1078789Sahrens }
1079789Sahrens 
1080789Sahrens /*
1081975Smarks  * Should ACE be inherited?
1082789Sahrens  */
1083789Sahrens static int
1084789Sahrens zfs_ace_can_use(znode_t *zp, ace_t *acep)
1085789Sahrens {
1086789Sahrens 	int vtype = ZTOV(zp)->v_type;
1087789Sahrens 
1088789Sahrens 	int	iflags = (acep->a_flags & 0xf);
1089789Sahrens 
1090789Sahrens 	if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE))
1091789Sahrens 		return (1);
1092789Sahrens 	else if (iflags & ACE_FILE_INHERIT_ACE)
1093975Smarks 		return (!((vtype == VDIR) &&
1094975Smarks 		    (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)));
1095789Sahrens 	return (0);
1096789Sahrens }
1097789Sahrens 
1098789Sahrens /*
1099789Sahrens  * Retrieve a files ACL
1100789Sahrens  */
1101789Sahrens int
1102789Sahrens zfs_getacl(znode_t *zp, vsecattr_t  *vsecp, cred_t *cr)
1103789Sahrens {
1104789Sahrens 	zfs_acl_t	*aclp;
1105789Sahrens 	ulong_t		mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT);
1106789Sahrens 	int		error;
1107789Sahrens 
1108789Sahrens 	if (error = zfs_zaccess(zp, ACE_READ_ACL, cr)) {
1109789Sahrens 		/*
1110789Sahrens 		 * If owner of file then allow reading of the
1111789Sahrens 		 * ACL.
1112789Sahrens 		 */
1113789Sahrens 		if (crgetuid(cr) != zp->z_phys->zp_uid)
1114789Sahrens 			return (error);
1115789Sahrens 	}
1116789Sahrens 
1117789Sahrens 	if (mask == 0)
1118789Sahrens 		return (ENOSYS);
1119789Sahrens 
1120789Sahrens 	mutex_enter(&zp->z_acl_lock);
1121789Sahrens 
11221544Seschrock 	error = zfs_acl_node_read(zp, &aclp);
11231544Seschrock 	if (error != 0) {
11241544Seschrock 		mutex_exit(&zp->z_acl_lock);
11251544Seschrock 		return (error);
11261544Seschrock 	}
11271544Seschrock 
1128789Sahrens 
1129789Sahrens 	if (mask & VSA_ACECNT) {
1130789Sahrens 		vsecp->vsa_aclcnt = aclp->z_acl_count;
1131789Sahrens 	}
1132789Sahrens 
1133789Sahrens 	if (mask & VSA_ACE) {
1134789Sahrens 		vsecp->vsa_aclentp = kmem_alloc(aclp->z_acl_count *
1135789Sahrens 		    sizeof (ace_t), KM_SLEEP);
1136789Sahrens 		bcopy(aclp->z_acl, vsecp->vsa_aclentp,
1137789Sahrens 		    aclp->z_acl_count * sizeof (ace_t));
1138789Sahrens 	}
1139789Sahrens 
1140789Sahrens 	mutex_exit(&zp->z_acl_lock);
1141789Sahrens 
1142789Sahrens 	zfs_acl_free(aclp);
1143789Sahrens 
1144789Sahrens 	return (0);
1145789Sahrens }
1146789Sahrens 
1147789Sahrens /*
1148789Sahrens  * Set a files ACL
1149789Sahrens  */
1150789Sahrens int
1151789Sahrens zfs_setacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr)
1152789Sahrens {
1153789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1154789Sahrens 	zilog_t		*zilog = zfsvfs->z_log;
1155789Sahrens 	ace_t		*acep = vsecp->vsa_aclentp;
1156789Sahrens 	int		aclcnt = vsecp->vsa_aclcnt;
1157789Sahrens 	ulong_t		mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT);
1158789Sahrens 	dmu_tx_t	*tx;
1159789Sahrens 	int		error;
1160789Sahrens 	int		inherit;
1161789Sahrens 	zfs_acl_t	*aclp;
1162789Sahrens 	uint64_t	seq = 0;
1163789Sahrens 
1164789Sahrens 	if (mask == 0)
1165789Sahrens 		return (EINVAL);
1166789Sahrens 
1167789Sahrens 	if (!zfs_acl_valid(zp, acep, aclcnt, &inherit))
1168789Sahrens 		return (EINVAL);
1169789Sahrens top:
1170789Sahrens 	error = zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr);
1171789Sahrens 	if (error == EACCES || error == ACCESS_UNDETERMINED) {
1172789Sahrens 		if ((error = secpolicy_vnode_setdac(cr,
1173789Sahrens 		    zp->z_phys->zp_uid)) != 0) {
1174789Sahrens 			return (error);
1175789Sahrens 		}
1176789Sahrens 	} else if (error) {
1177789Sahrens 		return (error == EROFS ? error : EPERM);
1178789Sahrens 	}
1179789Sahrens 
1180789Sahrens 	mutex_enter(&zp->z_lock);
1181789Sahrens 	mutex_enter(&zp->z_acl_lock);
1182789Sahrens 
1183789Sahrens 	tx = dmu_tx_create(zfsvfs->z_os);
1184789Sahrens 	dmu_tx_hold_bonus(tx, zp->z_id);
1185789Sahrens 
1186789Sahrens 	if (zp->z_phys->zp_acl.z_acl_extern_obj) {
1187789Sahrens 		dmu_tx_hold_write(tx, zp->z_phys->zp_acl.z_acl_extern_obj,
1188789Sahrens 		    0, ZFS_ACL_SIZE(aclcnt));
1189789Sahrens 	} else if (aclcnt > ACE_SLOT_CNT) {
1190789Sahrens 		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, ZFS_ACL_SIZE(aclcnt));
1191789Sahrens 	}
1192789Sahrens 
1193789Sahrens 	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1194789Sahrens 	if (error) {
1195789Sahrens 		dmu_tx_abort(tx);
1196789Sahrens 
1197789Sahrens 		mutex_exit(&zp->z_acl_lock);
1198789Sahrens 		mutex_exit(&zp->z_lock);
1199789Sahrens 
1200789Sahrens 		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1201789Sahrens 			txg_wait_open(dmu_objset_pool(zfsvfs->z_os), 0);
1202789Sahrens 			goto top;
1203789Sahrens 		}
1204789Sahrens 		return (error);
1205789Sahrens 	}
1206789Sahrens 
1207789Sahrens 	aclp = zfs_acl_alloc(aclcnt);
1208789Sahrens 	bcopy(acep, aclp->z_acl, sizeof (ace_t) * aclcnt);
1209789Sahrens 	aclp->z_acl_count = aclcnt;
1210789Sahrens 	error = zfs_aclset_common(zp, aclp, tx, &inherit);
1211789Sahrens 	ASSERT(error == 0);
1212789Sahrens 
1213789Sahrens 	zfs_acl_free(aclp);
1214789Sahrens 	seq = zfs_log_acl(zilog, tx, TX_ACL, zp, aclcnt, acep);
1215789Sahrens 	dmu_tx_commit(tx);
1216789Sahrens done:
1217789Sahrens 	mutex_exit(&zp->z_acl_lock);
1218789Sahrens 	mutex_exit(&zp->z_lock);
1219789Sahrens 
1220789Sahrens 	zil_commit(zilog, seq, 0);
1221789Sahrens 
1222789Sahrens 	return (error);
1223789Sahrens }
1224789Sahrens 
1225789Sahrens static int
1226*1576Smarks zfs_ace_access(ace_t *zacep, int *working_mode)
1227789Sahrens {
1228*1576Smarks 	if (*working_mode == 0) {
1229789Sahrens 		return (0);
1230789Sahrens 	}
1231789Sahrens 
1232*1576Smarks 	if (zacep->a_access_mask & *working_mode) {
1233789Sahrens 		if (zacep->a_type == ALLOW) {
1234*1576Smarks 			*working_mode &=
1235*1576Smarks 			    ~(*working_mode & zacep->a_access_mask);
1236*1576Smarks 			if (*working_mode == 0)
1237789Sahrens 				return (0);
1238789Sahrens 		} else if (zacep->a_type == DENY) {
1239789Sahrens 			return (EACCES);
1240789Sahrens 		}
1241789Sahrens 	}
1242789Sahrens 
1243789Sahrens 	/*
1244789Sahrens 	 * haven't been specifcally denied at this point
1245789Sahrens 	 * so return UNDETERMINED.
1246789Sahrens 	 */
1247789Sahrens 
1248789Sahrens 	return (ACCESS_UNDETERMINED);
1249789Sahrens }
1250789Sahrens 
1251789Sahrens 
1252789Sahrens static int
1253789Sahrens zfs_zaccess_common(znode_t *zp, int v4_mode, int *working_mode, cred_t *cr)
1254789Sahrens {
1255789Sahrens 	zfs_acl_t	*aclp;
1256789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1257789Sahrens 	ace_t		*zacep;
1258789Sahrens 	gid_t		gid;
1259789Sahrens 	int		cnt;
1260789Sahrens 	int		i;
12611544Seschrock 	int		error;
1262789Sahrens 	int		access_deny = ACCESS_UNDETERMINED;
1263789Sahrens 	uint_t		entry_type;
1264789Sahrens 	uid_t		uid = crgetuid(cr);
1265789Sahrens 
1266*1576Smarks 	*working_mode = v4_mode;
1267789Sahrens 
1268789Sahrens 	if (zfsvfs->z_assign >= TXG_INITIAL)		/* ZIL replay */
1269789Sahrens 		return (0);
1270789Sahrens 
1271789Sahrens 	if ((v4_mode & WRITE_MASK) &&
1272789Sahrens 	    (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) &&
1273789Sahrens 	    (!IS_DEVVP(ZTOV(zp)))) {
1274789Sahrens 		return (EROFS);
1275789Sahrens 	}
1276789Sahrens 
1277789Sahrens 	mutex_enter(&zp->z_acl_lock);
1278789Sahrens 
12791544Seschrock 	error = zfs_acl_node_read(zp, &aclp);
12801544Seschrock 	if (error != 0) {
12811544Seschrock 		mutex_exit(&zp->z_acl_lock);
12821544Seschrock 		return (error);
12831544Seschrock 	}
12841544Seschrock 
1285789Sahrens 
1286789Sahrens 	zacep = aclp->z_acl;
1287789Sahrens 	cnt = aclp->z_acl_count;
1288789Sahrens 
1289789Sahrens 	for (i = 0; i != cnt; i++) {
1290789Sahrens 
1291*1576Smarks 		DTRACE_PROBE2(zfs__access__common,
1292*1576Smarks 		    ace_t *, &zacep[i], int, *working_mode);
1293*1576Smarks 
1294789Sahrens 		if (zacep[i].a_flags & ACE_INHERIT_ONLY_ACE)
1295789Sahrens 			continue;
1296789Sahrens 
1297*1576Smarks 		entry_type = (zacep[i].a_flags & ACE_TYPE_FLAGS);
1298789Sahrens 		switch (entry_type) {
1299789Sahrens 		case ACE_OWNER:
1300789Sahrens 			if (uid == zp->z_phys->zp_uid) {
1301789Sahrens 				access_deny = zfs_ace_access(&zacep[i],
1302*1576Smarks 				    working_mode);
1303789Sahrens 			}
1304789Sahrens 			break;
1305789Sahrens 		case (ACE_IDENTIFIER_GROUP | ACE_GROUP):
1306789Sahrens 		case ACE_IDENTIFIER_GROUP:
1307789Sahrens 			/*
1308789Sahrens 			 * Owning group gid is in znode not ACL
1309789Sahrens 			 */
1310789Sahrens 			if (entry_type == (ACE_IDENTIFIER_GROUP | ACE_GROUP))
1311789Sahrens 				gid = zp->z_phys->zp_gid;
1312789Sahrens 			else
1313789Sahrens 				gid = zacep[i].a_who;
1314789Sahrens 
1315789Sahrens 			if (groupmember(gid, cr)) {
1316789Sahrens 				access_deny = zfs_ace_access(&zacep[i],
1317*1576Smarks 				    working_mode);
1318789Sahrens 			}
1319789Sahrens 			break;
1320789Sahrens 		case ACE_EVERYONE:
1321*1576Smarks 			access_deny = zfs_ace_access(&zacep[i], working_mode);
1322789Sahrens 			break;
1323789Sahrens 
1324789Sahrens 		/* USER Entry */
1325789Sahrens 		default:
1326789Sahrens 			if (entry_type == 0) {
1327789Sahrens 				if (uid == zacep[i].a_who) {
1328789Sahrens 					access_deny = zfs_ace_access(&zacep[i],
1329*1576Smarks 					    working_mode);
1330789Sahrens 				}
1331789Sahrens 				break;
1332789Sahrens 			}
1333789Sahrens 			zfs_acl_free(aclp);
1334789Sahrens 			mutex_exit(&zp->z_acl_lock);
1335789Sahrens 			return (EIO);
1336789Sahrens 		}
1337789Sahrens 
1338789Sahrens 		if (access_deny != ACCESS_UNDETERMINED)
1339789Sahrens 			break;
1340789Sahrens 	}
1341789Sahrens 
1342789Sahrens 	mutex_exit(&zp->z_acl_lock);
1343789Sahrens 	zfs_acl_free(aclp);
1344789Sahrens 
1345789Sahrens 	return (access_deny);
1346789Sahrens }
1347789Sahrens 
1348789Sahrens 
1349789Sahrens /*
1350789Sahrens  * Determine whether Access should be granted/denied, invoking least
1351789Sahrens  * priv subsytem when a deny is determined.
1352789Sahrens  */
1353789Sahrens int
1354789Sahrens zfs_zaccess(znode_t *zp, int mode, cred_t *cr)
1355789Sahrens {
1356*1576Smarks 	int	working_mode;
1357789Sahrens 	int	error;
1358789Sahrens 	int	is_attr;
1359789Sahrens 	znode_t	*xzp;
1360789Sahrens 	znode_t *check_zp = zp;
1361789Sahrens 
1362789Sahrens 	is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) &&
1363789Sahrens 	    (ZTOV(zp)->v_type == VDIR));
1364789Sahrens 
1365789Sahrens 	/*
1366789Sahrens 	 * If attribute then validate against base file
1367789Sahrens 	 */
1368789Sahrens 	if (is_attr) {
1369789Sahrens 		if ((error = zfs_zget(zp->z_zfsvfs,
1370789Sahrens 		    zp->z_phys->zp_parent, &xzp)) != 0)	{
1371789Sahrens 			return (error);
1372789Sahrens 		}
1373789Sahrens 		check_zp = xzp;
1374789Sahrens 		/*
1375789Sahrens 		 * fixup mode to map to xattr perms
1376789Sahrens 		 */
1377789Sahrens 
1378789Sahrens 		if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {
1379789Sahrens 			mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
1380789Sahrens 			mode |= ACE_WRITE_NAMED_ATTRS;
1381789Sahrens 		}
1382789Sahrens 
1383789Sahrens 		if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {
1384789Sahrens 			mode &= ~(ACE_READ_DATA|ACE_EXECUTE);
1385789Sahrens 			mode |= ACE_READ_NAMED_ATTRS;
1386789Sahrens 		}
1387789Sahrens 	}
1388789Sahrens 
1389789Sahrens 	error = zfs_zaccess_common(check_zp, mode, &working_mode, cr);
1390789Sahrens 
1391789Sahrens 	if (error == EROFS) {
1392789Sahrens 		if (is_attr)
1393789Sahrens 			VN_RELE(ZTOV(xzp));
1394789Sahrens 		return (error);
1395789Sahrens 	}
1396789Sahrens 
1397*1576Smarks 	if (error || working_mode) {
1398*1576Smarks 		working_mode = (zfs_v4_to_unix(working_mode) << 6);
1399789Sahrens 		error = secpolicy_vnode_access(cr, ZTOV(check_zp),
1400*1576Smarks 		    check_zp->z_phys->zp_uid, working_mode);
1401789Sahrens 	}
1402789Sahrens 
1403789Sahrens 	if (is_attr)
1404789Sahrens 		VN_RELE(ZTOV(xzp));
1405789Sahrens 
1406789Sahrens 	return (error);
1407789Sahrens }
1408789Sahrens 
1409789Sahrens /*
1410789Sahrens  * Special zaccess function to check for special nfsv4 perm.
1411789Sahrens  * doesn't call secpolicy_vnode_access() for failure, since that
1412789Sahrens  * would probably be the wrong policy function to call.
1413789Sahrens  * instead its up to the caller to handle that situation.
1414789Sahrens  */
1415789Sahrens 
1416789Sahrens int
1417789Sahrens zfs_zaccess_v4_perm(znode_t *zp, int mode, cred_t *cr)
1418789Sahrens {
1419789Sahrens 	int working_mode = 0;
1420789Sahrens 	return (zfs_zaccess_common(zp, mode, &working_mode, cr));
1421789Sahrens }
1422789Sahrens 
1423789Sahrens /*
1424789Sahrens  * Translate tradition unix VREAD/VWRITE/VEXEC mode into
1425789Sahrens  * native ACL format and call zfs_zaccess()
1426789Sahrens  */
1427789Sahrens int
1428789Sahrens zfs_zaccess_rwx(znode_t *zp, mode_t mode, cred_t *cr)
1429789Sahrens {
1430789Sahrens 	int v4_mode = zfs_unix_to_v4(mode >> 6);
1431789Sahrens 
1432789Sahrens 	return (zfs_zaccess(zp, v4_mode, cr));
1433789Sahrens }
1434789Sahrens 
1435789Sahrens /*
1436789Sahrens  * Determine whether Access should be granted/deny, without
1437789Sahrens  * consulting least priv subsystem.
1438789Sahrens  *
1439789Sahrens  *
1440789Sahrens  * The following chart is the recommended NFSv4 enforcement for
1441789Sahrens  * ability to delete an object.
1442789Sahrens  *
1443789Sahrens  *      -------------------------------------------------------
1444789Sahrens  *      |   Parent Dir  |           Target Object Permissions |
1445789Sahrens  *      |  permissions  |                                     |
1446789Sahrens  *      -------------------------------------------------------
1447789Sahrens  *      |               | ACL Allows | ACL Denies| Delete     |
1448789Sahrens  *      |               |  Delete    |  Delete   | unspecified|
1449789Sahrens  *      -------------------------------------------------------
1450789Sahrens  *      |  ACL Allows   | Permit     | Permit    | Permit     |
1451789Sahrens  *      |  DELETE_CHILD |                                     |
1452789Sahrens  *      -------------------------------------------------------
1453789Sahrens  *      |  ACL Denies   | Permit     | Deny      | Deny       |
1454789Sahrens  *      |  DELETE_CHILD |            |           |            |
1455789Sahrens  *      -------------------------------------------------------
1456789Sahrens  *      | ACL specifies |            |           |            |
1457789Sahrens  *      | only allow    | Permit     | Permit    | Permit     |
1458789Sahrens  *      | write and     |            |           |            |
1459789Sahrens  *      | execute       |            |           |            |
1460789Sahrens  *      -------------------------------------------------------
1461789Sahrens  *      | ACL denies    |            |           |            |
1462789Sahrens  *      | write and     | Permit     | Deny      | Deny       |
1463789Sahrens  *      | execute       |            |           |            |
1464789Sahrens  *      -------------------------------------------------------
1465789Sahrens  *         ^
1466789Sahrens  *         |
1467789Sahrens  *         No search privilege, can't even look up file?
1468789Sahrens  *
1469789Sahrens  */
1470789Sahrens int
1471789Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
1472789Sahrens {
1473789Sahrens 	int dzp_working_mode = 0;
1474789Sahrens 	int zp_working_mode = 0;
1475789Sahrens 	int dzp_error, zp_error;
14761308Smarks 	int error;
1477789Sahrens 
1478789Sahrens 	/*
1479789Sahrens 	 * Arghh, this check is going to require a couple of questions
1480789Sahrens 	 * to be asked.  We want specific DELETE permissions to
1481789Sahrens 	 * take precedence over WRITE/EXECUTE.  We don't
1482789Sahrens 	 * want an ACL such as this to mess us up.
1483789Sahrens 	 * user:sloar:write_data:deny,user:sloar:delete:allow
1484789Sahrens 	 *
1485789Sahrens 	 * However, deny permissions may ultimately be overridden
1486789Sahrens 	 * by secpolicy_vnode_access().
1487789Sahrens 	 */
1488789Sahrens 
1489789Sahrens 	dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD,
1490789Sahrens 	    &dzp_working_mode, cr);
1491789Sahrens 	zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, cr);
1492789Sahrens 
1493789Sahrens 	if (dzp_error == EROFS || zp_error == EROFS)
1494789Sahrens 		return (dzp_error);
1495789Sahrens 
1496789Sahrens 	/*
1497789Sahrens 	 * First handle the first row
1498789Sahrens 	 */
1499*1576Smarks 	if ((dzp_working_mode & ACE_DELETE_CHILD) == 0)
1500789Sahrens 		return (0);
1501789Sahrens 
1502789Sahrens 	/*
1503789Sahrens 	 * Second row
1504789Sahrens 	 */
1505789Sahrens 
1506*1576Smarks 	if ((zp_working_mode & ACE_DELETE) == 0)
1507789Sahrens 		return (0);
1508789Sahrens 
1509789Sahrens 	/*
1510789Sahrens 	 * Third Row
1511789Sahrens 	 */
1512789Sahrens 
1513789Sahrens 	dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE,
1514789Sahrens 	    &dzp_working_mode, cr);
1515789Sahrens 
1516789Sahrens 	if (dzp_error == EROFS)
1517789Sahrens 		return (dzp_error);
1518789Sahrens 
1519*1576Smarks 	if ((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0)
15201308Smarks 		goto sticky;
1521789Sahrens 
1522789Sahrens 	/*
1523789Sahrens 	 * Fourth Row
1524789Sahrens 	 */
1525789Sahrens 
1526*1576Smarks 	if (((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) != 0) &&
1527*1576Smarks 	    ((zp_working_mode & ACE_DELETE) == 0))
15281308Smarks 		goto sticky;
15291308Smarks 
15301308Smarks 	error = secpolicy_vnode_access(cr, ZTOV(zp),
15311308Smarks 	    dzp->z_phys->zp_uid, S_IWRITE|S_IEXEC);
1532789Sahrens 
15331308Smarks 	if (error)
15341308Smarks 		return (error);
15351308Smarks 
15361308Smarks sticky:
15371308Smarks 	error = zfs_sticky_remove_access(dzp, zp, cr);
15381308Smarks 
15391308Smarks 	return (error);
1540789Sahrens }
1541789Sahrens 
1542789Sahrens int
1543789Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
1544789Sahrens     znode_t *tzp, cred_t *cr)
1545789Sahrens {
1546789Sahrens 	int add_perm;
1547789Sahrens 	int error;
1548789Sahrens 
1549789Sahrens 	add_perm = (ZTOV(szp)->v_type == VDIR) ?
1550789Sahrens 	    ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE;
1551789Sahrens 
1552789Sahrens 	/*
1553789Sahrens 	 * Rename permissions are combination of delete permission +
1554789Sahrens 	 * add file/subdir permission.
1555789Sahrens 	 */
1556789Sahrens 
1557789Sahrens 	/*
1558789Sahrens 	 * first make sure we do the delete portion.
1559789Sahrens 	 *
1560789Sahrens 	 * If that succeeds then check for add_file/add_subdir permissions
1561789Sahrens 	 */
1562789Sahrens 
1563789Sahrens 	if (error = zfs_zaccess_delete(sdzp, szp, cr))
1564789Sahrens 		return (error);
1565789Sahrens 
1566789Sahrens 	/*
1567789Sahrens 	 * If we have a tzp, see if we can delete it?
1568789Sahrens 	 */
1569789Sahrens 	if (tzp) {
1570789Sahrens 		if (error = zfs_zaccess_delete(tdzp, tzp, cr))
1571789Sahrens 			return (error);
1572789Sahrens 	}
1573789Sahrens 
1574789Sahrens 	/*
1575789Sahrens 	 * Now check for add permissions
1576789Sahrens 	 */
15771308Smarks 	error = zfs_zaccess(tdzp, add_perm, cr);
1578789Sahrens 
1579789Sahrens 	return (error);
1580789Sahrens }
1581