xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_acl.c (revision 4300:d74de773d6e6)
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 /*
22*4300Smarks  * Copyright 2007 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>
421576Smarks #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 
781576Smarks #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 
1151576Smarks 	/*
1161576Smarks 	 * This is used for mapping v4 permissions into permissions
1171576Smarks 	 * that can be passed to secpolicy_vnode_access()
1181576Smarks 	 */
1191576Smarks 	if (access_mask & (ACE_READ_DATA | ACE_LIST_DIRECTORY |
1201576Smarks 	    ACE_READ_ATTRIBUTES | ACE_READ_ACL))
121789Sahrens 		new_mask |= S_IROTH;
1221576Smarks 	if (access_mask & (ACE_WRITE_DATA | ACE_APPEND_DATA |
1231576Smarks 	    ACE_WRITE_ATTRIBUTES | ACE_ADD_FILE | ACE_WRITE_NAMED_ATTRS))
124789Sahrens 		new_mask |= S_IWOTH;
1251576Smarks 	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++) {
1711576Smarks 		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 
3441576Smarks 		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,
441*4300Smarks 			    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 &&
5871576Smarks 	    ((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,
6731576Smarks 	    (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;
7791576Smarks 		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 
7912676Seschrock 		if (zfsvfs->z_acl_mode == ZFS_ACL_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 				 */
8232676Seschrock 				if (zfsvfs->z_acl_mode == ZFS_ACL_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 {
9052676Seschrock 	if ((zfsvfs->z_acl_inherit == ZFS_ACL_SECURE) &&
9061576Smarks 	    (acep->a_type == ALLOW))
9071576Smarks 		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;
9272676Seschrock 	if (zfsvfs->z_acl_inherit != ZFS_ACL_DISCARD) {
928789Sahrens 		for (i = 0; i != pace_cnt; i++) {
929789Sahrens 
9302676Seschrock 			if (zfsvfs->z_acl_inherit == ZFS_ACL_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);
9442676Seschrock 	if (ace_cnt && zfsvfs->z_acl_inherit != ZFS_ACL_DISCARD) {
945789Sahrens 		acep = aclp->z_acl;
946789Sahrens 		pacep = paclp->z_acl;
947789Sahrens 		for (i = 0; i != pace_cnt; i++) {
948789Sahrens 
9492676Seschrock 			if (zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW &&
950789Sahrens 			    pacep[i].a_type == ALLOW)
951789Sahrens 				continue;
952789Sahrens 
953789Sahrens 			if (zfs_ace_can_use(zp, &pacep[i])) {
9541576Smarks 
955789Sahrens 				/*
956789Sahrens 				 * Now create entry for inherited ace
957789Sahrens 				 */
9581576Smarks 
959789Sahrens 				acep[j] = pacep[i];
960789Sahrens 
9611576Smarks 				/*
9621576Smarks 				 * When AUDIT/ALARM a_types are supported
9631576Smarks 				 * they should be inherited here.
9641576Smarks 				 */
965789Sahrens 
9661576Smarks 				if ((pacep[i].a_flags &
9671576Smarks 				    ACE_NO_PROPAGATE_INHERIT_ACE) ||
9681576Smarks 				    (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 				 */
9821576Smarks 				if ((pacep[i].a_flags & (ACE_FILE_INHERIT_ACE |
9831576Smarks 				    ACE_DIRECTORY_INHERIT_ACE)) !=
984865Smarks 				    ACE_FILE_INHERIT_ACE) {
9851576Smarks 					j++;
9861576Smarks 					acep[j] = acep[j-1];
9871576Smarks 					acep[j-1].a_flags |=
9881576Smarks 					    ACE_INHERIT_ONLY_ACE;
9891576Smarks 					acep[j].a_flags &= ~ALL_INHERIT;
990865Smarks 				} else {
9911576Smarks 					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) ||
10332058Sxs154138 		    secpolicy_vnode_create_gid(cr) == 0))
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 
1163789Sahrens 	if (mask == 0)
1164*4300Smarks 		return (ENOSYS);
1165789Sahrens 
1166789Sahrens 	if (!zfs_acl_valid(zp, acep, aclcnt, &inherit))
1167789Sahrens 		return (EINVAL);
1168789Sahrens top:
1169789Sahrens 	error = zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr);
1170789Sahrens 	if (error == EACCES || error == ACCESS_UNDETERMINED) {
1171789Sahrens 		if ((error = secpolicy_vnode_setdac(cr,
1172789Sahrens 		    zp->z_phys->zp_uid)) != 0) {
1173789Sahrens 			return (error);
1174789Sahrens 		}
1175789Sahrens 	} else if (error) {
1176789Sahrens 		return (error == EROFS ? error : EPERM);
1177789Sahrens 	}
1178789Sahrens 
1179789Sahrens 	mutex_enter(&zp->z_lock);
1180789Sahrens 	mutex_enter(&zp->z_acl_lock);
1181789Sahrens 
1182789Sahrens 	tx = dmu_tx_create(zfsvfs->z_os);
1183789Sahrens 	dmu_tx_hold_bonus(tx, zp->z_id);
1184789Sahrens 
1185789Sahrens 	if (zp->z_phys->zp_acl.z_acl_extern_obj) {
1186789Sahrens 		dmu_tx_hold_write(tx, zp->z_phys->zp_acl.z_acl_extern_obj,
1187789Sahrens 		    0, ZFS_ACL_SIZE(aclcnt));
1188789Sahrens 	} else if (aclcnt > ACE_SLOT_CNT) {
1189789Sahrens 		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, ZFS_ACL_SIZE(aclcnt));
1190789Sahrens 	}
1191789Sahrens 
1192789Sahrens 	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1193789Sahrens 	if (error) {
1194789Sahrens 		mutex_exit(&zp->z_acl_lock);
1195789Sahrens 		mutex_exit(&zp->z_lock);
1196789Sahrens 
1197789Sahrens 		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
11982113Sahrens 			dmu_tx_wait(tx);
11992113Sahrens 			dmu_tx_abort(tx);
1200789Sahrens 			goto top;
1201789Sahrens 		}
12022113Sahrens 		dmu_tx_abort(tx);
1203789Sahrens 		return (error);
1204789Sahrens 	}
1205789Sahrens 
1206789Sahrens 	aclp = zfs_acl_alloc(aclcnt);
1207789Sahrens 	bcopy(acep, aclp->z_acl, sizeof (ace_t) * aclcnt);
1208789Sahrens 	aclp->z_acl_count = aclcnt;
1209789Sahrens 	error = zfs_aclset_common(zp, aclp, tx, &inherit);
1210789Sahrens 	ASSERT(error == 0);
1211789Sahrens 
1212789Sahrens 	zfs_acl_free(aclp);
12132638Sperrin 	zfs_log_acl(zilog, tx, TX_ACL, zp, aclcnt, acep);
1214789Sahrens 	dmu_tx_commit(tx);
1215789Sahrens done:
1216789Sahrens 	mutex_exit(&zp->z_acl_lock);
1217789Sahrens 	mutex_exit(&zp->z_lock);
1218789Sahrens 
1219789Sahrens 	return (error);
1220789Sahrens }
1221789Sahrens 
1222789Sahrens static int
12231576Smarks zfs_ace_access(ace_t *zacep, int *working_mode)
1224789Sahrens {
12251576Smarks 	if (*working_mode == 0) {
1226789Sahrens 		return (0);
1227789Sahrens 	}
1228789Sahrens 
12291576Smarks 	if (zacep->a_access_mask & *working_mode) {
1230789Sahrens 		if (zacep->a_type == ALLOW) {
12311576Smarks 			*working_mode &=
12321576Smarks 			    ~(*working_mode & zacep->a_access_mask);
12331576Smarks 			if (*working_mode == 0)
1234789Sahrens 				return (0);
1235789Sahrens 		} else if (zacep->a_type == DENY) {
1236789Sahrens 			return (EACCES);
1237789Sahrens 		}
1238789Sahrens 	}
1239789Sahrens 
1240789Sahrens 	/*
1241789Sahrens 	 * haven't been specifcally denied at this point
1242789Sahrens 	 * so return UNDETERMINED.
1243789Sahrens 	 */
1244789Sahrens 
1245789Sahrens 	return (ACCESS_UNDETERMINED);
1246789Sahrens }
1247789Sahrens 
1248789Sahrens 
1249789Sahrens static int
1250789Sahrens zfs_zaccess_common(znode_t *zp, int v4_mode, int *working_mode, cred_t *cr)
1251789Sahrens {
1252789Sahrens 	zfs_acl_t	*aclp;
1253789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1254789Sahrens 	ace_t		*zacep;
1255789Sahrens 	gid_t		gid;
1256789Sahrens 	int		cnt;
1257789Sahrens 	int		i;
12581544Seschrock 	int		error;
1259789Sahrens 	int		access_deny = ACCESS_UNDETERMINED;
1260789Sahrens 	uint_t		entry_type;
1261789Sahrens 	uid_t		uid = crgetuid(cr);
1262789Sahrens 
12632638Sperrin 	if (zfsvfs->z_assign >= TXG_INITIAL) {		/* ZIL replay */
12642638Sperrin 		*working_mode = 0;
12652638Sperrin 		return (0);
12662638Sperrin 	}
1267789Sahrens 
12682638Sperrin 	*working_mode = v4_mode;
1269789Sahrens 
1270789Sahrens 	if ((v4_mode & WRITE_MASK) &&
1271789Sahrens 	    (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) &&
1272789Sahrens 	    (!IS_DEVVP(ZTOV(zp)))) {
1273789Sahrens 		return (EROFS);
1274789Sahrens 	}
1275789Sahrens 
1276789Sahrens 	mutex_enter(&zp->z_acl_lock);
1277789Sahrens 
12781544Seschrock 	error = zfs_acl_node_read(zp, &aclp);
12791544Seschrock 	if (error != 0) {
12801544Seschrock 		mutex_exit(&zp->z_acl_lock);
12811544Seschrock 		return (error);
12821544Seschrock 	}
12831544Seschrock 
1284789Sahrens 
1285789Sahrens 	zacep = aclp->z_acl;
1286789Sahrens 	cnt = aclp->z_acl_count;
1287789Sahrens 
1288789Sahrens 	for (i = 0; i != cnt; i++) {
1289789Sahrens 
12901576Smarks 		DTRACE_PROBE2(zfs__access__common,
12911576Smarks 		    ace_t *, &zacep[i], int, *working_mode);
12921576Smarks 
1293789Sahrens 		if (zacep[i].a_flags & ACE_INHERIT_ONLY_ACE)
1294789Sahrens 			continue;
1295789Sahrens 
12961576Smarks 		entry_type = (zacep[i].a_flags & ACE_TYPE_FLAGS);
1297789Sahrens 		switch (entry_type) {
1298789Sahrens 		case ACE_OWNER:
1299789Sahrens 			if (uid == zp->z_phys->zp_uid) {
1300789Sahrens 				access_deny = zfs_ace_access(&zacep[i],
13011576Smarks 				    working_mode);
1302789Sahrens 			}
1303789Sahrens 			break;
1304789Sahrens 		case (ACE_IDENTIFIER_GROUP | ACE_GROUP):
1305789Sahrens 		case ACE_IDENTIFIER_GROUP:
1306789Sahrens 			/*
1307789Sahrens 			 * Owning group gid is in znode not ACL
1308789Sahrens 			 */
1309789Sahrens 			if (entry_type == (ACE_IDENTIFIER_GROUP | ACE_GROUP))
1310789Sahrens 				gid = zp->z_phys->zp_gid;
1311789Sahrens 			else
1312789Sahrens 				gid = zacep[i].a_who;
1313789Sahrens 
1314789Sahrens 			if (groupmember(gid, cr)) {
1315789Sahrens 				access_deny = zfs_ace_access(&zacep[i],
13161576Smarks 				    working_mode);
1317789Sahrens 			}
1318789Sahrens 			break;
1319789Sahrens 		case ACE_EVERYONE:
13201576Smarks 			access_deny = zfs_ace_access(&zacep[i], working_mode);
1321789Sahrens 			break;
1322789Sahrens 
1323789Sahrens 		/* USER Entry */
1324789Sahrens 		default:
1325789Sahrens 			if (entry_type == 0) {
1326789Sahrens 				if (uid == zacep[i].a_who) {
1327789Sahrens 					access_deny = zfs_ace_access(&zacep[i],
13281576Smarks 					    working_mode);
1329789Sahrens 				}
1330789Sahrens 				break;
1331789Sahrens 			}
1332789Sahrens 			zfs_acl_free(aclp);
1333789Sahrens 			mutex_exit(&zp->z_acl_lock);
1334789Sahrens 			return (EIO);
1335789Sahrens 		}
1336789Sahrens 
1337789Sahrens 		if (access_deny != ACCESS_UNDETERMINED)
1338789Sahrens 			break;
1339789Sahrens 	}
1340789Sahrens 
1341789Sahrens 	mutex_exit(&zp->z_acl_lock);
1342789Sahrens 	zfs_acl_free(aclp);
1343789Sahrens 
1344789Sahrens 	return (access_deny);
1345789Sahrens }
1346789Sahrens 
1347789Sahrens 
1348789Sahrens /*
1349789Sahrens  * Determine whether Access should be granted/denied, invoking least
1350789Sahrens  * priv subsytem when a deny is determined.
1351789Sahrens  */
1352789Sahrens int
1353789Sahrens zfs_zaccess(znode_t *zp, int mode, cred_t *cr)
1354789Sahrens {
13551576Smarks 	int	working_mode;
1356789Sahrens 	int	error;
1357789Sahrens 	int	is_attr;
1358789Sahrens 	znode_t	*xzp;
1359789Sahrens 	znode_t *check_zp = zp;
1360789Sahrens 
1361789Sahrens 	is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) &&
1362789Sahrens 	    (ZTOV(zp)->v_type == VDIR));
1363789Sahrens 
1364789Sahrens 	/*
1365789Sahrens 	 * If attribute then validate against base file
1366789Sahrens 	 */
1367789Sahrens 	if (is_attr) {
1368789Sahrens 		if ((error = zfs_zget(zp->z_zfsvfs,
1369789Sahrens 		    zp->z_phys->zp_parent, &xzp)) != 0)	{
1370789Sahrens 			return (error);
1371789Sahrens 		}
1372789Sahrens 		check_zp = xzp;
1373789Sahrens 		/*
1374789Sahrens 		 * fixup mode to map to xattr perms
1375789Sahrens 		 */
1376789Sahrens 
1377789Sahrens 		if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {
1378789Sahrens 			mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
1379789Sahrens 			mode |= ACE_WRITE_NAMED_ATTRS;
1380789Sahrens 		}
1381789Sahrens 
1382789Sahrens 		if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {
1383789Sahrens 			mode &= ~(ACE_READ_DATA|ACE_EXECUTE);
1384789Sahrens 			mode |= ACE_READ_NAMED_ATTRS;
1385789Sahrens 		}
1386789Sahrens 	}
1387789Sahrens 
1388789Sahrens 	error = zfs_zaccess_common(check_zp, mode, &working_mode, cr);
1389789Sahrens 
1390789Sahrens 	if (error == EROFS) {
1391789Sahrens 		if (is_attr)
1392789Sahrens 			VN_RELE(ZTOV(xzp));
1393789Sahrens 		return (error);
1394789Sahrens 	}
1395789Sahrens 
13961576Smarks 	if (error || working_mode) {
13971576Smarks 		working_mode = (zfs_v4_to_unix(working_mode) << 6);
1398789Sahrens 		error = secpolicy_vnode_access(cr, ZTOV(check_zp),
13991576Smarks 		    check_zp->z_phys->zp_uid, working_mode);
1400789Sahrens 	}
1401789Sahrens 
1402789Sahrens 	if (is_attr)
1403789Sahrens 		VN_RELE(ZTOV(xzp));
1404789Sahrens 
1405789Sahrens 	return (error);
1406789Sahrens }
1407789Sahrens 
1408789Sahrens /*
1409789Sahrens  * Special zaccess function to check for special nfsv4 perm.
1410789Sahrens  * doesn't call secpolicy_vnode_access() for failure, since that
1411789Sahrens  * would probably be the wrong policy function to call.
1412789Sahrens  * instead its up to the caller to handle that situation.
1413789Sahrens  */
1414789Sahrens 
1415789Sahrens int
1416789Sahrens zfs_zaccess_v4_perm(znode_t *zp, int mode, cred_t *cr)
1417789Sahrens {
1418789Sahrens 	int working_mode = 0;
1419789Sahrens 	return (zfs_zaccess_common(zp, mode, &working_mode, cr));
1420789Sahrens }
1421789Sahrens 
1422789Sahrens /*
1423789Sahrens  * Translate tradition unix VREAD/VWRITE/VEXEC mode into
1424789Sahrens  * native ACL format and call zfs_zaccess()
1425789Sahrens  */
1426789Sahrens int
1427789Sahrens zfs_zaccess_rwx(znode_t *zp, mode_t mode, cred_t *cr)
1428789Sahrens {
1429789Sahrens 	int v4_mode = zfs_unix_to_v4(mode >> 6);
1430789Sahrens 
1431789Sahrens 	return (zfs_zaccess(zp, v4_mode, cr));
1432789Sahrens }
1433789Sahrens 
14342604Smarks static int
14352604Smarks zfs_delete_final_check(znode_t *zp, znode_t *dzp, cred_t *cr)
14362604Smarks {
14372604Smarks 	int error;
14382604Smarks 
14392604Smarks 	error = secpolicy_vnode_access(cr, ZTOV(zp),
14402604Smarks 	    dzp->z_phys->zp_uid, S_IWRITE|S_IEXEC);
14412604Smarks 
14422604Smarks 	if (error == 0)
14432604Smarks 		error = zfs_sticky_remove_access(dzp, zp, cr);
14442604Smarks 
14452604Smarks 	return (error);
14462604Smarks }
14472604Smarks 
1448789Sahrens /*
1449789Sahrens  * Determine whether Access should be granted/deny, without
1450789Sahrens  * consulting least priv subsystem.
1451789Sahrens  *
1452789Sahrens  *
1453789Sahrens  * The following chart is the recommended NFSv4 enforcement for
1454789Sahrens  * ability to delete an object.
1455789Sahrens  *
1456789Sahrens  *      -------------------------------------------------------
1457789Sahrens  *      |   Parent Dir  |           Target Object Permissions |
1458789Sahrens  *      |  permissions  |                                     |
1459789Sahrens  *      -------------------------------------------------------
1460789Sahrens  *      |               | ACL Allows | ACL Denies| Delete     |
1461789Sahrens  *      |               |  Delete    |  Delete   | unspecified|
1462789Sahrens  *      -------------------------------------------------------
1463789Sahrens  *      |  ACL Allows   | Permit     | Permit    | Permit     |
1464789Sahrens  *      |  DELETE_CHILD |                                     |
1465789Sahrens  *      -------------------------------------------------------
1466789Sahrens  *      |  ACL Denies   | Permit     | Deny      | Deny       |
1467789Sahrens  *      |  DELETE_CHILD |            |           |            |
1468789Sahrens  *      -------------------------------------------------------
1469789Sahrens  *      | ACL specifies |            |           |            |
1470789Sahrens  *      | only allow    | Permit     | Permit    | Permit     |
1471789Sahrens  *      | write and     |            |           |            |
1472789Sahrens  *      | execute       |            |           |            |
1473789Sahrens  *      -------------------------------------------------------
1474789Sahrens  *      | ACL denies    |            |           |            |
1475789Sahrens  *      | write and     | Permit     | Deny      | Deny       |
1476789Sahrens  *      | execute       |            |           |            |
1477789Sahrens  *      -------------------------------------------------------
1478789Sahrens  *         ^
1479789Sahrens  *         |
1480789Sahrens  *         No search privilege, can't even look up file?
1481789Sahrens  *
1482789Sahrens  */
1483789Sahrens int
1484789Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
1485789Sahrens {
1486789Sahrens 	int dzp_working_mode = 0;
1487789Sahrens 	int zp_working_mode = 0;
1488789Sahrens 	int dzp_error, zp_error;
1489789Sahrens 
1490789Sahrens 	/*
1491789Sahrens 	 * Arghh, this check is going to require a couple of questions
1492789Sahrens 	 * to be asked.  We want specific DELETE permissions to
1493789Sahrens 	 * take precedence over WRITE/EXECUTE.  We don't
1494789Sahrens 	 * want an ACL such as this to mess us up.
14952604Smarks 	 * user:joe:write_data:deny,user:joe:delete:allow
1496789Sahrens 	 *
1497789Sahrens 	 * However, deny permissions may ultimately be overridden
1498789Sahrens 	 * by secpolicy_vnode_access().
1499789Sahrens 	 */
1500789Sahrens 
1501789Sahrens 	dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD,
1502789Sahrens 	    &dzp_working_mode, cr);
1503789Sahrens 	zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, cr);
1504789Sahrens 
1505789Sahrens 	if (dzp_error == EROFS || zp_error == EROFS)
1506789Sahrens 		return (dzp_error);
1507789Sahrens 
1508789Sahrens 	/*
15092604Smarks 	 * First check the first row.
15102604Smarks 	 * We only need to see if parent Allows delete_child
1511789Sahrens 	 */
15121576Smarks 	if ((dzp_working_mode & ACE_DELETE_CHILD) == 0)
1513789Sahrens 		return (0);
1514789Sahrens 
1515789Sahrens 	/*
1516789Sahrens 	 * Second row
15172604Smarks 	 * we already have the necessary information in
15182604Smarks 	 * zp_working_mode, zp_error and dzp_error.
1519789Sahrens 	 */
1520789Sahrens 
15211576Smarks 	if ((zp_working_mode & ACE_DELETE) == 0)
1522789Sahrens 		return (0);
1523789Sahrens 
1524789Sahrens 	/*
15252604Smarks 	 * Now zp_error should either be EACCES which indicates
15262604Smarks 	 * a "deny" delete entry or ACCESS_UNDETERMINED if the "delete"
15272604Smarks 	 * entry exists on the target.
15282604Smarks 	 *
15292604Smarks 	 * dzp_error should be either EACCES which indicates a "deny"
15302604Smarks 	 * entry for delete_child or ACCESS_UNDETERMINED if no delete_child
15312604Smarks 	 * entry exists.  If value is EACCES then we are done
15322604Smarks 	 * and zfs_delete_final_check() will make the final decision
15332604Smarks 	 * regarding to allow the delete.
15342604Smarks 	 */
15352604Smarks 
15362604Smarks 	ASSERT(zp_error != 0 && dzp_error != 0);
15372604Smarks 	if (dzp_error == EACCES)
15382604Smarks 		return (zfs_delete_final_check(zp, dzp, cr));
15392604Smarks 
15402604Smarks 	/*
1541789Sahrens 	 * Third Row
15422604Smarks 	 * Only need to check for write/execute on parent
1543789Sahrens 	 */
1544789Sahrens 
1545789Sahrens 	dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE,
1546789Sahrens 	    &dzp_working_mode, cr);
1547789Sahrens 
1548789Sahrens 	if (dzp_error == EROFS)
1549789Sahrens 		return (dzp_error);
1550789Sahrens 
15511576Smarks 	if ((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0)
15522604Smarks 		return (zfs_sticky_remove_access(dzp, zp, cr));
1553789Sahrens 
1554789Sahrens 	/*
1555789Sahrens 	 * Fourth Row
1556789Sahrens 	 */
1557789Sahrens 
15581576Smarks 	if (((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) != 0) &&
15591576Smarks 	    ((zp_working_mode & ACE_DELETE) == 0))
15602604Smarks 		return (zfs_sticky_remove_access(dzp, zp, cr));
1561789Sahrens 
15622604Smarks 	return (zfs_delete_final_check(zp, dzp, cr));
1563789Sahrens }
1564789Sahrens 
1565789Sahrens int
1566789Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
1567789Sahrens     znode_t *tzp, cred_t *cr)
1568789Sahrens {
1569789Sahrens 	int add_perm;
1570789Sahrens 	int error;
1571789Sahrens 
1572789Sahrens 	add_perm = (ZTOV(szp)->v_type == VDIR) ?
1573789Sahrens 	    ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE;
1574789Sahrens 
1575789Sahrens 	/*
1576789Sahrens 	 * Rename permissions are combination of delete permission +
1577789Sahrens 	 * add file/subdir permission.
1578789Sahrens 	 */
1579789Sahrens 
1580789Sahrens 	/*
1581789Sahrens 	 * first make sure we do the delete portion.
1582789Sahrens 	 *
1583789Sahrens 	 * If that succeeds then check for add_file/add_subdir permissions
1584789Sahrens 	 */
1585789Sahrens 
1586789Sahrens 	if (error = zfs_zaccess_delete(sdzp, szp, cr))
1587789Sahrens 		return (error);
1588789Sahrens 
1589789Sahrens 	/*
1590789Sahrens 	 * If we have a tzp, see if we can delete it?
1591789Sahrens 	 */
1592789Sahrens 	if (tzp) {
1593789Sahrens 		if (error = zfs_zaccess_delete(tdzp, tzp, cr))
1594789Sahrens 			return (error);
1595789Sahrens 	}
1596789Sahrens 
1597789Sahrens 	/*
1598789Sahrens 	 * Now check for add permissions
1599789Sahrens 	 */
16001308Smarks 	error = zfs_zaccess(tdzp, add_perm, cr);
1601789Sahrens 
1602789Sahrens 	return (error);
1603789Sahrens }
1604