4 * Common NFSv4 ACL handling code.
6 * Copyright (c) 2002, 2003 The Regents of the University of Michigan.
9 * Marius Aamodt Eriksen <marius@umich.edu>
10 * Jeff Sedlak <jsedlak@umich.edu>
11 * J. Bruce Fields <bfields@umich.edu>
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
33 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <linux/string.h>
40 #include <linux/slab.h>
41 #include <linux/list.h>
42 #include <linux/types.h>
44 #include <linux/module.h>
45 #include <linux/nfs_fs.h>
46 #include <linux/posix_acl.h>
47 #include <linux/nfs4.h>
48 #include <linux/nfs4_acl.h>
51 /* mode bit translations: */
52 #define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
53 #define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
54 #define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
55 #define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
56 #define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
58 /* We don't support these bits; insist they be neither allowed nor denied */
59 #define NFS4_MASK_UNSUPP (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
60 | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
62 /* flags used to simulate posix default ACLs */
63 #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
64 | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
66 #define MASK_EQUAL(mask1, mask2) \
67 ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
70 mask_from_posix(unsigned short perm
, unsigned int flags
)
72 int mask
= NFS4_ANYONE_MODE
;
74 if (flags
& NFS4_ACL_OWNER
)
75 mask
|= NFS4_OWNER_MODE
;
77 mask
|= NFS4_READ_MODE
;
79 mask
|= NFS4_WRITE_MODE
;
80 if ((perm
& ACL_WRITE
) && (flags
& NFS4_ACL_DIR
))
81 mask
|= NFS4_ACE_DELETE_CHILD
;
82 if (perm
& ACL_EXECUTE
)
83 mask
|= NFS4_EXECUTE_MODE
;
88 deny_mask(u32 allow_mask
, unsigned int flags
)
90 u32 ret
= ~allow_mask
& ~NFS4_MASK_UNSUPP
;
91 if (!(flags
& NFS4_ACL_DIR
))
92 ret
&= ~NFS4_ACE_DELETE_CHILD
;
96 /* XXX: modify functions to return NFS errors; they're only ever
97 * used by nfs code, after all.... */
100 mode_from_nfs4(u32 perm
, unsigned short *mode
, unsigned int flags
)
104 if (!(flags
& NFS4_ACL_DIR
))
105 ignore
|= NFS4_ACE_DELETE_CHILD
; /* ignore it */
108 if ((perm
& NFS4_READ_MODE
) == NFS4_READ_MODE
)
110 if ((perm
& NFS4_WRITE_MODE
) == NFS4_WRITE_MODE
)
112 if ((perm
& NFS4_EXECUTE_MODE
) == NFS4_EXECUTE_MODE
)
113 *mode
|= ACL_EXECUTE
;
114 if (!MASK_EQUAL(perm
, ignore
|mask_from_posix(*mode
, flags
)))
119 struct ace_container
{
120 struct nfs4_ace
*ace
;
121 struct list_head ace_l
;
124 static short ace2type(struct nfs4_ace
*);
125 static int _posix_to_nfsv4_one(struct posix_acl
*, struct nfs4_acl
*, unsigned int);
126 static struct posix_acl
*_nfsv4_to_posix_one(struct nfs4_acl
*, unsigned int);
127 int nfs4_acl_add_ace(struct nfs4_acl
*, u32
, u32
, u32
, int, uid_t
);
128 static int nfs4_acl_split(struct nfs4_acl
*, struct nfs4_acl
*);
131 nfs4_acl_posix_to_nfsv4(struct posix_acl
*pacl
, struct posix_acl
*dpacl
,
134 struct nfs4_acl
*acl
;
138 (posix_acl_valid(pacl
) < 0 || pacl
->a_count
== 0)) ||
140 (posix_acl_valid(dpacl
) < 0 || dpacl
->a_count
== 0)))
143 acl
= nfs4_acl_new();
150 error
= _posix_to_nfsv4_one(pacl
, acl
,
151 flags
& ~NFS4_ACL_TYPE_DEFAULT
);
157 error
= _posix_to_nfsv4_one(dpacl
, acl
,
158 flags
| NFS4_ACL_TYPE_DEFAULT
);
168 acl
= ERR_PTR(error
);
174 nfs4_acl_add_pair(struct nfs4_acl
*acl
, int eflag
, u32 mask
, int whotype
,
175 uid_t owner
, unsigned int flags
)
179 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
,
180 eflag
, mask
, whotype
, owner
);
183 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_DENIED_ACE_TYPE
,
184 eflag
, deny_mask(mask
, flags
), whotype
, owner
);
188 /* We assume the acl has been verified with posix_acl_valid. */
190 _posix_to_nfsv4_one(struct posix_acl
*pacl
, struct nfs4_acl
*acl
,
193 struct posix_acl_entry
*pa
, *pe
, *group_owner_entry
;
196 int eflag
= ((flags
& NFS4_ACL_TYPE_DEFAULT
) ?
197 NFS4_INHERITANCE_FLAGS
: 0);
199 BUG_ON(pacl
->a_count
< 3);
200 pe
= pacl
->a_entries
+ pacl
->a_count
;
201 pa
= pe
- 2; /* if mask entry exists, it's second from the last. */
202 if (pa
->e_tag
== ACL_MASK
)
203 mask_mask
= deny_mask(mask_from_posix(pa
->e_perm
, flags
), flags
);
207 pa
= pacl
->a_entries
;
208 BUG_ON(pa
->e_tag
!= ACL_USER_OBJ
);
209 mask
= mask_from_posix(pa
->e_perm
, flags
| NFS4_ACL_OWNER
);
210 error
= nfs4_acl_add_pair(acl
, eflag
, mask
, NFS4_ACL_WHO_OWNER
, 0, flags
);
215 while (pa
->e_tag
== ACL_USER
) {
216 mask
= mask_from_posix(pa
->e_perm
, flags
);
217 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_DENIED_ACE_TYPE
,
218 eflag
, mask_mask
, NFS4_ACL_WHO_NAMED
, pa
->e_id
);
223 error
= nfs4_acl_add_pair(acl
, eflag
, mask
,
224 NFS4_ACL_WHO_NAMED
, pa
->e_id
, flags
);
230 /* In the case of groups, we apply allow ACEs first, then deny ACEs,
231 * since a user can be in more than one group. */
235 if (pacl
->a_count
> 3) {
236 BUG_ON(pa
->e_tag
!= ACL_GROUP_OBJ
);
237 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_DENIED_ACE_TYPE
,
238 NFS4_ACE_IDENTIFIER_GROUP
| eflag
, mask_mask
,
239 NFS4_ACL_WHO_GROUP
, 0);
243 group_owner_entry
= pa
;
244 mask
= mask_from_posix(pa
->e_perm
, flags
);
245 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
,
246 NFS4_ACE_IDENTIFIER_GROUP
| eflag
, mask
,
247 NFS4_ACL_WHO_GROUP
, 0);
252 while (pa
->e_tag
== ACL_GROUP
) {
253 mask
= mask_from_posix(pa
->e_perm
, flags
);
254 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_DENIED_ACE_TYPE
,
255 NFS4_ACE_IDENTIFIER_GROUP
| eflag
, mask_mask
,
256 NFS4_ACL_WHO_NAMED
, pa
->e_id
);
260 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
,
261 NFS4_ACE_IDENTIFIER_GROUP
| eflag
, mask
,
262 NFS4_ACL_WHO_NAMED
, pa
->e_id
);
270 pa
= group_owner_entry
;
271 mask
= mask_from_posix(pa
->e_perm
, flags
);
272 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_DENIED_ACE_TYPE
,
273 NFS4_ACE_IDENTIFIER_GROUP
| eflag
,
274 deny_mask(mask
, flags
), NFS4_ACL_WHO_GROUP
, 0);
278 while (pa
->e_tag
== ACL_GROUP
) {
279 mask
= mask_from_posix(pa
->e_perm
, flags
);
280 error
= nfs4_acl_add_ace(acl
, NFS4_ACE_ACCESS_DENIED_ACE_TYPE
,
281 NFS4_ACE_IDENTIFIER_GROUP
| eflag
,
282 deny_mask(mask
, flags
), NFS4_ACL_WHO_NAMED
, pa
->e_id
);
288 if (pa
->e_tag
== ACL_MASK
)
290 BUG_ON(pa
->e_tag
!= ACL_OTHER
);
291 mask
= mask_from_posix(pa
->e_perm
, flags
);
292 error
= nfs4_acl_add_pair(acl
, eflag
, mask
, NFS4_ACL_WHO_EVERYONE
, 0, flags
);
299 sort_pacl_range(struct posix_acl
*pacl
, int start
, int end
) {
301 struct posix_acl_entry tmp
;
303 /* We just do a bubble sort; easy to do in place, and we're not
304 * expecting acl's to be long enough to justify anything more. */
307 for (i
= start
; i
< end
; i
++) {
308 if (pacl
->a_entries
[i
].e_id
309 > pacl
->a_entries
[i
+1].e_id
) {
311 tmp
= pacl
->a_entries
[i
];
312 pacl
->a_entries
[i
] = pacl
->a_entries
[i
+1];
313 pacl
->a_entries
[i
+1] = tmp
;
320 sort_pacl(struct posix_acl
*pacl
)
322 /* posix_acl_valid requires that users and groups be in order
326 if (pacl
->a_count
<= 4)
327 return; /* no users or groups */
329 while (pacl
->a_entries
[i
].e_tag
== ACL_USER
)
331 sort_pacl_range(pacl
, 1, i
-1);
333 BUG_ON(pacl
->a_entries
[i
].e_tag
!= ACL_GROUP_OBJ
);
335 while (pacl
->a_entries
[j
].e_tag
== ACL_GROUP
)
337 sort_pacl_range(pacl
, i
, j
-1);
342 write_pace(struct nfs4_ace
*ace
, struct posix_acl
*pacl
,
343 struct posix_acl_entry
**pace
, short tag
, unsigned int flags
)
345 struct posix_acl_entry
*this = *pace
;
347 if (*pace
== pacl
->a_entries
+ pacl
->a_count
)
348 return -EINVAL
; /* fell off the end */
351 if (tag
== ACL_USER_OBJ
)
352 flags
|= NFS4_ACL_OWNER
;
353 if (mode_from_nfs4(ace
->access_mask
, &this->e_perm
, flags
))
355 this->e_id
= (tag
== ACL_USER
|| tag
== ACL_GROUP
?
356 ace
->who
: ACL_UNDEFINED_ID
);
360 static struct nfs4_ace
*
361 get_next_v4_ace(struct list_head
**p
, struct list_head
*head
)
363 struct nfs4_ace
*ace
;
368 ace
= list_entry(*p
, struct nfs4_ace
, l_ace
);
374 nfs4_acl_nfsv4_to_posix(struct nfs4_acl
*acl
, struct posix_acl
**pacl
,
375 struct posix_acl
**dpacl
, unsigned int flags
)
377 struct nfs4_acl
*dacl
;
383 dacl
= nfs4_acl_new();
387 error
= nfs4_acl_split(acl
, dacl
);
392 if (acl
->naces
== 0) {
397 *pacl
= _nfsv4_to_posix_one(acl
, flags
);
399 error
= PTR_ERR(*pacl
);
407 if (dacl
->naces
== 0) {
408 if (pacl
== NULL
|| *pacl
== NULL
)
414 *dpacl
= _nfsv4_to_posix_one(dacl
, flags
);
415 if (IS_ERR(*dpacl
)) {
416 error
= PTR_ERR(*dpacl
);
424 posix_acl_release(*pacl
);
433 same_who(struct nfs4_ace
*a
, struct nfs4_ace
*b
)
435 return a
->whotype
== b
->whotype
&&
436 (a
->whotype
!= NFS4_ACL_WHO_NAMED
|| a
->who
== b
->who
);
440 complementary_ace_pair(struct nfs4_ace
*allow
, struct nfs4_ace
*deny
,
444 if (!(flags
& NFS4_ACL_DIR
))
445 ignore
|= NFS4_ACE_DELETE_CHILD
;
446 return MASK_EQUAL(ignore
|deny_mask(allow
->access_mask
, flags
),
447 ignore
|deny
->access_mask
) &&
448 allow
->type
== NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
&&
449 deny
->type
== NFS4_ACE_ACCESS_DENIED_ACE_TYPE
&&
450 allow
->flag
== deny
->flag
&&
451 same_who(allow
, deny
);
455 user_obj_from_v4(struct nfs4_acl
*n4acl
, struct list_head
**p
,
456 struct posix_acl
*pacl
, struct posix_acl_entry
**pace
,
460 struct nfs4_ace
*ace
, *ace2
;
462 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
465 if (ace2type(ace
) != ACL_USER_OBJ
)
467 error
= write_pace(ace
, pacl
, pace
, ACL_USER_OBJ
, flags
);
471 ace2
= get_next_v4_ace(p
, &n4acl
->ace_head
);
474 if (!complementary_ace_pair(ace
, ace2
, flags
))
482 users_from_v4(struct nfs4_acl
*n4acl
, struct list_head
**p
,
483 struct nfs4_ace
**mask_ace
,
484 struct posix_acl
*pacl
, struct posix_acl_entry
**pace
,
488 struct nfs4_ace
*ace
, *ace2
;
490 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
493 while (ace2type(ace
) == ACL_USER
) {
494 if (ace
->type
!= NFS4_ACE_ACCESS_DENIED_ACE_TYPE
)
497 !MASK_EQUAL(ace
->access_mask
, (*mask_ace
)->access_mask
))
500 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
503 if (ace
->type
!= NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
)
505 error
= write_pace(ace
, pacl
, pace
, ACL_USER
, flags
);
509 ace2
= get_next_v4_ace(p
, &n4acl
->ace_head
);
512 if (!complementary_ace_pair(ace
, ace2
, flags
))
514 if ((*mask_ace
)->flag
!= ace2
->flag
||
515 !same_who(*mask_ace
, ace2
))
517 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
527 group_obj_and_groups_from_v4(struct nfs4_acl
*n4acl
, struct list_head
**p
,
528 struct nfs4_ace
**mask_ace
,
529 struct posix_acl
*pacl
, struct posix_acl_entry
**pace
,
533 struct nfs4_ace
*ace
, *ace2
;
534 struct ace_container
*ac
;
535 struct list_head group_l
;
537 INIT_LIST_HEAD(&group_l
);
538 ace
= list_entry(*p
, struct nfs4_ace
, l_ace
);
540 /* group owner (mask and allow aces) */
542 if (pacl
->a_count
!= 3) {
543 /* then the group owner should be preceded by mask */
544 if (ace
->type
!= NFS4_ACE_ACCESS_DENIED_ACE_TYPE
)
547 !MASK_EQUAL(ace
->access_mask
, (*mask_ace
)->access_mask
))
550 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
554 if ((*mask_ace
)->flag
!= ace
->flag
|| !same_who(*mask_ace
, ace
))
558 if (ace2type(ace
) != ACL_GROUP_OBJ
)
561 ac
= kmalloc(sizeof(*ac
), GFP_KERNEL
);
566 list_add_tail(&ac
->ace_l
, &group_l
);
569 if (ace
->type
!= NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
)
572 error
= write_pace(ace
, pacl
, pace
, ACL_GROUP_OBJ
, flags
);
577 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
581 /* groups (mask and allow aces) */
583 while (ace2type(ace
) == ACL_GROUP
) {
584 if (*mask_ace
== NULL
)
587 if (ace
->type
!= NFS4_ACE_ACCESS_DENIED_ACE_TYPE
||
588 !MASK_EQUAL(ace
->access_mask
, (*mask_ace
)->access_mask
))
592 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
595 ac
= kmalloc(sizeof(*ac
), GFP_KERNEL
);
600 if (ace
->type
!= NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
||
601 !same_who(ace
, *mask_ace
))
605 list_add_tail(&ac
->ace_l
, &group_l
);
607 error
= write_pace(ace
, pacl
, pace
, ACL_GROUP
, flags
);
611 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
616 /* group owner (deny ace) */
618 if (ace2type(ace
) != ACL_GROUP_OBJ
)
620 ac
= list_entry(group_l
.next
, struct ace_container
, ace_l
);
622 if (!complementary_ace_pair(ace2
, ace
, flags
))
624 list_del(group_l
.next
);
627 /* groups (deny aces) */
629 while (!list_empty(&group_l
)) {
630 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
633 if (ace2type(ace
) != ACL_GROUP
)
635 ac
= list_entry(group_l
.next
, struct ace_container
, ace_l
);
637 if (!complementary_ace_pair(ace2
, ace
, flags
))
639 list_del(group_l
.next
);
643 ace
= get_next_v4_ace(p
, &n4acl
->ace_head
);
646 if (ace2type(ace
) != ACL_OTHER
)
650 while (!list_empty(&group_l
)) {
651 ac
= list_entry(group_l
.next
, struct ace_container
, ace_l
);
652 list_del(group_l
.next
);
659 mask_from_v4(struct nfs4_acl
*n4acl
, struct list_head
**p
,
660 struct nfs4_ace
**mask_ace
,
661 struct posix_acl
*pacl
, struct posix_acl_entry
**pace
,
665 struct nfs4_ace
*ace
;
667 ace
= list_entry(*p
, struct nfs4_ace
, l_ace
);
668 if (pacl
->a_count
!= 3) {
669 if (*mask_ace
== NULL
)
671 (*mask_ace
)->access_mask
= deny_mask((*mask_ace
)->access_mask
, flags
);
672 write_pace(*mask_ace
, pacl
, pace
, ACL_MASK
, flags
);
680 other_from_v4(struct nfs4_acl
*n4acl
, struct list_head
**p
,
681 struct posix_acl
*pacl
, struct posix_acl_entry
**pace
,
685 struct nfs4_ace
*ace
, *ace2
;
687 ace
= list_entry(*p
, struct nfs4_ace
, l_ace
);
688 if (ace
->type
!= NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE
)
690 error
= write_pace(ace
, pacl
, pace
, ACL_OTHER
, flags
);
694 ace2
= get_next_v4_ace(p
, &n4acl
->ace_head
);
697 if (!complementary_ace_pair(ace
, ace2
, flags
))
705 calculate_posix_ace_count(struct nfs4_acl
*n4acl
)
707 if (n4acl
->naces
== 6) /* owner, owner group, and other only */
709 else { /* Otherwise there must be a mask entry. */
710 /* Also, the remaining entries are for named users and
711 * groups, and come in threes (mask, allow, deny): */
712 if (n4acl
->naces
< 7)
714 if ((n4acl
->naces
- 7) % 3)
716 return 4 + (n4acl
->naces
- 7)/3;
721 static struct posix_acl
*
722 _nfsv4_to_posix_one(struct nfs4_acl
*n4acl
, unsigned int flags
)
724 struct posix_acl
*pacl
;
725 int error
= -EINVAL
, nace
= 0;
727 struct nfs4_ace
*mask_ace
= NULL
;
728 struct posix_acl_entry
*pace
;
730 nace
= calculate_posix_ace_count(n4acl
);
734 pacl
= posix_acl_alloc(nace
, GFP_KERNEL
);
739 pace
= &pacl
->a_entries
[0];
740 p
= &n4acl
->ace_head
;
742 error
= user_obj_from_v4(n4acl
, &p
, pacl
, &pace
, flags
);
746 error
= users_from_v4(n4acl
, &p
, &mask_ace
, pacl
, &pace
, flags
);
750 error
= group_obj_and_groups_from_v4(n4acl
, &p
, &mask_ace
, pacl
, &pace
,
755 error
= mask_from_v4(n4acl
, &p
, &mask_ace
, pacl
, &pace
, flags
);
758 error
= other_from_v4(n4acl
, &p
, pacl
, &pace
, flags
);
763 if (p
->next
!= &n4acl
->ace_head
)
765 if (pace
!= pacl
->a_entries
+ pacl
->a_count
)
772 posix_acl_release(pacl
);
774 pacl
= ERR_PTR(error
);
779 nfs4_acl_split(struct nfs4_acl
*acl
, struct nfs4_acl
*dacl
)
781 struct list_head
*h
, *n
;
782 struct nfs4_ace
*ace
;
785 list_for_each_safe(h
, n
, &acl
->ace_head
) {
786 ace
= list_entry(h
, struct nfs4_ace
, l_ace
);
788 if ((ace
->flag
& NFS4_INHERITANCE_FLAGS
)
789 != NFS4_INHERITANCE_FLAGS
)
792 error
= nfs4_acl_add_ace(dacl
, ace
->type
, ace
->flag
,
793 ace
->access_mask
, ace
->whotype
, ace
->who
) == -1;
807 ace2type(struct nfs4_ace
*ace
)
809 switch (ace
->whotype
) {
810 case NFS4_ACL_WHO_NAMED
:
811 return (ace
->flag
& NFS4_ACE_IDENTIFIER_GROUP
?
812 ACL_GROUP
: ACL_USER
);
813 case NFS4_ACL_WHO_OWNER
:
815 case NFS4_ACL_WHO_GROUP
:
816 return ACL_GROUP_OBJ
;
817 case NFS4_ACL_WHO_EVERYONE
:
824 EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4
);
825 EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix
);
830 struct nfs4_acl
*acl
;
832 if ((acl
= kmalloc(sizeof(*acl
), GFP_KERNEL
)) == NULL
)
836 INIT_LIST_HEAD(&acl
->ace_head
);
842 nfs4_acl_free(struct nfs4_acl
*acl
)
845 struct nfs4_ace
*ace
;
850 while (!list_empty(&acl
->ace_head
)) {
851 h
= acl
->ace_head
.next
;
853 ace
= list_entry(h
, struct nfs4_ace
, l_ace
);
863 nfs4_acl_add_ace(struct nfs4_acl
*acl
, u32 type
, u32 flag
, u32 access_mask
,
864 int whotype
, uid_t who
)
866 struct nfs4_ace
*ace
;
868 if ((ace
= kmalloc(sizeof(*ace
), GFP_KERNEL
)) == NULL
)
873 ace
->access_mask
= access_mask
;
874 ace
->whotype
= whotype
;
877 list_add_tail(&ace
->l_ace
, &acl
->ace_head
);
890 .stringlen
= sizeof("OWNER@") - 1,
891 .type
= NFS4_ACL_WHO_OWNER
,
895 .stringlen
= sizeof("GROUP@") - 1,
896 .type
= NFS4_ACL_WHO_GROUP
,
899 .string
= "EVERYONE@",
900 .stringlen
= sizeof("EVERYONE@") - 1,
901 .type
= NFS4_ACL_WHO_EVERYONE
,
906 nfs4_acl_get_whotype(char *p
, u32 len
)
910 for (i
=0; i
< sizeof(s2t_map
) / sizeof(*s2t_map
); i
++) {
911 if (s2t_map
[i
].stringlen
== len
&&
912 0 == memcmp(s2t_map
[i
].string
, p
, len
))
913 return s2t_map
[i
].type
;
915 return NFS4_ACL_WHO_NAMED
;
919 nfs4_acl_write_who(int who
, char *p
)
923 for (i
=0; i
< sizeof(s2t_map
) / sizeof(*s2t_map
); i
++) {
924 if (s2t_map
[i
].type
== who
) {
925 memcpy(p
, s2t_map
[i
].string
, s2t_map
[i
].stringlen
);
926 return s2t_map
[i
].stringlen
;
934 match_who(struct nfs4_ace
*ace
, uid_t owner
, gid_t group
, uid_t who
)
936 switch (ace
->whotype
) {
937 case NFS4_ACL_WHO_NAMED
:
938 return who
== ace
->who
;
939 case NFS4_ACL_WHO_OWNER
:
941 case NFS4_ACL_WHO_GROUP
:
943 case NFS4_ACL_WHO_EVERYONE
:
950 EXPORT_SYMBOL(nfs4_acl_new
);
951 EXPORT_SYMBOL(nfs4_acl_free
);
952 EXPORT_SYMBOL(nfs4_acl_add_ace
);
953 EXPORT_SYMBOL(nfs4_acl_get_whotype
);
954 EXPORT_SYMBOL(nfs4_acl_write_who
);