xref: /illumos-gate/usr/src/common/acl/acl_common.c (revision 705610572a32b33c0da7d60b05c6dc30597a9e5a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
24  * Copyright 2023 RackTop Systems, Inc.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/errno.h>
30 #include <sys/avl.h>
31 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
32 #include <sys/debug.h>
33 #include <sys/kmem.h>
34 #include <sys/systm.h>
35 #include <sys/sysmacros.h>
36 #include <acl/acl_common.h>
37 #else
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <stddef.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <assert.h>
44 #include <grp.h>
45 #include <pwd.h>
46 #include <acl_common.h>
47 #define	ASSERT	assert
48 #endif
49 
50 #define	ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \
51     ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \
52     ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL)
53 
54 
55 #define	ACL_SYNCHRONIZE_SET_DENY		0x0000001
56 #define	ACL_SYNCHRONIZE_SET_ALLOW		0x0000002
57 #define	ACL_SYNCHRONIZE_ERR_DENY		0x0000004
58 #define	ACL_SYNCHRONIZE_ERR_ALLOW		0x0000008
59 
60 #define	ACL_WRITE_OWNER_SET_DENY		0x0000010
61 #define	ACL_WRITE_OWNER_SET_ALLOW		0x0000020
62 #define	ACL_WRITE_OWNER_ERR_DENY		0x0000040
63 #define	ACL_WRITE_OWNER_ERR_ALLOW		0x0000080
64 
65 #define	ACL_DELETE_SET_DENY			0x0000100
66 #define	ACL_DELETE_SET_ALLOW			0x0000200
67 #define	ACL_DELETE_ERR_DENY			0x0000400
68 #define	ACL_DELETE_ERR_ALLOW			0x0000800
69 
70 #define	ACL_WRITE_ATTRS_OWNER_SET_DENY		0x0001000
71 #define	ACL_WRITE_ATTRS_OWNER_SET_ALLOW		0x0002000
72 #define	ACL_WRITE_ATTRS_OWNER_ERR_DENY		0x0004000
73 #define	ACL_WRITE_ATTRS_OWNER_ERR_ALLOW		0x0008000
74 
75 #define	ACL_WRITE_ATTRS_WRITER_SET_DENY		0x0010000
76 #define	ACL_WRITE_ATTRS_WRITER_SET_ALLOW	0x0020000
77 #define	ACL_WRITE_ATTRS_WRITER_ERR_DENY		0x0040000
78 #define	ACL_WRITE_ATTRS_WRITER_ERR_ALLOW	0x0080000
79 
80 #define	ACL_WRITE_NAMED_WRITER_SET_DENY		0x0100000
81 #define	ACL_WRITE_NAMED_WRITER_SET_ALLOW	0x0200000
82 #define	ACL_WRITE_NAMED_WRITER_ERR_DENY		0x0400000
83 #define	ACL_WRITE_NAMED_WRITER_ERR_ALLOW	0x0800000
84 
85 #define	ACL_READ_NAMED_READER_SET_DENY		0x1000000
86 #define	ACL_READ_NAMED_READER_SET_ALLOW		0x2000000
87 #define	ACL_READ_NAMED_READER_ERR_DENY		0x4000000
88 #define	ACL_READ_NAMED_READER_ERR_ALLOW		0x8000000
89 
90 
91 #define	ACE_VALID_MASK_BITS (\
92     ACE_READ_DATA | \
93     ACE_LIST_DIRECTORY | \
94     ACE_WRITE_DATA | \
95     ACE_ADD_FILE | \
96     ACE_APPEND_DATA | \
97     ACE_ADD_SUBDIRECTORY | \
98     ACE_READ_NAMED_ATTRS | \
99     ACE_WRITE_NAMED_ATTRS | \
100     ACE_EXECUTE | \
101     ACE_DELETE_CHILD | \
102     ACE_READ_ATTRIBUTES | \
103     ACE_WRITE_ATTRIBUTES | \
104     ACE_DELETE | \
105     ACE_READ_ACL | \
106     ACE_WRITE_ACL | \
107     ACE_WRITE_OWNER | \
108     ACE_SYNCHRONIZE)
109 
110 #define	ACE_MASK_UNDEFINED			0x80000000
111 
112 #define	ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \
113     ACE_DIRECTORY_INHERIT_ACE | \
114     ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
115     ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
116     ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
117 
118 /*
119  * ACL conversion helpers
120  */
121 
122 typedef enum {
123 	ace_unused,
124 	ace_user_obj,
125 	ace_user,
126 	ace_group, /* includes GROUP and GROUP_OBJ */
127 	ace_other_obj
128 } ace_to_aent_state_t;
129 
130 typedef struct acevals {
131 	uid_t key;
132 	avl_node_t avl;
133 	uint32_t mask;
134 	uint32_t allowed;
135 	uint32_t denied;
136 	int aent_type;
137 } acevals_t;
138 
139 typedef struct ace_list {
140 	acevals_t user_obj;
141 	avl_tree_t user;
142 	int numusers;
143 	acevals_t group_obj;
144 	avl_tree_t group;
145 	int numgroups;
146 	acevals_t other_obj;
147 	uint32_t acl_mask;
148 	int hasmask;
149 	int dfacl_flag;
150 	ace_to_aent_state_t state;
151 	int seen; /* bitmask of all aclent_t a_type values seen */
152 } ace_list_t;
153 
154 /*
155  * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
156  * v = Ptr to array/vector of objs
157  * n = # objs in the array
158  * s = size of each obj (must be multiples of a word size)
159  * f = ptr to function to compare two objs
160  *	returns (-1 = less than, 0 = equal, 1 = greater than
161  */
162 void
ksort(caddr_t v,int n,int s,int (* f)())163 ksort(caddr_t v, int n, int s, int (*f)())
164 {
165 	int g, i, j, ii;
166 	unsigned int *p1, *p2;
167 	unsigned int tmp;
168 
169 	/* No work to do */
170 	if (v == NULL || n <= 1)
171 		return;
172 
173 	/* Sanity check on arguments */
174 	ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0);
175 	ASSERT(s > 0);
176 	for (g = n / 2; g > 0; g /= 2) {
177 		for (i = g; i < n; i++) {
178 			for (j = i - g; j >= 0 &&
179 			    (*f)(v + j * s, v + (j + g) * s) == 1;
180 			    j -= g) {
181 				p1 = (void *)(v + j * s);
182 				p2 = (void *)(v + (j + g) * s);
183 				for (ii = 0; ii < s / 4; ii++) {
184 					tmp = *p1;
185 					*p1++ = *p2;
186 					*p2++ = tmp;
187 				}
188 			}
189 		}
190 	}
191 }
192 
193 /*
194  * Compare two acls, all fields.  Returns:
195  * -1 (less than)
196  *  0 (equal)
197  * +1 (greater than)
198  */
199 int
cmp2acls(void * a,void * b)200 cmp2acls(void *a, void *b)
201 {
202 	aclent_t *x = (aclent_t *)a;
203 	aclent_t *y = (aclent_t *)b;
204 
205 	/* Compare types */
206 	if (x->a_type < y->a_type)
207 		return (-1);
208 	if (x->a_type > y->a_type)
209 		return (1);
210 	/* Equal types; compare id's */
211 	if (x->a_id < y->a_id)
212 		return (-1);
213 	if (x->a_id > y->a_id)
214 		return (1);
215 	/* Equal ids; compare perms */
216 	if (x->a_perm < y->a_perm)
217 		return (-1);
218 	if (x->a_perm > y->a_perm)
219 		return (1);
220 	/* Totally equal */
221 	return (0);
222 }
223 
224 /*ARGSUSED*/
225 static void *
cacl_realloc(void * ptr,size_t size,size_t new_size)226 cacl_realloc(void *ptr, size_t size, size_t new_size)
227 {
228 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
229 	void *tmp;
230 
231 	tmp = kmem_alloc(new_size, KM_SLEEP);
232 	(void) memcpy(tmp, ptr, (size < new_size) ? size : new_size);
233 	kmem_free(ptr, size);
234 	return (tmp);
235 #else
236 	return (realloc(ptr, new_size));
237 #endif
238 }
239 
240 static int
cacl_malloc(void ** ptr,size_t size)241 cacl_malloc(void **ptr, size_t size)
242 {
243 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
244 	*ptr = kmem_zalloc(size, KM_SLEEP);
245 	return (0);
246 #else
247 	*ptr = calloc(1, size);
248 	if (*ptr == NULL)
249 		return (errno);
250 
251 	return (0);
252 #endif
253 }
254 
255 /*ARGSUSED*/
256 static void
cacl_free(void * ptr,size_t size)257 cacl_free(void *ptr, size_t size)
258 {
259 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
260 	kmem_free(ptr, size);
261 #else
262 	free(ptr);
263 #endif
264 }
265 
266 acl_t *
acl_alloc(enum acl_type type)267 acl_alloc(enum acl_type type)
268 {
269 	acl_t *aclp;
270 
271 	if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0)
272 		return (NULL);
273 
274 	aclp->acl_aclp = NULL;
275 	aclp->acl_cnt = 0;
276 
277 	switch (type) {
278 	case ACE_T:
279 		aclp->acl_type = ACE_T;
280 		aclp->acl_entry_size = sizeof (ace_t);
281 		break;
282 	case ACLENT_T:
283 		aclp->acl_type = ACLENT_T;
284 		aclp->acl_entry_size = sizeof (aclent_t);
285 		break;
286 	default:
287 		acl_free(aclp);
288 		aclp = NULL;
289 	}
290 	return (aclp);
291 }
292 
293 /*
294  * Free acl_t structure
295  */
296 void
acl_free(acl_t * aclp)297 acl_free(acl_t *aclp)
298 {
299 	int acl_size;
300 
301 	if (aclp == NULL)
302 		return;
303 
304 	if (aclp->acl_aclp) {
305 		acl_size = aclp->acl_cnt * aclp->acl_entry_size;
306 		cacl_free(aclp->acl_aclp, acl_size);
307 	}
308 
309 	cacl_free(aclp, sizeof (acl_t));
310 }
311 
312 static uint32_t
access_mask_set(int haswriteperm,int hasreadperm,int isowner,int isallow)313 access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow)
314 {
315 	uint32_t access_mask = 0;
316 	int acl_produce;
317 	int synchronize_set = 0, write_owner_set = 0;
318 	int delete_set = 0, write_attrs_set = 0;
319 	int read_named_set = 0, write_named_set = 0;
320 
321 	acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW |
322 	    ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
323 	    ACL_WRITE_ATTRS_WRITER_SET_DENY);
324 
325 	if (isallow) {
326 		synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW;
327 		write_owner_set = ACL_WRITE_OWNER_SET_ALLOW;
328 		delete_set = ACL_DELETE_SET_ALLOW;
329 		if (hasreadperm)
330 			read_named_set = ACL_READ_NAMED_READER_SET_ALLOW;
331 		if (haswriteperm)
332 			write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
333 		if (isowner)
334 			write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
335 		else if (haswriteperm)
336 			write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
337 	} else {
338 
339 		synchronize_set = ACL_SYNCHRONIZE_SET_DENY;
340 		write_owner_set = ACL_WRITE_OWNER_SET_DENY;
341 		delete_set = ACL_DELETE_SET_DENY;
342 		if (hasreadperm)
343 			read_named_set = ACL_READ_NAMED_READER_SET_DENY;
344 		if (haswriteperm)
345 			write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY;
346 		if (isowner)
347 			write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY;
348 		else if (haswriteperm)
349 			write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY;
350 		else
351 			/*
352 			 * If the entity is not the owner and does not
353 			 * have write permissions ACE_WRITE_ATTRIBUTES will
354 			 * always go in the DENY ACE.
355 			 */
356 			access_mask |= ACE_WRITE_ATTRIBUTES;
357 	}
358 
359 	if (acl_produce & synchronize_set)
360 		access_mask |= ACE_SYNCHRONIZE;
361 	if (acl_produce & write_owner_set)
362 		access_mask |= ACE_WRITE_OWNER;
363 	if (acl_produce & delete_set)
364 		access_mask |= ACE_DELETE;
365 	if (acl_produce & write_attrs_set)
366 		access_mask |= ACE_WRITE_ATTRIBUTES;
367 	if (acl_produce & read_named_set)
368 		access_mask |= ACE_READ_NAMED_ATTRS;
369 	if (acl_produce & write_named_set)
370 		access_mask |= ACE_WRITE_NAMED_ATTRS;
371 
372 	return (access_mask);
373 }
374 
375 /*
376  * Given an mode_t, convert it into an access_mask as used
377  * by nfsace, assuming aclent_t -> nfsace semantics.
378  */
379 static uint32_t
mode_to_ace_access(mode_t mode,boolean_t isdir,int isowner,int isallow)380 mode_to_ace_access(mode_t mode, boolean_t isdir, int isowner, int isallow)
381 {
382 	uint32_t access = 0;
383 	int haswriteperm = 0;
384 	int hasreadperm = 0;
385 
386 	if (isallow) {
387 		haswriteperm = (mode & S_IWOTH);
388 		hasreadperm = (mode & S_IROTH);
389 	} else {
390 		haswriteperm = !(mode & S_IWOTH);
391 		hasreadperm = !(mode & S_IROTH);
392 	}
393 
394 	/*
395 	 * The following call takes care of correctly setting the following
396 	 * mask bits in the access_mask:
397 	 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
398 	 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
399 	 */
400 	access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow);
401 
402 	if (isallow) {
403 		access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES;
404 		if (isowner)
405 			access |= ACE_WRITE_ACL;
406 	} else {
407 		if (! isowner)
408 			access |= ACE_WRITE_ACL;
409 	}
410 
411 	/* read */
412 	if (mode & S_IROTH) {
413 		access |= ACE_READ_DATA;
414 	}
415 	/* write */
416 	if (mode & S_IWOTH) {
417 		access |= ACE_WRITE_DATA |
418 		    ACE_APPEND_DATA;
419 		if (isdir)
420 			access |= ACE_DELETE_CHILD;
421 	}
422 	/* exec */
423 	if (mode & S_IXOTH) {
424 		access |= ACE_EXECUTE;
425 	}
426 
427 	return (access);
428 }
429 
430 /*
431  * Given an nfsace (presumably an ALLOW entry), make a
432  * corresponding DENY entry at the address given.
433  */
434 static void
ace_make_deny(ace_t * allow,ace_t * deny,int isdir,int isowner)435 ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner)
436 {
437 	(void) memcpy(deny, allow, sizeof (ace_t));
438 
439 	deny->a_who = allow->a_who;
440 
441 	deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
442 	deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS;
443 	if (isdir)
444 		deny->a_access_mask ^= ACE_DELETE_CHILD;
445 
446 	deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER |
447 	    ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
448 	    ACE_WRITE_NAMED_ATTRS);
449 	deny->a_access_mask |= access_mask_set((allow->a_access_mask &
450 	    ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner,
451 	    B_FALSE);
452 }
453 /*
454  * Make an initial pass over an array of aclent_t's.  Gather
455  * information such as an ACL_MASK (if any), number of users,
456  * number of groups, and whether the array needs to be sorted.
457  */
458 static int
ln_aent_preprocess(aclent_t * aclent,int n,int * hasmask,mode_t * mask,int * numuser,int * numgroup,int * needsort)459 ln_aent_preprocess(aclent_t *aclent, int n,
460     int *hasmask, mode_t *mask,
461     int *numuser, int *numgroup, int *needsort)
462 {
463 	int error = 0;
464 	int i;
465 	int curtype = 0;
466 
467 	*hasmask = 0;
468 	*mask = 07;
469 	*needsort = 0;
470 	*numuser = 0;
471 	*numgroup = 0;
472 
473 	for (i = 0; i < n; i++) {
474 		if (aclent[i].a_type < curtype)
475 			*needsort = 1;
476 		else if (aclent[i].a_type > curtype)
477 			curtype = aclent[i].a_type;
478 		if (aclent[i].a_type & USER)
479 			(*numuser)++;
480 		if (aclent[i].a_type & (GROUP | GROUP_OBJ))
481 			(*numgroup)++;
482 		if (aclent[i].a_type & CLASS_OBJ) {
483 			if (*hasmask) {
484 				error = EINVAL;
485 				goto out;
486 			} else {
487 				*hasmask = 1;
488 				*mask = aclent[i].a_perm;
489 			}
490 		}
491 	}
492 
493 	if ((! *hasmask) && (*numuser + *numgroup > 1)) {
494 		error = EINVAL;
495 		goto out;
496 	}
497 
498 out:
499 	return (error);
500 }
501 
502 /*
503  * Convert an array of aclent_t into an array of nfsace entries,
504  * following POSIX draft -> nfsv4 conversion semantics as outlined in
505  * the IETF draft.
506  */
507 static int
ln_aent_to_ace(aclent_t * aclent,int n,ace_t ** acepp,int * rescount,int isdir)508 ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir)
509 {
510 	int error = 0;
511 	mode_t mask;
512 	int numuser, numgroup, needsort;
513 	int resultsize = 0;
514 	int i, groupi = 0, skip;
515 	ace_t *acep, *result = NULL;
516 	int hasmask;
517 
518 	error = ln_aent_preprocess(aclent, n, &hasmask, &mask,
519 	    &numuser, &numgroup, &needsort);
520 	if (error != 0)
521 		goto out;
522 
523 	/* allow + deny for each aclent */
524 	resultsize = n * 2;
525 	if (hasmask) {
526 		/*
527 		 * stick extra deny on the group_obj and on each
528 		 * user|group for the mask (the group_obj was added
529 		 * into the count for numgroup)
530 		 */
531 		resultsize += numuser + numgroup;
532 		/* ... and don't count the mask itself */
533 		resultsize -= 2;
534 	}
535 
536 	/* sort the source if necessary */
537 	if (needsort)
538 		ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls);
539 
540 	if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0)
541 		goto out;
542 
543 	acep = result;
544 
545 	for (i = 0; i < n; i++) {
546 		/*
547 		 * don't process CLASS_OBJ (mask); mask was grabbed in
548 		 * ln_aent_preprocess()
549 		 */
550 		if (aclent[i].a_type & CLASS_OBJ)
551 			continue;
552 
553 		/* If we need an ACL_MASK emulator, prepend it now */
554 		if ((hasmask) &&
555 		    (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) {
556 			acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
557 			acep->a_flags = 0;
558 			if (aclent[i].a_type & GROUP_OBJ) {
559 				acep->a_who = (uid_t)-1;
560 				acep->a_flags |=
561 				    (ACE_IDENTIFIER_GROUP|ACE_GROUP);
562 			} else if (aclent[i].a_type & USER) {
563 				acep->a_who = aclent[i].a_id;
564 			} else {
565 				acep->a_who = aclent[i].a_id;
566 				acep->a_flags |= ACE_IDENTIFIER_GROUP;
567 			}
568 			if (aclent[i].a_type & ACL_DEFAULT) {
569 				acep->a_flags |= ACE_INHERIT_ONLY_ACE |
570 				    ACE_FILE_INHERIT_ACE |
571 				    ACE_DIRECTORY_INHERIT_ACE;
572 			}
573 			/*
574 			 * Set the access mask for the prepended deny
575 			 * ace.  To do this, we invert the mask (found
576 			 * in ln_aent_preprocess()) then convert it to an
577 			 * DENY ace access_mask.
578 			 */
579 			acep->a_access_mask = mode_to_ace_access((mask ^ 07),
580 			    isdir, 0, 0);
581 			acep += 1;
582 		}
583 
584 		/* handle a_perm -> access_mask */
585 		acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm,
586 		    isdir, aclent[i].a_type & USER_OBJ, 1);
587 
588 		/* emulate a default aclent */
589 		if (aclent[i].a_type & ACL_DEFAULT) {
590 			acep->a_flags |= ACE_INHERIT_ONLY_ACE |
591 			    ACE_FILE_INHERIT_ACE |
592 			    ACE_DIRECTORY_INHERIT_ACE;
593 		}
594 
595 		/*
596 		 * handle a_perm and a_id
597 		 *
598 		 * this must be done last, since it involves the
599 		 * corresponding deny aces, which are handled
600 		 * differently for each different a_type.
601 		 */
602 		if (aclent[i].a_type & USER_OBJ) {
603 			acep->a_who = (uid_t)-1;
604 			acep->a_flags |= ACE_OWNER;
605 			ace_make_deny(acep, acep + 1, isdir, B_TRUE);
606 			acep += 2;
607 		} else if (aclent[i].a_type & USER) {
608 			acep->a_who = aclent[i].a_id;
609 			ace_make_deny(acep, acep + 1, isdir, B_FALSE);
610 			acep += 2;
611 		} else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) {
612 			if (aclent[i].a_type & GROUP_OBJ) {
613 				acep->a_who = (uid_t)-1;
614 				acep->a_flags |= ACE_GROUP;
615 			} else {
616 				acep->a_who = aclent[i].a_id;
617 			}
618 			acep->a_flags |= ACE_IDENTIFIER_GROUP;
619 			/*
620 			 * Set the corresponding deny for the group ace.
621 			 *
622 			 * The deny aces go after all of the groups, unlike
623 			 * everything else, where they immediately follow
624 			 * the allow ace.
625 			 *
626 			 * We calculate "skip", the number of slots to
627 			 * skip ahead for the deny ace, here.
628 			 *
629 			 * The pattern is:
630 			 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
631 			 * thus, skip is
632 			 * (2 * numgroup) - 1 - groupi
633 			 * (2 * numgroup) to account for MD + A
634 			 * - 1 to account for the fact that we're on the
635 			 * access (A), not the mask (MD)
636 			 * - groupi to account for the fact that we have
637 			 * passed up groupi number of MD's.
638 			 */
639 			skip = (2 * numgroup) - 1 - groupi;
640 			ace_make_deny(acep, acep + skip, isdir, B_FALSE);
641 			/*
642 			 * If we just did the last group, skip acep past
643 			 * all of the denies; else, just move ahead one.
644 			 */
645 			if (++groupi >= numgroup)
646 				acep += numgroup + 1;
647 			else
648 				acep += 1;
649 		} else if (aclent[i].a_type & OTHER_OBJ) {
650 			acep->a_who = (uid_t)-1;
651 			acep->a_flags |= ACE_EVERYONE;
652 			ace_make_deny(acep, acep + 1, isdir, B_FALSE);
653 			acep += 2;
654 		} else {
655 			error = EINVAL;
656 			goto out;
657 		}
658 	}
659 
660 	*acepp = result;
661 	*rescount = resultsize;
662 
663 out:
664 	if (error != 0) {
665 		if ((result != NULL) && (resultsize > 0)) {
666 			cacl_free(result, resultsize * sizeof (ace_t));
667 		}
668 	}
669 
670 	return (error);
671 }
672 
673 static int
convert_aent_to_ace(aclent_t * aclentp,int aclcnt,boolean_t isdir,ace_t ** retacep,int * retacecnt)674 convert_aent_to_ace(aclent_t *aclentp, int aclcnt, boolean_t isdir,
675     ace_t **retacep, int *retacecnt)
676 {
677 	ace_t *acep;
678 	ace_t *dfacep;
679 	int acecnt = 0;
680 	int dfacecnt = 0;
681 	int dfaclstart = 0;
682 	int dfaclcnt = 0;
683 	aclent_t *aclp;
684 	int i;
685 	int error;
686 	int acesz, dfacesz;
687 
688 	ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls);
689 
690 	for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) {
691 		if (aclp->a_type & ACL_DEFAULT)
692 			break;
693 	}
694 
695 	if (i < aclcnt) {
696 		dfaclstart = i;
697 		dfaclcnt = aclcnt - i;
698 	}
699 
700 	if (dfaclcnt && !isdir) {
701 		return (EINVAL);
702 	}
703 
704 	error = ln_aent_to_ace(aclentp, i,  &acep, &acecnt, isdir);
705 	if (error)
706 		return (error);
707 
708 	if (dfaclcnt) {
709 		error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt,
710 		    &dfacep, &dfacecnt, isdir);
711 		if (error) {
712 			if (acep) {
713 				cacl_free(acep, acecnt * sizeof (ace_t));
714 			}
715 			return (error);
716 		}
717 	}
718 
719 	if (dfacecnt != 0) {
720 		acesz = sizeof (ace_t) * acecnt;
721 		dfacesz = sizeof (ace_t) * dfacecnt;
722 		acep = cacl_realloc(acep, acesz, acesz + dfacesz);
723 		if (acep == NULL)
724 			return (ENOMEM);
725 		if (dfaclcnt) {
726 			(void) memcpy(acep + acecnt, dfacep, dfacesz);
727 		}
728 	}
729 	if (dfaclcnt)
730 		cacl_free(dfacep, dfacecnt * sizeof (ace_t));
731 
732 	*retacecnt = acecnt + dfacecnt;
733 	*retacep = acep;
734 	return (0);
735 }
736 
737 static int
ace_mask_to_mode(uint32_t mask,o_mode_t * modep,boolean_t isdir)738 ace_mask_to_mode(uint32_t  mask, o_mode_t *modep, boolean_t isdir)
739 {
740 	int error = 0;
741 	o_mode_t mode = 0;
742 	uint32_t bits, wantbits;
743 
744 	/* read */
745 	if (mask & ACE_READ_DATA)
746 		mode |= S_IROTH;
747 
748 	/* write */
749 	wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA);
750 	if (isdir)
751 		wantbits |= ACE_DELETE_CHILD;
752 	bits = mask & wantbits;
753 	if (bits != 0) {
754 		if (bits != wantbits) {
755 			error = ENOTSUP;
756 			goto out;
757 		}
758 		mode |= S_IWOTH;
759 	}
760 
761 	/* exec */
762 	if (mask & ACE_EXECUTE) {
763 		mode |= S_IXOTH;
764 	}
765 
766 	*modep = mode;
767 
768 out:
769 	return (error);
770 }
771 
772 static void
acevals_init(acevals_t * vals,uid_t key)773 acevals_init(acevals_t *vals, uid_t key)
774 {
775 	bzero(vals, sizeof (*vals));
776 	vals->allowed = ACE_MASK_UNDEFINED;
777 	vals->denied = ACE_MASK_UNDEFINED;
778 	vals->mask = ACE_MASK_UNDEFINED;
779 	vals->key = key;
780 }
781 
782 static void
ace_list_init(ace_list_t * al,int dfacl_flag)783 ace_list_init(ace_list_t *al, int dfacl_flag)
784 {
785 	acevals_init(&al->user_obj, 0);
786 	acevals_init(&al->group_obj, 0);
787 	acevals_init(&al->other_obj, 0);
788 	al->numusers = 0;
789 	al->numgroups = 0;
790 	al->acl_mask = 0;
791 	al->hasmask = 0;
792 	al->state = ace_unused;
793 	al->seen = 0;
794 	al->dfacl_flag = dfacl_flag;
795 }
796 
797 /*
798  * Find or create an acevals holder for a given id and avl tree.
799  *
800  * Note that only one thread will ever touch these avl trees, so
801  * there is no need for locking.
802  */
803 static acevals_t *
acevals_find(ace_t * ace,avl_tree_t * avl,int * num)804 acevals_find(ace_t *ace, avl_tree_t *avl, int *num)
805 {
806 	acevals_t key, *rc;
807 	avl_index_t where;
808 
809 	key.key = ace->a_who;
810 	rc = avl_find(avl, &key, &where);
811 	if (rc != NULL)
812 		return (rc);
813 
814 	/* this memory is freed by ln_ace_to_aent()->ace_list_free() */
815 	if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0)
816 		return (NULL);
817 
818 	acevals_init(rc, ace->a_who);
819 	avl_insert(avl, rc, where);
820 	(*num)++;
821 
822 	return (rc);
823 }
824 
825 static int
access_mask_check(ace_t * acep,int mask_bit,int isowner)826 access_mask_check(ace_t *acep, int mask_bit, int isowner)
827 {
828 	int set_deny, err_deny;
829 	int set_allow, err_allow;
830 	int acl_consume;
831 	int haswriteperm, hasreadperm;
832 
833 	if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
834 		haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1;
835 		hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1;
836 	} else {
837 		haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0;
838 		hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0;
839 	}
840 
841 	acl_consume = (ACL_SYNCHRONIZE_ERR_DENY |
842 	    ACL_DELETE_ERR_DENY |
843 	    ACL_WRITE_OWNER_ERR_DENY |
844 	    ACL_WRITE_OWNER_ERR_ALLOW |
845 	    ACL_WRITE_ATTRS_OWNER_SET_ALLOW |
846 	    ACL_WRITE_ATTRS_OWNER_ERR_DENY |
847 	    ACL_WRITE_ATTRS_WRITER_SET_DENY |
848 	    ACL_WRITE_ATTRS_WRITER_ERR_ALLOW |
849 	    ACL_WRITE_NAMED_WRITER_ERR_DENY |
850 	    ACL_READ_NAMED_READER_ERR_DENY);
851 
852 	if (mask_bit == ACE_SYNCHRONIZE) {
853 		set_deny = ACL_SYNCHRONIZE_SET_DENY;
854 		err_deny =  ACL_SYNCHRONIZE_ERR_DENY;
855 		set_allow = ACL_SYNCHRONIZE_SET_ALLOW;
856 		err_allow = ACL_SYNCHRONIZE_ERR_ALLOW;
857 	} else if (mask_bit == ACE_WRITE_OWNER) {
858 		set_deny = ACL_WRITE_OWNER_SET_DENY;
859 		err_deny =  ACL_WRITE_OWNER_ERR_DENY;
860 		set_allow = ACL_WRITE_OWNER_SET_ALLOW;
861 		err_allow = ACL_WRITE_OWNER_ERR_ALLOW;
862 	} else if (mask_bit == ACE_DELETE) {
863 		set_deny = ACL_DELETE_SET_DENY;
864 		err_deny =  ACL_DELETE_ERR_DENY;
865 		set_allow = ACL_DELETE_SET_ALLOW;
866 		err_allow = ACL_DELETE_ERR_ALLOW;
867 	} else if (mask_bit == ACE_WRITE_ATTRIBUTES) {
868 		if (isowner) {
869 			set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY;
870 			err_deny =  ACL_WRITE_ATTRS_OWNER_ERR_DENY;
871 			set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW;
872 			err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW;
873 		} else if (haswriteperm) {
874 			set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY;
875 			err_deny =  ACL_WRITE_ATTRS_WRITER_ERR_DENY;
876 			set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW;
877 			err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW;
878 		} else {
879 			if (((acep->a_access_mask & mask_bit) != 0) &&
880 			    (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE)) {
881 				return (ENOTSUP);
882 			}
883 			return (0);
884 		}
885 	} else if (mask_bit == ACE_READ_NAMED_ATTRS) {
886 		if (!hasreadperm)
887 			return (0);
888 
889 		set_deny = ACL_READ_NAMED_READER_SET_DENY;
890 		err_deny = ACL_READ_NAMED_READER_ERR_DENY;
891 		set_allow = ACL_READ_NAMED_READER_SET_ALLOW;
892 		err_allow = ACL_READ_NAMED_READER_ERR_ALLOW;
893 	} else if (mask_bit == ACE_WRITE_NAMED_ATTRS) {
894 		if (!haswriteperm)
895 			return (0);
896 
897 		set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY;
898 		err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY;
899 		set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW;
900 		err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW;
901 	} else {
902 		return (EINVAL);
903 	}
904 
905 	if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) {
906 		if (acl_consume & set_deny) {
907 			if (!(acep->a_access_mask & mask_bit)) {
908 				return (ENOTSUP);
909 			}
910 		} else if (acl_consume & err_deny) {
911 			if (acep->a_access_mask & mask_bit) {
912 				return (ENOTSUP);
913 			}
914 		}
915 	} else {
916 		/* ACE_ACCESS_ALLOWED_ACE_TYPE */
917 		if (acl_consume & set_allow) {
918 			if (!(acep->a_access_mask & mask_bit)) {
919 				return (ENOTSUP);
920 			}
921 		} else if (acl_consume & err_allow) {
922 			if (acep->a_access_mask & mask_bit) {
923 				return (ENOTSUP);
924 			}
925 		}
926 	}
927 	return (0);
928 }
929 
930 static int
ace_to_aent_legal(ace_t * acep)931 ace_to_aent_legal(ace_t *acep)
932 {
933 	int error = 0;
934 	int isowner;
935 
936 	/* only ALLOW or DENY */
937 	if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) &&
938 	    (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) {
939 		error = ENOTSUP;
940 		goto out;
941 	}
942 
943 	/* check for invalid flags */
944 	if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) {
945 		error = EINVAL;
946 		goto out;
947 	}
948 
949 	/* some flags are illegal */
950 	if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG |
951 	    ACE_FAILED_ACCESS_ACE_FLAG |
952 	    ACE_NO_PROPAGATE_INHERIT_ACE)) {
953 		error = ENOTSUP;
954 		goto out;
955 	}
956 
957 	/* check for invalid masks */
958 	if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) {
959 		error = EINVAL;
960 		goto out;
961 	}
962 
963 	if ((acep->a_flags & ACE_OWNER)) {
964 		isowner = 1;
965 	} else {
966 		isowner = 0;
967 	}
968 
969 	error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner);
970 	if (error)
971 		goto out;
972 
973 	error = access_mask_check(acep, ACE_WRITE_OWNER, isowner);
974 	if (error)
975 		goto out;
976 
977 	error = access_mask_check(acep, ACE_DELETE, isowner);
978 	if (error)
979 		goto out;
980 
981 	error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner);
982 	if (error)
983 		goto out;
984 
985 	error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner);
986 	if (error)
987 		goto out;
988 
989 	error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner);
990 	if (error)
991 		goto out;
992 
993 	/* more detailed checking of masks */
994 	if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
995 		if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) {
996 			error = ENOTSUP;
997 			goto out;
998 		}
999 		if ((acep->a_access_mask & ACE_WRITE_DATA) &&
1000 		    (! (acep->a_access_mask & ACE_APPEND_DATA))) {
1001 			error = ENOTSUP;
1002 			goto out;
1003 		}
1004 		if ((! (acep->a_access_mask & ACE_WRITE_DATA)) &&
1005 		    (acep->a_access_mask & ACE_APPEND_DATA)) {
1006 			error = ENOTSUP;
1007 			goto out;
1008 		}
1009 	}
1010 
1011 	/* ACL enforcement */
1012 	if ((acep->a_access_mask & ACE_READ_ACL) &&
1013 	    (acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE)) {
1014 		error = ENOTSUP;
1015 		goto out;
1016 	}
1017 	if (acep->a_access_mask & ACE_WRITE_ACL) {
1018 		if ((acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) &&
1019 		    (isowner)) {
1020 			error = ENOTSUP;
1021 			goto out;
1022 		}
1023 		if ((acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) &&
1024 		    (! isowner)) {
1025 			error = ENOTSUP;
1026 			goto out;
1027 		}
1028 	}
1029 
1030 out:
1031 	return (error);
1032 }
1033 
1034 static int
ace_allow_to_mode(uint32_t mask,o_mode_t * modep,boolean_t isdir)1035 ace_allow_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir)
1036 {
1037 	/* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
1038 	if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) !=
1039 	    (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) {
1040 		return (ENOTSUP);
1041 	}
1042 
1043 	return (ace_mask_to_mode(mask, modep, isdir));
1044 }
1045 
1046 static int
acevals_to_aent(acevals_t * vals,aclent_t * dest,ace_list_t * list,uid_t owner,gid_t group,boolean_t isdir)1047 acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list,
1048     uid_t owner, gid_t group, boolean_t isdir)
1049 {
1050 	int error;
1051 	uint32_t  flips = ACE_POSIX_SUPPORTED_BITS;
1052 
1053 	if (isdir)
1054 		flips |= ACE_DELETE_CHILD;
1055 	if (vals->allowed != (vals->denied ^ flips)) {
1056 		error = ENOTSUP;
1057 		goto out;
1058 	}
1059 	if ((list->hasmask) && (list->acl_mask != vals->mask) &&
1060 	    (vals->aent_type & (USER | GROUP | GROUP_OBJ))) {
1061 		error = ENOTSUP;
1062 		goto out;
1063 	}
1064 	error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir);
1065 	if (error != 0)
1066 		goto out;
1067 	dest->a_type = vals->aent_type;
1068 	if (dest->a_type & (USER | GROUP)) {
1069 		dest->a_id = vals->key;
1070 	} else if (dest->a_type & USER_OBJ) {
1071 		dest->a_id = owner;
1072 	} else if (dest->a_type & GROUP_OBJ) {
1073 		dest->a_id = group;
1074 	} else if (dest->a_type & OTHER_OBJ) {
1075 		dest->a_id = 0;
1076 	} else {
1077 		error = EINVAL;
1078 		goto out;
1079 	}
1080 
1081 out:
1082 	return (error);
1083 }
1084 
1085 
1086 static int
ace_list_to_aent(ace_list_t * list,aclent_t ** aclentp,int * aclcnt,uid_t owner,gid_t group,boolean_t isdir)1087 ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt,
1088     uid_t owner, gid_t group, boolean_t isdir)
1089 {
1090 	int error = 0;
1091 	aclent_t *aent, *result = NULL;
1092 	acevals_t *vals;
1093 	int resultcount;
1094 
1095 	if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) !=
1096 	    (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) {
1097 		return (ENOTSUP);
1098 	}
1099 
1100 	if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) {
1101 		return (ENOTSUP);
1102 	}
1103 
1104 	resultcount = 3 + list->numusers + list->numgroups;
1105 	/*
1106 	 * This must be the same condition as below, when we add the CLASS_OBJ
1107 	 * (aka ACL mask)
1108 	 */
1109 	if ((list->hasmask) || (! list->dfacl_flag))
1110 		resultcount += 1;
1111 
1112 	if (cacl_malloc((void **)&result,
1113 	    resultcount * sizeof (aclent_t)) != 0) {
1114 		error = ENOMEM;
1115 		goto out;
1116 	}
1117 	aent = result;
1118 
1119 	/* USER_OBJ */
1120 	if (!(list->user_obj.aent_type & USER_OBJ)) {
1121 		error = EINVAL;
1122 		goto out;
1123 	}
1124 
1125 	error = acevals_to_aent(&list->user_obj, aent, list, owner, group,
1126 	    isdir);
1127 
1128 	if (error != 0)
1129 		goto out;
1130 	++aent;
1131 	/* USER */
1132 	vals = NULL;
1133 	for (vals = avl_first(&list->user); vals != NULL;
1134 	    vals = AVL_NEXT(&list->user, vals)) {
1135 		if (!(vals->aent_type & USER)) {
1136 			error = EINVAL;
1137 			goto out;
1138 		}
1139 		error = acevals_to_aent(vals, aent, list, owner, group,
1140 		    isdir);
1141 		if (error != 0)
1142 			goto out;
1143 		++aent;
1144 	}
1145 	/* GROUP_OBJ */
1146 	if (!(list->group_obj.aent_type & GROUP_OBJ)) {
1147 		error = EINVAL;
1148 		goto out;
1149 	}
1150 	error = acevals_to_aent(&list->group_obj, aent, list, owner, group,
1151 	    isdir);
1152 	if (error != 0)
1153 		goto out;
1154 	++aent;
1155 	/* GROUP */
1156 	vals = NULL;
1157 	for (vals = avl_first(&list->group); vals != NULL;
1158 	    vals = AVL_NEXT(&list->group, vals)) {
1159 		if (!(vals->aent_type & GROUP)) {
1160 			error = EINVAL;
1161 			goto out;
1162 		}
1163 		error = acevals_to_aent(vals, aent, list, owner, group,
1164 		    isdir);
1165 		if (error != 0)
1166 			goto out;
1167 		++aent;
1168 	}
1169 	/*
1170 	 * CLASS_OBJ (aka ACL_MASK)
1171 	 *
1172 	 * An ACL_MASK is not fabricated if the ACL is a default ACL.
1173 	 * This is to follow UFS's behavior.
1174 	 */
1175 	if ((list->hasmask) || (! list->dfacl_flag)) {
1176 		if (list->hasmask) {
1177 			uint32_t flips = ACE_POSIX_SUPPORTED_BITS;
1178 			if (isdir)
1179 				flips |= ACE_DELETE_CHILD;
1180 			error = ace_mask_to_mode(list->acl_mask ^ flips,
1181 			    &aent->a_perm, isdir);
1182 			if (error != 0)
1183 				goto out;
1184 		} else {
1185 			/* fabricate the ACL_MASK from the group permissions */
1186 			error = ace_mask_to_mode(list->group_obj.allowed,
1187 			    &aent->a_perm, isdir);
1188 			if (error != 0)
1189 				goto out;
1190 		}
1191 		aent->a_id = 0;
1192 		aent->a_type = CLASS_OBJ | list->dfacl_flag;
1193 		++aent;
1194 	}
1195 	/* OTHER_OBJ */
1196 	if (!(list->other_obj.aent_type & OTHER_OBJ)) {
1197 		error = EINVAL;
1198 		goto out;
1199 	}
1200 	error = acevals_to_aent(&list->other_obj, aent, list, owner, group,
1201 	    isdir);
1202 	if (error != 0)
1203 		goto out;
1204 	++aent;
1205 
1206 	*aclentp = result;
1207 	*aclcnt = resultcount;
1208 
1209 out:
1210 	if (error != 0) {
1211 		if (result != NULL)
1212 			cacl_free(result, resultcount * sizeof (aclent_t));
1213 	}
1214 
1215 	return (error);
1216 }
1217 
1218 
1219 /*
1220  * free all data associated with an ace_list
1221  */
1222 static void
ace_list_free(ace_list_t * al)1223 ace_list_free(ace_list_t *al)
1224 {
1225 	acevals_t *node;
1226 	void *cookie;
1227 
1228 	if (al == NULL)
1229 		return;
1230 
1231 	cookie = NULL;
1232 	while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL)
1233 		cacl_free(node, sizeof (acevals_t));
1234 	cookie = NULL;
1235 	while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL)
1236 		cacl_free(node, sizeof (acevals_t));
1237 
1238 	avl_destroy(&al->user);
1239 	avl_destroy(&al->group);
1240 
1241 	/* free the container itself */
1242 	cacl_free(al, sizeof (ace_list_t));
1243 }
1244 
1245 static int
acevals_compare(const void * va,const void * vb)1246 acevals_compare(const void *va, const void *vb)
1247 {
1248 	const acevals_t *a = va, *b = vb;
1249 
1250 	if (a->key == b->key)
1251 		return (0);
1252 
1253 	if (a->key > b->key)
1254 		return (1);
1255 
1256 	else
1257 		return (-1);
1258 }
1259 
1260 /*
1261  * Convert a list of ace_t entries to equivalent regular and default
1262  * aclent_t lists.  Return error (ENOTSUP) when conversion is not possible.
1263  */
1264 static int
ln_ace_to_aent(ace_t * ace,int n,uid_t owner,gid_t group,aclent_t ** aclentp,int * aclcnt,aclent_t ** dfaclentp,int * dfaclcnt,boolean_t isdir)1265 ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group,
1266     aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt,
1267     boolean_t isdir)
1268 {
1269 	int error = 0;
1270 	ace_t *acep;
1271 	uint32_t bits;
1272 	int i;
1273 	ace_list_t *normacl = NULL, *dfacl = NULL, *acl;
1274 	acevals_t *vals;
1275 
1276 	*aclentp = NULL;
1277 	*aclcnt = 0;
1278 	*dfaclentp = NULL;
1279 	*dfaclcnt = 0;
1280 
1281 	/* we need at least user_obj, group_obj, and other_obj */
1282 	if (n < 6) {
1283 		error = ENOTSUP;
1284 		goto out;
1285 	}
1286 	if (ace == NULL) {
1287 		error = EINVAL;
1288 		goto out;
1289 	}
1290 
1291 	error = cacl_malloc((void **)&normacl, sizeof (ace_list_t));
1292 	if (error != 0)
1293 		goto out;
1294 
1295 	avl_create(&normacl->user, acevals_compare, sizeof (acevals_t),
1296 	    offsetof(acevals_t, avl));
1297 	avl_create(&normacl->group, acevals_compare, sizeof (acevals_t),
1298 	    offsetof(acevals_t, avl));
1299 
1300 	ace_list_init(normacl, 0);
1301 
1302 	error = cacl_malloc((void **)&dfacl, sizeof (ace_list_t));
1303 	if (error != 0)
1304 		goto out;
1305 
1306 	avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t),
1307 	    offsetof(acevals_t, avl));
1308 	avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t),
1309 	    offsetof(acevals_t, avl));
1310 	ace_list_init(dfacl, ACL_DEFAULT);
1311 
1312 	/* process every ace_t... */
1313 	for (i = 0; i < n; i++) {
1314 		acep = &ace[i];
1315 
1316 		/* rule out certain cases quickly */
1317 		error = ace_to_aent_legal(acep);
1318 		if (error != 0)
1319 			goto out;
1320 
1321 		/*
1322 		 * Turn off these bits in order to not have to worry about
1323 		 * them when doing the checks for compliments.
1324 		 */
1325 		acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE |
1326 		    ACE_SYNCHRONIZE | ACE_WRITE_ATTRIBUTES |
1327 		    ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS);
1328 
1329 		/* see if this should be a regular or default acl */
1330 		bits = acep->a_flags &
1331 		    (ACE_INHERIT_ONLY_ACE |
1332 		    ACE_FILE_INHERIT_ACE |
1333 		    ACE_DIRECTORY_INHERIT_ACE);
1334 		if (bits != 0) {
1335 			/* all or nothing on these inherit bits */
1336 			if (bits != (ACE_INHERIT_ONLY_ACE |
1337 			    ACE_FILE_INHERIT_ACE |
1338 			    ACE_DIRECTORY_INHERIT_ACE)) {
1339 				error = ENOTSUP;
1340 				goto out;
1341 			}
1342 			acl = dfacl;
1343 		} else {
1344 			acl = normacl;
1345 		}
1346 
1347 		if ((acep->a_flags & ACE_OWNER)) {
1348 			if (acl->state > ace_user_obj) {
1349 				error = ENOTSUP;
1350 				goto out;
1351 			}
1352 			acl->state = ace_user_obj;
1353 			acl->seen |= USER_OBJ;
1354 			vals = &acl->user_obj;
1355 			vals->aent_type = USER_OBJ | acl->dfacl_flag;
1356 		} else if ((acep->a_flags & ACE_EVERYONE)) {
1357 			acl->state = ace_other_obj;
1358 			acl->seen |= OTHER_OBJ;
1359 			vals = &acl->other_obj;
1360 			vals->aent_type = OTHER_OBJ | acl->dfacl_flag;
1361 		} else if (acep->a_flags & ACE_IDENTIFIER_GROUP) {
1362 			if (acl->state > ace_group) {
1363 				error = ENOTSUP;
1364 				goto out;
1365 			}
1366 			if ((acep->a_flags & ACE_GROUP)) {
1367 				acl->seen |= GROUP_OBJ;
1368 				vals = &acl->group_obj;
1369 				vals->aent_type = GROUP_OBJ | acl->dfacl_flag;
1370 			} else {
1371 				acl->seen |= GROUP;
1372 				vals = acevals_find(acep, &acl->group,
1373 				    &acl->numgroups);
1374 				if (vals == NULL) {
1375 					error = ENOMEM;
1376 					goto out;
1377 				}
1378 				vals->aent_type = GROUP | acl->dfacl_flag;
1379 			}
1380 			acl->state = ace_group;
1381 		} else {
1382 			if (acl->state > ace_user) {
1383 				error = ENOTSUP;
1384 				goto out;
1385 			}
1386 			acl->state = ace_user;
1387 			acl->seen |= USER;
1388 			vals = acevals_find(acep, &acl->user,
1389 			    &acl->numusers);
1390 			if (vals == NULL) {
1391 				error = ENOMEM;
1392 				goto out;
1393 			}
1394 			vals->aent_type = USER | acl->dfacl_flag;
1395 		}
1396 
1397 		if (!(acl->state > ace_unused)) {
1398 			error = EINVAL;
1399 			goto out;
1400 		}
1401 
1402 		if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) {
1403 			/* no more than one allowed per aclent_t */
1404 			if (vals->allowed != ACE_MASK_UNDEFINED) {
1405 				error = ENOTSUP;
1406 				goto out;
1407 			}
1408 			vals->allowed = acep->a_access_mask;
1409 		} else {
1410 			/*
1411 			 * it's a DENY; if there was a previous DENY, it
1412 			 * must have been an ACL_MASK.
1413 			 */
1414 			if (vals->denied != ACE_MASK_UNDEFINED) {
1415 				/* ACL_MASK is for USER and GROUP only */
1416 				if ((acl->state != ace_user) &&
1417 				    (acl->state != ace_group)) {
1418 					error = ENOTSUP;
1419 					goto out;
1420 				}
1421 
1422 				if (! acl->hasmask) {
1423 					acl->hasmask = 1;
1424 					acl->acl_mask = vals->denied;
1425 				/* check for mismatched ACL_MASK emulations */
1426 				} else if (acl->acl_mask != vals->denied) {
1427 					error = ENOTSUP;
1428 					goto out;
1429 				}
1430 				vals->mask = vals->denied;
1431 			}
1432 			vals->denied = acep->a_access_mask;
1433 		}
1434 	}
1435 
1436 	/* done collating; produce the aclent_t lists */
1437 	if (normacl->state != ace_unused) {
1438 		error = ace_list_to_aent(normacl, aclentp, aclcnt,
1439 		    owner, group, isdir);
1440 		if (error != 0) {
1441 			goto out;
1442 		}
1443 	}
1444 	if (dfacl->state != ace_unused) {
1445 		error = ace_list_to_aent(dfacl, dfaclentp, dfaclcnt,
1446 		    owner, group, isdir);
1447 		if (error != 0) {
1448 			goto out;
1449 		}
1450 	}
1451 
1452 out:
1453 	if (normacl != NULL)
1454 		ace_list_free(normacl);
1455 	if (dfacl != NULL)
1456 		ace_list_free(dfacl);
1457 
1458 	return (error);
1459 }
1460 
1461 static int
convert_ace_to_aent(ace_t * acebufp,int acecnt,boolean_t isdir,uid_t owner,gid_t group,aclent_t ** retaclentp,int * retaclcnt)1462 convert_ace_to_aent(ace_t *acebufp, int acecnt, boolean_t isdir,
1463     uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt)
1464 {
1465 	int error = 0;
1466 	aclent_t *aclentp, *dfaclentp;
1467 	int aclcnt, dfaclcnt;
1468 	int aclsz, dfaclsz = 0;
1469 
1470 	error = ln_ace_to_aent(acebufp, acecnt, owner, group,
1471 	    &aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir);
1472 
1473 	if (error)
1474 		return (error);
1475 
1476 
1477 	if (dfaclcnt != 0) {
1478 		/*
1479 		 * Slap aclentp and dfaclentp into a single array.
1480 		 */
1481 		aclsz = sizeof (aclent_t) * aclcnt;
1482 		dfaclsz = sizeof (aclent_t) * dfaclcnt;
1483 		aclentp = cacl_realloc(aclentp, aclsz, aclsz + dfaclsz);
1484 		if (aclentp != NULL) {
1485 			(void) memcpy(aclentp + aclcnt, dfaclentp, dfaclsz);
1486 		} else {
1487 			error = ENOMEM;
1488 		}
1489 	}
1490 
1491 	if (aclentp) {
1492 		*retaclentp = aclentp;
1493 		*retaclcnt = aclcnt + dfaclcnt;
1494 	}
1495 
1496 	if (dfaclentp)
1497 		cacl_free(dfaclentp, dfaclsz);
1498 
1499 	return (error);
1500 }
1501 
1502 
1503 int
acl_translate(acl_t * aclp,int target_flavor,boolean_t isdir,uid_t owner,gid_t group)1504 acl_translate(acl_t *aclp, int target_flavor, boolean_t isdir, uid_t owner,
1505     gid_t group)
1506 {
1507 	int aclcnt;
1508 	void *acldata;
1509 	int error;
1510 
1511 	/*
1512 	 * See if we need to translate
1513 	 */
1514 	if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) ||
1515 	    (target_flavor == _ACL_ACLENT_ENABLED &&
1516 	    aclp->acl_type == ACLENT_T))
1517 		return (0);
1518 
1519 	if (target_flavor == -1) {
1520 		error = EINVAL;
1521 		goto out;
1522 	}
1523 
1524 	if (target_flavor ==  _ACL_ACE_ENABLED &&
1525 	    aclp->acl_type == ACLENT_T) {
1526 		error = convert_aent_to_ace(aclp->acl_aclp,
1527 		    aclp->acl_cnt, isdir, (ace_t **)&acldata, &aclcnt);
1528 		if (error)
1529 			goto out;
1530 
1531 	} else if (target_flavor == _ACL_ACLENT_ENABLED &&
1532 	    aclp->acl_type == ACE_T) {
1533 		error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt,
1534 		    isdir, owner, group, (aclent_t **)&acldata, &aclcnt);
1535 		if (error)
1536 			goto out;
1537 	} else {
1538 		error = ENOTSUP;
1539 		goto out;
1540 	}
1541 
1542 	/*
1543 	 * replace old acl with newly translated acl
1544 	 */
1545 	cacl_free(aclp->acl_aclp, aclp->acl_cnt * aclp->acl_entry_size);
1546 	aclp->acl_aclp = acldata;
1547 	aclp->acl_cnt = aclcnt;
1548 	if (target_flavor == _ACL_ACE_ENABLED) {
1549 		aclp->acl_type = ACE_T;
1550 		aclp->acl_entry_size = sizeof (ace_t);
1551 	} else {
1552 		aclp->acl_type = ACLENT_T;
1553 		aclp->acl_entry_size = sizeof (aclent_t);
1554 	}
1555 	return (0);
1556 
1557 out:
1558 
1559 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1560 	return (error);
1561 #else
1562 	errno = error;
1563 	return (-1);
1564 #endif
1565 }
1566 
1567 #define	SET_ACE(acl, index, who, mask, type, flags) { \
1568 	acl[0][index].a_who = (uint32_t)who; \
1569 	acl[0][index].a_type = type; \
1570 	acl[0][index].a_flags = flags; \
1571 	acl[0][index++].a_access_mask = mask; \
1572 }
1573 
1574 void
acl_trivial_access_masks(mode_t mode,boolean_t isdir,trivial_acl_t * masks)1575 acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks)
1576 {
1577 	uint32_t read_mask = ACE_READ_DATA;
1578 	uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA;
1579 	uint32_t execute_mask = ACE_EXECUTE;
1580 
1581 	if (isdir)
1582 		write_mask |= ACE_DELETE_CHILD;
1583 
1584 	masks->deny1 = 0;
1585 	if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
1586 		masks->deny1 |= read_mask;
1587 	if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))
1588 		masks->deny1 |= write_mask;
1589 	if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
1590 		masks->deny1 |= execute_mask;
1591 
1592 	masks->deny2 = 0;
1593 	if (!(mode & S_IRGRP) && (mode & S_IROTH))
1594 		masks->deny2 |= read_mask;
1595 	if (!(mode & S_IWGRP) && (mode & S_IWOTH))
1596 		masks->deny2 |= write_mask;
1597 	if (!(mode & S_IXGRP) && (mode & S_IXOTH))
1598 		masks->deny2 |= execute_mask;
1599 
1600 	masks->allow0 = 0;
1601 	if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))
1602 		masks->allow0 |= read_mask;
1603 	if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))
1604 		masks->allow0 |= write_mask;
1605 	if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))
1606 		masks->allow0 |= execute_mask;
1607 
1608 	masks->owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|
1609 	    ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES|
1610 	    ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE;
1611 	if (mode & S_IRUSR)
1612 		masks->owner |= read_mask;
1613 	if (mode & S_IWUSR)
1614 		masks->owner |= write_mask;
1615 	if (mode & S_IXUSR)
1616 		masks->owner |= execute_mask;
1617 
1618 	masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
1619 	    ACE_SYNCHRONIZE;
1620 	if (mode & S_IRGRP)
1621 		masks->group |= read_mask;
1622 	if (mode & S_IWGRP)
1623 		masks->group |= write_mask;
1624 	if (mode & S_IXGRP)
1625 		masks->group |= execute_mask;
1626 
1627 	masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS|
1628 	    ACE_SYNCHRONIZE;
1629 	if (mode & S_IROTH)
1630 		masks->everyone |= read_mask;
1631 	if (mode & S_IWOTH)
1632 		masks->everyone |= write_mask;
1633 	if (mode & S_IXOTH)
1634 		masks->everyone |= execute_mask;
1635 }
1636 
1637 int
acl_trivial_create(mode_t mode,boolean_t isdir,ace_t ** acl,int * count)1638 acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count)
1639 {
1640 	int		index = 0;
1641 	int		error;
1642 	trivial_acl_t	masks;
1643 
1644 	*count = 3;
1645 	acl_trivial_access_masks(mode, isdir, &masks);
1646 
1647 	if (masks.allow0)
1648 		(*count)++;
1649 	if (masks.deny1)
1650 		(*count)++;
1651 	if (masks.deny2)
1652 		(*count)++;
1653 
1654 	if ((error = cacl_malloc((void **)acl, *count * sizeof (ace_t))) != 0)
1655 		return (error);
1656 
1657 	if (masks.allow0) {
1658 		SET_ACE(acl, index, -1, masks.allow0,
1659 		    ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_OWNER);
1660 	}
1661 	if (masks.deny1) {
1662 		SET_ACE(acl, index, -1, masks.deny1,
1663 		    ACE_ACCESS_DENIED_ACE_TYPE, ACE_OWNER);
1664 	}
1665 	if (masks.deny2) {
1666 		SET_ACE(acl, index, -1, masks.deny2,
1667 		    ACE_ACCESS_DENIED_ACE_TYPE, ACE_GROUP|ACE_IDENTIFIER_GROUP);
1668 	}
1669 
1670 	SET_ACE(acl, index, -1, masks.owner, ACE_ACCESS_ALLOWED_ACE_TYPE,
1671 	    ACE_OWNER);
1672 	SET_ACE(acl, index, -1, masks.group, ACE_ACCESS_ALLOWED_ACE_TYPE,
1673 	    ACE_IDENTIFIER_GROUP|ACE_GROUP);
1674 	SET_ACE(acl, index, -1, masks.everyone, ACE_ACCESS_ALLOWED_ACE_TYPE,
1675 	    ACE_EVERYONE);
1676 
1677 	return (0);
1678 }
1679 
1680 /*
1681  * Convenience macro for ACE rights implied for owner in a trivial ACL:
1682  * write_owner/write_acl/write_attributes/write_xattr
1683  */
1684 #define	ACE_OWNER_MASK	(\
1685 	ACE_WRITE_OWNER|\
1686 	ACE_WRITE_ACL|\
1687 	ACE_WRITE_ATTRIBUTES|\
1688 	ACE_WRITE_NAMED_ATTRS)
1689 
1690 /*
1691  * ace_trivial:
1692  * determine whether an ace_t acl is trivial
1693  *
1694  * Trivialness implies that the acl is composed of only
1695  * owner, group, everyone entries.  ACL can't
1696  * have read_acl denied, and write_owner/write_acl/write_attributes
1697  * can only be owner@ entry.
1698  *
1699  * Returns zero if this is a "trivial" ACL, else 1.
1700  */
1701 int
ace_trivial_common(void * acep,int aclcnt,uint64_t (* walk)(void *,uint64_t,int aclcnt,uint16_t *,uint16_t *,uint32_t *))1702 ace_trivial_common(void *acep, int aclcnt,
1703     uint64_t (*walk)(void *, uint64_t, int aclcnt,
1704     uint16_t *, uint16_t *, uint32_t *))
1705 {
1706 	uint16_t flags;
1707 	uint32_t mask;
1708 	uint16_t type;
1709 	uint64_t cookie = 0;
1710 	uint32_t owner_allow = 0;
1711 	uint32_t owner_deny = 0;
1712 
1713 	while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))
1714 	    != 0) {
1715 		switch (flags & ACE_TYPE_FLAGS) {
1716 		case ACE_OWNER:
1717 		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
1718 		case ACE_EVERYONE:
1719 			break;
1720 		default:
1721 			return (1);
1722 
1723 		}
1724 
1725 		if (flags & (ACE_FILE_INHERIT_ACE|
1726 		    ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
1727 		    ACE_INHERIT_ONLY_ACE))
1728 			return (1);
1729 
1730 		/*
1731 		 * Special check for some special bits
1732 		 *
1733 		 * Don't allow anybody to deny reading basic
1734 		 * attributes or a files ACL.
1735 		 */
1736 		if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
1737 		    (type == ACE_ACCESS_DENIED_ACE_TYPE))
1738 			return (1);
1739 
1740 		/*
1741 		 * Delete permission is never set by default
1742 		 */
1743 		if (mask & ACE_DELETE)
1744 			return (1);
1745 
1746 		/*
1747 		 * Child delete permission should be accompanied by write
1748 		 */
1749 		if ((mask & ACE_DELETE_CHILD) && !(mask & ACE_WRITE_DATA))
1750 			return (1);
1751 
1752 		/*
1753 		 * only allow owner@ to have
1754 		 * write_acl/write_owner/write_attributes/write_xattr/
1755 		 */
1756 		if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
1757 		    (flags & ACE_OWNER) == 0 &&
1758 		    (mask & ACE_OWNER_MASK) != 0)
1759 			return (1);
1760 
1761 		/* Accumulate owner masks */
1762 		if ((flags & ACE_OWNER) != 0) {
1763 			if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
1764 				owner_allow |= mask;
1765 			if (type == ACE_ACCESS_DENIED_ACE_TYPE)
1766 				owner_deny |= mask;
1767 		}
1768 	}
1769 
1770 	/*
1771 	 * If owner was not allowed the usual implied rights,
1772 	 * then this should not be considered a trivial ACL.
1773 	 * In cases like mode 0745 we may have owner@ on
1774 	 * multiple ACEs, so we have to check the combined
1775 	 * access masks.
1776 	 */
1777 	if ((owner_deny & ACE_OWNER_MASK) != 0)
1778 		return (1);
1779 	if ((owner_allow & ACE_OWNER_MASK) != ACE_OWNER_MASK)
1780 		return (1);
1781 
1782 	return (0);
1783 }
1784 
1785 uint64_t
ace_walk(void * datap,uint64_t cookie,int aclcnt,uint16_t * flags,uint16_t * type,uint32_t * mask)1786 ace_walk(void *datap, uint64_t cookie, int aclcnt, uint16_t *flags,
1787     uint16_t *type, uint32_t *mask)
1788 {
1789 	ace_t *acep = datap;
1790 
1791 	if (cookie >= aclcnt)
1792 		return (0);
1793 
1794 	*flags = acep[cookie].a_flags;
1795 	*type = acep[cookie].a_type;
1796 	*mask = acep[cookie++].a_access_mask;
1797 
1798 	return (cookie);
1799 }
1800 
1801 int
ace_trivial(ace_t * acep,int aclcnt)1802 ace_trivial(ace_t *acep, int aclcnt)
1803 {
1804 	return (ace_trivial_common(acep, aclcnt, ace_walk));
1805 }
1806