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 https://opensource.org/licenses/CDDL-1.0.
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 2011 Nexenta Systems, Inc. All rights reserved.
26 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/sysmacros.h>
34 #include <acl/acl_common.h>
35 #include <sys/debug.h>
44 #include <acl_common.h>
47 #define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \
48 ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \
49 ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL)
52 #define ACL_SYNCHRONIZE_SET_DENY 0x0000001
53 #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002
54 #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004
55 #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008
57 #define ACL_WRITE_OWNER_SET_DENY 0x0000010
58 #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020
59 #define ACL_WRITE_OWNER_ERR_DENY 0x0000040
60 #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080
62 #define ACL_DELETE_SET_DENY 0x0000100
63 #define ACL_DELETE_SET_ALLOW 0x0000200
64 #define ACL_DELETE_ERR_DENY 0x0000400
65 #define ACL_DELETE_ERR_ALLOW 0x0000800
67 #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000
68 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000
69 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000
70 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000
72 #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000
73 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000
74 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000
75 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000
77 #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000
78 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000
79 #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000
80 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000
82 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000
83 #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000
84 #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000
85 #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000
88 #define ACE_VALID_MASK_BITS (\
90 ACE_LIST_DIRECTORY | \
94 ACE_ADD_SUBDIRECTORY | \
95 ACE_READ_NAMED_ATTRS | \
96 ACE_WRITE_NAMED_ATTRS | \
99 ACE_READ_ATTRIBUTES | \
100 ACE_WRITE_ATTRIBUTES | \
107 #define ACE_MASK_UNDEFINED 0x80000000
109 #define ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \
110 ACE_DIRECTORY_INHERIT_ACE | \
111 ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \
112 ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \
113 ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE)
116 * ACL conversion helpers
123 ace_group
, /* includes GROUP and GROUP_OBJ */
125 } ace_to_aent_state_t
;
127 typedef struct acevals
{
136 typedef struct ace_list
{
147 ace_to_aent_state_t state
;
148 int seen
; /* bitmask of all aclent_t a_type values seen */
152 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified.
153 * v = Ptr to array/vector of objs
154 * n = # objs in the array
155 * s = size of each obj (must be multiples of a word size)
156 * f = ptr to function to compare two objs
157 * returns (-1 = less than, 0 = equal, 1 = greater than
160 ksort(caddr_t v
, int n
, int s
, int (*f
)(void *, void *))
163 unsigned int *p1
, *p2
;
167 if (v
== NULL
|| n
<= 1)
170 /* Sanity check on arguments */
171 ASSERT3U(((uintptr_t)v
& 0x3), ==, 0);
172 ASSERT3S((s
& 0x3), ==, 0);
174 for (g
= n
/ 2; g
> 0; g
/= 2) {
175 for (i
= g
; i
< n
; i
++) {
176 for (j
= i
- g
; j
>= 0 &&
177 (*f
)(v
+ j
* s
, v
+ (j
+ g
) * s
) == 1;
179 p1
= (void *)(v
+ j
* s
);
180 p2
= (void *)(v
+ (j
+ g
) * s
);
181 for (ii
= 0; ii
< s
/ 4; ii
++) {
192 * Compare two acls, all fields. Returns:
198 cmp2acls(void *a
, void *b
)
200 aclent_t
*x
= (aclent_t
*)a
;
201 aclent_t
*y
= (aclent_t
*)b
;
204 if (x
->a_type
< y
->a_type
)
206 if (x
->a_type
> y
->a_type
)
208 /* Equal types; compare id's */
209 if (x
->a_id
< y
->a_id
)
211 if (x
->a_id
> y
->a_id
)
213 /* Equal ids; compare perms */
214 if (x
->a_perm
< y
->a_perm
)
216 if (x
->a_perm
> y
->a_perm
)
223 cacl_malloc(void **ptr
, size_t size
)
225 *ptr
= kmem_zalloc(size
, KM_SLEEP
);
230 #if !defined(_KERNEL)
232 acl_alloc(enum acl_type type
)
236 if (cacl_malloc((void **)&aclp
, sizeof (acl_t
)) != 0)
239 aclp
->acl_aclp
= NULL
;
244 aclp
->acl_type
= ACE_T
;
245 aclp
->acl_entry_size
= sizeof (ace_t
);
248 aclp
->acl_type
= ACLENT_T
;
249 aclp
->acl_entry_size
= sizeof (aclent_t
);
259 * Free acl_t structure
262 acl_free(acl_t
*aclp
)
269 if (aclp
->acl_aclp
) {
270 acl_size
= aclp
->acl_cnt
* aclp
->acl_entry_size
;
271 cacl_free(aclp
->acl_aclp
, acl_size
);
274 cacl_free(aclp
, sizeof (acl_t
));
278 access_mask_set(int haswriteperm
, int hasreadperm
, int isowner
, int isallow
)
280 uint32_t access_mask
= 0;
282 int synchronize_set
= 0, write_owner_set
= 0;
283 int delete_set
= 0, write_attrs_set
= 0;
284 int read_named_set
= 0, write_named_set
= 0;
286 acl_produce
= (ACL_SYNCHRONIZE_SET_ALLOW
|
287 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
288 ACL_WRITE_ATTRS_WRITER_SET_DENY
);
291 synchronize_set
= ACL_SYNCHRONIZE_SET_ALLOW
;
292 write_owner_set
= ACL_WRITE_OWNER_SET_ALLOW
;
293 delete_set
= ACL_DELETE_SET_ALLOW
;
295 read_named_set
= ACL_READ_NAMED_READER_SET_ALLOW
;
297 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
299 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
300 else if (haswriteperm
)
301 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
304 synchronize_set
= ACL_SYNCHRONIZE_SET_DENY
;
305 write_owner_set
= ACL_WRITE_OWNER_SET_DENY
;
306 delete_set
= ACL_DELETE_SET_DENY
;
308 read_named_set
= ACL_READ_NAMED_READER_SET_DENY
;
310 write_named_set
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
312 write_attrs_set
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
313 else if (haswriteperm
)
314 write_attrs_set
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
317 * If the entity is not the owner and does not
318 * have write permissions ACE_WRITE_ATTRIBUTES will
319 * always go in the DENY ACE.
321 access_mask
|= ACE_WRITE_ATTRIBUTES
;
324 if (acl_produce
& synchronize_set
)
325 access_mask
|= ACE_SYNCHRONIZE
;
326 if (acl_produce
& write_owner_set
)
327 access_mask
|= ACE_WRITE_OWNER
;
328 if (acl_produce
& delete_set
)
329 access_mask
|= ACE_DELETE
;
330 if (acl_produce
& write_attrs_set
)
331 access_mask
|= ACE_WRITE_ATTRIBUTES
;
332 if (acl_produce
& read_named_set
)
333 access_mask
|= ACE_READ_NAMED_ATTRS
;
334 if (acl_produce
& write_named_set
)
335 access_mask
|= ACE_WRITE_NAMED_ATTRS
;
337 return (access_mask
);
341 * Given an mode_t, convert it into an access_mask as used
342 * by nfsace, assuming aclent_t -> nfsace semantics.
345 mode_to_ace_access(mode_t mode
, boolean_t isdir
, int isowner
, int isallow
)
348 int haswriteperm
= 0;
352 haswriteperm
= (mode
& S_IWOTH
);
353 hasreadperm
= (mode
& S_IROTH
);
355 haswriteperm
= !(mode
& S_IWOTH
);
356 hasreadperm
= !(mode
& S_IROTH
);
360 * The following call takes care of correctly setting the following
361 * mask bits in the access_mask:
362 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE,
363 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS
365 access
= access_mask_set(haswriteperm
, hasreadperm
, isowner
, isallow
);
368 access
|= ACE_READ_ACL
| ACE_READ_ATTRIBUTES
;
370 access
|= ACE_WRITE_ACL
;
373 access
|= ACE_WRITE_ACL
;
377 if (mode
& S_IROTH
) {
378 access
|= ACE_READ_DATA
;
381 if (mode
& S_IWOTH
) {
382 access
|= ACE_WRITE_DATA
|
385 access
|= ACE_DELETE_CHILD
;
388 if (mode
& S_IXOTH
) {
389 access
|= ACE_EXECUTE
;
396 * Given an nfsace (presumably an ALLOW entry), make a
397 * corresponding DENY entry at the address given.
400 ace_make_deny(ace_t
*allow
, ace_t
*deny
, int isdir
, int isowner
)
402 (void) memcpy(deny
, allow
, sizeof (ace_t
));
404 deny
->a_who
= allow
->a_who
;
406 deny
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
407 deny
->a_access_mask
^= ACE_POSIX_SUPPORTED_BITS
;
409 deny
->a_access_mask
^= ACE_DELETE_CHILD
;
411 deny
->a_access_mask
&= ~(ACE_SYNCHRONIZE
| ACE_WRITE_OWNER
|
412 ACE_DELETE
| ACE_WRITE_ATTRIBUTES
| ACE_READ_NAMED_ATTRS
|
413 ACE_WRITE_NAMED_ATTRS
);
414 deny
->a_access_mask
|= access_mask_set((allow
->a_access_mask
&
415 ACE_WRITE_DATA
), (allow
->a_access_mask
& ACE_READ_DATA
), isowner
,
419 * Make an initial pass over an array of aclent_t's. Gather
420 * information such as an ACL_MASK (if any), number of users,
421 * number of groups, and whether the array needs to be sorted.
424 ln_aent_preprocess(aclent_t
*aclent
, int n
,
425 int *hasmask
, mode_t
*mask
,
426 int *numuser
, int *numgroup
, int *needsort
)
438 for (i
= 0; i
< n
; i
++) {
439 if (aclent
[i
].a_type
< curtype
)
441 else if (aclent
[i
].a_type
> curtype
)
442 curtype
= aclent
[i
].a_type
;
443 if (aclent
[i
].a_type
& USER
)
445 if (aclent
[i
].a_type
& (GROUP
| GROUP_OBJ
))
447 if (aclent
[i
].a_type
& CLASS_OBJ
) {
453 *mask
= aclent
[i
].a_perm
;
458 if ((! *hasmask
) && (*numuser
+ *numgroup
> 1)) {
468 * Convert an array of aclent_t into an array of nfsace entries,
469 * following POSIX draft -> nfsv4 conversion semantics as outlined in
473 ln_aent_to_ace(aclent_t
*aclent
, int n
, ace_t
**acepp
, int *rescount
, int isdir
)
477 int numuser
, numgroup
, needsort
;
479 int i
, groupi
= 0, skip
;
480 ace_t
*acep
, *result
= NULL
;
483 error
= ln_aent_preprocess(aclent
, n
, &hasmask
, &mask
,
484 &numuser
, &numgroup
, &needsort
);
488 /* allow + deny for each aclent */
492 * stick extra deny on the group_obj and on each
493 * user|group for the mask (the group_obj was added
494 * into the count for numgroup)
496 resultsize
+= numuser
+ numgroup
;
497 /* ... and don't count the mask itself */
501 /* sort the source if necessary */
503 ksort((caddr_t
)aclent
, n
, sizeof (aclent_t
), cmp2acls
);
505 if (cacl_malloc((void **)&result
, resultsize
* sizeof (ace_t
)) != 0)
510 for (i
= 0; i
< n
; i
++) {
512 * don't process CLASS_OBJ (mask); mask was grabbed in
513 * ln_aent_preprocess()
515 if (aclent
[i
].a_type
& CLASS_OBJ
)
518 /* If we need an ACL_MASK emulator, prepend it now */
520 (aclent
[i
].a_type
& (USER
| GROUP
| GROUP_OBJ
))) {
521 acep
->a_type
= ACE_ACCESS_DENIED_ACE_TYPE
;
523 if (aclent
[i
].a_type
& GROUP_OBJ
) {
524 acep
->a_who
= (uid_t
)-1;
526 (ACE_IDENTIFIER_GROUP
|ACE_GROUP
);
527 } else if (aclent
[i
].a_type
& USER
) {
528 acep
->a_who
= aclent
[i
].a_id
;
530 acep
->a_who
= aclent
[i
].a_id
;
531 acep
->a_flags
|= ACE_IDENTIFIER_GROUP
;
533 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
534 acep
->a_flags
|= ACE_INHERIT_ONLY_ACE
|
535 ACE_FILE_INHERIT_ACE
|
536 ACE_DIRECTORY_INHERIT_ACE
;
539 * Set the access mask for the prepended deny
540 * ace. To do this, we invert the mask (found
541 * in ln_aent_preprocess()) then convert it to an
542 * DENY ace access_mask.
544 acep
->a_access_mask
= mode_to_ace_access((mask
^ 07),
549 /* handle a_perm -> access_mask */
550 acep
->a_access_mask
= mode_to_ace_access(aclent
[i
].a_perm
,
551 isdir
, aclent
[i
].a_type
& USER_OBJ
, 1);
553 /* emulate a default aclent */
554 if (aclent
[i
].a_type
& ACL_DEFAULT
) {
555 acep
->a_flags
|= ACE_INHERIT_ONLY_ACE
|
556 ACE_FILE_INHERIT_ACE
|
557 ACE_DIRECTORY_INHERIT_ACE
;
561 * handle a_perm and a_id
563 * this must be done last, since it involves the
564 * corresponding deny aces, which are handled
565 * differently for each different a_type.
567 if (aclent
[i
].a_type
& USER_OBJ
) {
568 acep
->a_who
= (uid_t
)-1;
569 acep
->a_flags
|= ACE_OWNER
;
570 ace_make_deny(acep
, acep
+ 1, isdir
, B_TRUE
);
572 } else if (aclent
[i
].a_type
& USER
) {
573 acep
->a_who
= aclent
[i
].a_id
;
574 ace_make_deny(acep
, acep
+ 1, isdir
, B_FALSE
);
576 } else if (aclent
[i
].a_type
& (GROUP_OBJ
| GROUP
)) {
577 if (aclent
[i
].a_type
& GROUP_OBJ
) {
578 acep
->a_who
= (uid_t
)-1;
579 acep
->a_flags
|= ACE_GROUP
;
581 acep
->a_who
= aclent
[i
].a_id
;
583 acep
->a_flags
|= ACE_IDENTIFIER_GROUP
;
585 * Set the corresponding deny for the group ace.
587 * The deny aces go after all of the groups, unlike
588 * everything else, where they immediately follow
591 * We calculate "skip", the number of slots to
592 * skip ahead for the deny ace, here.
595 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3
597 * (2 * numgroup) - 1 - groupi
598 * (2 * numgroup) to account for MD + A
599 * - 1 to account for the fact that we're on the
600 * access (A), not the mask (MD)
601 * - groupi to account for the fact that we have
602 * passed up groupi number of MD's.
604 skip
= (2 * numgroup
) - 1 - groupi
;
605 ace_make_deny(acep
, acep
+ skip
, isdir
, B_FALSE
);
607 * If we just did the last group, skip acep past
608 * all of the denies; else, just move ahead one.
610 if (++groupi
>= numgroup
)
611 acep
+= numgroup
+ 1;
614 } else if (aclent
[i
].a_type
& OTHER_OBJ
) {
615 acep
->a_who
= (uid_t
)-1;
616 acep
->a_flags
|= ACE_EVERYONE
;
617 ace_make_deny(acep
, acep
+ 1, isdir
, B_FALSE
);
626 *rescount
= resultsize
;
630 if ((result
!= NULL
) && (resultsize
> 0)) {
631 cacl_free(result
, resultsize
* sizeof (ace_t
));
639 convert_aent_to_ace(aclent_t
*aclentp
, int aclcnt
, boolean_t isdir
,
640 ace_t
**retacep
, int *retacecnt
)
653 ksort((caddr_t
)aclentp
, aclcnt
, sizeof (aclent_t
), cmp2acls
);
655 for (i
= 0, aclp
= aclentp
; i
< aclcnt
; aclp
++, i
++) {
656 if (aclp
->a_type
& ACL_DEFAULT
)
662 dfaclcnt
= aclcnt
- i
;
665 if (dfaclcnt
&& !isdir
) {
669 error
= ln_aent_to_ace(aclentp
, i
, &acep
, &acecnt
, isdir
);
674 error
= ln_aent_to_ace(&aclentp
[dfaclstart
], dfaclcnt
,
675 &dfacep
, &dfacecnt
, isdir
);
678 cacl_free(acep
, acecnt
* sizeof (ace_t
));
685 acesz
= sizeof (ace_t
) * acecnt
;
686 dfacesz
= sizeof (ace_t
) * dfacecnt
;
687 acep
= cacl_realloc(acep
, acesz
, acesz
+ dfacesz
);
691 (void) memcpy(acep
+ acecnt
, dfacep
, dfacesz
);
695 cacl_free(dfacep
, dfacecnt
* sizeof (ace_t
));
697 *retacecnt
= acecnt
+ dfacecnt
;
703 ace_mask_to_mode(uint32_t mask
, o_mode_t
*modep
, boolean_t isdir
)
707 uint32_t bits
, wantbits
;
710 if (mask
& ACE_READ_DATA
)
714 wantbits
= (ACE_WRITE_DATA
| ACE_APPEND_DATA
);
716 wantbits
|= ACE_DELETE_CHILD
;
717 bits
= mask
& wantbits
;
719 if (bits
!= wantbits
) {
727 if (mask
& ACE_EXECUTE
) {
738 acevals_init(acevals_t
*vals
, uid_t key
)
740 memset(vals
, 0, sizeof (*vals
));
741 vals
->allowed
= ACE_MASK_UNDEFINED
;
742 vals
->denied
= ACE_MASK_UNDEFINED
;
743 vals
->mask
= ACE_MASK_UNDEFINED
;
748 ace_list_init(ace_list_t
*al
, int dfacl_flag
)
750 acevals_init(&al
->user_obj
, 0);
751 acevals_init(&al
->group_obj
, 0);
752 acevals_init(&al
->other_obj
, 0);
757 al
->state
= ace_unused
;
759 al
->dfacl_flag
= dfacl_flag
;
763 * Find or create an acevals holder for a given id and avl tree.
765 * Note that only one thread will ever touch these avl trees, so
766 * there is no need for locking.
769 acevals_find(ace_t
*ace
, avl_tree_t
*avl
, int *num
)
774 key
.key
= ace
->a_who
;
775 rc
= avl_find(avl
, &key
, &where
);
779 /* this memory is freed by ln_ace_to_aent()->ace_list_free() */
780 if (cacl_malloc((void **)&rc
, sizeof (acevals_t
)) != 0)
783 acevals_init(rc
, ace
->a_who
);
784 avl_insert(avl
, rc
, where
);
791 access_mask_check(ace_t
*acep
, int mask_bit
, int isowner
)
793 int set_deny
, err_deny
;
794 int set_allow
, err_allow
;
796 int haswriteperm
, hasreadperm
;
798 if (acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) {
799 haswriteperm
= (acep
->a_access_mask
& ACE_WRITE_DATA
) ? 0 : 1;
800 hasreadperm
= (acep
->a_access_mask
& ACE_READ_DATA
) ? 0 : 1;
802 haswriteperm
= (acep
->a_access_mask
& ACE_WRITE_DATA
) ? 1 : 0;
803 hasreadperm
= (acep
->a_access_mask
& ACE_READ_DATA
) ? 1 : 0;
806 acl_consume
= (ACL_SYNCHRONIZE_ERR_DENY
|
807 ACL_DELETE_ERR_DENY
|
808 ACL_WRITE_OWNER_ERR_DENY
|
809 ACL_WRITE_OWNER_ERR_ALLOW
|
810 ACL_WRITE_ATTRS_OWNER_SET_ALLOW
|
811 ACL_WRITE_ATTRS_OWNER_ERR_DENY
|
812 ACL_WRITE_ATTRS_WRITER_SET_DENY
|
813 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
|
814 ACL_WRITE_NAMED_WRITER_ERR_DENY
|
815 ACL_READ_NAMED_READER_ERR_DENY
);
817 if (mask_bit
== ACE_SYNCHRONIZE
) {
818 set_deny
= ACL_SYNCHRONIZE_SET_DENY
;
819 err_deny
= ACL_SYNCHRONIZE_ERR_DENY
;
820 set_allow
= ACL_SYNCHRONIZE_SET_ALLOW
;
821 err_allow
= ACL_SYNCHRONIZE_ERR_ALLOW
;
822 } else if (mask_bit
== ACE_WRITE_OWNER
) {
823 set_deny
= ACL_WRITE_OWNER_SET_DENY
;
824 err_deny
= ACL_WRITE_OWNER_ERR_DENY
;
825 set_allow
= ACL_WRITE_OWNER_SET_ALLOW
;
826 err_allow
= ACL_WRITE_OWNER_ERR_ALLOW
;
827 } else if (mask_bit
== ACE_DELETE
) {
828 set_deny
= ACL_DELETE_SET_DENY
;
829 err_deny
= ACL_DELETE_ERR_DENY
;
830 set_allow
= ACL_DELETE_SET_ALLOW
;
831 err_allow
= ACL_DELETE_ERR_ALLOW
;
832 } else if (mask_bit
== ACE_WRITE_ATTRIBUTES
) {
834 set_deny
= ACL_WRITE_ATTRS_OWNER_SET_DENY
;
835 err_deny
= ACL_WRITE_ATTRS_OWNER_ERR_DENY
;
836 set_allow
= ACL_WRITE_ATTRS_OWNER_SET_ALLOW
;
837 err_allow
= ACL_WRITE_ATTRS_OWNER_ERR_ALLOW
;
838 } else if (haswriteperm
) {
839 set_deny
= ACL_WRITE_ATTRS_WRITER_SET_DENY
;
840 err_deny
= ACL_WRITE_ATTRS_WRITER_ERR_DENY
;
841 set_allow
= ACL_WRITE_ATTRS_WRITER_SET_ALLOW
;
842 err_allow
= ACL_WRITE_ATTRS_WRITER_ERR_ALLOW
;
844 if ((acep
->a_access_mask
& mask_bit
) &&
845 (acep
->a_type
& ACE_ACCESS_ALLOWED_ACE_TYPE
)) {
850 } else if (mask_bit
== ACE_READ_NAMED_ATTRS
) {
854 set_deny
= ACL_READ_NAMED_READER_SET_DENY
;
855 err_deny
= ACL_READ_NAMED_READER_ERR_DENY
;
856 set_allow
= ACL_READ_NAMED_READER_SET_ALLOW
;
857 err_allow
= ACL_READ_NAMED_READER_ERR_ALLOW
;
858 } else if (mask_bit
== ACE_WRITE_NAMED_ATTRS
) {
862 set_deny
= ACL_WRITE_NAMED_WRITER_SET_DENY
;
863 err_deny
= ACL_WRITE_NAMED_WRITER_ERR_DENY
;
864 set_allow
= ACL_WRITE_NAMED_WRITER_SET_ALLOW
;
865 err_allow
= ACL_WRITE_NAMED_WRITER_ERR_ALLOW
;
870 if (acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) {
871 if (acl_consume
& set_deny
) {
872 if (!(acep
->a_access_mask
& mask_bit
)) {
875 } else if (acl_consume
& err_deny
) {
876 if (acep
->a_access_mask
& mask_bit
) {
881 /* ACE_ACCESS_ALLOWED_ACE_TYPE */
882 if (acl_consume
& set_allow
) {
883 if (!(acep
->a_access_mask
& mask_bit
)) {
886 } else if (acl_consume
& err_allow
) {
887 if (acep
->a_access_mask
& mask_bit
) {
896 ace_to_aent_legal(ace_t
*acep
)
901 /* only ALLOW or DENY */
902 if ((acep
->a_type
!= ACE_ACCESS_ALLOWED_ACE_TYPE
) &&
903 (acep
->a_type
!= ACE_ACCESS_DENIED_ACE_TYPE
)) {
908 /* check for invalid flags */
909 if (acep
->a_flags
& ~(ACE_VALID_FLAG_BITS
)) {
914 /* some flags are illegal */
915 if (acep
->a_flags
& (ACE_SUCCESSFUL_ACCESS_ACE_FLAG
|
916 ACE_FAILED_ACCESS_ACE_FLAG
|
917 ACE_NO_PROPAGATE_INHERIT_ACE
)) {
922 /* check for invalid masks */
923 if (acep
->a_access_mask
& ~(ACE_VALID_MASK_BITS
)) {
928 if ((acep
->a_flags
& ACE_OWNER
)) {
934 error
= access_mask_check(acep
, ACE_SYNCHRONIZE
, isowner
);
938 error
= access_mask_check(acep
, ACE_WRITE_OWNER
, isowner
);
942 error
= access_mask_check(acep
, ACE_DELETE
, isowner
);
946 error
= access_mask_check(acep
, ACE_WRITE_ATTRIBUTES
, isowner
);
950 error
= access_mask_check(acep
, ACE_READ_NAMED_ATTRS
, isowner
);
954 error
= access_mask_check(acep
, ACE_WRITE_NAMED_ATTRS
, isowner
);
958 /* more detailed checking of masks */
959 if (acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) {
960 if (! (acep
->a_access_mask
& ACE_READ_ATTRIBUTES
)) {
964 if ((acep
->a_access_mask
& ACE_WRITE_DATA
) &&
965 (! (acep
->a_access_mask
& ACE_APPEND_DATA
))) {
969 if ((! (acep
->a_access_mask
& ACE_WRITE_DATA
)) &&
970 (acep
->a_access_mask
& ACE_APPEND_DATA
)) {
976 /* ACL enforcement */
977 if ((acep
->a_access_mask
& ACE_READ_ACL
) &&
978 (acep
->a_type
!= ACE_ACCESS_ALLOWED_ACE_TYPE
)) {
982 if (acep
->a_access_mask
& ACE_WRITE_ACL
) {
983 if ((acep
->a_type
== ACE_ACCESS_DENIED_ACE_TYPE
) &&
988 if ((acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) &&
1000 ace_allow_to_mode(uint32_t mask
, o_mode_t
*modep
, boolean_t isdir
)
1002 /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */
1003 if ((mask
& (ACE_READ_ACL
| ACE_READ_ATTRIBUTES
)) !=
1004 (ACE_READ_ACL
| ACE_READ_ATTRIBUTES
)) {
1008 return (ace_mask_to_mode(mask
, modep
, isdir
));
1012 acevals_to_aent(acevals_t
*vals
, aclent_t
*dest
, ace_list_t
*list
,
1013 uid_t owner
, gid_t group
, boolean_t isdir
)
1016 uint32_t flips
= ACE_POSIX_SUPPORTED_BITS
;
1019 flips
|= ACE_DELETE_CHILD
;
1020 if (vals
->allowed
!= (vals
->denied
^ flips
)) {
1024 if ((list
->hasmask
) && (list
->acl_mask
!= vals
->mask
) &&
1025 (vals
->aent_type
& (USER
| GROUP
| GROUP_OBJ
))) {
1029 error
= ace_allow_to_mode(vals
->allowed
, &dest
->a_perm
, isdir
);
1032 dest
->a_type
= vals
->aent_type
;
1033 if (dest
->a_type
& (USER
| GROUP
)) {
1034 dest
->a_id
= vals
->key
;
1035 } else if (dest
->a_type
& USER_OBJ
) {
1037 } else if (dest
->a_type
& GROUP_OBJ
) {
1039 } else if (dest
->a_type
& OTHER_OBJ
) {
1052 ace_list_to_aent(ace_list_t
*list
, aclent_t
**aclentp
, int *aclcnt
,
1053 uid_t owner
, gid_t group
, boolean_t isdir
)
1056 aclent_t
*aent
, *result
= NULL
;
1060 if ((list
->seen
& (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) !=
1061 (USER_OBJ
| GROUP_OBJ
| OTHER_OBJ
)) {
1065 if ((! list
->hasmask
) && (list
->numusers
+ list
->numgroups
> 0)) {
1070 resultcount
= 3 + list
->numusers
+ list
->numgroups
;
1072 * This must be the same condition as below, when we add the CLASS_OBJ
1075 if ((list
->hasmask
) || (! list
->dfacl_flag
))
1078 if (cacl_malloc((void **)&result
,
1079 resultcount
* sizeof (aclent_t
)) != 0) {
1086 if (!(list
->user_obj
.aent_type
& USER_OBJ
)) {
1091 error
= acevals_to_aent(&list
->user_obj
, aent
, list
, owner
, group
,
1099 for (vals
= avl_first(&list
->user
); vals
!= NULL
;
1100 vals
= AVL_NEXT(&list
->user
, vals
)) {
1101 if (!(vals
->aent_type
& USER
)) {
1105 error
= acevals_to_aent(vals
, aent
, list
, owner
, group
,
1112 if (!(list
->group_obj
.aent_type
& GROUP_OBJ
)) {
1116 error
= acevals_to_aent(&list
->group_obj
, aent
, list
, owner
, group
,
1123 for (vals
= avl_first(&list
->group
); vals
!= NULL
;
1124 vals
= AVL_NEXT(&list
->group
, vals
)) {
1125 if (!(vals
->aent_type
& GROUP
)) {
1129 error
= acevals_to_aent(vals
, aent
, list
, owner
, group
,
1136 * CLASS_OBJ (aka ACL_MASK)
1138 * An ACL_MASK is not fabricated if the ACL is a default ACL.
1139 * This is to follow UFS's behavior.
1141 if ((list
->hasmask
) || (! list
->dfacl_flag
)) {
1142 if (list
->hasmask
) {
1143 uint32_t flips
= ACE_POSIX_SUPPORTED_BITS
;
1145 flips
|= ACE_DELETE_CHILD
;
1146 error
= ace_mask_to_mode(list
->acl_mask
^ flips
,
1147 &aent
->a_perm
, isdir
);
1151 /* fabricate the ACL_MASK from the group permissions */
1152 error
= ace_mask_to_mode(list
->group_obj
.allowed
,
1153 &aent
->a_perm
, isdir
);
1158 aent
->a_type
= CLASS_OBJ
| list
->dfacl_flag
;
1162 if (!(list
->other_obj
.aent_type
& OTHER_OBJ
)) {
1166 error
= acevals_to_aent(&list
->other_obj
, aent
, list
, owner
, group
,
1173 *aclcnt
= resultcount
;
1178 cacl_free(result
, resultcount
* sizeof (aclent_t
));
1186 * free all data associated with an ace_list
1189 ace_list_free(ace_list_t
*al
)
1198 while ((node
= avl_destroy_nodes(&al
->user
, &cookie
)) != NULL
)
1199 cacl_free(node
, sizeof (acevals_t
));
1201 while ((node
= avl_destroy_nodes(&al
->group
, &cookie
)) != NULL
)
1202 cacl_free(node
, sizeof (acevals_t
));
1204 avl_destroy(&al
->user
);
1205 avl_destroy(&al
->group
);
1207 /* free the container itself */
1208 cacl_free(al
, sizeof (ace_list_t
));
1212 acevals_compare(const void *va
, const void *vb
)
1214 const acevals_t
*a
= va
, *b
= vb
;
1216 if (a
->key
== b
->key
)
1219 if (a
->key
> b
->key
)
1227 * Convert a list of ace_t entries to equivalent regular and default
1228 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible.
1231 ln_ace_to_aent(ace_t
*ace
, int n
, uid_t owner
, gid_t group
,
1232 aclent_t
**aclentp
, int *aclcnt
, aclent_t
**dfaclentp
, int *dfaclcnt
,
1239 ace_list_t
*normacl
= NULL
, *dfacl
= NULL
, *acl
;
1247 /* we need at least user_obj, group_obj, and other_obj */
1257 error
= cacl_malloc((void **)&normacl
, sizeof (ace_list_t
));
1261 avl_create(&normacl
->user
, acevals_compare
, sizeof (acevals_t
),
1262 offsetof(acevals_t
, avl
));
1263 avl_create(&normacl
->group
, acevals_compare
, sizeof (acevals_t
),
1264 offsetof(acevals_t
, avl
));
1266 ace_list_init(normacl
, 0);
1268 error
= cacl_malloc((void **)&dfacl
, sizeof (ace_list_t
));
1272 avl_create(&dfacl
->user
, acevals_compare
, sizeof (acevals_t
),
1273 offsetof(acevals_t
, avl
));
1274 avl_create(&dfacl
->group
, acevals_compare
, sizeof (acevals_t
),
1275 offsetof(acevals_t
, avl
));
1276 ace_list_init(dfacl
, ACL_DEFAULT
);
1278 /* process every ace_t... */
1279 for (i
= 0; i
< n
; i
++) {
1282 /* rule out certain cases quickly */
1283 error
= ace_to_aent_legal(acep
);
1288 * Turn off these bits in order to not have to worry about
1289 * them when doing the checks for compliments.
1291 acep
->a_access_mask
&= ~(ACE_WRITE_OWNER
| ACE_DELETE
|
1292 ACE_SYNCHRONIZE
| ACE_WRITE_ATTRIBUTES
|
1293 ACE_READ_NAMED_ATTRS
| ACE_WRITE_NAMED_ATTRS
);
1295 /* see if this should be a regular or default acl */
1296 bits
= acep
->a_flags
&
1297 (ACE_INHERIT_ONLY_ACE
|
1298 ACE_FILE_INHERIT_ACE
|
1299 ACE_DIRECTORY_INHERIT_ACE
);
1301 /* all or nothing on these inherit bits */
1302 if (bits
!= (ACE_INHERIT_ONLY_ACE
|
1303 ACE_FILE_INHERIT_ACE
|
1304 ACE_DIRECTORY_INHERIT_ACE
)) {
1313 if ((acep
->a_flags
& ACE_OWNER
)) {
1314 if (acl
->state
> ace_user_obj
) {
1318 acl
->state
= ace_user_obj
;
1319 acl
->seen
|= USER_OBJ
;
1320 vals
= &acl
->user_obj
;
1321 vals
->aent_type
= USER_OBJ
| acl
->dfacl_flag
;
1322 } else if ((acep
->a_flags
& ACE_EVERYONE
)) {
1323 acl
->state
= ace_other_obj
;
1324 acl
->seen
|= OTHER_OBJ
;
1325 vals
= &acl
->other_obj
;
1326 vals
->aent_type
= OTHER_OBJ
| acl
->dfacl_flag
;
1327 } else if (acep
->a_flags
& ACE_IDENTIFIER_GROUP
) {
1328 if (acl
->state
> ace_group
) {
1332 if ((acep
->a_flags
& ACE_GROUP
)) {
1333 acl
->seen
|= GROUP_OBJ
;
1334 vals
= &acl
->group_obj
;
1335 vals
->aent_type
= GROUP_OBJ
| acl
->dfacl_flag
;
1338 vals
= acevals_find(acep
, &acl
->group
,
1344 vals
->aent_type
= GROUP
| acl
->dfacl_flag
;
1346 acl
->state
= ace_group
;
1348 if (acl
->state
> ace_user
) {
1352 acl
->state
= ace_user
;
1354 vals
= acevals_find(acep
, &acl
->user
,
1360 vals
->aent_type
= USER
| acl
->dfacl_flag
;
1363 if (!(acl
->state
> ace_unused
)) {
1368 if (acep
->a_type
== ACE_ACCESS_ALLOWED_ACE_TYPE
) {
1369 /* no more than one allowed per aclent_t */
1370 if (vals
->allowed
!= ACE_MASK_UNDEFINED
) {
1374 vals
->allowed
= acep
->a_access_mask
;
1377 * it's a DENY; if there was a previous DENY, it
1378 * must have been an ACL_MASK.
1380 if (vals
->denied
!= ACE_MASK_UNDEFINED
) {
1381 /* ACL_MASK is for USER and GROUP only */
1382 if ((acl
->state
!= ace_user
) &&
1383 (acl
->state
!= ace_group
)) {
1388 if (! acl
->hasmask
) {
1390 acl
->acl_mask
= vals
->denied
;
1391 /* check for mismatched ACL_MASK emulations */
1392 } else if (acl
->acl_mask
!= vals
->denied
) {
1396 vals
->mask
= vals
->denied
;
1398 vals
->denied
= acep
->a_access_mask
;
1402 /* done collating; produce the aclent_t lists */
1403 if (normacl
->state
!= ace_unused
) {
1404 error
= ace_list_to_aent(normacl
, aclentp
, aclcnt
,
1405 owner
, group
, isdir
);
1410 if (dfacl
->state
!= ace_unused
) {
1411 error
= ace_list_to_aent(dfacl
, dfaclentp
, dfaclcnt
,
1412 owner
, group
, isdir
);
1419 if (normacl
!= NULL
)
1420 ace_list_free(normacl
);
1422 ace_list_free(dfacl
);
1428 convert_ace_to_aent(ace_t
*acebufp
, int acecnt
, boolean_t isdir
,
1429 uid_t owner
, gid_t group
, aclent_t
**retaclentp
, int *retaclcnt
)
1432 aclent_t
*aclentp
, *dfaclentp
;
1433 int aclcnt
, dfaclcnt
;
1436 error
= ln_ace_to_aent(acebufp
, acecnt
, owner
, group
,
1437 &aclentp
, &aclcnt
, &dfaclentp
, &dfaclcnt
, isdir
);
1443 if (dfaclcnt
!= 0) {
1445 * Slap aclentp and dfaclentp into a single array.
1447 aclsz
= sizeof (aclent_t
) * aclcnt
;
1448 dfaclsz
= sizeof (aclent_t
) * dfaclcnt
;
1449 aclentp
= cacl_realloc(aclentp
, aclsz
, aclsz
+ dfaclsz
);
1450 if (aclentp
!= NULL
) {
1451 (void) memcpy(aclentp
+ aclcnt
, dfaclentp
, dfaclsz
);
1458 *retaclentp
= aclentp
;
1459 *retaclcnt
= aclcnt
+ dfaclcnt
;
1463 cacl_free(dfaclentp
, dfaclsz
);
1470 acl_translate(acl_t
*aclp
, int target_flavor
, boolean_t isdir
, uid_t owner
,
1478 * See if we need to translate
1480 if ((target_flavor
== _ACL_ACE_ENABLED
&& aclp
->acl_type
== ACE_T
) ||
1481 (target_flavor
== _ACL_ACLENT_ENABLED
&&
1482 aclp
->acl_type
== ACLENT_T
))
1485 if (target_flavor
== -1) {
1490 if (target_flavor
== _ACL_ACE_ENABLED
&&
1491 aclp
->acl_type
== ACLENT_T
) {
1492 error
= convert_aent_to_ace(aclp
->acl_aclp
,
1493 aclp
->acl_cnt
, isdir
, (ace_t
**)&acldata
, &aclcnt
);
1497 } else if (target_flavor
== _ACL_ACLENT_ENABLED
&&
1498 aclp
->acl_type
== ACE_T
) {
1499 error
= convert_ace_to_aent(aclp
->acl_aclp
, aclp
->acl_cnt
,
1500 isdir
, owner
, group
, (aclent_t
**)&acldata
, &aclcnt
);
1509 * replace old acl with newly translated acl
1511 cacl_free(aclp
->acl_aclp
, aclp
->acl_cnt
* aclp
->acl_entry_size
);
1512 aclp
->acl_aclp
= acldata
;
1513 aclp
->acl_cnt
= aclcnt
;
1514 if (target_flavor
== _ACL_ACE_ENABLED
) {
1515 aclp
->acl_type
= ACE_T
;
1516 aclp
->acl_entry_size
= sizeof (ace_t
);
1518 aclp
->acl_type
= ACLENT_T
;
1519 aclp
->acl_entry_size
= sizeof (aclent_t
);
1525 #if !defined(_KERNEL)
1532 #endif /* !_KERNEL */
1534 #define SET_ACE(acl, index, who, mask, type, flags) { \
1535 acl[0][index].a_who = (uint32_t)who; \
1536 acl[0][index].a_type = type; \
1537 acl[0][index].a_flags = flags; \
1538 acl[0][index++].a_access_mask = mask; \
1542 acl_trivial_access_masks(mode_t mode
, boolean_t isdir
, trivial_acl_t
*masks
)
1544 uint32_t read_mask
= ACE_READ_DATA
;
1545 uint32_t write_mask
= ACE_WRITE_DATA
|ACE_APPEND_DATA
;
1546 uint32_t execute_mask
= ACE_EXECUTE
;
1548 (void) isdir
; /* will need this later */
1551 if (!(mode
& S_IRUSR
) && (mode
& (S_IRGRP
|S_IROTH
)))
1552 masks
->deny1
|= read_mask
;
1553 if (!(mode
& S_IWUSR
) && (mode
& (S_IWGRP
|S_IWOTH
)))
1554 masks
->deny1
|= write_mask
;
1555 if (!(mode
& S_IXUSR
) && (mode
& (S_IXGRP
|S_IXOTH
)))
1556 masks
->deny1
|= execute_mask
;
1559 if (!(mode
& S_IRGRP
) && (mode
& S_IROTH
))
1560 masks
->deny2
|= read_mask
;
1561 if (!(mode
& S_IWGRP
) && (mode
& S_IWOTH
))
1562 masks
->deny2
|= write_mask
;
1563 if (!(mode
& S_IXGRP
) && (mode
& S_IXOTH
))
1564 masks
->deny2
|= execute_mask
;
1567 if ((mode
& S_IRUSR
) && (!(mode
& S_IRGRP
) && (mode
& S_IROTH
)))
1568 masks
->allow0
|= read_mask
;
1569 if ((mode
& S_IWUSR
) && (!(mode
& S_IWGRP
) && (mode
& S_IWOTH
)))
1570 masks
->allow0
|= write_mask
;
1571 if ((mode
& S_IXUSR
) && (!(mode
& S_IXGRP
) && (mode
& S_IXOTH
)))
1572 masks
->allow0
|= execute_mask
;
1574 masks
->owner
= ACE_WRITE_ATTRIBUTES
|ACE_WRITE_OWNER
|ACE_WRITE_ACL
|
1575 ACE_WRITE_NAMED_ATTRS
|ACE_READ_ACL
|ACE_READ_ATTRIBUTES
|
1576 ACE_READ_NAMED_ATTRS
|ACE_SYNCHRONIZE
;
1578 masks
->owner
|= read_mask
;
1580 masks
->owner
|= write_mask
;
1582 masks
->owner
|= execute_mask
;
1584 masks
->group
= ACE_READ_ACL
|ACE_READ_ATTRIBUTES
|ACE_READ_NAMED_ATTRS
|
1587 masks
->group
|= read_mask
;
1589 masks
->group
|= write_mask
;
1591 masks
->group
|= execute_mask
;
1593 masks
->everyone
= ACE_READ_ACL
|ACE_READ_ATTRIBUTES
|ACE_READ_NAMED_ATTRS
|
1596 masks
->everyone
|= read_mask
;
1598 masks
->everyone
|= write_mask
;
1600 masks
->everyone
|= execute_mask
;
1604 acl_trivial_create(mode_t mode
, boolean_t isdir
, ace_t
**acl
, int *count
)
1608 trivial_acl_t masks
;
1611 acl_trivial_access_masks(mode
, isdir
, &masks
);
1620 if ((error
= cacl_malloc((void **)acl
, *count
* sizeof (ace_t
))) != 0)
1624 SET_ACE(acl
, index
, -1, masks
.allow0
,
1625 ACE_ACCESS_ALLOWED_ACE_TYPE
, ACE_OWNER
);
1628 SET_ACE(acl
, index
, -1, masks
.deny1
,
1629 ACE_ACCESS_DENIED_ACE_TYPE
, ACE_OWNER
);
1632 SET_ACE(acl
, index
, -1, masks
.deny2
,
1633 ACE_ACCESS_DENIED_ACE_TYPE
, ACE_GROUP
|ACE_IDENTIFIER_GROUP
);
1636 SET_ACE(acl
, index
, -1, masks
.owner
, ACE_ACCESS_ALLOWED_ACE_TYPE
,
1638 SET_ACE(acl
, index
, -1, masks
.group
, ACE_ACCESS_ALLOWED_ACE_TYPE
,
1639 ACE_IDENTIFIER_GROUP
|ACE_GROUP
);
1640 SET_ACE(acl
, index
, -1, masks
.everyone
, ACE_ACCESS_ALLOWED_ACE_TYPE
,
1648 * determine whether an ace_t acl is trivial
1650 * Trivialness implies that the acl is composed of only
1651 * owner, group, everyone entries. ACL can't
1652 * have read_acl denied, and write_owner/write_acl/write_attributes
1653 * can only be owner@ entry.
1656 ace_trivial_common(void *acep
, int aclcnt
,
1657 uintptr_t (*walk
)(void *, uintptr_t, int aclcnt
,
1658 uint16_t *, uint16_t *, uint32_t *))
1663 uintptr_t cookie
= 0;
1665 while ((cookie
= walk(acep
, cookie
, aclcnt
, &flags
, &type
, &mask
))) {
1666 switch (flags
& ACE_TYPE_FLAGS
) {
1668 case ACE_GROUP
|ACE_IDENTIFIER_GROUP
:
1676 if (flags
& (ACE_FILE_INHERIT_ACE
|
1677 ACE_DIRECTORY_INHERIT_ACE
|ACE_NO_PROPAGATE_INHERIT_ACE
|
1678 ACE_INHERIT_ONLY_ACE
))
1682 * Special check for some special bits
1684 * Don't allow anybody to deny reading basic
1685 * attributes or a files ACL.
1687 if ((mask
& (ACE_READ_ACL
|ACE_READ_ATTRIBUTES
)) &&
1688 (type
== ACE_ACCESS_DENIED_ACE_TYPE
))
1692 * Delete permissions are never set by default
1694 if (mask
& (ACE_DELETE
|ACE_DELETE_CHILD
))
1697 * only allow owner@ to have
1698 * write_acl/write_owner/write_attributes/write_xattr/
1700 if (type
== ACE_ACCESS_ALLOWED_ACE_TYPE
&&
1701 (!(flags
& ACE_OWNER
) && (mask
&
1702 (ACE_WRITE_OWNER
|ACE_WRITE_ACL
| ACE_WRITE_ATTRIBUTES
|
1703 ACE_WRITE_NAMED_ATTRS
))))