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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/sysmacros.h>
34 #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 */
153 ace_t trivial_acl
[] = {
154 {(uid_t
)-1, 0, ACE_OWNER
, ACE_ACCESS_DENIED_ACE_TYPE
},
155 {(uid_t
)-1, ACE_WRITE_ACL
|ACE_WRITE_OWNER
|ACE_WRITE_ATTRIBUTES
|
156 ACE_WRITE_NAMED_ATTRS
, ACE_OWNER
, ACE_ACCESS_ALLOWED_ACE_TYPE
},
157 {(uid_t
)-1, 0, ACE_GROUP
|ACE_IDENTIFIER_GROUP
,
158 ACE_ACCESS_DENIED_ACE_TYPE
},
159 {(uid_t
)-1, 0, ACE_GROUP
|ACE_IDENTIFIER_GROUP
,
160 ACE_ACCESS_ALLOWED_ACE_TYPE
},
161 {(uid_t
)-1, ACE_WRITE_ACL
|ACE_WRITE_OWNER
| ACE_WRITE_ATTRIBUTES
|
162 ACE_WRITE_NAMED_ATTRS
, ACE_EVERYONE
, ACE_ACCESS_DENIED_ACE_TYPE
},
163 {(uid_t
)-1, ACE_READ_ACL
|ACE_READ_ATTRIBUTES
|ACE_READ_NAMED_ATTRS
|
164 ACE_SYNCHRONIZE
, ACE_EVERYONE
, ACE_ACCESS_ALLOWED_ACE_TYPE
}
169 adjust_ace_pair_common(void *pair
, size_t access_off
,
170 size_t pairsize
, mode_t mode
)
172 char *datap
= (char *)pair
;
173 uint32_t *amask0
= (uint32_t *)(uintptr_t)(datap
+ access_off
);
174 uint32_t *amask1
= (uint32_t *)(uintptr_t)(datap
+ pairsize
+
177 *amask1
|= ACE_READ_DATA
;
179 *amask0
|= ACE_READ_DATA
;
181 *amask1
|= ACE_WRITE_DATA
|ACE_APPEND_DATA
;
183 *amask0
|= ACE_WRITE_DATA
|ACE_APPEND_DATA
;
185 *amask1
|= ACE_EXECUTE
;
187 *amask0
|= ACE_EXECUTE
;
191 adjust_ace_pair(ace_t
*pair
, mode_t mode
)
193 adjust_ace_pair_common(pair
, offsetof(ace_t
, a_access_mask
),
194 sizeof (ace_t
), mode
);
198 ace_allow_deny_helper(uint16_t type
, boolean_t
*allow
, boolean_t
*deny
)
200 if (type
== ACE_ACCESS_ALLOWED_ACE_TYPE
)
202 else if (type
== ACE_ACCESS_DENIED_ACE_TYPE
)
208 * determine whether an ace_t acl is trivial
210 * Trivialness implies that the acl is composed of only
211 * owner, group, everyone entries. ACL can't
212 * have read_acl denied, and write_owner/write_acl/write_attributes
213 * can only be owner@ entry.
216 ace_trivial_common(void *acep
, int aclcnt
,
217 uint64_t (*walk
)(void *, uint64_t, int aclcnt
,
218 uint16_t *, uint16_t *, uint32_t *))
220 boolean_t owner_allow
= B_FALSE
;
221 boolean_t group_allow
= B_FALSE
;
222 boolean_t everyone_allow
= B_FALSE
;
223 boolean_t owner_deny
= B_FALSE
;
224 boolean_t group_deny
= B_FALSE
;
225 boolean_t everyone_deny
= B_FALSE
;
231 while (cookie
= walk(acep
, cookie
, aclcnt
, &flags
, &type
, &mask
)) {
232 switch (flags
& ACE_TYPE_FLAGS
) {
234 if (group_allow
|| group_deny
|| everyone_allow
||
237 ace_allow_deny_helper(type
, &owner_allow
, &owner_deny
);
239 case ACE_GROUP
|ACE_IDENTIFIER_GROUP
:
240 if (everyone_allow
|| everyone_deny
&&
241 (!owner_allow
&& !owner_deny
))
243 ace_allow_deny_helper(type
, &group_allow
, &group_deny
);
247 if (!owner_allow
&& !owner_deny
&&
248 !group_allow
&& !group_deny
)
250 ace_allow_deny_helper(type
,
251 &everyone_allow
, &everyone_deny
);
258 if (flags
& (ACE_FILE_INHERIT_ACE
|
259 ACE_DIRECTORY_INHERIT_ACE
|ACE_NO_PROPAGATE_INHERIT_ACE
|
260 ACE_INHERIT_ONLY_ACE
))
264 * Special check for some special bits
266 * Don't allow anybody to deny reading basic
267 * attributes or a files ACL.
269 if ((mask
& (ACE_READ_ACL
|ACE_READ_ATTRIBUTES
)) &&
270 (type
== ACE_ACCESS_DENIED_ACE_TYPE
))
274 * Allow on owner@ to allow
275 * write_acl/write_owner/write_attributes
277 if (type
== ACE_ACCESS_ALLOWED_ACE_TYPE
&&
278 (!(flags
& ACE_OWNER
) && (mask
&
279 (ACE_WRITE_OWNER
|ACE_WRITE_ACL
|ACE_WRITE_ATTRIBUTES
))))
284 if (!owner_allow
|| !owner_deny
|| !group_allow
|| !group_deny
||
285 !everyone_allow
|| !everyone_deny
)
292 ace_walk(void *datap
, uint64_t cookie
, int aclcnt
, uint16_t *flags
,
293 uint16_t *type
, uint32_t *mask
)
297 if (cookie
>= aclcnt
)
300 *flags
= acep
[cookie
].a_flags
;
301 *type
= acep
[cookie
].a_type
;
302 *mask
= acep
[cookie
++].a_access_mask
;
308 ace_trivial(ace_t
*acep
, int aclcnt
)
310 return (ace_trivial_common(acep
, aclcnt
, ace_walk
));
314 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
315 * v = Ptr to array/vector of objs
316 * n = # objs in the array
317 * s = size of each obj (must be multiples of a word size)
318 * f = ptr to function to compare two objs
319 * returns (-1 = less than, 0 = equal, 1 = greater than
322 ksort(caddr_t v
, int n
, int s
, int (*f
)())
325 unsigned int *p1
, *p2
;
329 if (v
== NULL
|| n
<= 1)
332 /* Sanity check on arguments */
333 ASSERT(((uintptr_t)v
& 0x3) == 0 && (s
& 0x3) == 0);
335 for (g
= n
/ 2; g
> 0; g
/= 2) {
336 for (i
= g
; i
< n
; i
++) {
337 for (j
= i
- g
; j
>= 0 &&
338 (*f
)(v
+ j
* s
, v
+ (j
+ g
) * s
) == 1;
340 p1
= (void *)(v
+ j
* s
);
341 p2
= (void *)(v
+ (j
+ g
) * s
);
342 for (ii
= 0; ii
< s
/ 4; ii
++) {
353 * Compare two acls, all fields. Returns:
359 cmp2acls(void *a
, void *b
)
361 aclent_t
*x
= (aclent_t
*)a
;
362 aclent_t
*y
= (aclent_t
*)b
;
365 if (x
->a_type
< y
->a_type
)
367 if (x
->a_type
> y
->a_type
)
369 /* Equal types; compare id's */
370 if (x
->a_id
< y
->a_id
)
372 if (x
->a_id
> y
->a_id
)
374 /* Equal ids; compare perms */
375 if (x
->a_perm
< y
->a_perm
)
377 if (x
->a_perm
> y
->a_perm
)
385 cacl_realloc(void *ptr
, size_t size
, size_t new_size
)
390 tmp
= kmem_alloc(new_size
, KM_SLEEP
);
391 (void) memcpy(tmp
, ptr
, (size
< new_size
) ? size
: new_size
);
392 kmem_free(ptr
, size
);
395 return (realloc(ptr
, new_size
));
400 cacl_malloc(void **ptr
, size_t size
)
403 *ptr
= kmem_zalloc(size
, KM_SLEEP
);
406 *ptr
= calloc(1, size
);
416 cacl_free(void *ptr
, size_t size
)
419 kmem_free(ptr
, size
);
426 acl_alloc(enum acl_type type
)
430 if (cacl_malloc((void **)&aclp
, sizeof (acl_t
)) != 0)
433 aclp
->acl_aclp
= NULL
;
438 aclp
->acl_type
= ACE_T
;
439 aclp
->acl_entry_size
= sizeof (ace_t
);
442 aclp
->acl_type
= ACLENT_T
;
443 aclp
->acl_entry_size
= sizeof (aclent_t
);
453 * Free acl_t structure
456 acl_free(acl_t
*aclp
)
463 if (aclp
->acl_aclp
) {
464 acl_size
= aclp
->acl_cnt
* aclp
->acl_entry_size
;
465 cacl_free(aclp
->acl_aclp
, acl_size
);
468 cacl_free(aclp
, sizeof (acl_t
));
472 access_mask_set(int haswriteperm
, int hasreadperm
, int isowner
, int isallow
)
474 uint32_t access_mask
= 0;
476 int synchronize_set
= 0, write_owner_set
= 0;
477 int delete_set
= 0, write_attrs_set
= 0;
478 int read_named_set
= 0, write_named_set
= 0;
480 acl_produce
= (ACL_SYNCHRONIZE_SET_ALLOW
|
481 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
482 ACL_WRITE_ATTRS_WRITER_SET_DENY
);
485 synchronize_set
= ACL_SYNCHRONIZE_SET_ALLOW
;
486 write_owner_set
= ACL_WRITE_OWNER_SET_ALLOW
;
487 delete_set
= ACL_DELETE_SET_ALLOW
;
489 read_named_set
= ACL_READ_NAMED_READER_SET_ALLOW
;
491 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
493 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
494 else if (haswriteperm
)
495 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
498 synchronize_set
= ACL_SYNCHRONIZE_SET_DENY
;
499 write_owner_set
= ACL_WRITE_OWNER_SET_DENY
;
500 delete_set
= ACL_DELETE_SET_DENY
;
502 read_named_set
= ACL_READ_NAMED_READER_SET_DENY
;
504 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
506 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
507 else if (haswriteperm
)
508 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
511 * If the entity is not the owner and does not
512 * have write permissions ACE_WRITE_ATTRIBUTES will
513 * always go in the DENY ACE.
515 access_mask
|= ACE_WRITE_ATTRIBUTES
;
518 if (acl_produce
& synchronize_set
)
519 access_mask
|= ACE_SYNCHRONIZE
;
520 if (acl_produce
& write_owner_set
)
521 access_mask
|= ACE_WRITE_OWNER
;
522 if (acl_produce
& delete_set
)
523 access_mask
|= ACE_DELETE
;
524 if (acl_produce
& write_attrs_set
)
525 access_mask
|= ACE_WRITE_ATTRIBUTES
;
526 if (acl_produce
& read_named_set
)
527 access_mask
|= ACE_READ_NAMED_ATTRS
;
528 if (acl_produce
& write_named_set
)
529 access_mask
|= ACE_WRITE_NAMED_ATTRS
;
531 return (access_mask
);
535 * Given an mode_t, convert it into an access_mask as used
536 * by nfsace, assuming aclent_t -> nfsace semantics.
539 mode_to_ace_access(mode_t mode
, int isdir
, int isowner
, int isallow
)
542 int haswriteperm
= 0;
546 haswriteperm
= (mode
& S_IWOTH
);
547 hasreadperm
= (mode
& S_IROTH
);
549 haswriteperm
= !(mode
& S_IWOTH
);
550 hasreadperm
= !(mode
& S_IROTH
);
554 * The following call takes care of correctly setting the following
555 * mask bits in the access_mask:
556 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
557 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
559 access
= access_mask_set(haswriteperm
, hasreadperm
, isowner
, isallow
);
562 access
|= ACE_READ_ACL
| ACE_READ_ATTRIBUTES
;
564 access
|= ACE_WRITE_ACL
;
567 access
|= ACE_WRITE_ACL
;
571 if (mode
& S_IROTH
) {
572 access
|= ACE_READ_DATA
;
575 if (mode
& S_IWOTH
) {
576 access
|= ACE_WRITE_DATA
|
579 access
|= ACE_DELETE_CHILD
;
583 access
|= ACE_EXECUTE
;
590 * Given an nfsace (presumably an ALLOW entry), make a
591 * corresponding DENY entry at the address given.
594 ace_make_deny(ace_t
*allow
, ace_t
*deny
, int isdir
, int isowner
)
596 (void) memcpy(deny
, allow
, sizeof (ace_t
));
598 deny
->a_who
= allow
->a_who
;
600 deny
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
601 deny
->a_access_mask
^= ACE_POSIX_SUPPORTED_BITS
;
603 deny
->a_access_mask
^= ACE_DELETE_CHILD
;
605 deny
->a_access_mask
&= ~(ACE_SYNCHRONIZE
| ACE_WRITE_OWNER
|
606 ACE_DELETE
| ACE_WRITE_ATTRIBUTES
| ACE_READ_NAMED_ATTRS
|
607 ACE_WRITE_NAMED_ATTRS
);
608 deny
->a_access_mask
|= access_mask_set((allow
->a_access_mask
&
609 ACE_WRITE_DATA
), (allow
->a_access_mask
& ACE_READ_DATA
), isowner
,
613 * Make an initial pass over an array of aclent_t's. Gather
614 * information such as an ACL_MASK (if any), number of users,
615 * number of groups, and whether the array needs to be sorted.
618 ln_aent_preprocess(aclent_t
*aclent
, int n
,
619 int *hasmask
, mode_t
*mask
,
620 int *numuser
, int *numgroup
, int *needsort
)
632 for (i
= 0; i
< n
; i
++) {
633 if (aclent
[i
].a_type
< curtype
)
635 else if (aclent
[i
].a_type
> curtype
)
636 curtype
= aclent
[i
].a_type
;
637 if (aclent
[i
].a_type
& USER
)
639 if (aclent
[i
].a_type
& (GROUP
| GROUP_OBJ
))
641 if (aclent
[i
].a_type
& CLASS_OBJ
) {
647 *mask
= aclent
[i
].a_perm
;
652 if ((! *hasmask
) && (*numuser
+ *numgroup
> 1)) {
662 * Convert an array of aclent_t into an array of nfsace entries,
663 * following POSIX draft -> nfsv4 conversion semantics as outlined in
667 ln_aent_to_ace(aclent_t
*aclent
, int n
, ace_t
**acepp
, int *rescount
, int isdir
)
671 int numuser
, numgroup
, needsort
;
673 int i
, groupi
= 0, skip
;
674 ace_t
*acep
, *result
= NULL
;
677 error
= ln_aent_preprocess(aclent
, n
, &hasmask
, &mask
,
678 &numuser
, &numgroup
, &needsort
);
682 /* allow + deny for each aclent */
686 * stick extra deny on the group_obj and on each
687 * user|group for the mask (the group_obj was added
688 * into the count for numgroup)
690 resultsize
+= numuser
+ numgroup
;
691 /* ... and don't count the mask itself */
695 /* sort the source if necessary */
697 ksort((caddr_t
)aclent
, n
, sizeof (aclent_t
), cmp2acls
);
699 if (cacl_malloc((void **)&result
, resultsize
* sizeof (ace_t
)) != 0)
704 for (i
= 0; i
< n
; i
++) {
706 * don't process CLASS_OBJ (mask); mask was grabbed in
707 * ln_aent_preprocess()
709 if (aclent
[i
].a_type
& CLASS_OBJ
)
712 /* If we need an ACL_MASK emulator, prepend it now */
714 (aclent
[i
].a_type
& (USER
| GROUP
| GROUP_OBJ
))) {
715 acep
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
717 if (aclent
[i
].a_type
& GROUP_OBJ
) {
718 acep
->a_who
= (uid_t
)-1;
720 (ACE_IDENTIFIER_GROUP
|ACE_GROUP
);
721 } else if (aclent
[i
].a_type
& USER
) {
722 acep
->a_who
= aclent
[i
].a_id
;
724 acep
->a_who
= aclent
[i
].a_id
;
725 acep
->a_flags
|= ACE_IDENTIFIER_GROUP
;
727 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
728 acep
->a_flags
|= ACE_INHERIT_ONLY_ACE
|
729 ACE_FILE_INHERIT_ACE
|
730 ACE_DIRECTORY_INHERIT_ACE
;
733 * Set the access mask for the prepended deny
734 * ace. To do this, we invert the mask (found
735 * in ln_aent_preprocess()) then convert it to an
736 * DENY ace access_mask.
738 acep
->a_access_mask
= mode_to_ace_access((mask
^ 07),
743 /* handle a_perm -> access_mask */
744 acep
->a_access_mask
= mode_to_ace_access(aclent
[i
].a_perm
,
745 isdir
, aclent
[i
].a_type
& USER_OBJ
, 1);
747 /* emulate a default aclent */
748 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
749 acep
->a_flags
|= ACE_INHERIT_ONLY_ACE
|
750 ACE_FILE_INHERIT_ACE
|
751 ACE_DIRECTORY_INHERIT_ACE
;
755 * handle a_perm and a_id
757 * this must be done last, since it involves the
758 * corresponding deny aces, which are handled
759 * differently for each different a_type.
761 if (aclent
[i
].a_type
& USER_OBJ
) {
762 acep
->a_who
= (uid_t
)-1;
763 acep
->a_flags
|= ACE_OWNER
;
764 ace_make_deny(acep
, acep
+ 1, isdir
, B_TRUE
);
766 } else if (aclent
[i
].a_type
& USER
) {
767 acep
->a_who
= aclent
[i
].a_id
;
768 ace_make_deny(acep
, acep
+ 1, isdir
, B_FALSE
);
770 } else if (aclent
[i
].a_type
& (GROUP_OBJ
| GROUP
)) {
771 if (aclent
[i
].a_type
& GROUP_OBJ
) {
772 acep
->a_who
= (uid_t
)-1;
773 acep
->a_flags
|= ACE_GROUP
;
775 acep
->a_who
= aclent
[i
].a_id
;
777 acep
->a_flags
|= ACE_IDENTIFIER_GROUP
;
779 * Set the corresponding deny for the group ace.
781 * The deny aces go after all of the groups, unlike
782 * everything else, where they immediately follow
785 * We calculate "skip", the number of slots to
786 * skip ahead for the deny ace, here.
789 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
791 * (2 * numgroup) - 1 - groupi
792 * (2 * numgroup) to account for MD + A
793 * - 1 to account for the fact that we're on the
794 * access (A), not the mask (MD)
795 * - groupi to account for the fact that we have
796 * passed up groupi number of MD's.
798 skip
= (2 * numgroup
) - 1 - groupi
;
799 ace_make_deny(acep
, acep
+ skip
, isdir
, B_FALSE
);
801 * If we just did the last group, skip acep past
802 * all of the denies; else, just move ahead one.
804 if (++groupi
>= numgroup
)
805 acep
+= numgroup
+ 1;
808 } else if (aclent
[i
].a_type
& OTHER_OBJ
) {
809 acep
->a_who
= (uid_t
)-1;
810 acep
->a_flags
|= ACE_EVERYONE
;
811 ace_make_deny(acep
, acep
+ 1, isdir
, B_FALSE
);
820 *rescount
= resultsize
;
824 if ((result
!= NULL
) && (resultsize
> 0)) {
825 cacl_free(result
, resultsize
* sizeof (ace_t
));
833 convert_aent_to_ace(aclent_t
*aclentp
, int aclcnt
, int isdir
,
834 ace_t
**retacep
, int *retacecnt
)
847 ksort((caddr_t
)aclentp
, aclcnt
, sizeof (aclent_t
), cmp2acls
);
849 for (i
= 0, aclp
= aclentp
; i
< aclcnt
; aclp
++, i
++) {
850 if (aclp
->a_type
& ACL_DEFAULT
)
856 dfaclcnt
= aclcnt
- i
;
859 if (dfaclcnt
&& isdir
== 0) {
863 error
= ln_aent_to_ace(aclentp
, i
, &acep
, &acecnt
, isdir
);
868 error
= ln_aent_to_ace(&aclentp
[dfaclstart
], dfaclcnt
,
869 &dfacep
, &dfacecnt
, isdir
);
872 cacl_free(acep
, acecnt
* sizeof (ace_t
));
879 acesz
= sizeof (ace_t
) * acecnt
;
880 dfacesz
= sizeof (ace_t
) * dfacecnt
;
881 acep
= cacl_realloc(acep
, acesz
, acesz
+ dfacesz
);
885 (void) memcpy(acep
+ acecnt
, dfacep
, dfacesz
);
889 cacl_free(dfacep
, dfacecnt
* sizeof (ace_t
));
891 *retacecnt
= acecnt
+ dfacecnt
;
897 ace_mask_to_mode(uint32_t mask
, o_mode_t
*modep
, int isdir
)
901 uint32_t bits
, wantbits
;
904 if (mask
& ACE_READ_DATA
)
908 wantbits
= (ACE_WRITE_DATA
| ACE_APPEND_DATA
);
910 wantbits
|= ACE_DELETE_CHILD
;
911 bits
= mask
& wantbits
;
913 if (bits
!= wantbits
) {
921 if (mask
& ACE_EXECUTE
) {
932 acevals_init(acevals_t
*vals
, uid_t key
)
934 bzero(vals
, sizeof (*vals
));
935 vals
->allowed
= ACE_MASK_UNDEFINED
;
936 vals
->denied
= ACE_MASK_UNDEFINED
;
937 vals
->mask
= ACE_MASK_UNDEFINED
;
942 ace_list_init(ace_list_t
*al
, int dfacl_flag
)
944 acevals_init(&al
->user_obj
, NULL
);
945 acevals_init(&al
->group_obj
, NULL
);
946 acevals_init(&al
->other_obj
, NULL
);
951 al
->state
= ace_unused
;
953 al
->dfacl_flag
= dfacl_flag
;
957 * Find or create an acevals holder for a given id and avl tree.
959 * Note that only one thread will ever touch these avl trees, so
960 * there is no need for locking.
963 acevals_find(ace_t
*ace
, avl_tree_t
*avl
, int *num
)
968 key
.key
= ace
->a_who
;
969 rc
= avl_find(avl
, &key
, &where
);
973 /* this memory is freed by ln_ace_to_aent()->ace_list_free() */
974 if (cacl_malloc((void **)&rc
, sizeof (acevals_t
)) != 0)
977 acevals_init(rc
, ace
->a_who
);
978 avl_insert(avl
, rc
, where
);
985 access_mask_check(ace_t
*acep
, int mask_bit
, int isowner
)
987 int set_deny
, err_deny
;
988 int set_allow
, err_allow
;
990 int haswriteperm
, hasreadperm
;
992 if (acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) {
993 haswriteperm
= (acep
->a_access_mask
& ACE_WRITE_DATA
) ? 0 : 1;
994 hasreadperm
= (acep
->a_access_mask
& ACE_READ_DATA
) ? 0 : 1;
996 haswriteperm
= (acep
->a_access_mask
& ACE_WRITE_DATA
) ? 1 : 0;
997 hasreadperm
= (acep
->a_access_mask
& ACE_READ_DATA
) ? 1 : 0;
1000 acl_consume
= (ACL_SYNCHRONIZE_ERR_DENY
|
1001 ACL_DELETE_ERR_DENY
|
1002 ACL_WRITE_OWNER_ERR_DENY
|
1003 ACL_WRITE_OWNER_ERR_ALLOW
|
1004 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
1005 ACL_WRITE_ATTRS_OWNER_ERR_DENY
|
1006 ACL_WRITE_ATTRS_WRITER_SET_DENY
|
1007 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
|
1008 ACL_WRITE_NAMED_WRITER_ERR_DENY
|
1009 ACL_READ_NAMED_READER_ERR_DENY
);
1011 if (mask_bit
== ACE_SYNCHRONIZE
) {
1012 set_deny
= ACL_SYNCHRONIZE_SET_DENY
;
1013 err_deny
= ACL_SYNCHRONIZE_ERR_DENY
;
1014 set_allow
= ACL_SYNCHRONIZE_SET_ALLOW
;
1015 err_allow
= ACL_SYNCHRONIZE_ERR_ALLOW
;
1016 } else if (mask_bit
== ACE_WRITE_OWNER
) {
1017 set_deny
= ACL_WRITE_OWNER_SET_DENY
;
1018 err_deny
= ACL_WRITE_OWNER_ERR_DENY
;
1019 set_allow
= ACL_WRITE_OWNER_SET_ALLOW
;
1020 err_allow
= ACL_WRITE_OWNER_ERR_ALLOW
;
1021 } else if (mask_bit
== ACE_DELETE
) {
1022 set_deny
= ACL_DELETE_SET_DENY
;
1023 err_deny
= ACL_DELETE_ERR_DENY
;
1024 set_allow
= ACL_DELETE_SET_ALLOW
;
1025 err_allow
= ACL_DELETE_ERR_ALLOW
;
1026 } else if (mask_bit
== ACE_WRITE_ATTRIBUTES
) {
1028 set_deny
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
1029 err_deny
= ACL_WRITE_ATTRS_OWNER_ERR_DENY
;
1030 set_allow
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
1031 err_allow
= ACL_WRITE_ATTRS_OWNER_ERR_ALLOW
;
1032 } else if (haswriteperm
) {
1033 set_deny
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
1034 err_deny
= ACL_WRITE_ATTRS_WRITER_ERR_DENY
;
1035 set_allow
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
1036 err_allow
= ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
;
1038 if ((acep
->a_access_mask
& mask_bit
) &&
1039 (acep
->a_type
& ACE_ACCESS_ALLOWED_ACE_TYPE
)) {
1044 } else if (mask_bit
== ACE_READ_NAMED_ATTRS
) {
1048 set_deny
= ACL_READ_NAMED_READER_SET_DENY
;
1049 err_deny
= ACL_READ_NAMED_READER_ERR_DENY
;
1050 set_allow
= ACL_READ_NAMED_READER_SET_ALLOW
;
1051 err_allow
= ACL_READ_NAMED_READER_ERR_ALLOW
;
1052 } else if (mask_bit
== ACE_WRITE_NAMED_ATTRS
) {
1056 set_deny
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
1057 err_deny
= ACL_WRITE_NAMED_WRITER_ERR_DENY
;
1058 set_allow
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
1059 err_allow
= ACL_WRITE_NAMED_WRITER_ERR_ALLOW
;
1064 if (acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) {
1065 if (acl_consume
& set_deny
) {
1066 if (!(acep
->a_access_mask
& mask_bit
)) {
1069 } else if (acl_consume
& err_deny
) {
1070 if (acep
->a_access_mask
& mask_bit
) {
1075 /* ACE_ACCESS_ALLOWED_ACE_TYPE */
1076 if (acl_consume
& set_allow
) {
1077 if (!(acep
->a_access_mask
& mask_bit
)) {
1080 } else if (acl_consume
& err_allow
) {
1081 if (acep
->a_access_mask
& mask_bit
) {
1090 ace_to_aent_legal(ace_t
*acep
)
1095 /* only ALLOW or DENY */
1096 if ((acep
->a_type
!= ACE_ACCESS_ALLOWED_ACE_TYPE
) &&
1097 (acep
->a_type
!= ACE_ACCESS_DENIED_ACE_TYPE
)) {
1102 /* check for invalid flags */
1103 if (acep
->a_flags
& ~(ACE_VALID_FLAG_BITS
)) {
1108 /* some flags are illegal */
1109 if (acep
->a_flags
& (ACE_SUCCESSFUL_ACCESS_ACE_FLAG
|
1110 ACE_FAILED_ACCESS_ACE_FLAG
|
1111 ACE_NO_PROPAGATE_INHERIT_ACE
)) {
1116 /* check for invalid masks */
1117 if (acep
->a_access_mask
& ~(ACE_VALID_MASK_BITS
)) {
1122 if ((acep
->a_flags
& ACE_OWNER
)) {
1128 error
= access_mask_check(acep
, ACE_SYNCHRONIZE
, isowner
);
1132 error
= access_mask_check(acep
, ACE_WRITE_OWNER
, isowner
);
1136 error
= access_mask_check(acep
, ACE_DELETE
, isowner
);
1140 error
= access_mask_check(acep
, ACE_WRITE_ATTRIBUTES
, isowner
);
1144 error
= access_mask_check(acep
, ACE_READ_NAMED_ATTRS
, isowner
);
1148 error
= access_mask_check(acep
, ACE_WRITE_NAMED_ATTRS
, isowner
);
1152 /* more detailed checking of masks */
1153 if (acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) {
1154 if (! (acep
->a_access_mask
& ACE_READ_ATTRIBUTES
)) {
1158 if ((acep
->a_access_mask
& ACE_WRITE_DATA
) &&
1159 (! (acep
->a_access_mask
& ACE_APPEND_DATA
))) {
1163 if ((! (acep
->a_access_mask
& ACE_WRITE_DATA
)) &&
1164 (acep
->a_access_mask
& ACE_APPEND_DATA
)) {
1170 /* ACL enforcement */
1171 if ((acep
->a_access_mask
& ACE_READ_ACL
) &&
1172 (acep
->a_type
!= ACE_ACCESS_ALLOWED_ACE_TYPE
)) {
1176 if (acep
->a_access_mask
& ACE_WRITE_ACL
) {
1177 if ((acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) &&
1182 if ((acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) &&
1194 ace_allow_to_mode(uint32_t mask
, o_mode_t
*modep
, int isdir
)
1196 /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
1197 if ((mask
& (ACE_READ_ACL
| ACE_READ_ATTRIBUTES
)) !=
1198 (ACE_READ_ACL
| ACE_READ_ATTRIBUTES
)) {
1202 return (ace_mask_to_mode(mask
, modep
, isdir
));
1206 acevals_to_aent(acevals_t
*vals
, aclent_t
*dest
, ace_list_t
*list
,
1207 uid_t owner
, gid_t group
, int isdir
)
1210 uint32_t flips
= ACE_POSIX_SUPPORTED_BITS
;
1213 flips
|= ACE_DELETE_CHILD
;
1214 if (vals
->allowed
!= (vals
->denied
^ flips
)) {
1218 if ((list
->hasmask
) && (list
->acl_mask
!= vals
->mask
) &&
1219 (vals
->aent_type
& (USER
| GROUP
| GROUP_OBJ
))) {
1223 error
= ace_allow_to_mode(vals
->allowed
, &dest
->a_perm
, isdir
);
1226 dest
->a_type
= vals
->aent_type
;
1227 if (dest
->a_type
& (USER
| GROUP
)) {
1228 dest
->a_id
= vals
->key
;
1229 } else if (dest
->a_type
& USER_OBJ
) {
1231 } else if (dest
->a_type
& GROUP_OBJ
) {
1233 } else if (dest
->a_type
& OTHER_OBJ
) {
1246 ace_list_to_aent(ace_list_t
*list
, aclent_t
**aclentp
, int *aclcnt
,
1247 uid_t owner
, gid_t group
, int isdir
)
1250 aclent_t
*aent
, *result
= NULL
;
1254 if ((list
->seen
& (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) !=
1255 (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) {
1259 if ((! list
->hasmask
) && (list
->numusers
+ list
->numgroups
> 0)) {
1264 resultcount
= 3 + list
->numusers
+ list
->numgroups
;
1266 * This must be the same condition as below, when we add the CLASS_OBJ
1269 if ((list
->hasmask
) || (! list
->dfacl_flag
))
1272 if (cacl_malloc((void **)&result
,
1273 resultcount
* sizeof (aclent_t
)) != 0) {
1280 if (!(list
->user_obj
.aent_type
& USER_OBJ
)) {
1285 error
= acevals_to_aent(&list
->user_obj
, aent
, list
, owner
, group
,
1293 for (vals
= avl_first(&list
->user
); vals
!= NULL
;
1294 vals
= AVL_NEXT(&list
->user
, vals
)) {
1295 if (!(vals
->aent_type
& USER
)) {
1299 error
= acevals_to_aent(vals
, aent
, list
, owner
, group
,
1306 if (!(list
->group_obj
.aent_type
& GROUP_OBJ
)) {
1310 error
= acevals_to_aent(&list
->group_obj
, aent
, list
, owner
, group
,
1317 for (vals
= avl_first(&list
->group
); vals
!= NULL
;
1318 vals
= AVL_NEXT(&list
->group
, vals
)) {
1319 if (!(vals
->aent_type
& GROUP
)) {
1323 error
= acevals_to_aent(vals
, aent
, list
, owner
, group
,
1330 * CLASS_OBJ (aka ACL_MASK)
1332 * An ACL_MASK is not fabricated if the ACL is a default ACL.
1333 * This is to follow UFS's behavior.
1335 if ((list
->hasmask
) || (! list
->dfacl_flag
)) {
1336 if (list
->hasmask
) {
1337 uint32_t flips
= ACE_POSIX_SUPPORTED_BITS
;
1339 flips
|= ACE_DELETE_CHILD
;
1340 error
= ace_mask_to_mode(list
->acl_mask
^ flips
,
1341 &aent
->a_perm
, isdir
);
1345 /* fabricate the ACL_MASK from the group permissions */
1346 error
= ace_mask_to_mode(list
->group_obj
.allowed
,
1347 &aent
->a_perm
, isdir
);
1352 aent
->a_type
= CLASS_OBJ
| list
->dfacl_flag
;
1356 if (!(list
->other_obj
.aent_type
& OTHER_OBJ
)) {
1360 error
= acevals_to_aent(&list
->other_obj
, aent
, list
, owner
, group
,
1367 *aclcnt
= resultcount
;
1372 cacl_free(result
, resultcount
* sizeof (aclent_t
));
1380 * free all data associated with an ace_list
1383 ace_list_free(ace_list_t
*al
)
1392 while ((node
= avl_destroy_nodes(&al
->user
, &cookie
)) != NULL
)
1393 cacl_free(node
, sizeof (acevals_t
));
1395 while ((node
= avl_destroy_nodes(&al
->group
, &cookie
)) != NULL
)
1396 cacl_free(node
, sizeof (acevals_t
));
1398 avl_destroy(&al
->user
);
1399 avl_destroy(&al
->group
);
1401 /* free the container itself */
1402 cacl_free(al
, sizeof (ace_list_t
));
1406 acevals_compare(const void *va
, const void *vb
)
1408 const acevals_t
*a
= va
, *b
= vb
;
1410 if (a
->key
== b
->key
)
1413 if (a
->key
> b
->key
)
1421 * Convert a list of ace_t entries to equivalent regular and default
1422 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible.
1425 ln_ace_to_aent(ace_t
*ace
, int n
, uid_t owner
, gid_t group
,
1426 aclent_t
**aclentp
, int *aclcnt
, aclent_t
**dfaclentp
, int *dfaclcnt
,
1433 ace_list_t
*normacl
= NULL
, *dfacl
= NULL
, *acl
;
1441 /* we need at least user_obj, group_obj, and other_obj */
1451 error
= cacl_malloc((void **)&normacl
, sizeof (ace_list_t
));
1455 avl_create(&normacl
->user
, acevals_compare
, sizeof (acevals_t
),
1456 offsetof(acevals_t
, avl
));
1457 avl_create(&normacl
->group
, acevals_compare
, sizeof (acevals_t
),
1458 offsetof(acevals_t
, avl
));
1460 ace_list_init(normacl
, 0);
1462 error
= cacl_malloc((void **)&dfacl
, sizeof (ace_list_t
));
1466 avl_create(&dfacl
->user
, acevals_compare
, sizeof (acevals_t
),
1467 offsetof(acevals_t
, avl
));
1468 avl_create(&dfacl
->group
, acevals_compare
, sizeof (acevals_t
),
1469 offsetof(acevals_t
, avl
));
1470 ace_list_init(dfacl
, ACL_DEFAULT
);
1472 /* process every ace_t... */
1473 for (i
= 0; i
< n
; i
++) {
1476 /* rule out certain cases quickly */
1477 error
= ace_to_aent_legal(acep
);
1482 * Turn off these bits in order to not have to worry about
1483 * them when doing the checks for compliments.
1485 acep
->a_access_mask
&= ~(ACE_WRITE_OWNER
| ACE_DELETE
|
1486 ACE_SYNCHRONIZE
| ACE_WRITE_ATTRIBUTES
|
1487 ACE_READ_NAMED_ATTRS
| ACE_WRITE_NAMED_ATTRS
);
1489 /* see if this should be a regular or default acl */
1490 bits
= acep
->a_flags
&
1491 (ACE_INHERIT_ONLY_ACE
|
1492 ACE_FILE_INHERIT_ACE
|
1493 ACE_DIRECTORY_INHERIT_ACE
);
1495 /* all or nothing on these inherit bits */
1496 if (bits
!= (ACE_INHERIT_ONLY_ACE
|
1497 ACE_FILE_INHERIT_ACE
|
1498 ACE_DIRECTORY_INHERIT_ACE
)) {
1507 if ((acep
->a_flags
& ACE_OWNER
)) {
1508 if (acl
->state
> ace_user_obj
) {
1512 acl
->state
= ace_user_obj
;
1513 acl
->seen
|= USER_OBJ
;
1514 vals
= &acl
->user_obj
;
1515 vals
->aent_type
= USER_OBJ
| acl
->dfacl_flag
;
1516 } else if ((acep
->a_flags
& ACE_EVERYONE
)) {
1517 acl
->state
= ace_other_obj
;
1518 acl
->seen
|= OTHER_OBJ
;
1519 vals
= &acl
->other_obj
;
1520 vals
->aent_type
= OTHER_OBJ
| acl
->dfacl_flag
;
1521 } else if (acep
->a_flags
& ACE_IDENTIFIER_GROUP
) {
1522 if (acl
->state
> ace_group
) {
1526 if ((acep
->a_flags
& ACE_GROUP
)) {
1527 acl
->seen
|= GROUP_OBJ
;
1528 vals
= &acl
->group_obj
;
1529 vals
->aent_type
= GROUP_OBJ
| acl
->dfacl_flag
;
1532 vals
= acevals_find(acep
, &acl
->group
,
1538 vals
->aent_type
= GROUP
| acl
->dfacl_flag
;
1540 acl
->state
= ace_group
;
1542 if (acl
->state
> ace_user
) {
1546 acl
->state
= ace_user
;
1548 vals
= acevals_find(acep
, &acl
->user
,
1554 vals
->aent_type
= USER
| acl
->dfacl_flag
;
1557 if (!(acl
->state
> ace_unused
)) {
1562 if (acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) {
1563 /* no more than one allowed per aclent_t */
1564 if (vals
->allowed
!= ACE_MASK_UNDEFINED
) {
1568 vals
->allowed
= acep
->a_access_mask
;
1571 * it's a DENY; if there was a previous DENY, it
1572 * must have been an ACL_MASK.
1574 if (vals
->denied
!= ACE_MASK_UNDEFINED
) {
1575 /* ACL_MASK is for USER and GROUP only */
1576 if ((acl
->state
!= ace_user
) &&
1577 (acl
->state
!= ace_group
)) {
1582 if (! acl
->hasmask
) {
1584 acl
->acl_mask
= vals
->denied
;
1585 /* check for mismatched ACL_MASK emulations */
1586 } else if (acl
->acl_mask
!= vals
->denied
) {
1590 vals
->mask
= vals
->denied
;
1592 vals
->denied
= acep
->a_access_mask
;
1596 /* done collating; produce the aclent_t lists */
1597 if (normacl
->state
!= ace_unused
) {
1598 error
= ace_list_to_aent(normacl
, aclentp
, aclcnt
,
1599 owner
, group
, isdir
);
1604 if (dfacl
->state
!= ace_unused
) {
1605 error
= ace_list_to_aent(dfacl
, dfaclentp
, dfaclcnt
,
1606 owner
, group
, isdir
);
1613 if (normacl
!= NULL
)
1614 ace_list_free(normacl
);
1616 ace_list_free(dfacl
);
1622 convert_ace_to_aent(ace_t
*acebufp
, int acecnt
, int isdir
,
1623 uid_t owner
, gid_t group
, aclent_t
**retaclentp
, int *retaclcnt
)
1626 aclent_t
*aclentp
, *dfaclentp
;
1627 int aclcnt
, dfaclcnt
;
1630 error
= ln_ace_to_aent(acebufp
, acecnt
, owner
, group
,
1631 &aclentp
, &aclcnt
, &dfaclentp
, &dfaclcnt
, isdir
);
1637 if (dfaclcnt
!= 0) {
1639 * Slap aclentp and dfaclentp into a single array.
1641 aclsz
= sizeof (aclent_t
) * aclcnt
;
1642 dfaclsz
= sizeof (aclent_t
) * dfaclcnt
;
1643 aclentp
= cacl_realloc(aclentp
, aclsz
, aclsz
+ dfaclsz
);
1644 if (aclentp
!= NULL
) {
1645 (void) memcpy(aclentp
+ aclcnt
, dfaclentp
, dfaclsz
);
1652 *retaclentp
= aclentp
;
1653 *retaclcnt
= aclcnt
+ dfaclcnt
;
1657 cacl_free(dfaclentp
, dfaclsz
);
1664 acl_translate(acl_t
*aclp
, int target_flavor
, int isdir
, uid_t owner
,
1672 * See if we need to translate
1674 if ((target_flavor
== _ACL_ACE_ENABLED
&& aclp
->acl_type
== ACE_T
) ||
1675 (target_flavor
== _ACL_ACLENT_ENABLED
&&
1676 aclp
->acl_type
== ACLENT_T
))
1679 if (target_flavor
== -1) {
1684 if (target_flavor
== _ACL_ACE_ENABLED
&&
1685 aclp
->acl_type
== ACLENT_T
) {
1686 error
= convert_aent_to_ace(aclp
->acl_aclp
,
1687 aclp
->acl_cnt
, isdir
, (ace_t
**)&acldata
, &aclcnt
);
1691 } else if (target_flavor
== _ACL_ACLENT_ENABLED
&&
1692 aclp
->acl_type
== ACE_T
) {
1693 error
= convert_ace_to_aent(aclp
->acl_aclp
, aclp
->acl_cnt
,
1694 isdir
, owner
, group
, (aclent_t
**)&acldata
, &aclcnt
);
1703 * replace old acl with newly translated acl
1705 cacl_free(aclp
->acl_aclp
, aclp
->acl_cnt
* aclp
->acl_entry_size
);
1706 aclp
->acl_aclp
= acldata
;
1707 aclp
->acl_cnt
= aclcnt
;
1708 if (target_flavor
== _ACL_ACE_ENABLED
) {
1709 aclp
->acl_type
= ACE_T
;
1710 aclp
->acl_entry_size
= sizeof (ace_t
);
1712 aclp
->acl_type
= ACLENT_T
;
1713 aclp
->acl_entry_size
= sizeof (aclent_t
);
1719 #if !defined(_KERNEL)