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.
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.
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]
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26 #include <sys/types.h>
28 #include <sys/errno.h>
30 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
31 #include <sys/debug.h>
33 #include <sys/systm.h>
34 #include <sys/sysmacros.h>
35 #include <acl/acl_common.h>
45 #include <acl_common.h>
49 #define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \
50 ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \
51 ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL)
54 #define ACL_SYNCHRONIZE_SET_DENY 0x0000001
55 #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002
56 #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004
57 #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008
59 #define ACL_WRITE_OWNER_SET_DENY 0x0000010
60 #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020
61 #define ACL_WRITE_OWNER_ERR_DENY 0x0000040
62 #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080
64 #define ACL_DELETE_SET_DENY 0x0000100
65 #define ACL_DELETE_SET_ALLOW 0x0000200
66 #define ACL_DELETE_ERR_DENY 0x0000400
67 #define ACL_DELETE_ERR_ALLOW 0x0000800
69 #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000
70 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000
71 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000
72 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000
74 #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000
75 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000
76 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000
77 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000
79 #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000
80 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000
81 #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000
82 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000
84 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000
85 #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000
86 #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000
87 #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000
90 #define ACE_VALID_MASK_BITS (\
92 ACE_LIST_DIRECTORY | \
96 ACE_ADD_SUBDIRECTORY | \
97 ACE_READ_NAMED_ATTRS | \
98 ACE_WRITE_NAMED_ATTRS | \
101 ACE_READ_ATTRIBUTES | \
102 ACE_WRITE_ATTRIBUTES | \
109 #define ACE_MASK_UNDEFINED 0x80000000
111 #define ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \
112 ACE_DIRECTORY_INHERIT_ACE | \
113 ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
114 ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
115 ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
118 * ACL conversion helpers
125 ace_group
, /* includes GROUP and GROUP_OBJ */
127 } ace_to_aent_state_t
;
129 typedef struct acevals
{
138 typedef struct ace_list
{
149 ace_to_aent_state_t state
;
150 int seen
; /* bitmask of all aclent_t a_type values seen */
154 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
155 * v = Ptr to array/vector of objs
156 * n = # objs in the array
157 * s = size of each obj (must be multiples of a word size)
158 * f = ptr to function to compare two objs
159 * returns (-1 = less than, 0 = equal, 1 = greater than
162 ksort(caddr_t v
, int n
, int s
, int (*f
)())
165 unsigned int *p1
, *p2
;
169 if (v
== NULL
|| n
<= 1)
172 /* Sanity check on arguments */
173 ASSERT(((uintptr_t)v
& 0x3) == 0 && (s
& 0x3) == 0);
175 for (g
= n
/ 2; g
> 0; g
/= 2) {
176 for (i
= g
; i
< n
; i
++) {
177 for (j
= i
- g
; j
>= 0 &&
178 (*f
)(v
+ j
* s
, v
+ (j
+ g
) * s
) == 1;
180 p1
= (void *)(v
+ j
* s
);
181 p2
= (void *)(v
+ (j
+ g
) * s
);
182 for (ii
= 0; ii
< s
/ 4; ii
++) {
193 * Compare two acls, all fields. Returns:
199 cmp2acls(void *a
, void *b
)
201 aclent_t
*x
= (aclent_t
*)a
;
202 aclent_t
*y
= (aclent_t
*)b
;
205 if (x
->a_type
< y
->a_type
)
207 if (x
->a_type
> y
->a_type
)
209 /* Equal types; compare id's */
210 if (x
->a_id
< y
->a_id
)
212 if (x
->a_id
> y
->a_id
)
214 /* Equal ids; compare perms */
215 if (x
->a_perm
< y
->a_perm
)
217 if (x
->a_perm
> y
->a_perm
)
225 cacl_realloc(void *ptr
, size_t size
, size_t new_size
)
227 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
230 tmp
= kmem_alloc(new_size
, KM_SLEEP
);
231 (void) memcpy(tmp
, ptr
, (size
< new_size
) ? size
: new_size
);
232 kmem_free(ptr
, size
);
235 return (realloc(ptr
, new_size
));
240 cacl_malloc(void **ptr
, size_t size
)
242 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
243 *ptr
= kmem_zalloc(size
, KM_SLEEP
);
246 *ptr
= calloc(1, size
);
256 cacl_free(void *ptr
, size_t size
)
258 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
259 kmem_free(ptr
, size
);
266 acl_alloc(enum acl_type type
)
270 if (cacl_malloc((void **)&aclp
, sizeof (acl_t
)) != 0)
273 aclp
->acl_aclp
= NULL
;
278 aclp
->acl_type
= ACE_T
;
279 aclp
->acl_entry_size
= sizeof (ace_t
);
282 aclp
->acl_type
= ACLENT_T
;
283 aclp
->acl_entry_size
= sizeof (aclent_t
);
293 * Free acl_t structure
296 acl_free(acl_t
*aclp
)
303 if (aclp
->acl_aclp
) {
304 acl_size
= aclp
->acl_cnt
* aclp
->acl_entry_size
;
305 cacl_free(aclp
->acl_aclp
, acl_size
);
308 cacl_free(aclp
, sizeof (acl_t
));
312 access_mask_set(int haswriteperm
, int hasreadperm
, int isowner
, int isallow
)
314 uint32_t access_mask
= 0;
316 int synchronize_set
= 0, write_owner_set
= 0;
317 int delete_set
= 0, write_attrs_set
= 0;
318 int read_named_set
= 0, write_named_set
= 0;
320 acl_produce
= (ACL_SYNCHRONIZE_SET_ALLOW
|
321 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
322 ACL_WRITE_ATTRS_WRITER_SET_DENY
);
325 synchronize_set
= ACL_SYNCHRONIZE_SET_ALLOW
;
326 write_owner_set
= ACL_WRITE_OWNER_SET_ALLOW
;
327 delete_set
= ACL_DELETE_SET_ALLOW
;
329 read_named_set
= ACL_READ_NAMED_READER_SET_ALLOW
;
331 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
333 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
334 else if (haswriteperm
)
335 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
338 synchronize_set
= ACL_SYNCHRONIZE_SET_DENY
;
339 write_owner_set
= ACL_WRITE_OWNER_SET_DENY
;
340 delete_set
= ACL_DELETE_SET_DENY
;
342 read_named_set
= ACL_READ_NAMED_READER_SET_DENY
;
344 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
346 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
347 else if (haswriteperm
)
348 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
351 * If the entity is not the owner and does not
352 * have write permissions ACE_WRITE_ATTRIBUTES will
353 * always go in the DENY ACE.
355 access_mask
|= ACE_WRITE_ATTRIBUTES
;
358 if (acl_produce
& synchronize_set
)
359 access_mask
|= ACE_SYNCHRONIZE
;
360 if (acl_produce
& write_owner_set
)
361 access_mask
|= ACE_WRITE_OWNER
;
362 if (acl_produce
& delete_set
)
363 access_mask
|= ACE_DELETE
;
364 if (acl_produce
& write_attrs_set
)
365 access_mask
|= ACE_WRITE_ATTRIBUTES
;
366 if (acl_produce
& read_named_set
)
367 access_mask
|= ACE_READ_NAMED_ATTRS
;
368 if (acl_produce
& write_named_set
)
369 access_mask
|= ACE_WRITE_NAMED_ATTRS
;
371 return (access_mask
);
375 * Given an mode_t, convert it into an access_mask as used
376 * by nfsace, assuming aclent_t -> nfsace semantics.
379 mode_to_ace_access(mode_t mode
, boolean_t isdir
, int isowner
, int isallow
)
382 int haswriteperm
= 0;
386 haswriteperm
= (mode
& S_IWOTH
);
387 hasreadperm
= (mode
& S_IROTH
);
389 haswriteperm
= !(mode
& S_IWOTH
);
390 hasreadperm
= !(mode
& S_IROTH
);
394 * The following call takes care of correctly setting the following
395 * mask bits in the access_mask:
396 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
397 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
399 access
= access_mask_set(haswriteperm
, hasreadperm
, isowner
, isallow
);
402 access
|= ACE_READ_ACL
| ACE_READ_ATTRIBUTES
;
404 access
|= ACE_WRITE_ACL
;
407 access
|= ACE_WRITE_ACL
;
411 if (mode
& S_IROTH
) {
412 access
|= ACE_READ_DATA
;
415 if (mode
& S_IWOTH
) {
416 access
|= ACE_WRITE_DATA
|
419 access
|= ACE_DELETE_CHILD
;
422 if (mode
& S_IXOTH
) {
423 access
|= ACE_EXECUTE
;
430 * Given an nfsace (presumably an ALLOW entry), make a
431 * corresponding DENY entry at the address given.
434 ace_make_deny(ace_t
*allow
, ace_t
*deny
, int isdir
, int isowner
)
436 (void) memcpy(deny
, allow
, sizeof (ace_t
));
438 deny
->a_who
= allow
->a_who
;
440 deny
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
441 deny
->a_access_mask
^= ACE_POSIX_SUPPORTED_BITS
;
443 deny
->a_access_mask
^= ACE_DELETE_CHILD
;
445 deny
->a_access_mask
&= ~(ACE_SYNCHRONIZE
| ACE_WRITE_OWNER
|
446 ACE_DELETE
| ACE_WRITE_ATTRIBUTES
| ACE_READ_NAMED_ATTRS
|
447 ACE_WRITE_NAMED_ATTRS
);
448 deny
->a_access_mask
|= access_mask_set((allow
->a_access_mask
&
449 ACE_WRITE_DATA
), (allow
->a_access_mask
& ACE_READ_DATA
), isowner
,
453 * Make an initial pass over an array of aclent_t's. Gather
454 * information such as an ACL_MASK (if any), number of users,
455 * number of groups, and whether the array needs to be sorted.
458 ln_aent_preprocess(aclent_t
*aclent
, int n
,
459 int *hasmask
, mode_t
*mask
,
460 int *numuser
, int *numgroup
, int *needsort
)
472 for (i
= 0; i
< n
; i
++) {
473 if (aclent
[i
].a_type
< curtype
)
475 else if (aclent
[i
].a_type
> curtype
)
476 curtype
= aclent
[i
].a_type
;
477 if (aclent
[i
].a_type
& USER
)
479 if (aclent
[i
].a_type
& (GROUP
| GROUP_OBJ
))
481 if (aclent
[i
].a_type
& CLASS_OBJ
) {
487 *mask
= aclent
[i
].a_perm
;
492 if ((! *hasmask
) && (*numuser
+ *numgroup
> 1)) {
502 * Convert an array of aclent_t into an array of nfsace entries,
503 * following POSIX draft -> nfsv4 conversion semantics as outlined in
507 ln_aent_to_ace(aclent_t
*aclent
, int n
, ace_t
**acepp
, int *rescount
, int isdir
)
511 int numuser
, numgroup
, needsort
;
513 int i
, groupi
= 0, skip
;
514 ace_t
*acep
, *result
= NULL
;
517 error
= ln_aent_preprocess(aclent
, n
, &hasmask
, &mask
,
518 &numuser
, &numgroup
, &needsort
);
522 /* allow + deny for each aclent */
526 * stick extra deny on the group_obj and on each
527 * user|group for the mask (the group_obj was added
528 * into the count for numgroup)
530 resultsize
+= numuser
+ numgroup
;
531 /* ... and don't count the mask itself */
535 /* sort the source if necessary */
537 ksort((caddr_t
)aclent
, n
, sizeof (aclent_t
), cmp2acls
);
539 if (cacl_malloc((void **)&result
, resultsize
* sizeof (ace_t
)) != 0)
544 for (i
= 0; i
< n
; i
++) {
546 * don't process CLASS_OBJ (mask); mask was grabbed in
547 * ln_aent_preprocess()
549 if (aclent
[i
].a_type
& CLASS_OBJ
)
552 /* If we need an ACL_MASK emulator, prepend it now */
554 (aclent
[i
].a_type
& (USER
| GROUP
| GROUP_OBJ
))) {
555 acep
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
557 if (aclent
[i
].a_type
& GROUP_OBJ
) {
558 acep
->a_who
= (uid_t
)-1;
560 (ACE_IDENTIFIER_GROUP
|ACE_GROUP
);
561 } else if (aclent
[i
].a_type
& USER
) {
562 acep
->a_who
= aclent
[i
].a_id
;
564 acep
->a_who
= aclent
[i
].a_id
;
565 acep
->a_flags
|= ACE_IDENTIFIER_GROUP
;
567 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
568 acep
->a_flags
|= ACE_INHERIT_ONLY_ACE
|
569 ACE_FILE_INHERIT_ACE
|
570 ACE_DIRECTORY_INHERIT_ACE
;
573 * Set the access mask for the prepended deny
574 * ace. To do this, we invert the mask (found
575 * in ln_aent_preprocess()) then convert it to an
576 * DENY ace access_mask.
578 acep
->a_access_mask
= mode_to_ace_access((mask
^ 07),
583 /* handle a_perm -> access_mask */
584 acep
->a_access_mask
= mode_to_ace_access(aclent
[i
].a_perm
,
585 isdir
, aclent
[i
].a_type
& USER_OBJ
, 1);
587 /* emulate a default aclent */
588 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
589 acep
->a_flags
|= ACE_INHERIT_ONLY_ACE
|
590 ACE_FILE_INHERIT_ACE
|
591 ACE_DIRECTORY_INHERIT_ACE
;
595 * handle a_perm and a_id
597 * this must be done last, since it involves the
598 * corresponding deny aces, which are handled
599 * differently for each different a_type.
601 if (aclent
[i
].a_type
& USER_OBJ
) {
602 acep
->a_who
= (uid_t
)-1;
603 acep
->a_flags
|= ACE_OWNER
;
604 ace_make_deny(acep
, acep
+ 1, isdir
, B_TRUE
);
606 } else if (aclent
[i
].a_type
& USER
) {
607 acep
->a_who
= aclent
[i
].a_id
;
608 ace_make_deny(acep
, acep
+ 1, isdir
, B_FALSE
);
610 } else if (aclent
[i
].a_type
& (GROUP_OBJ
| GROUP
)) {
611 if (aclent
[i
].a_type
& GROUP_OBJ
) {
612 acep
->a_who
= (uid_t
)-1;
613 acep
->a_flags
|= ACE_GROUP
;
615 acep
->a_who
= aclent
[i
].a_id
;
617 acep
->a_flags
|= ACE_IDENTIFIER_GROUP
;
619 * Set the corresponding deny for the group ace.
621 * The deny aces go after all of the groups, unlike
622 * everything else, where they immediately follow
625 * We calculate "skip", the number of slots to
626 * skip ahead for the deny ace, here.
629 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
631 * (2 * numgroup) - 1 - groupi
632 * (2 * numgroup) to account for MD + A
633 * - 1 to account for the fact that we're on the
634 * access (A), not the mask (MD)
635 * - groupi to account for the fact that we have
636 * passed up groupi number of MD's.
638 skip
= (2 * numgroup
) - 1 - groupi
;
639 ace_make_deny(acep
, acep
+ skip
, isdir
, B_FALSE
);
641 * If we just did the last group, skip acep past
642 * all of the denies; else, just move ahead one.
644 if (++groupi
>= numgroup
)
645 acep
+= numgroup
+ 1;
648 } else if (aclent
[i
].a_type
& OTHER_OBJ
) {
649 acep
->a_who
= (uid_t
)-1;
650 acep
->a_flags
|= ACE_EVERYONE
;
651 ace_make_deny(acep
, acep
+ 1, isdir
, B_FALSE
);
660 *rescount
= resultsize
;
664 if ((result
!= NULL
) && (resultsize
> 0)) {
665 cacl_free(result
, resultsize
* sizeof (ace_t
));
673 convert_aent_to_ace(aclent_t
*aclentp
, int aclcnt
, boolean_t isdir
,
674 ace_t
**retacep
, int *retacecnt
)
687 ksort((caddr_t
)aclentp
, aclcnt
, sizeof (aclent_t
), cmp2acls
);
689 for (i
= 0, aclp
= aclentp
; i
< aclcnt
; aclp
++, i
++) {
690 if (aclp
->a_type
& ACL_DEFAULT
)
696 dfaclcnt
= aclcnt
- i
;
699 if (dfaclcnt
&& !isdir
) {
703 error
= ln_aent_to_ace(aclentp
, i
, &acep
, &acecnt
, isdir
);
708 error
= ln_aent_to_ace(&aclentp
[dfaclstart
], dfaclcnt
,
709 &dfacep
, &dfacecnt
, isdir
);
712 cacl_free(acep
, acecnt
* sizeof (ace_t
));
719 acesz
= sizeof (ace_t
) * acecnt
;
720 dfacesz
= sizeof (ace_t
) * dfacecnt
;
721 acep
= cacl_realloc(acep
, acesz
, acesz
+ dfacesz
);
725 (void) memcpy(acep
+ acecnt
, dfacep
, dfacesz
);
729 cacl_free(dfacep
, dfacecnt
* sizeof (ace_t
));
731 *retacecnt
= acecnt
+ dfacecnt
;
737 ace_mask_to_mode(uint32_t mask
, o_mode_t
*modep
, boolean_t isdir
)
741 uint32_t bits
, wantbits
;
744 if (mask
& ACE_READ_DATA
)
748 wantbits
= (ACE_WRITE_DATA
| ACE_APPEND_DATA
);
750 wantbits
|= ACE_DELETE_CHILD
;
751 bits
= mask
& wantbits
;
753 if (bits
!= wantbits
) {
761 if (mask
& ACE_EXECUTE
) {
772 acevals_init(acevals_t
*vals
, uid_t key
)
774 bzero(vals
, sizeof (*vals
));
775 vals
->allowed
= ACE_MASK_UNDEFINED
;
776 vals
->denied
= ACE_MASK_UNDEFINED
;
777 vals
->mask
= ACE_MASK_UNDEFINED
;
782 ace_list_init(ace_list_t
*al
, int dfacl_flag
)
784 acevals_init(&al
->user_obj
, NULL
);
785 acevals_init(&al
->group_obj
, NULL
);
786 acevals_init(&al
->other_obj
, NULL
);
791 al
->state
= ace_unused
;
793 al
->dfacl_flag
= dfacl_flag
;
797 * Find or create an acevals holder for a given id and avl tree.
799 * Note that only one thread will ever touch these avl trees, so
800 * there is no need for locking.
803 acevals_find(ace_t
*ace
, avl_tree_t
*avl
, int *num
)
808 key
.key
= ace
->a_who
;
809 rc
= avl_find(avl
, &key
, &where
);
813 /* this memory is freed by ln_ace_to_aent()->ace_list_free() */
814 if (cacl_malloc((void **)&rc
, sizeof (acevals_t
)) != 0)
817 acevals_init(rc
, ace
->a_who
);
818 avl_insert(avl
, rc
, where
);
825 access_mask_check(ace_t
*acep
, int mask_bit
, int isowner
)
827 int set_deny
, err_deny
;
828 int set_allow
, err_allow
;
830 int haswriteperm
, hasreadperm
;
832 if (acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) {
833 haswriteperm
= (acep
->a_access_mask
& ACE_WRITE_DATA
) ? 0 : 1;
834 hasreadperm
= (acep
->a_access_mask
& ACE_READ_DATA
) ? 0 : 1;
836 haswriteperm
= (acep
->a_access_mask
& ACE_WRITE_DATA
) ? 1 : 0;
837 hasreadperm
= (acep
->a_access_mask
& ACE_READ_DATA
) ? 1 : 0;
840 acl_consume
= (ACL_SYNCHRONIZE_ERR_DENY
|
841 ACL_DELETE_ERR_DENY
|
842 ACL_WRITE_OWNER_ERR_DENY
|
843 ACL_WRITE_OWNER_ERR_ALLOW
|
844 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
845 ACL_WRITE_ATTRS_OWNER_ERR_DENY
|
846 ACL_WRITE_ATTRS_WRITER_SET_DENY
|
847 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
|
848 ACL_WRITE_NAMED_WRITER_ERR_DENY
|
849 ACL_READ_NAMED_READER_ERR_DENY
);
851 if (mask_bit
== ACE_SYNCHRONIZE
) {
852 set_deny
= ACL_SYNCHRONIZE_SET_DENY
;
853 err_deny
= ACL_SYNCHRONIZE_ERR_DENY
;
854 set_allow
= ACL_SYNCHRONIZE_SET_ALLOW
;
855 err_allow
= ACL_SYNCHRONIZE_ERR_ALLOW
;
856 } else if (mask_bit
== ACE_WRITE_OWNER
) {
857 set_deny
= ACL_WRITE_OWNER_SET_DENY
;
858 err_deny
= ACL_WRITE_OWNER_ERR_DENY
;
859 set_allow
= ACL_WRITE_OWNER_SET_ALLOW
;
860 err_allow
= ACL_WRITE_OWNER_ERR_ALLOW
;
861 } else if (mask_bit
== ACE_DELETE
) {
862 set_deny
= ACL_DELETE_SET_DENY
;
863 err_deny
= ACL_DELETE_ERR_DENY
;
864 set_allow
= ACL_DELETE_SET_ALLOW
;
865 err_allow
= ACL_DELETE_ERR_ALLOW
;
866 } else if (mask_bit
== ACE_WRITE_ATTRIBUTES
) {
868 set_deny
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
869 err_deny
= ACL_WRITE_ATTRS_OWNER_ERR_DENY
;
870 set_allow
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
871 err_allow
= ACL_WRITE_ATTRS_OWNER_ERR_ALLOW
;
872 } else if (haswriteperm
) {
873 set_deny
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
874 err_deny
= ACL_WRITE_ATTRS_WRITER_ERR_DENY
;
875 set_allow
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
876 err_allow
= ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
;
878 if ((acep
->a_access_mask
& mask_bit
) &&
879 (acep
->a_type
& ACE_ACCESS_ALLOWED_ACE_TYPE
)) {
884 } else if (mask_bit
== ACE_READ_NAMED_ATTRS
) {
888 set_deny
= ACL_READ_NAMED_READER_SET_DENY
;
889 err_deny
= ACL_READ_NAMED_READER_ERR_DENY
;
890 set_allow
= ACL_READ_NAMED_READER_SET_ALLOW
;
891 err_allow
= ACL_READ_NAMED_READER_ERR_ALLOW
;
892 } else if (mask_bit
== ACE_WRITE_NAMED_ATTRS
) {
896 set_deny
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
897 err_deny
= ACL_WRITE_NAMED_WRITER_ERR_DENY
;
898 set_allow
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
899 err_allow
= ACL_WRITE_NAMED_WRITER_ERR_ALLOW
;
904 if (acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) {
905 if (acl_consume
& set_deny
) {
906 if (!(acep
->a_access_mask
& mask_bit
)) {
909 } else if (acl_consume
& err_deny
) {
910 if (acep
->a_access_mask
& mask_bit
) {
915 /* ACE_ACCESS_ALLOWED_ACE_TYPE */
916 if (acl_consume
& set_allow
) {
917 if (!(acep
->a_access_mask
& mask_bit
)) {
920 } else if (acl_consume
& err_allow
) {
921 if (acep
->a_access_mask
& mask_bit
) {
930 ace_to_aent_legal(ace_t
*acep
)
935 /* only ALLOW or DENY */
936 if ((acep
->a_type
!= ACE_ACCESS_ALLOWED_ACE_TYPE
) &&
937 (acep
->a_type
!= ACE_ACCESS_DENIED_ACE_TYPE
)) {
942 /* check for invalid flags */
943 if (acep
->a_flags
& ~(ACE_VALID_FLAG_BITS
)) {
948 /* some flags are illegal */
949 if (acep
->a_flags
& (ACE_SUCCESSFUL_ACCESS_ACE_FLAG
|
950 ACE_FAILED_ACCESS_ACE_FLAG
|
951 ACE_NO_PROPAGATE_INHERIT_ACE
)) {
956 /* check for invalid masks */
957 if (acep
->a_access_mask
& ~(ACE_VALID_MASK_BITS
)) {
962 if ((acep
->a_flags
& ACE_OWNER
)) {
968 error
= access_mask_check(acep
, ACE_SYNCHRONIZE
, isowner
);
972 error
= access_mask_check(acep
, ACE_WRITE_OWNER
, isowner
);
976 error
= access_mask_check(acep
, ACE_DELETE
, isowner
);
980 error
= access_mask_check(acep
, ACE_WRITE_ATTRIBUTES
, isowner
);
984 error
= access_mask_check(acep
, ACE_READ_NAMED_ATTRS
, isowner
);
988 error
= access_mask_check(acep
, ACE_WRITE_NAMED_ATTRS
, isowner
);
992 /* more detailed checking of masks */
993 if (acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) {
994 if (! (acep
->a_access_mask
& ACE_READ_ATTRIBUTES
)) {
998 if ((acep
->a_access_mask
& ACE_WRITE_DATA
) &&
999 (! (acep
->a_access_mask
& ACE_APPEND_DATA
))) {
1003 if ((! (acep
->a_access_mask
& ACE_WRITE_DATA
)) &&
1004 (acep
->a_access_mask
& ACE_APPEND_DATA
)) {
1010 /* ACL enforcement */
1011 if ((acep
->a_access_mask
& ACE_READ_ACL
) &&
1012 (acep
->a_type
!= ACE_ACCESS_ALLOWED_ACE_TYPE
)) {
1016 if (acep
->a_access_mask
& ACE_WRITE_ACL
) {
1017 if ((acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) &&
1022 if ((acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) &&
1034 ace_allow_to_mode(uint32_t mask
, o_mode_t
*modep
, boolean_t isdir
)
1036 /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
1037 if ((mask
& (ACE_READ_ACL
| ACE_READ_ATTRIBUTES
)) !=
1038 (ACE_READ_ACL
| ACE_READ_ATTRIBUTES
)) {
1042 return (ace_mask_to_mode(mask
, modep
, isdir
));
1046 acevals_to_aent(acevals_t
*vals
, aclent_t
*dest
, ace_list_t
*list
,
1047 uid_t owner
, gid_t group
, boolean_t isdir
)
1050 uint32_t flips
= ACE_POSIX_SUPPORTED_BITS
;
1053 flips
|= ACE_DELETE_CHILD
;
1054 if (vals
->allowed
!= (vals
->denied
^ flips
)) {
1058 if ((list
->hasmask
) && (list
->acl_mask
!= vals
->mask
) &&
1059 (vals
->aent_type
& (USER
| GROUP
| GROUP_OBJ
))) {
1063 error
= ace_allow_to_mode(vals
->allowed
, &dest
->a_perm
, isdir
);
1066 dest
->a_type
= vals
->aent_type
;
1067 if (dest
->a_type
& (USER
| GROUP
)) {
1068 dest
->a_id
= vals
->key
;
1069 } else if (dest
->a_type
& USER_OBJ
) {
1071 } else if (dest
->a_type
& GROUP_OBJ
) {
1073 } else if (dest
->a_type
& OTHER_OBJ
) {
1086 ace_list_to_aent(ace_list_t
*list
, aclent_t
**aclentp
, int *aclcnt
,
1087 uid_t owner
, gid_t group
, boolean_t isdir
)
1090 aclent_t
*aent
, *result
= NULL
;
1094 if ((list
->seen
& (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) !=
1095 (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) {
1099 if ((! list
->hasmask
) && (list
->numusers
+ list
->numgroups
> 0)) {
1104 resultcount
= 3 + list
->numusers
+ list
->numgroups
;
1106 * This must be the same condition as below, when we add the CLASS_OBJ
1109 if ((list
->hasmask
) || (! list
->dfacl_flag
))
1112 if (cacl_malloc((void **)&result
,
1113 resultcount
* sizeof (aclent_t
)) != 0) {
1120 if (!(list
->user_obj
.aent_type
& USER_OBJ
)) {
1125 error
= acevals_to_aent(&list
->user_obj
, aent
, list
, owner
, group
,
1133 for (vals
= avl_first(&list
->user
); vals
!= NULL
;
1134 vals
= AVL_NEXT(&list
->user
, vals
)) {
1135 if (!(vals
->aent_type
& USER
)) {
1139 error
= acevals_to_aent(vals
, aent
, list
, owner
, group
,
1146 if (!(list
->group_obj
.aent_type
& GROUP_OBJ
)) {
1150 error
= acevals_to_aent(&list
->group_obj
, aent
, list
, owner
, group
,
1157 for (vals
= avl_first(&list
->group
); vals
!= NULL
;
1158 vals
= AVL_NEXT(&list
->group
, vals
)) {
1159 if (!(vals
->aent_type
& GROUP
)) {
1163 error
= acevals_to_aent(vals
, aent
, list
, owner
, group
,
1170 * CLASS_OBJ (aka ACL_MASK)
1172 * An ACL_MASK is not fabricated if the ACL is a default ACL.
1173 * This is to follow UFS's behavior.
1175 if ((list
->hasmask
) || (! list
->dfacl_flag
)) {
1176 if (list
->hasmask
) {
1177 uint32_t flips
= ACE_POSIX_SUPPORTED_BITS
;
1179 flips
|= ACE_DELETE_CHILD
;
1180 error
= ace_mask_to_mode(list
->acl_mask
^ flips
,
1181 &aent
->a_perm
, isdir
);
1185 /* fabricate the ACL_MASK from the group permissions */
1186 error
= ace_mask_to_mode(list
->group_obj
.allowed
,
1187 &aent
->a_perm
, isdir
);
1192 aent
->a_type
= CLASS_OBJ
| list
->dfacl_flag
;
1196 if (!(list
->other_obj
.aent_type
& OTHER_OBJ
)) {
1200 error
= acevals_to_aent(&list
->other_obj
, aent
, list
, owner
, group
,
1207 *aclcnt
= resultcount
;
1212 cacl_free(result
, resultcount
* sizeof (aclent_t
));
1220 * free all data associated with an ace_list
1223 ace_list_free(ace_list_t
*al
)
1232 while ((node
= avl_destroy_nodes(&al
->user
, &cookie
)) != NULL
)
1233 cacl_free(node
, sizeof (acevals_t
));
1235 while ((node
= avl_destroy_nodes(&al
->group
, &cookie
)) != NULL
)
1236 cacl_free(node
, sizeof (acevals_t
));
1238 avl_destroy(&al
->user
);
1239 avl_destroy(&al
->group
);
1241 /* free the container itself */
1242 cacl_free(al
, sizeof (ace_list_t
));
1246 acevals_compare(const void *va
, const void *vb
)
1248 const acevals_t
*a
= va
, *b
= vb
;
1250 if (a
->key
== b
->key
)
1253 if (a
->key
> b
->key
)
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.
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
,
1273 ace_list_t
*normacl
= NULL
, *dfacl
= NULL
, *acl
;
1281 /* we need at least user_obj, group_obj, and other_obj */
1291 error
= cacl_malloc((void **)&normacl
, sizeof (ace_list_t
));
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
));
1300 ace_list_init(normacl
, 0);
1302 error
= cacl_malloc((void **)&dfacl
, sizeof (ace_list_t
));
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
);
1312 /* process every ace_t... */
1313 for (i
= 0; i
< n
; i
++) {
1316 /* rule out certain cases quickly */
1317 error
= ace_to_aent_legal(acep
);
1322 * Turn off these bits in order to not have to worry about
1323 * them when doing the checks for compliments.
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
);
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
);
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
)) {
1347 if ((acep
->a_flags
& ACE_OWNER
)) {
1348 if (acl
->state
> ace_user_obj
) {
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
) {
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
;
1372 vals
= acevals_find(acep
, &acl
->group
,
1378 vals
->aent_type
= GROUP
| acl
->dfacl_flag
;
1380 acl
->state
= ace_group
;
1382 if (acl
->state
> ace_user
) {
1386 acl
->state
= ace_user
;
1388 vals
= acevals_find(acep
, &acl
->user
,
1394 vals
->aent_type
= USER
| acl
->dfacl_flag
;
1397 if (!(acl
->state
> ace_unused
)) {
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
) {
1408 vals
->allowed
= acep
->a_access_mask
;
1411 * it's a DENY; if there was a previous DENY, it
1412 * must have been an ACL_MASK.
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
)) {
1422 if (! acl
->hasmask
) {
1424 acl
->acl_mask
= vals
->denied
;
1425 /* check for mismatched ACL_MASK emulations */
1426 } else if (acl
->acl_mask
!= vals
->denied
) {
1430 vals
->mask
= vals
->denied
;
1432 vals
->denied
= acep
->a_access_mask
;
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
);
1444 if (dfacl
->state
!= ace_unused
) {
1445 error
= ace_list_to_aent(dfacl
, dfaclentp
, dfaclcnt
,
1446 owner
, group
, isdir
);
1453 if (normacl
!= NULL
)
1454 ace_list_free(normacl
);
1456 ace_list_free(dfacl
);
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
)
1466 aclent_t
*aclentp
, *dfaclentp
;
1467 int aclcnt
, dfaclcnt
;
1468 int aclsz
, dfaclsz
= 0;
1470 error
= ln_ace_to_aent(acebufp
, acecnt
, owner
, group
,
1471 &aclentp
, &aclcnt
, &dfaclentp
, &dfaclcnt
, isdir
);
1477 if (dfaclcnt
!= 0) {
1479 * Slap aclentp and dfaclentp into a single array.
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
);
1492 *retaclentp
= aclentp
;
1493 *retaclcnt
= aclcnt
+ dfaclcnt
;
1497 cacl_free(dfaclentp
, dfaclsz
);
1504 acl_translate(acl_t
*aclp
, int target_flavor
, boolean_t isdir
, uid_t owner
,
1512 * See if we need to translate
1514 if ((target_flavor
== _ACL_ACE_ENABLED
&& aclp
->acl_type
== ACE_T
) ||
1515 (target_flavor
== _ACL_ACLENT_ENABLED
&&
1516 aclp
->acl_type
== ACLENT_T
))
1519 if (target_flavor
== -1) {
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
);
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
);
1543 * replace old acl with newly translated acl
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
);
1552 aclp
->acl_type
= ACLENT_T
;
1553 aclp
->acl_entry_size
= sizeof (aclent_t
);
1559 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
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; \
1575 acl_trivial_access_masks(mode_t mode
, boolean_t isdir
, trivial_acl_t
*masks
)
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
;
1582 write_mask
|= ACE_DELETE_CHILD
;
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
;
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
;
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
;
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
;
1612 masks
->owner
|= read_mask
;
1614 masks
->owner
|= write_mask
;
1616 masks
->owner
|= execute_mask
;
1618 masks
->group
= ACE_READ_ACL
|ACE_READ_ATTRIBUTES
|ACE_READ_NAMED_ATTRS
|
1621 masks
->group
|= read_mask
;
1623 masks
->group
|= write_mask
;
1625 masks
->group
|= execute_mask
;
1627 masks
->everyone
= ACE_READ_ACL
|ACE_READ_ATTRIBUTES
|ACE_READ_NAMED_ATTRS
|
1630 masks
->everyone
|= read_mask
;
1632 masks
->everyone
|= write_mask
;
1634 masks
->everyone
|= execute_mask
;
1638 acl_trivial_create(mode_t mode
, boolean_t isdir
, ace_t
**acl
, int *count
)
1642 trivial_acl_t masks
;
1645 acl_trivial_access_masks(mode
, isdir
, &masks
);
1654 if ((error
= cacl_malloc((void **)acl
, *count
* sizeof (ace_t
))) != 0)
1658 SET_ACE(acl
, index
, -1, masks
.allow0
,
1659 ACE_ACCESS_ALLOWED_ACE_TYPE
, ACE_OWNER
);
1662 SET_ACE(acl
, index
, -1, masks
.deny1
,
1663 ACE_ACCESS_DENIED_ACE_TYPE
, ACE_OWNER
);
1666 SET_ACE(acl
, index
, -1, masks
.deny2
,
1667 ACE_ACCESS_DENIED_ACE_TYPE
, ACE_GROUP
|ACE_IDENTIFIER_GROUP
);
1670 SET_ACE(acl
, index
, -1, masks
.owner
, ACE_ACCESS_ALLOWED_ACE_TYPE
,
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
,
1682 * determine whether an ace_t acl is trivial
1684 * Trivialness implies that the acl is composed of only
1685 * owner, group, everyone entries. ACL can't
1686 * have read_acl denied, and write_owner/write_acl/write_attributes
1687 * can only be owner@ entry.
1690 ace_trivial_common(void *acep
, int aclcnt
,
1691 uint64_t (*walk
)(void *, uint64_t, int aclcnt
,
1692 uint16_t *, uint16_t *, uint32_t *))
1697 uint64_t cookie
= 0;
1699 while (cookie
= walk(acep
, cookie
, aclcnt
, &flags
, &type
, &mask
)) {
1700 switch (flags
& ACE_TYPE_FLAGS
) {
1702 case ACE_GROUP
|ACE_IDENTIFIER_GROUP
:
1710 if (flags
& (ACE_FILE_INHERIT_ACE
|
1711 ACE_DIRECTORY_INHERIT_ACE
|ACE_NO_PROPAGATE_INHERIT_ACE
|
1712 ACE_INHERIT_ONLY_ACE
))
1716 * Special check for some special bits
1718 * Don't allow anybody to deny reading basic
1719 * attributes or a files ACL.
1721 if ((mask
& (ACE_READ_ACL
|ACE_READ_ATTRIBUTES
)) &&
1722 (type
== ACE_ACCESS_DENIED_ACE_TYPE
))
1726 * Delete permission is never set by default
1728 if (mask
& ACE_DELETE
)
1732 * Child delete permission should be accompanied by write
1734 if ((mask
& ACE_DELETE_CHILD
) && !(mask
& ACE_WRITE_DATA
))
1738 * only allow owner@ to have
1739 * write_acl/write_owner/write_attributes/write_xattr/
1741 if (type
== ACE_ACCESS_ALLOWED_ACE_TYPE
&&
1742 (!(flags
& ACE_OWNER
) && (mask
&
1743 (ACE_WRITE_OWNER
|ACE_WRITE_ACL
| ACE_WRITE_ATTRIBUTES
|
1744 ACE_WRITE_NAMED_ATTRS
))))
1752 ace_walk(void *datap
, uint64_t cookie
, int aclcnt
, uint16_t *flags
,
1753 uint16_t *type
, uint32_t *mask
)
1755 ace_t
*acep
= datap
;
1757 if (cookie
>= aclcnt
)
1760 *flags
= acep
[cookie
].a_flags
;
1761 *type
= acep
[cookie
].a_type
;
1762 *mask
= acep
[cookie
++].a_access_mask
;
1768 ace_trivial(ace_t
*acep
, int aclcnt
)
1770 return (ace_trivial_common(acep
, aclcnt
, ace_walk
));