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