xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_acl.c (revision 789:b348f31ed315)
1*789Sahrens /*
2*789Sahrens  * CDDL HEADER START
3*789Sahrens  *
4*789Sahrens  * The contents of this file are subject to the terms of the
5*789Sahrens  * Common Development and Distribution License, Version 1.0 only
6*789Sahrens  * (the "License").  You may not use this file except in compliance
7*789Sahrens  * with the License.
8*789Sahrens  *
9*789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*789Sahrens  * or http://www.opensolaris.org/os/licensing.
11*789Sahrens  * See the License for the specific language governing permissions
12*789Sahrens  * and limitations under the License.
13*789Sahrens  *
14*789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
15*789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
17*789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
18*789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
19*789Sahrens  *
20*789Sahrens  * CDDL HEADER END
21*789Sahrens  */
22*789Sahrens /*
23*789Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*789Sahrens  * Use is subject to license terms.
25*789Sahrens  */
26*789Sahrens 
27*789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*789Sahrens 
29*789Sahrens #include <sys/types.h>
30*789Sahrens #include <sys/param.h>
31*789Sahrens #include <sys/time.h>
32*789Sahrens #include <sys/systm.h>
33*789Sahrens #include <sys/sysmacros.h>
34*789Sahrens #include <sys/resource.h>
35*789Sahrens #include <sys/vfs.h>
36*789Sahrens #include <sys/vnode.h>
37*789Sahrens #include <sys/file.h>
38*789Sahrens #include <sys/stat.h>
39*789Sahrens #include <sys/kmem.h>
40*789Sahrens #include <sys/cmn_err.h>
41*789Sahrens #include <sys/errno.h>
42*789Sahrens #include <sys/unistd.h>
43*789Sahrens #include <sys/fs/zfs.h>
44*789Sahrens #include <sys/mode.h>
45*789Sahrens #include <sys/policy.h>
46*789Sahrens #include <sys/zfs_znode.h>
47*789Sahrens #include <sys/zfs_acl.h>
48*789Sahrens #include <sys/zfs_dir.h>
49*789Sahrens #include <sys/zfs_vfsops.h>
50*789Sahrens #include <sys/dmu.h>
51*789Sahrens #include <sys/zap.h>
52*789Sahrens #include <util/qsort.h>
53*789Sahrens #include "fs/fs_subr.h"
54*789Sahrens #include <acl/acl_common.h>
55*789Sahrens 
56*789Sahrens #define	ALLOW	ACE_ACCESS_ALLOWED_ACE_TYPE
57*789Sahrens #define	DENY	ACE_ACCESS_DENIED_ACE_TYPE
58*789Sahrens 
59*789Sahrens #define	OWNING_GROUP		(ACE_GROUP|ACE_IDENTIFIER_GROUP)
60*789Sahrens #define	EVERYONE_ALLOW_MASK (ACE_READ_ACL|ACE_READ_ATTRIBUTES | \
61*789Sahrens     ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE)
62*789Sahrens #define	EVERYONE_DENY_MASK (ACE_WRITE_ACL|ACE_WRITE_OWNER | \
63*789Sahrens     ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS)
64*789Sahrens #define	OWNER_ALLOW_MASK (ACE_WRITE_ACL | ACE_WRITE_OWNER | \
65*789Sahrens     ACE_WRITE_ATTRIBUTES|ACE_WRITE_NAMED_ATTRS)
66*789Sahrens #define	WRITE_MASK (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_WRITE_NAMED_ATTRS| \
67*789Sahrens     ACE_WRITE_ATTRIBUTES|ACE_WRITE_ACL|ACE_WRITE_OWNER)
68*789Sahrens 
69*789Sahrens #define	OGE_CLEAR	(ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \
70*789Sahrens     ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE)
71*789Sahrens 
72*789Sahrens #define	OKAY_MASK_BITS (ACE_READ_DATA|ACE_LIST_DIRECTORY|ACE_WRITE_DATA| \
73*789Sahrens     ACE_ADD_FILE|ACE_APPEND_DATA|ACE_ADD_SUBDIRECTORY|ACE_EXECUTE)
74*789Sahrens 
75*789Sahrens #define	ALL_INHERIT	(ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE | \
76*789Sahrens     ACE_NO_PROPAGATE_INHERIT_ACE|ACE_INHERIT_ONLY_ACE)
77*789Sahrens 
78*789Sahrens #define	SECURE_NO_INHERIT	(ACE_WRITE_ACL|ACE_WRITE_OWNER)
79*789Sahrens 
80*789Sahrens #define	OGE_PAD	6		/* traditional owner/group/everyone ACES */
81*789Sahrens 
82*789Sahrens static int zfs_ace_can_use(znode_t *zp, ace_t *);
83*789Sahrens 
84*789Sahrens static zfs_acl_t *
85*789Sahrens zfs_acl_alloc(int slots)
86*789Sahrens {
87*789Sahrens 	zfs_acl_t *aclp;
88*789Sahrens 
89*789Sahrens 	aclp = kmem_zalloc(sizeof (zfs_acl_t), KM_SLEEP);
90*789Sahrens 	if (slots != 0) {
91*789Sahrens 		aclp->z_acl = kmem_alloc(ZFS_ACL_SIZE(slots), KM_SLEEP);
92*789Sahrens 		aclp->z_acl_count = 0;
93*789Sahrens 		aclp->z_state = ACL_DATA_ALLOCED;
94*789Sahrens 	} else {
95*789Sahrens 		aclp->z_state = 0;
96*789Sahrens 	}
97*789Sahrens 	aclp->z_slots = slots;
98*789Sahrens 	return (aclp);
99*789Sahrens }
100*789Sahrens 
101*789Sahrens void
102*789Sahrens zfs_acl_free(zfs_acl_t *aclp)
103*789Sahrens {
104*789Sahrens 	if (aclp->z_state == ACL_DATA_ALLOCED) {
105*789Sahrens 		kmem_free(aclp->z_acl, ZFS_ACL_SIZE(aclp->z_slots));
106*789Sahrens 	}
107*789Sahrens 	kmem_free(aclp, sizeof (zfs_acl_t));
108*789Sahrens }
109*789Sahrens 
110*789Sahrens static uint32_t
111*789Sahrens zfs_v4_to_unix(uint32_t access_mask)
112*789Sahrens {
113*789Sahrens 	uint32_t new_mask = 0;
114*789Sahrens 
115*789Sahrens 	if (access_mask & (ACE_READ_DATA | ACE_LIST_DIRECTORY))
116*789Sahrens 		new_mask |= S_IROTH;
117*789Sahrens 	if (access_mask & (ACE_WRITE_DATA|ACE_APPEND_DATA|ACE_ADD_FILE))
118*789Sahrens 		new_mask |= S_IWOTH;
119*789Sahrens 	if (access_mask & (ACE_EXECUTE|ACE_READ_NAMED_ATTRS))
120*789Sahrens 		new_mask |= S_IXOTH;
121*789Sahrens 
122*789Sahrens 	return (new_mask);
123*789Sahrens }
124*789Sahrens 
125*789Sahrens /*
126*789Sahrens  * Convert unix access mask to v4 access mask
127*789Sahrens  */
128*789Sahrens static uint32_t
129*789Sahrens zfs_unix_to_v4(uint32_t access_mask)
130*789Sahrens {
131*789Sahrens 	uint32_t new_mask = 0;
132*789Sahrens 
133*789Sahrens 	if (access_mask & 01)
134*789Sahrens 		new_mask |= (ACE_EXECUTE);
135*789Sahrens 	if (access_mask & 02) {
136*789Sahrens 		new_mask |= (ACE_WRITE_DATA);
137*789Sahrens 	} if (access_mask & 04) {
138*789Sahrens 		new_mask |= ACE_READ_DATA;
139*789Sahrens 	}
140*789Sahrens 	return (new_mask);
141*789Sahrens }
142*789Sahrens 
143*789Sahrens static void
144*789Sahrens zfs_set_ace(ace_t *zacep, uint32_t access_mask, int access_type,
145*789Sahrens     uid_t uid, int entry_type)
146*789Sahrens {
147*789Sahrens 	zacep->a_access_mask = access_mask;
148*789Sahrens 	zacep->a_type = access_type;
149*789Sahrens 	zacep->a_who = uid;
150*789Sahrens 	zacep->a_flags = entry_type;
151*789Sahrens }
152*789Sahrens 
153*789Sahrens static uint64_t
154*789Sahrens zfs_mode_compute(znode_t *zp, zfs_acl_t *aclp)
155*789Sahrens {
156*789Sahrens 	int 	i;
157*789Sahrens 	int	entry_type;
158*789Sahrens 	mode_t	mode = (zp->z_phys->zp_mode &
159*789Sahrens 	    (S_IFMT | S_ISUID | S_ISGID | S_ISVTX));
160*789Sahrens 	mode_t	 seen = 0;
161*789Sahrens 	ace_t 	*acep;
162*789Sahrens 
163*789Sahrens 	for (i = 0, acep = aclp->z_acl;
164*789Sahrens 	    i != aclp->z_acl_count; i++, acep++) {
165*789Sahrens 		entry_type = (acep->a_flags & 0xf040);
166*789Sahrens 		if (entry_type == ACE_OWNER) {
167*789Sahrens 			if ((acep->a_access_mask & ACE_READ_DATA) &&
168*789Sahrens 			    (!(seen & S_IRUSR))) {
169*789Sahrens 				seen |= S_IRUSR;
170*789Sahrens 				if (acep->a_type == ALLOW) {
171*789Sahrens 					mode |= S_IRUSR;
172*789Sahrens 				}
173*789Sahrens 			}
174*789Sahrens 			if ((acep->a_access_mask & ACE_WRITE_DATA) &&
175*789Sahrens 			    (!(seen & S_IWUSR))) {
176*789Sahrens 				seen |= S_IWUSR;
177*789Sahrens 				if (acep->a_type == ALLOW) {
178*789Sahrens 					mode |= S_IWUSR;
179*789Sahrens 				}
180*789Sahrens 			}
181*789Sahrens 			if ((acep->a_access_mask & ACE_EXECUTE) &&
182*789Sahrens 			    (!(seen & S_IXUSR))) {
183*789Sahrens 				seen |= S_IXUSR;
184*789Sahrens 				if (acep->a_type == ALLOW) {
185*789Sahrens 					mode |= S_IXUSR;
186*789Sahrens 				}
187*789Sahrens 			}
188*789Sahrens 		} else if (entry_type == OWNING_GROUP) {
189*789Sahrens 			if ((acep->a_access_mask & ACE_READ_DATA) &&
190*789Sahrens 			    (!(seen & S_IRGRP))) {
191*789Sahrens 				seen |= S_IRGRP;
192*789Sahrens 				if (acep->a_type == ALLOW) {
193*789Sahrens 					mode |= S_IRGRP;
194*789Sahrens 				}
195*789Sahrens 			}
196*789Sahrens 			if ((acep->a_access_mask & ACE_WRITE_DATA) &&
197*789Sahrens 			    (!(seen & S_IWGRP))) {
198*789Sahrens 				seen |= S_IWGRP;
199*789Sahrens 				if (acep->a_type == ALLOW) {
200*789Sahrens 					mode |= S_IWGRP;
201*789Sahrens 				}
202*789Sahrens 			}
203*789Sahrens 			if ((acep->a_access_mask & ACE_EXECUTE) &&
204*789Sahrens 			    (!(seen & S_IXGRP))) {
205*789Sahrens 				seen |= S_IXGRP;
206*789Sahrens 				if (acep->a_type == ALLOW) {
207*789Sahrens 					mode |= S_IXGRP;
208*789Sahrens 				}
209*789Sahrens 			}
210*789Sahrens 		} else if (entry_type == ACE_EVERYONE) {
211*789Sahrens 			if ((acep->a_access_mask & ACE_READ_DATA)) {
212*789Sahrens 				if (!(seen & S_IRUSR)) {
213*789Sahrens 					seen |= S_IRUSR;
214*789Sahrens 					if (acep->a_type == ALLOW) {
215*789Sahrens 						mode |= S_IRUSR;
216*789Sahrens 					}
217*789Sahrens 				}
218*789Sahrens 				if (!(seen & S_IRGRP)) {
219*789Sahrens 					seen |= S_IRGRP;
220*789Sahrens 					if (acep->a_type == ALLOW) {
221*789Sahrens 						mode |= S_IRGRP;
222*789Sahrens 					}
223*789Sahrens 				}
224*789Sahrens 				if (!(seen & S_IROTH)) {
225*789Sahrens 					seen |= S_IROTH;
226*789Sahrens 					if (acep->a_type == ALLOW) {
227*789Sahrens 						mode |= S_IROTH;
228*789Sahrens 					}
229*789Sahrens 				}
230*789Sahrens 			}
231*789Sahrens 			if ((acep->a_access_mask & ACE_WRITE_DATA)) {
232*789Sahrens 				if (!(seen & S_IWUSR)) {
233*789Sahrens 					seen |= S_IWUSR;
234*789Sahrens 					if (acep->a_type == ALLOW) {
235*789Sahrens 						mode |= S_IWUSR;
236*789Sahrens 					}
237*789Sahrens 				}
238*789Sahrens 				if (!(seen & S_IWGRP)) {
239*789Sahrens 					seen |= S_IWGRP;
240*789Sahrens 					if (acep->a_type == ALLOW) {
241*789Sahrens 						mode |= S_IWGRP;
242*789Sahrens 					}
243*789Sahrens 				}
244*789Sahrens 				if (!(seen & S_IWOTH)) {
245*789Sahrens 					seen |= S_IWOTH;
246*789Sahrens 					if (acep->a_type == ALLOW) {
247*789Sahrens 						mode |= S_IWOTH;
248*789Sahrens 					}
249*789Sahrens 				}
250*789Sahrens 			}
251*789Sahrens 			if ((acep->a_access_mask & ACE_EXECUTE)) {
252*789Sahrens 				if (!(seen & S_IXUSR)) {
253*789Sahrens 					seen |= S_IXUSR;
254*789Sahrens 					if (acep->a_type == ALLOW) {
255*789Sahrens 						mode |= S_IXUSR;
256*789Sahrens 					}
257*789Sahrens 				}
258*789Sahrens 				if (!(seen & S_IXGRP)) {
259*789Sahrens 					seen |= S_IXGRP;
260*789Sahrens 					if (acep->a_type == ALLOW) {
261*789Sahrens 						mode |= S_IXGRP;
262*789Sahrens 					}
263*789Sahrens 				}
264*789Sahrens 				if (!(seen & S_IXOTH)) {
265*789Sahrens 					seen |= S_IXOTH;
266*789Sahrens 					if (acep->a_type == ALLOW) {
267*789Sahrens 						mode |= S_IXOTH;
268*789Sahrens 					}
269*789Sahrens 				}
270*789Sahrens 			}
271*789Sahrens 		}
272*789Sahrens 	}
273*789Sahrens 	return (mode);
274*789Sahrens }
275*789Sahrens 
276*789Sahrens static zfs_acl_t *
277*789Sahrens zfs_acl_node_read_internal(znode_t *zp)
278*789Sahrens {
279*789Sahrens 	zfs_acl_t	*aclp;
280*789Sahrens 
281*789Sahrens 	aclp = zfs_acl_alloc(0);
282*789Sahrens 	aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count;
283*789Sahrens 	aclp->z_acl = &zp->z_phys->zp_acl.z_ace_data[0];
284*789Sahrens 
285*789Sahrens 	return (aclp);
286*789Sahrens }
287*789Sahrens 
288*789Sahrens /*
289*789Sahrens  * Read an external acl object.
290*789Sahrens  */
291*789Sahrens zfs_acl_t *
292*789Sahrens zfs_acl_node_read(znode_t *zp)
293*789Sahrens {
294*789Sahrens 	uint64_t extacl = zp->z_phys->zp_acl.z_acl_extern_obj;
295*789Sahrens 	zfs_acl_t	*aclp;
296*789Sahrens 
297*789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_acl_lock));
298*789Sahrens 
299*789Sahrens 	if (zp->z_phys->zp_acl.z_acl_extern_obj == 0)
300*789Sahrens 		return (zfs_acl_node_read_internal(zp));
301*789Sahrens 
302*789Sahrens 	aclp = zfs_acl_alloc(zp->z_phys->zp_acl.z_acl_count);
303*789Sahrens 
304*789Sahrens 	dmu_read(zp->z_zfsvfs->z_os, extacl, 0,
305*789Sahrens 	    ZFS_ACL_SIZE(zp->z_phys->zp_acl.z_acl_count), aclp->z_acl);
306*789Sahrens 
307*789Sahrens 	aclp->z_acl_count = zp->z_phys->zp_acl.z_acl_count;
308*789Sahrens 
309*789Sahrens 	return (aclp);
310*789Sahrens }
311*789Sahrens 
312*789Sahrens static boolean_t
313*789Sahrens zfs_acl_valid(znode_t *zp, ace_t *uace, int aclcnt, int *inherit)
314*789Sahrens {
315*789Sahrens 	ace_t 	*acep;
316*789Sahrens 	int i;
317*789Sahrens 
318*789Sahrens 	*inherit = 0;
319*789Sahrens 
320*789Sahrens 	if (aclcnt > MAX_ACL_ENTRIES || aclcnt <= 0) {
321*789Sahrens 		return (B_FALSE);
322*789Sahrens 	}
323*789Sahrens 
324*789Sahrens 	for (i = 0, acep = uace; i != aclcnt; i++, acep++) {
325*789Sahrens 
326*789Sahrens 		/*
327*789Sahrens 		 * first check type of entry
328*789Sahrens 		 */
329*789Sahrens 
330*789Sahrens 		switch (acep->a_flags & 0xf040) {
331*789Sahrens 		case ACE_OWNER:
332*789Sahrens 			acep->a_who = -1;
333*789Sahrens 			break;
334*789Sahrens 		case (ACE_IDENTIFIER_GROUP | ACE_GROUP):
335*789Sahrens 		case ACE_IDENTIFIER_GROUP:
336*789Sahrens 			if (acep->a_flags & ACE_GROUP) {
337*789Sahrens 				acep->a_who = -1;
338*789Sahrens 			}
339*789Sahrens 			break;
340*789Sahrens 		case ACE_EVERYONE:
341*789Sahrens 			acep->a_who = -1;
342*789Sahrens 			break;
343*789Sahrens 		}
344*789Sahrens 
345*789Sahrens 		/*
346*789Sahrens 		 * next check inheritance level flags
347*789Sahrens 		 */
348*789Sahrens 
349*789Sahrens 		if (acep->a_type != ALLOW && acep->a_type != DENY)
350*789Sahrens 			return (B_FALSE);
351*789Sahrens 
352*789Sahrens 		/*
353*789Sahrens 		 * Only directories should have inheritance flags.
354*789Sahrens 		 */
355*789Sahrens 		if (ZTOV(zp)->v_type != VDIR && (acep->a_flags &
356*789Sahrens 		    (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE|
357*789Sahrens 		    ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE))) {
358*789Sahrens 			return (B_FALSE);
359*789Sahrens 		}
360*789Sahrens 
361*789Sahrens 		if (acep->a_flags &
362*789Sahrens 		    (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))
363*789Sahrens 			*inherit = 1;
364*789Sahrens 
365*789Sahrens 		if (acep->a_flags &
366*789Sahrens 		    (ACE_INHERIT_ONLY_ACE|ACE_NO_PROPAGATE_INHERIT_ACE)) {
367*789Sahrens 			if ((acep->a_flags & (ACE_FILE_INHERIT_ACE|
368*789Sahrens 			    ACE_DIRECTORY_INHERIT_ACE)) == 0) {
369*789Sahrens 				return (B_FALSE);
370*789Sahrens 			}
371*789Sahrens 		}
372*789Sahrens 	}
373*789Sahrens 
374*789Sahrens 	return (B_TRUE);
375*789Sahrens }
376*789Sahrens /*
377*789Sahrens  * common code for setting acl's.
378*789Sahrens  *
379*789Sahrens  * This function is called from zfs_mode_update, zfs_perm_init, and zfs_setacl.
380*789Sahrens  * zfs_setacl passes a non-NULL inherit pointer (ihp) to indicate that it's
381*789Sahrens  * already checked the acl and knows whether to inherit.
382*789Sahrens  */
383*789Sahrens int
384*789Sahrens zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, dmu_tx_t *tx, int *ihp)
385*789Sahrens {
386*789Sahrens 	int 		inherit = 0;
387*789Sahrens 	int		error;
388*789Sahrens 	znode_phys_t	*zphys = zp->z_phys;
389*789Sahrens 	zfs_znode_acl_t	*zacl = &zphys->zp_acl;
390*789Sahrens 	uint32_t	acl_phys_size = ZFS_ACL_SIZE(aclp->z_acl_count);
391*789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
392*789Sahrens 	uint64_t	aoid = zphys->zp_acl.z_acl_extern_obj;
393*789Sahrens 
394*789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_lock));
395*789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_acl_lock));
396*789Sahrens 
397*789Sahrens 	if (ihp)
398*789Sahrens 		inherit = *ihp;		/* already determined by caller */
399*789Sahrens 	else if (!zfs_acl_valid(zp, aclp->z_acl,
400*789Sahrens 	    aclp->z_acl_count, &inherit)) {
401*789Sahrens 		return (EINVAL);
402*789Sahrens 	}
403*789Sahrens 
404*789Sahrens 	dmu_buf_will_dirty(zp->z_dbuf, tx);
405*789Sahrens 
406*789Sahrens 	/*
407*789Sahrens 	 * Will ACL fit internally?
408*789Sahrens 	 */
409*789Sahrens 	if (aclp->z_acl_count > ACE_SLOT_CNT) {
410*789Sahrens 		if (aoid == 0) {
411*789Sahrens 			aoid = dmu_object_alloc(zfsvfs->z_os,
412*789Sahrens 			    DMU_OT_ACL, acl_phys_size, DMU_OT_NONE, 0, tx);
413*789Sahrens 		} else {
414*789Sahrens 			(void) dmu_object_set_blocksize(zfsvfs->z_os, aoid,
415*789Sahrens 			    acl_phys_size, 0, tx);
416*789Sahrens 		}
417*789Sahrens 		zphys->zp_acl.z_acl_extern_obj = aoid;
418*789Sahrens 		zphys->zp_acl.z_acl_count = aclp->z_acl_count;
419*789Sahrens 		dmu_write(zfsvfs->z_os, aoid, 0,
420*789Sahrens 		    acl_phys_size, aclp->z_acl, tx);
421*789Sahrens 	} else {
422*789Sahrens 		/*
423*789Sahrens 		 * Migrating back embedded?
424*789Sahrens 		 */
425*789Sahrens 		if (zphys->zp_acl.z_acl_extern_obj) {
426*789Sahrens 			error = dmu_object_free(zfsvfs->z_os,
427*789Sahrens 				zp->z_phys->zp_acl.z_acl_extern_obj, tx);
428*789Sahrens 			if (error)
429*789Sahrens 				return (error);
430*789Sahrens 			zphys->zp_acl.z_acl_extern_obj = 0;
431*789Sahrens 		}
432*789Sahrens 		bcopy(aclp->z_acl, zacl->z_ace_data,
433*789Sahrens 		    aclp->z_acl_count * sizeof (ace_t));
434*789Sahrens 		zacl->z_acl_count = aclp->z_acl_count;
435*789Sahrens 	}
436*789Sahrens 	if (inherit)
437*789Sahrens 		zp->z_phys->zp_flags |= ZFS_INHERIT_ACE;
438*789Sahrens 	else
439*789Sahrens 		zp->z_phys->zp_flags &= ~ZFS_INHERIT_ACE;
440*789Sahrens 
441*789Sahrens 	zphys->zp_mode = zfs_mode_compute(zp, aclp);
442*789Sahrens 	zfs_time_stamper_locked(zp, STATE_CHANGED, tx);
443*789Sahrens 
444*789Sahrens 	return (0);
445*789Sahrens }
446*789Sahrens 
447*789Sahrens /*
448*789Sahrens  * Create space for slots_needed ACEs to be append
449*789Sahrens  * to aclp.
450*789Sahrens  */
451*789Sahrens static void
452*789Sahrens zfs_acl_append(zfs_acl_t *aclp, int slots_needed)
453*789Sahrens {
454*789Sahrens 	ace_t	*newacep;
455*789Sahrens 	ace_t	*oldaclp;
456*789Sahrens 	int	slot_cnt;
457*789Sahrens 	int 	slots_left = aclp->z_slots - aclp->z_acl_count;
458*789Sahrens 
459*789Sahrens 	if (aclp->z_state == ACL_DATA_ALLOCED)
460*789Sahrens 		ASSERT(aclp->z_slots >= aclp->z_acl_count);
461*789Sahrens 	if (slots_left < slots_needed || aclp->z_state != ACL_DATA_ALLOCED) {
462*789Sahrens 		slot_cnt = aclp->z_slots +  1 + (slots_needed - slots_left);
463*789Sahrens 		newacep = kmem_alloc(ZFS_ACL_SIZE(slot_cnt), KM_SLEEP);
464*789Sahrens 		bcopy(aclp->z_acl, newacep,
465*789Sahrens 		    ZFS_ACL_SIZE(aclp->z_acl_count));
466*789Sahrens 		oldaclp = aclp->z_acl;
467*789Sahrens 		if (aclp->z_state == ACL_DATA_ALLOCED)
468*789Sahrens 			kmem_free(oldaclp, ZFS_ACL_SIZE(aclp->z_slots));
469*789Sahrens 		aclp->z_acl = newacep;
470*789Sahrens 		aclp->z_slots = slot_cnt;
471*789Sahrens 		aclp->z_state = ACL_DATA_ALLOCED;
472*789Sahrens 	}
473*789Sahrens }
474*789Sahrens 
475*789Sahrens /*
476*789Sahrens  * Remove "slot" ACE from aclp
477*789Sahrens  */
478*789Sahrens static void
479*789Sahrens zfs_ace_remove(zfs_acl_t *aclp, int slot)
480*789Sahrens {
481*789Sahrens 	if (aclp->z_acl_count > 1) {
482*789Sahrens 		(void) memmove(&aclp->z_acl[slot],
483*789Sahrens 		    &aclp->z_acl[slot +1], sizeof (ace_t) *
484*789Sahrens 		    (--aclp->z_acl_count - slot));
485*789Sahrens 	} else
486*789Sahrens 		aclp->z_acl_count--;
487*789Sahrens }
488*789Sahrens 
489*789Sahrens /*
490*789Sahrens  * Update access mask for prepended ACE
491*789Sahrens  *
492*789Sahrens  * This applies the "groupmask" value for aclmode property.
493*789Sahrens  */
494*789Sahrens static void
495*789Sahrens zfs_acl_prepend_fixup(ace_t *acep, ace_t *origacep, mode_t mode, uid_t owner)
496*789Sahrens {
497*789Sahrens 
498*789Sahrens 	int	rmask, wmask, xmask;
499*789Sahrens 	int	user_ace;
500*789Sahrens 
501*789Sahrens 	user_ace = (!(acep->a_flags &
502*789Sahrens 	    (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP)));
503*789Sahrens 
504*789Sahrens 	if (user_ace && (acep->a_who == owner)) {
505*789Sahrens 		rmask = S_IRUSR;
506*789Sahrens 		wmask = S_IWUSR;
507*789Sahrens 		xmask = S_IXUSR;
508*789Sahrens 	} else {
509*789Sahrens 		rmask = S_IRGRP;
510*789Sahrens 		wmask = S_IWGRP;
511*789Sahrens 		xmask = S_IXGRP;
512*789Sahrens 	}
513*789Sahrens 
514*789Sahrens 	if (origacep->a_access_mask & ACE_READ_DATA) {
515*789Sahrens 		if (mode & rmask)
516*789Sahrens 			acep->a_access_mask &= ~ACE_READ_DATA;
517*789Sahrens 		else
518*789Sahrens 			acep->a_access_mask |= ACE_READ_DATA;
519*789Sahrens 	}
520*789Sahrens 
521*789Sahrens 	if (origacep->a_access_mask & ACE_WRITE_DATA) {
522*789Sahrens 		if (mode & wmask)
523*789Sahrens 			acep->a_access_mask &= ~ACE_WRITE_DATA;
524*789Sahrens 		else
525*789Sahrens 			acep->a_access_mask |= ACE_WRITE_DATA;
526*789Sahrens 	}
527*789Sahrens 
528*789Sahrens 	if (origacep->a_access_mask & ACE_APPEND_DATA) {
529*789Sahrens 		if (mode & wmask)
530*789Sahrens 			acep->a_access_mask &= ~ACE_APPEND_DATA;
531*789Sahrens 		else
532*789Sahrens 			acep->a_access_mask |= ACE_APPEND_DATA;
533*789Sahrens 	}
534*789Sahrens 
535*789Sahrens 	if (origacep->a_access_mask & ACE_EXECUTE) {
536*789Sahrens 		if (mode & xmask)
537*789Sahrens 			acep->a_access_mask &= ~ACE_EXECUTE;
538*789Sahrens 		else
539*789Sahrens 			acep->a_access_mask |= ACE_EXECUTE;
540*789Sahrens 	}
541*789Sahrens }
542*789Sahrens 
543*789Sahrens /*
544*789Sahrens  * Apply mode to canonical six ACEs.
545*789Sahrens  */
546*789Sahrens static void
547*789Sahrens zfs_acl_fixup_canonical_six(zfs_acl_t *aclp, mode_t mode)
548*789Sahrens {
549*789Sahrens 	int	cnt;
550*789Sahrens 	ace_t	*acep;
551*789Sahrens 
552*789Sahrens 	cnt = aclp->z_acl_count -1;
553*789Sahrens 	acep = aclp->z_acl;
554*789Sahrens 
555*789Sahrens 	/*
556*789Sahrens 	 * Fixup final ACEs to match the mode
557*789Sahrens 	 */
558*789Sahrens 
559*789Sahrens 	ASSERT(cnt >= 5);
560*789Sahrens 	adjust_ace_pair(&acep[cnt - 1], mode);	/* everyone@ */
561*789Sahrens 	adjust_ace_pair(&acep[cnt - 3], (mode & 0070) >> 3);	/* group@ */
562*789Sahrens 	adjust_ace_pair(&acep[cnt - 5], (mode & 0700) >> 6);	/* owner@ */
563*789Sahrens }
564*789Sahrens 
565*789Sahrens 
566*789Sahrens static int
567*789Sahrens zfs_acl_ace_match(ace_t *acep, int allow_deny, int type, int mask)
568*789Sahrens {
569*789Sahrens 	return (acep->a_access_mask == mask && acep->a_type == allow_deny &&
570*789Sahrens 	    ((acep->a_flags & 0xf040) == type));
571*789Sahrens }
572*789Sahrens 
573*789Sahrens /*
574*789Sahrens  * Can prepended ACE be reused?
575*789Sahrens  */
576*789Sahrens static int
577*789Sahrens zfs_reuse_deny(ace_t *acep, int i)
578*789Sahrens {
579*789Sahrens 	int okay_masks;
580*789Sahrens 
581*789Sahrens 	if (i < 1)
582*789Sahrens 		return (B_FALSE);
583*789Sahrens 
584*789Sahrens 	if (acep[i-1].a_type != DENY)
585*789Sahrens 		return (B_FALSE);
586*789Sahrens 
587*789Sahrens 	if (acep[i-1].a_flags != (acep[i].a_flags & ACE_IDENTIFIER_GROUP))
588*789Sahrens 		return (B_FALSE);
589*789Sahrens 
590*789Sahrens 	okay_masks = (acep[i].a_access_mask & OKAY_MASK_BITS);
591*789Sahrens 
592*789Sahrens 	if (acep[i-1].a_access_mask & ~okay_masks)
593*789Sahrens 		return (B_FALSE);
594*789Sahrens 
595*789Sahrens 	return (B_TRUE);
596*789Sahrens }
597*789Sahrens 
598*789Sahrens /*
599*789Sahrens  * Create space to prepend an ACE
600*789Sahrens  */
601*789Sahrens static void
602*789Sahrens zfs_acl_prepend(zfs_acl_t *aclp, int i)
603*789Sahrens {
604*789Sahrens 	ace_t	*oldaclp = NULL;
605*789Sahrens 	ace_t	*to, *from;
606*789Sahrens 	int	slots_left = aclp->z_slots - aclp->z_acl_count;
607*789Sahrens 	int	oldslots;
608*789Sahrens 	int	need_free = 0;
609*789Sahrens 
610*789Sahrens 	if (aclp->z_state == ACL_DATA_ALLOCED)
611*789Sahrens 		ASSERT(aclp->z_slots >= aclp->z_acl_count);
612*789Sahrens 
613*789Sahrens 	if (slots_left == 0 || aclp->z_state != ACL_DATA_ALLOCED) {
614*789Sahrens 
615*789Sahrens 		to = kmem_alloc(ZFS_ACL_SIZE(aclp->z_acl_count +
616*789Sahrens 		    OGE_PAD), KM_SLEEP);
617*789Sahrens 		if (aclp->z_state == ACL_DATA_ALLOCED)
618*789Sahrens 			need_free++;
619*789Sahrens 		from = aclp->z_acl;
620*789Sahrens 		oldaclp = aclp->z_acl;
621*789Sahrens 		(void) memmove(to, from,
622*789Sahrens 		    sizeof (ace_t) * aclp->z_acl_count);
623*789Sahrens 		aclp->z_state = ACL_DATA_ALLOCED;
624*789Sahrens 	} else {
625*789Sahrens 		from = aclp->z_acl;
626*789Sahrens 		to = aclp->z_acl;
627*789Sahrens 	}
628*789Sahrens 
629*789Sahrens 
630*789Sahrens 	(void) memmove(&to[i + 1], &from[i],
631*789Sahrens 	    sizeof (ace_t) * (aclp->z_acl_count - i));
632*789Sahrens 
633*789Sahrens 	if (oldaclp) {
634*789Sahrens 		aclp->z_acl = to;
635*789Sahrens 		oldslots = aclp->z_slots;
636*789Sahrens 		aclp->z_slots = aclp->z_acl_count + OGE_PAD;
637*789Sahrens 		if (need_free)
638*789Sahrens 			kmem_free(oldaclp, ZFS_ACL_SIZE(oldslots));
639*789Sahrens 	}
640*789Sahrens 
641*789Sahrens }
642*789Sahrens 
643*789Sahrens /*
644*789Sahrens  * Prepend deny ACE
645*789Sahrens  */
646*789Sahrens static void
647*789Sahrens zfs_acl_prepend_deny(znode_t *zp, zfs_acl_t *aclp, int i,
648*789Sahrens     mode_t mode)
649*789Sahrens {
650*789Sahrens 	ace_t	*acep;
651*789Sahrens 
652*789Sahrens 	zfs_acl_prepend(aclp, i);
653*789Sahrens 
654*789Sahrens 	acep = aclp->z_acl;
655*789Sahrens 	zfs_set_ace(&acep[i], 0, DENY, acep[i + 1].a_who,
656*789Sahrens 	    (acep[i + 1].a_flags & 0xf040));
657*789Sahrens 	zfs_acl_prepend_fixup(&acep[i], &acep[i+1], mode, zp->z_phys->zp_uid);
658*789Sahrens 	aclp->z_acl_count++;
659*789Sahrens }
660*789Sahrens 
661*789Sahrens /*
662*789Sahrens  * Split an inherited ACE into inherit_only ACE
663*789Sahrens  * and original ACE with inheritance flags stripped off.
664*789Sahrens  */
665*789Sahrens static void
666*789Sahrens zfs_acl_split_ace(zfs_acl_t *aclp, int i)
667*789Sahrens {
668*789Sahrens 	ace_t *acep = aclp->z_acl;
669*789Sahrens 
670*789Sahrens 	zfs_acl_prepend(aclp, i);
671*789Sahrens 	acep = aclp->z_acl;
672*789Sahrens 	acep[i] = acep[i + 1];
673*789Sahrens 	acep[i].a_flags |= ACE_INHERIT_ONLY_ACE;
674*789Sahrens 	acep[i + 1].a_flags &= ~ALL_INHERIT;
675*789Sahrens 	aclp->z_acl_count++;
676*789Sahrens }
677*789Sahrens 
678*789Sahrens /*
679*789Sahrens  * Are ACES started at index i, the canonical six ACES?
680*789Sahrens  */
681*789Sahrens static int
682*789Sahrens zfs_have_canonical_six(zfs_acl_t *aclp, int i)
683*789Sahrens {
684*789Sahrens 	ace_t *acep = aclp->z_acl;
685*789Sahrens 
686*789Sahrens 	if ((zfs_acl_ace_match(&acep[i],
687*789Sahrens 	    DENY, ACE_OWNER, 0) &&
688*789Sahrens 	    zfs_acl_ace_match(&acep[i + 1], ALLOW, ACE_OWNER,
689*789Sahrens 	    OWNER_ALLOW_MASK) && zfs_acl_ace_match(&acep[i + 2],
690*789Sahrens 	    DENY, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 3],
691*789Sahrens 	    ALLOW, OWNING_GROUP, 0) && zfs_acl_ace_match(&acep[i + 4],
692*789Sahrens 	    DENY, ACE_EVERYONE, EVERYONE_DENY_MASK) &&
693*789Sahrens 	    zfs_acl_ace_match(&acep[i + 5], ALLOW, ACE_EVERYONE,
694*789Sahrens 	    EVERYONE_ALLOW_MASK))) {
695*789Sahrens 		return (1);
696*789Sahrens 	} else {
697*789Sahrens 		return (0);
698*789Sahrens 	}
699*789Sahrens }
700*789Sahrens 
701*789Sahrens /*
702*789Sahrens  * Apply step 1g, to group entries
703*789Sahrens  *
704*789Sahrens  * Need to deal with corner case where group may have
705*789Sahrens  * greater permissions than owner.  If so then limit
706*789Sahrens  * group permissions, based on what extra permissions
707*789Sahrens  * group has.
708*789Sahrens  */
709*789Sahrens static void
710*789Sahrens zfs_fixup_group_entries(ace_t *acep, mode_t mode)
711*789Sahrens {
712*789Sahrens 	mode_t extramode = (mode >> 3) & 07;
713*789Sahrens 	mode_t ownermode = (mode >> 6);
714*789Sahrens 
715*789Sahrens 	if (acep[0].a_flags & ACE_IDENTIFIER_GROUP) {
716*789Sahrens 
717*789Sahrens 		extramode &= ~ownermode;
718*789Sahrens 
719*789Sahrens 		if (extramode) {
720*789Sahrens 			if (extramode & 04) {
721*789Sahrens 				acep[0].a_access_mask &= ~ACE_READ_DATA;
722*789Sahrens 				acep[1].a_access_mask &= ~ACE_READ_DATA;
723*789Sahrens 			}
724*789Sahrens 			if (extramode & 02) {
725*789Sahrens 				acep[0].a_access_mask &=
726*789Sahrens 				    ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
727*789Sahrens 				acep[1].a_access_mask &=
728*789Sahrens 				    ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
729*789Sahrens 			}
730*789Sahrens 			if (extramode & 01) {
731*789Sahrens 				acep[0].a_access_mask &= ~ACE_EXECUTE;
732*789Sahrens 				acep[1].a_access_mask &= ~ACE_EXECUTE;
733*789Sahrens 			}
734*789Sahrens 		}
735*789Sahrens 	}
736*789Sahrens }
737*789Sahrens 
738*789Sahrens /*
739*789Sahrens  * Apply the chmod algorithm as described
740*789Sahrens  * in PSARC/2002/240
741*789Sahrens  */
742*789Sahrens static int
743*789Sahrens zfs_acl_chmod(znode_t *zp, uint64_t mode, zfs_acl_t *aclp,
744*789Sahrens     dmu_tx_t *tx)
745*789Sahrens {
746*789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
747*789Sahrens 	ace_t 		*acep;
748*789Sahrens 	int 		i;
749*789Sahrens 	int		error;
750*789Sahrens 	int 		entry_type;
751*789Sahrens 	int 		reuse_deny;
752*789Sahrens 	int 		need_canonical_six = 1;
753*789Sahrens 
754*789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_acl_lock));
755*789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_lock));
756*789Sahrens 
757*789Sahrens 	i = 0;
758*789Sahrens 	while (i < aclp->z_acl_count) {
759*789Sahrens 		acep = aclp->z_acl;
760*789Sahrens 		entry_type = (acep[i].a_flags & 0xf040);
761*789Sahrens 
762*789Sahrens 		if ((acep[i].a_type != ALLOW && acep[i].a_type != DENY) ||
763*789Sahrens 		    (acep[i].a_flags & ACE_INHERIT_ONLY_ACE)) {
764*789Sahrens 			i++;
765*789Sahrens 			continue;
766*789Sahrens 		}
767*789Sahrens 
768*789Sahrens 
769*789Sahrens 		if (zfsvfs->z_acl_mode == DISCARD) {
770*789Sahrens 			zfs_ace_remove(aclp, i);
771*789Sahrens 			continue;
772*789Sahrens 		}
773*789Sahrens 
774*789Sahrens 		/*
775*789Sahrens 		 * Need to split ace into two?
776*789Sahrens 		 */
777*789Sahrens 		if ((acep[i].a_flags & (ACE_FILE_INHERIT_ACE|
778*789Sahrens 		    ACE_DIRECTORY_INHERIT_ACE)) &&
779*789Sahrens 		    (!(acep[i].a_flags & ACE_INHERIT_ONLY_ACE))) {
780*789Sahrens 			zfs_acl_split_ace(aclp, i);
781*789Sahrens 			i++;
782*789Sahrens 			continue;
783*789Sahrens 		}
784*789Sahrens 
785*789Sahrens 		if (entry_type == ACE_OWNER || entry_type == ACE_EVERYONE ||
786*789Sahrens 		    (entry_type == OWNING_GROUP)) {
787*789Sahrens 			acep[i].a_access_mask &= ~OGE_CLEAR;
788*789Sahrens 			i++;
789*789Sahrens 			continue;
790*789Sahrens 
791*789Sahrens 		} else {
792*789Sahrens 			if (acep[i].a_type == ALLOW) {
793*789Sahrens 
794*789Sahrens 				/*
795*789Sahrens 				 * Check preceding ACE if any, to see
796*789Sahrens 				 * if we need to prepend a DENY ACE.
797*789Sahrens 				 * This is only applicable when the acl_mode
798*789Sahrens 				 * property == groupmask.
799*789Sahrens 				 */
800*789Sahrens 				if (zfsvfs->z_acl_mode == GROUPMASK) {
801*789Sahrens 
802*789Sahrens 					reuse_deny = zfs_reuse_deny(acep, i);
803*789Sahrens 
804*789Sahrens 					if (reuse_deny == B_FALSE) {
805*789Sahrens 						zfs_acl_prepend_deny(zp, aclp,
806*789Sahrens 						    i, mode);
807*789Sahrens 						i++;
808*789Sahrens 						acep = aclp->z_acl;
809*789Sahrens 					} else {
810*789Sahrens 						zfs_acl_prepend_fixup(
811*789Sahrens 						    &acep[i - 1],
812*789Sahrens 						    &acep[i], mode,
813*789Sahrens 						    zp->z_phys->zp_uid);
814*789Sahrens 					}
815*789Sahrens 					zfs_fixup_group_entries(&acep[i - 1],
816*789Sahrens 					    mode);
817*789Sahrens 				}
818*789Sahrens 			}
819*789Sahrens 			i++;
820*789Sahrens 		}
821*789Sahrens 	}
822*789Sahrens 
823*789Sahrens 	/*
824*789Sahrens 	 * Check out last six aces, if we have six.
825*789Sahrens 	 */
826*789Sahrens 
827*789Sahrens 	if (aclp->z_acl_count >= 6) {
828*789Sahrens 		i = aclp->z_acl_count - 6;
829*789Sahrens 
830*789Sahrens 		if (zfs_have_canonical_six(aclp, i)) {
831*789Sahrens 			need_canonical_six = 0;
832*789Sahrens 		}
833*789Sahrens 	}
834*789Sahrens 
835*789Sahrens 	if (need_canonical_six) {
836*789Sahrens 
837*789Sahrens 		zfs_acl_append(aclp, 6);
838*789Sahrens 		i = aclp->z_acl_count;
839*789Sahrens 		acep = aclp->z_acl;
840*789Sahrens 		zfs_set_ace(&acep[i++], 0, DENY, -1, ACE_OWNER);
841*789Sahrens 		zfs_set_ace(&acep[i++], OWNER_ALLOW_MASK, ALLOW, -1, ACE_OWNER);
842*789Sahrens 		zfs_set_ace(&acep[i++], 0, DENY, -1, OWNING_GROUP);
843*789Sahrens 		zfs_set_ace(&acep[i++], 0, ALLOW, -1, OWNING_GROUP);
844*789Sahrens 		zfs_set_ace(&acep[i++], EVERYONE_DENY_MASK,
845*789Sahrens 		    DENY, -1, ACE_EVERYONE);
846*789Sahrens 		zfs_set_ace(&acep[i++], EVERYONE_ALLOW_MASK,
847*789Sahrens 		    ALLOW, -1, ACE_EVERYONE);
848*789Sahrens 		aclp->z_acl_count += 6;
849*789Sahrens 	}
850*789Sahrens 
851*789Sahrens 	zfs_acl_fixup_canonical_six(aclp, mode);
852*789Sahrens 
853*789Sahrens 	zp->z_phys->zp_mode = mode;
854*789Sahrens 	error = zfs_aclset_common(zp, aclp, tx, NULL);
855*789Sahrens 	return (error);
856*789Sahrens }
857*789Sahrens 
858*789Sahrens 
859*789Sahrens int
860*789Sahrens zfs_acl_chmod_setattr(znode_t *zp, uint64_t mode, dmu_tx_t *tx)
861*789Sahrens {
862*789Sahrens 	zfs_acl_t *aclp;
863*789Sahrens 	int error;
864*789Sahrens 
865*789Sahrens 	ASSERT(MUTEX_HELD(&zp->z_lock));
866*789Sahrens 	mutex_enter(&zp->z_acl_lock);
867*789Sahrens 	aclp = zfs_acl_node_read(zp);
868*789Sahrens 	error = zfs_acl_chmod(zp, mode, aclp, tx);
869*789Sahrens 	mutex_exit(&zp->z_acl_lock);
870*789Sahrens 	zfs_acl_free(aclp);
871*789Sahrens 	return (error);
872*789Sahrens }
873*789Sahrens 
874*789Sahrens /*
875*789Sahrens  * strip off write_owner and write_acl
876*789Sahrens  */
877*789Sahrens static void
878*789Sahrens zfs_securemode_update(zfsvfs_t *zfsvfs, ace_t *acep)
879*789Sahrens {
880*789Sahrens 	if ((zfsvfs->z_acl_inherit == SECURE) &&
881*789Sahrens 	    acep->a_type == ALLOW)
882*789Sahrens 		acep->a_access_mask &= ~SECURE_NO_INHERIT;
883*789Sahrens }
884*789Sahrens 
885*789Sahrens /*
886*789Sahrens  * inherit inheritable ACEs from parent
887*789Sahrens  */
888*789Sahrens static zfs_acl_t *
889*789Sahrens zfs_acl_inherit(znode_t *zp, zfs_acl_t *paclp)
890*789Sahrens {
891*789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
892*789Sahrens 	ace_t 		*pacep;
893*789Sahrens 	ace_t		*acep;
894*789Sahrens 	int 		ace_cnt = 0;
895*789Sahrens 	int		pace_cnt;
896*789Sahrens 	int 		i, j;
897*789Sahrens 	zfs_acl_t	*aclp = NULL;
898*789Sahrens 
899*789Sahrens 	i = j = 0;
900*789Sahrens 	pace_cnt = paclp->z_acl_count;
901*789Sahrens 	pacep = paclp->z_acl;
902*789Sahrens 	if (zfsvfs->z_acl_inherit != DISCARD) {
903*789Sahrens 		for (i = 0; i != pace_cnt; i++) {
904*789Sahrens 
905*789Sahrens 			if (zfsvfs->z_acl_inherit == NOALLOW &&
906*789Sahrens 			    pacep[i].a_type == ALLOW)
907*789Sahrens 				continue;
908*789Sahrens 
909*789Sahrens 			if (zfs_ace_can_use(zp, &pacep[i])) {
910*789Sahrens 				ace_cnt++;
911*789Sahrens 				if (!(pacep[i].a_flags &
912*789Sahrens 				    ACE_NO_PROPAGATE_INHERIT_ACE))
913*789Sahrens 					ace_cnt++;
914*789Sahrens 			}
915*789Sahrens 		}
916*789Sahrens 	}
917*789Sahrens 
918*789Sahrens 	aclp = zfs_acl_alloc(ace_cnt + OGE_PAD);
919*789Sahrens 	if (ace_cnt && zfsvfs->z_acl_inherit != DISCARD) {
920*789Sahrens 		acep = aclp->z_acl;
921*789Sahrens 		pacep = paclp->z_acl;
922*789Sahrens 		for (i = 0; i != pace_cnt; i++) {
923*789Sahrens 
924*789Sahrens 			if (zfsvfs->z_acl_inherit == NOALLOW &&
925*789Sahrens 			    pacep[i].a_type == ALLOW)
926*789Sahrens 				continue;
927*789Sahrens 
928*789Sahrens 			if (zfs_ace_can_use(zp, &pacep[i])) {
929*789Sahrens 				/*
930*789Sahrens 				 * Now create entry for inherited ace
931*789Sahrens 				 */
932*789Sahrens 				acep[j] = pacep[i];
933*789Sahrens 
934*789Sahrens 				if (pacep[i].a_flags &
935*789Sahrens 				    ACE_NO_PROPAGATE_INHERIT_ACE) {
936*789Sahrens 					acep[j].a_flags &= ~ALL_INHERIT;
937*789Sahrens 					j++;
938*789Sahrens 					continue;
939*789Sahrens 				}
940*789Sahrens 
941*789Sahrens 				if (pacep[i].a_type != ALLOW &&
942*789Sahrens 				    pacep[i].a_type != DENY) {
943*789Sahrens 					zfs_securemode_update(zfsvfs, &acep[j]);
944*789Sahrens 					j++;
945*789Sahrens 					continue;
946*789Sahrens 				}
947*789Sahrens 
948*789Sahrens 				if (ZTOV(zp)->v_type != VDIR) {
949*789Sahrens 					acep[j].a_flags &= ~ALL_INHERIT;
950*789Sahrens 					zfs_securemode_update(zfsvfs, &acep[j]);
951*789Sahrens 					j++;
952*789Sahrens 					continue;
953*789Sahrens 				}
954*789Sahrens 
955*789Sahrens 				ASSERT(ZTOV(zp)->v_type == VDIR);
956*789Sahrens 
957*789Sahrens 				/*
958*789Sahrens 				 * If we are inheriting an ACE targeted for
959*789Sahrens 				 * only files, then leave the inherit_only
960*789Sahrens 				 * one for future propagation.
961*789Sahrens 				 */
962*789Sahrens 				if ((acep[j].a_flags & (ACE_FILE_INHERIT_ACE |
963*789Sahrens 				    ACE_DIRECTORY_INHERIT_ACE)) !=
964*789Sahrens 				    ACE_FILE_INHERIT_ACE)
965*789Sahrens 					acep[j].a_flags &=
966*789Sahrens 					    ~ACE_INHERIT_ONLY_ACE;
967*789Sahrens 
968*789Sahrens 				zfs_securemode_update(zfsvfs, &acep[j]);
969*789Sahrens 				j++;
970*789Sahrens 			}
971*789Sahrens 		}
972*789Sahrens 	}
973*789Sahrens 	aclp->z_acl_count = j;
974*789Sahrens 	ASSERT(aclp->z_slots >= aclp->z_acl_count);
975*789Sahrens 
976*789Sahrens 	return (aclp);
977*789Sahrens }
978*789Sahrens 
979*789Sahrens /*
980*789Sahrens  * Create file system object initial permissions
981*789Sahrens  * including inheritable ACEs.
982*789Sahrens  */
983*789Sahrens void
984*789Sahrens zfs_perm_init(znode_t *zp, znode_t *parent, int flag,
985*789Sahrens     vattr_t *vap, dmu_tx_t *tx, cred_t *cr)
986*789Sahrens {
987*789Sahrens 	uint64_t	mode;
988*789Sahrens 	uid_t		uid;
989*789Sahrens 	gid_t		gid;
990*789Sahrens 	int		error;
991*789Sahrens 	int		pull_down;
992*789Sahrens 	zfs_acl_t	*aclp, *paclp;
993*789Sahrens 
994*789Sahrens 	mode = MAKEIMODE(vap->va_type, vap->va_mode);
995*789Sahrens 
996*789Sahrens 	/*
997*789Sahrens 	 * Determine uid and gid.
998*789Sahrens 	 */
999*789Sahrens 	if ((flag & (IS_ROOT_NODE | IS_REPLAY)) ||
1000*789Sahrens 	    ((flag & IS_XATTR) && (vap->va_type == VDIR))) {
1001*789Sahrens 		uid = vap->va_uid;
1002*789Sahrens 		gid = vap->va_gid;
1003*789Sahrens 	} else {
1004*789Sahrens 		uid = crgetuid(cr);
1005*789Sahrens 		if ((vap->va_mask & AT_GID) &&
1006*789Sahrens 		    ((vap->va_gid == parent->z_phys->zp_gid) ||
1007*789Sahrens 		    groupmember(vap->va_gid, cr) ||
1008*789Sahrens 		    secpolicy_vnode_create_gid(cr)))
1009*789Sahrens 			gid = vap->va_gid;
1010*789Sahrens 		else
1011*789Sahrens 			gid = (parent->z_phys->zp_mode & S_ISGID) ?
1012*789Sahrens 			    parent->z_phys->zp_gid : crgetgid(cr);
1013*789Sahrens 	}
1014*789Sahrens 
1015*789Sahrens 	/*
1016*789Sahrens 	 * If we're creating a directory, and the parent directory has the
1017*789Sahrens 	 * set-GID bit set, set in on the new directory.
1018*789Sahrens 	 * Otherwise, if the user is neither privileged nor a member of the
1019*789Sahrens 	 * file's new group, clear the file's set-GID bit.
1020*789Sahrens 	 */
1021*789Sahrens 
1022*789Sahrens 	if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR))
1023*789Sahrens 		mode |= S_ISGID;
1024*789Sahrens 	else {
1025*789Sahrens 		if ((mode & S_ISGID) &&
1026*789Sahrens 		    secpolicy_vnode_setids_setgids(cr, gid) != 0)
1027*789Sahrens 			mode &= ~S_ISGID;
1028*789Sahrens 	}
1029*789Sahrens 
1030*789Sahrens 	zp->z_phys->zp_uid = uid;
1031*789Sahrens 	zp->z_phys->zp_gid = gid;
1032*789Sahrens 	zp->z_phys->zp_mode = mode;
1033*789Sahrens 
1034*789Sahrens 	mutex_enter(&parent->z_lock);
1035*789Sahrens 	pull_down = (parent->z_phys->zp_flags & ZFS_INHERIT_ACE);
1036*789Sahrens 	if (pull_down) {
1037*789Sahrens 		mutex_enter(&parent->z_acl_lock);
1038*789Sahrens 		paclp = zfs_acl_node_read(parent);
1039*789Sahrens 		mutex_exit(&parent->z_acl_lock);
1040*789Sahrens 		aclp = zfs_acl_inherit(zp, paclp);
1041*789Sahrens 		zfs_acl_free(paclp);
1042*789Sahrens 	} else {
1043*789Sahrens 		aclp = zfs_acl_alloc(6);
1044*789Sahrens 	}
1045*789Sahrens 	mutex_exit(&parent->z_lock);
1046*789Sahrens 	mutex_enter(&zp->z_lock);
1047*789Sahrens 	mutex_enter(&zp->z_acl_lock);
1048*789Sahrens 	error = zfs_acl_chmod(zp, mode, aclp, tx);
1049*789Sahrens 	mutex_exit(&zp->z_lock);
1050*789Sahrens 	mutex_exit(&zp->z_acl_lock);
1051*789Sahrens 	ASSERT3U(error, ==, 0);
1052*789Sahrens 	zfs_acl_free(aclp);
1053*789Sahrens }
1054*789Sahrens 
1055*789Sahrens /*
1056*789Sahrens  * Can use be used for inheritance
1057*789Sahrens  */
1058*789Sahrens static int
1059*789Sahrens zfs_ace_can_use(znode_t *zp, ace_t *acep)
1060*789Sahrens {
1061*789Sahrens 	int vtype = ZTOV(zp)->v_type;
1062*789Sahrens 
1063*789Sahrens 	int	iflags = (acep->a_flags & 0xf);
1064*789Sahrens 
1065*789Sahrens 	if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE))
1066*789Sahrens 		return (1);
1067*789Sahrens 
1068*789Sahrens 	else if (iflags & ACE_FILE_INHERIT_ACE)
1069*789Sahrens 		return (1);
1070*789Sahrens 
1071*789Sahrens 	return (0);
1072*789Sahrens }
1073*789Sahrens 
1074*789Sahrens /*
1075*789Sahrens  * Retrieve a files ACL
1076*789Sahrens  */
1077*789Sahrens int
1078*789Sahrens zfs_getacl(znode_t *zp, vsecattr_t  *vsecp, cred_t *cr)
1079*789Sahrens {
1080*789Sahrens 	zfs_acl_t	*aclp;
1081*789Sahrens 	ulong_t		mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT);
1082*789Sahrens 	int		error;
1083*789Sahrens 
1084*789Sahrens 	if (error = zfs_zaccess(zp, ACE_READ_ACL, cr)) {
1085*789Sahrens 		/*
1086*789Sahrens 		 * If owner of file then allow reading of the
1087*789Sahrens 		 * ACL.
1088*789Sahrens 		 */
1089*789Sahrens 		if (crgetuid(cr) != zp->z_phys->zp_uid)
1090*789Sahrens 			return (error);
1091*789Sahrens 	}
1092*789Sahrens 
1093*789Sahrens 	if (mask == 0)
1094*789Sahrens 		return (ENOSYS);
1095*789Sahrens 
1096*789Sahrens 	mutex_enter(&zp->z_acl_lock);
1097*789Sahrens 
1098*789Sahrens 	aclp = zfs_acl_node_read(zp);
1099*789Sahrens 
1100*789Sahrens 	if (mask & VSA_ACECNT) {
1101*789Sahrens 		vsecp->vsa_aclcnt = aclp->z_acl_count;
1102*789Sahrens 	}
1103*789Sahrens 
1104*789Sahrens 	if (mask & VSA_ACE) {
1105*789Sahrens 		vsecp->vsa_aclentp = kmem_alloc(aclp->z_acl_count *
1106*789Sahrens 		    sizeof (ace_t), KM_SLEEP);
1107*789Sahrens 		bcopy(aclp->z_acl, vsecp->vsa_aclentp,
1108*789Sahrens 		    aclp->z_acl_count * sizeof (ace_t));
1109*789Sahrens 	}
1110*789Sahrens 
1111*789Sahrens 	mutex_exit(&zp->z_acl_lock);
1112*789Sahrens 
1113*789Sahrens 	zfs_acl_free(aclp);
1114*789Sahrens 
1115*789Sahrens 	return (0);
1116*789Sahrens }
1117*789Sahrens 
1118*789Sahrens /*
1119*789Sahrens  * Set a files ACL
1120*789Sahrens  */
1121*789Sahrens int
1122*789Sahrens zfs_setacl(znode_t *zp, vsecattr_t *vsecp, cred_t *cr)
1123*789Sahrens {
1124*789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1125*789Sahrens 	zilog_t		*zilog = zfsvfs->z_log;
1126*789Sahrens 	ace_t		*acep = vsecp->vsa_aclentp;
1127*789Sahrens 	int		aclcnt = vsecp->vsa_aclcnt;
1128*789Sahrens 	ulong_t		mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT);
1129*789Sahrens 	dmu_tx_t	*tx;
1130*789Sahrens 	int		error;
1131*789Sahrens 	int		inherit;
1132*789Sahrens 	zfs_acl_t	*aclp;
1133*789Sahrens 	uint64_t	seq = 0;
1134*789Sahrens 
1135*789Sahrens 	if (mask == 0)
1136*789Sahrens 		return (EINVAL);
1137*789Sahrens 
1138*789Sahrens 	if (!zfs_acl_valid(zp, acep, aclcnt, &inherit))
1139*789Sahrens 		return (EINVAL);
1140*789Sahrens top:
1141*789Sahrens 	error = zfs_zaccess_v4_perm(zp, ACE_WRITE_ACL, cr);
1142*789Sahrens 	if (error == EACCES || error == ACCESS_UNDETERMINED) {
1143*789Sahrens 		if ((error = secpolicy_vnode_setdac(cr,
1144*789Sahrens 		    zp->z_phys->zp_uid)) != 0) {
1145*789Sahrens 			return (error);
1146*789Sahrens 		}
1147*789Sahrens 	} else if (error) {
1148*789Sahrens 		return (error == EROFS ? error : EPERM);
1149*789Sahrens 	}
1150*789Sahrens 
1151*789Sahrens 	mutex_enter(&zp->z_lock);
1152*789Sahrens 	mutex_enter(&zp->z_acl_lock);
1153*789Sahrens 
1154*789Sahrens 	tx = dmu_tx_create(zfsvfs->z_os);
1155*789Sahrens 	dmu_tx_hold_bonus(tx, zp->z_id);
1156*789Sahrens 
1157*789Sahrens 	if (zp->z_phys->zp_acl.z_acl_extern_obj) {
1158*789Sahrens 		dmu_tx_hold_write(tx, zp->z_phys->zp_acl.z_acl_extern_obj,
1159*789Sahrens 		    0, ZFS_ACL_SIZE(aclcnt));
1160*789Sahrens 	} else if (aclcnt > ACE_SLOT_CNT) {
1161*789Sahrens 		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, ZFS_ACL_SIZE(aclcnt));
1162*789Sahrens 	}
1163*789Sahrens 
1164*789Sahrens 	error = dmu_tx_assign(tx, zfsvfs->z_assign);
1165*789Sahrens 	if (error) {
1166*789Sahrens 		dmu_tx_abort(tx);
1167*789Sahrens 
1168*789Sahrens 		mutex_exit(&zp->z_acl_lock);
1169*789Sahrens 		mutex_exit(&zp->z_lock);
1170*789Sahrens 
1171*789Sahrens 		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT) {
1172*789Sahrens 			txg_wait_open(dmu_objset_pool(zfsvfs->z_os), 0);
1173*789Sahrens 			goto top;
1174*789Sahrens 		}
1175*789Sahrens 		return (error);
1176*789Sahrens 	}
1177*789Sahrens 
1178*789Sahrens 	aclp = zfs_acl_alloc(aclcnt);
1179*789Sahrens 	bcopy(acep, aclp->z_acl, sizeof (ace_t) * aclcnt);
1180*789Sahrens 	aclp->z_acl_count = aclcnt;
1181*789Sahrens 	error = zfs_aclset_common(zp, aclp, tx, &inherit);
1182*789Sahrens 	ASSERT(error == 0);
1183*789Sahrens 
1184*789Sahrens 	zfs_acl_free(aclp);
1185*789Sahrens 	seq = zfs_log_acl(zilog, tx, TX_ACL, zp, aclcnt, acep);
1186*789Sahrens 	dmu_tx_commit(tx);
1187*789Sahrens done:
1188*789Sahrens 	mutex_exit(&zp->z_acl_lock);
1189*789Sahrens 	mutex_exit(&zp->z_lock);
1190*789Sahrens 
1191*789Sahrens 	zil_commit(zilog, seq, 0);
1192*789Sahrens 
1193*789Sahrens 	return (error);
1194*789Sahrens }
1195*789Sahrens 
1196*789Sahrens static int
1197*789Sahrens zfs_ace_access(ace_t *zacep, int mode_wanted, int *working_mode)
1198*789Sahrens {
1199*789Sahrens 	if ((*working_mode & mode_wanted) == mode_wanted) {
1200*789Sahrens 		return (0);
1201*789Sahrens 	}
1202*789Sahrens 
1203*789Sahrens 	if (zacep->a_access_mask & mode_wanted) {
1204*789Sahrens 		if (zacep->a_type == ALLOW) {
1205*789Sahrens 			*working_mode |= (mode_wanted & zacep->a_access_mask);
1206*789Sahrens 			if ((*working_mode & mode_wanted) == mode_wanted)
1207*789Sahrens 				return (0);
1208*789Sahrens 		} else if (zacep->a_type == DENY) {
1209*789Sahrens 			return (EACCES);
1210*789Sahrens 		}
1211*789Sahrens 	}
1212*789Sahrens 
1213*789Sahrens 	/*
1214*789Sahrens 	 * haven't been specifcally denied at this point
1215*789Sahrens 	 * so return UNDETERMINED.
1216*789Sahrens 	 */
1217*789Sahrens 
1218*789Sahrens 	return (ACCESS_UNDETERMINED);
1219*789Sahrens }
1220*789Sahrens 
1221*789Sahrens 
1222*789Sahrens static int
1223*789Sahrens zfs_zaccess_common(znode_t *zp, int v4_mode, int *working_mode, cred_t *cr)
1224*789Sahrens {
1225*789Sahrens 	zfs_acl_t	*aclp;
1226*789Sahrens 	zfsvfs_t	*zfsvfs = zp->z_zfsvfs;
1227*789Sahrens 	ace_t		*zacep;
1228*789Sahrens 	gid_t		gid;
1229*789Sahrens 	int		mode_wanted = v4_mode;
1230*789Sahrens 	int		cnt;
1231*789Sahrens 	int		i;
1232*789Sahrens 	int		access_deny = ACCESS_UNDETERMINED;
1233*789Sahrens 	uint_t		entry_type;
1234*789Sahrens 	uid_t		uid = crgetuid(cr);
1235*789Sahrens 
1236*789Sahrens 	*working_mode = 0;
1237*789Sahrens 
1238*789Sahrens 	if (zfsvfs->z_assign >= TXG_INITIAL)		/* ZIL replay */
1239*789Sahrens 		return (0);
1240*789Sahrens 
1241*789Sahrens 	if ((v4_mode & WRITE_MASK) &&
1242*789Sahrens 	    (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) &&
1243*789Sahrens 	    (!IS_DEVVP(ZTOV(zp)))) {
1244*789Sahrens 		return (EROFS);
1245*789Sahrens 	}
1246*789Sahrens 
1247*789Sahrens 	mutex_enter(&zp->z_acl_lock);
1248*789Sahrens 
1249*789Sahrens 	aclp = zfs_acl_node_read(zp);
1250*789Sahrens 
1251*789Sahrens 	zacep = aclp->z_acl;
1252*789Sahrens 	cnt = aclp->z_acl_count;
1253*789Sahrens 
1254*789Sahrens 	for (i = 0; i != cnt; i++) {
1255*789Sahrens 
1256*789Sahrens 		if (zacep[i].a_flags & ACE_INHERIT_ONLY_ACE)
1257*789Sahrens 			continue;
1258*789Sahrens 
1259*789Sahrens 		entry_type = (zacep[i].a_flags & 0xf040);
1260*789Sahrens 		switch (entry_type) {
1261*789Sahrens 		case ACE_OWNER:
1262*789Sahrens 			if (uid == zp->z_phys->zp_uid) {
1263*789Sahrens 				access_deny = zfs_ace_access(&zacep[i],
1264*789Sahrens 				    mode_wanted, working_mode);
1265*789Sahrens 			}
1266*789Sahrens 			break;
1267*789Sahrens 		case (ACE_IDENTIFIER_GROUP | ACE_GROUP):
1268*789Sahrens 		case ACE_IDENTIFIER_GROUP:
1269*789Sahrens 			/*
1270*789Sahrens 			 * Owning group gid is in znode not ACL
1271*789Sahrens 			 */
1272*789Sahrens 			if (entry_type == (ACE_IDENTIFIER_GROUP | ACE_GROUP))
1273*789Sahrens 				gid = zp->z_phys->zp_gid;
1274*789Sahrens 			else
1275*789Sahrens 				gid = zacep[i].a_who;
1276*789Sahrens 
1277*789Sahrens 			if (groupmember(gid, cr)) {
1278*789Sahrens 				access_deny = zfs_ace_access(&zacep[i],
1279*789Sahrens 				    mode_wanted, working_mode);
1280*789Sahrens 			}
1281*789Sahrens 			break;
1282*789Sahrens 		case ACE_EVERYONE:
1283*789Sahrens 			access_deny = zfs_ace_access(&zacep[i],
1284*789Sahrens 			    mode_wanted, working_mode);
1285*789Sahrens 			break;
1286*789Sahrens 
1287*789Sahrens 		/* USER Entry */
1288*789Sahrens 		default:
1289*789Sahrens 			if (entry_type == 0) {
1290*789Sahrens 				if (uid == zacep[i].a_who) {
1291*789Sahrens 					access_deny = zfs_ace_access(&zacep[i],
1292*789Sahrens 					    mode_wanted, working_mode);
1293*789Sahrens 				}
1294*789Sahrens 				break;
1295*789Sahrens 			}
1296*789Sahrens 			zfs_acl_free(aclp);
1297*789Sahrens 			mutex_exit(&zp->z_acl_lock);
1298*789Sahrens 			return (EIO);
1299*789Sahrens 		}
1300*789Sahrens 
1301*789Sahrens 		if (access_deny != ACCESS_UNDETERMINED)
1302*789Sahrens 			break;
1303*789Sahrens 
1304*789Sahrens 	}
1305*789Sahrens 
1306*789Sahrens 	mutex_exit(&zp->z_acl_lock);
1307*789Sahrens 	zfs_acl_free(aclp);
1308*789Sahrens 
1309*789Sahrens 	return (access_deny);
1310*789Sahrens }
1311*789Sahrens 
1312*789Sahrens 
1313*789Sahrens /*
1314*789Sahrens  * Determine whether Access should be granted/denied, invoking least
1315*789Sahrens  * priv subsytem when a deny is determined.
1316*789Sahrens  */
1317*789Sahrens int
1318*789Sahrens zfs_zaccess(znode_t *zp, int mode, cred_t *cr)
1319*789Sahrens {
1320*789Sahrens 	int	working_mode = 0;
1321*789Sahrens 	int	error;
1322*789Sahrens 	int	is_attr;
1323*789Sahrens 	znode_t	*xzp;
1324*789Sahrens 	znode_t *check_zp = zp;
1325*789Sahrens 
1326*789Sahrens 	is_attr = ((zp->z_phys->zp_flags & ZFS_XATTR) &&
1327*789Sahrens 	    (ZTOV(zp)->v_type == VDIR));
1328*789Sahrens 
1329*789Sahrens 	/*
1330*789Sahrens 	 * If attribute then validate against base file
1331*789Sahrens 	 */
1332*789Sahrens 	if (is_attr) {
1333*789Sahrens 		if ((error = zfs_zget(zp->z_zfsvfs,
1334*789Sahrens 		    zp->z_phys->zp_parent, &xzp)) != 0)	{
1335*789Sahrens 			return (error);
1336*789Sahrens 		}
1337*789Sahrens 		check_zp = xzp;
1338*789Sahrens 		/*
1339*789Sahrens 		 * fixup mode to map to xattr perms
1340*789Sahrens 		 */
1341*789Sahrens 
1342*789Sahrens 		if (mode & (ACE_WRITE_DATA|ACE_APPEND_DATA)) {
1343*789Sahrens 			mode &= ~(ACE_WRITE_DATA|ACE_APPEND_DATA);
1344*789Sahrens 			mode |= ACE_WRITE_NAMED_ATTRS;
1345*789Sahrens 		}
1346*789Sahrens 
1347*789Sahrens 		if (mode & (ACE_READ_DATA|ACE_EXECUTE)) {
1348*789Sahrens 			mode &= ~(ACE_READ_DATA|ACE_EXECUTE);
1349*789Sahrens 			mode |= ACE_READ_NAMED_ATTRS;
1350*789Sahrens 		}
1351*789Sahrens 	}
1352*789Sahrens 
1353*789Sahrens 	error = zfs_zaccess_common(check_zp, mode, &working_mode, cr);
1354*789Sahrens 
1355*789Sahrens 	if (error == EROFS) {
1356*789Sahrens 		if (is_attr)
1357*789Sahrens 			VN_RELE(ZTOV(xzp));
1358*789Sahrens 		return (error);
1359*789Sahrens 	}
1360*789Sahrens 
1361*789Sahrens 	if (error || (working_mode != mode)) {
1362*789Sahrens 		error = secpolicy_vnode_access(cr, ZTOV(check_zp),
1363*789Sahrens 		    check_zp->z_phys->zp_uid, ~zfs_v4_to_unix(working_mode));
1364*789Sahrens 	}
1365*789Sahrens 
1366*789Sahrens 	if (is_attr)
1367*789Sahrens 		VN_RELE(ZTOV(xzp));
1368*789Sahrens 
1369*789Sahrens 	return (error);
1370*789Sahrens }
1371*789Sahrens 
1372*789Sahrens /*
1373*789Sahrens  * Special zaccess function to check for special nfsv4 perm.
1374*789Sahrens  * doesn't call secpolicy_vnode_access() for failure, since that
1375*789Sahrens  * would probably be the wrong policy function to call.
1376*789Sahrens  * instead its up to the caller to handle that situation.
1377*789Sahrens  */
1378*789Sahrens 
1379*789Sahrens int
1380*789Sahrens zfs_zaccess_v4_perm(znode_t *zp, int mode, cred_t *cr)
1381*789Sahrens {
1382*789Sahrens 	int working_mode = 0;
1383*789Sahrens 	return (zfs_zaccess_common(zp, mode, &working_mode, cr));
1384*789Sahrens }
1385*789Sahrens 
1386*789Sahrens /*
1387*789Sahrens  * Translate tradition unix VREAD/VWRITE/VEXEC mode into
1388*789Sahrens  * native ACL format and call zfs_zaccess()
1389*789Sahrens  */
1390*789Sahrens int
1391*789Sahrens zfs_zaccess_rwx(znode_t *zp, mode_t mode, cred_t *cr)
1392*789Sahrens {
1393*789Sahrens 	int v4_mode = zfs_unix_to_v4(mode >> 6);
1394*789Sahrens 
1395*789Sahrens 	return (zfs_zaccess(zp, v4_mode, cr));
1396*789Sahrens }
1397*789Sahrens 
1398*789Sahrens /*
1399*789Sahrens  * Determine whether Access should be granted/deny, without
1400*789Sahrens  * consulting least priv subsystem.
1401*789Sahrens  *
1402*789Sahrens  *
1403*789Sahrens  * The following chart is the recommended NFSv4 enforcement for
1404*789Sahrens  * ability to delete an object.
1405*789Sahrens  *
1406*789Sahrens  *      -------------------------------------------------------
1407*789Sahrens  *      |   Parent Dir  |           Target Object Permissions |
1408*789Sahrens  *      |  permissions  |                                     |
1409*789Sahrens  *      -------------------------------------------------------
1410*789Sahrens  *      |               | ACL Allows | ACL Denies| Delete     |
1411*789Sahrens  *      |               |  Delete    |  Delete   | unspecified|
1412*789Sahrens  *      -------------------------------------------------------
1413*789Sahrens  *      |  ACL Allows   | Permit     | Permit    | Permit     |
1414*789Sahrens  *      |  DELETE_CHILD |                                     |
1415*789Sahrens  *      -------------------------------------------------------
1416*789Sahrens  *      |  ACL Denies   | Permit     | Deny      | Deny       |
1417*789Sahrens  *      |  DELETE_CHILD |            |           |            |
1418*789Sahrens  *      -------------------------------------------------------
1419*789Sahrens  *      | ACL specifies |            |           |            |
1420*789Sahrens  *      | only allow    | Permit     | Permit    | Permit     |
1421*789Sahrens  *      | write and     |            |           |            |
1422*789Sahrens  *      | execute       |            |           |            |
1423*789Sahrens  *      -------------------------------------------------------
1424*789Sahrens  *      | ACL denies    |            |           |            |
1425*789Sahrens  *      | write and     | Permit     | Deny      | Deny       |
1426*789Sahrens  *      | execute       |            |           |            |
1427*789Sahrens  *      -------------------------------------------------------
1428*789Sahrens  *         ^
1429*789Sahrens  *         |
1430*789Sahrens  *         No search privilege, can't even look up file?
1431*789Sahrens  *
1432*789Sahrens  */
1433*789Sahrens int
1434*789Sahrens zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
1435*789Sahrens {
1436*789Sahrens 	int dzp_working_mode = 0;
1437*789Sahrens 	int zp_working_mode = 0;
1438*789Sahrens 	int dzp_error, zp_error;
1439*789Sahrens 
1440*789Sahrens 	/*
1441*789Sahrens 	 * Arghh, this check is going to require a couple of questions
1442*789Sahrens 	 * to be asked.  We want specific DELETE permissions to
1443*789Sahrens 	 * take precedence over WRITE/EXECUTE.  We don't
1444*789Sahrens 	 * want an ACL such as this to mess us up.
1445*789Sahrens 	 * user:sloar:write_data:deny,user:sloar:delete:allow
1446*789Sahrens 	 *
1447*789Sahrens 	 * However, deny permissions may ultimately be overridden
1448*789Sahrens 	 * by secpolicy_vnode_access().
1449*789Sahrens 	 */
1450*789Sahrens 
1451*789Sahrens 	dzp_error = zfs_zaccess_common(dzp, ACE_DELETE_CHILD,
1452*789Sahrens 	    &dzp_working_mode, cr);
1453*789Sahrens 	zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, cr);
1454*789Sahrens 
1455*789Sahrens 	if (dzp_error == EROFS || zp_error == EROFS)
1456*789Sahrens 		return (dzp_error);
1457*789Sahrens 
1458*789Sahrens 	/*
1459*789Sahrens 	 * First handle the first row
1460*789Sahrens 	 */
1461*789Sahrens 	if (dzp_working_mode & ACE_DELETE_CHILD)
1462*789Sahrens 		return (0);
1463*789Sahrens 
1464*789Sahrens 	/*
1465*789Sahrens 	 * Second row
1466*789Sahrens 	 */
1467*789Sahrens 
1468*789Sahrens 	if (zp_working_mode & ACE_DELETE)
1469*789Sahrens 		return (0);
1470*789Sahrens 
1471*789Sahrens 	/*
1472*789Sahrens 	 * Third Row
1473*789Sahrens 	 */
1474*789Sahrens 
1475*789Sahrens 	dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE,
1476*789Sahrens 	    &dzp_working_mode, cr);
1477*789Sahrens 
1478*789Sahrens 	if (dzp_error == EROFS)
1479*789Sahrens 		return (dzp_error);
1480*789Sahrens 
1481*789Sahrens 	if (dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE))
1482*789Sahrens 		return (0);
1483*789Sahrens 
1484*789Sahrens 	/*
1485*789Sahrens 	 * Fourth Row
1486*789Sahrens 	 */
1487*789Sahrens 
1488*789Sahrens 	if (((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0) &&
1489*789Sahrens 	    (zp_working_mode & ACE_DELETE))
1490*789Sahrens 		return (0);
1491*789Sahrens 
1492*789Sahrens 	return (secpolicy_vnode_access(cr, ZTOV(zp), dzp->z_phys->zp_uid,
1493*789Sahrens 	    S_IWRITE|S_IEXEC));
1494*789Sahrens }
1495*789Sahrens 
1496*789Sahrens int
1497*789Sahrens zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
1498*789Sahrens     znode_t *tzp, cred_t *cr)
1499*789Sahrens {
1500*789Sahrens 	int add_perm;
1501*789Sahrens 	int error;
1502*789Sahrens 
1503*789Sahrens 	add_perm = (ZTOV(szp)->v_type == VDIR) ?
1504*789Sahrens 	    ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE;
1505*789Sahrens 
1506*789Sahrens 	/*
1507*789Sahrens 	 * Rename permissions are combination of delete permission +
1508*789Sahrens 	 * add file/subdir permission.
1509*789Sahrens 	 */
1510*789Sahrens 
1511*789Sahrens 	/*
1512*789Sahrens 	 * first make sure we do the delete portion.
1513*789Sahrens 	 *
1514*789Sahrens 	 * If that succeeds then check for add_file/add_subdir permissions
1515*789Sahrens 	 */
1516*789Sahrens 
1517*789Sahrens 	if (error = zfs_zaccess_delete(sdzp, szp, cr))
1518*789Sahrens 		return (error);
1519*789Sahrens 
1520*789Sahrens 	/*
1521*789Sahrens 	 * If we have a tzp, see if we can delete it?
1522*789Sahrens 	 */
1523*789Sahrens 	if (tzp) {
1524*789Sahrens 		if (error = zfs_zaccess_delete(tdzp, tzp, cr))
1525*789Sahrens 			return (error);
1526*789Sahrens 	}
1527*789Sahrens 
1528*789Sahrens 	/*
1529*789Sahrens 	 * Now check for add permissions
1530*789Sahrens 	 */
1531*789Sahrens 	if (error = zfs_zaccess(sdzp, add_perm, cr))
1532*789Sahrens 		return (error);
1533*789Sahrens 
1534*789Sahrens 	error = zfs_sticky_remove_access(sdzp, szp, cr);
1535*789Sahrens 
1536*789Sahrens 	return (error);
1537*789Sahrens }
1538