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 | NFS4_ACE_READ_NAMED_ATTRS)
53 #define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_WRITE_NAMED_ATTRS | 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 /* flags used to simulate posix default ACLs */
59 #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
60 | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
62 #define MASK_EQUAL(mask1, mask2) \
63 ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
66 mask_from_posix(unsigned short perm, unsigned int flags)
68 int mask = NFS4_ANYONE_MODE;
70 if (flags & NFS4_ACL_OWNER)
71 mask |= NFS4_OWNER_MODE;
73 mask |= NFS4_READ_MODE;
75 mask |= NFS4_WRITE_MODE;
76 if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
77 mask |= NFS4_ACE_DELETE_CHILD;
78 if (perm & ACL_EXECUTE)
79 mask |= NFS4_EXECUTE_MODE;
84 deny_mask(u32 allow_mask, unsigned int flags)
86 u32 ret = ~allow_mask & ~NFS4_ACE_DELETE;
87 if (!(flags & NFS4_ACL_DIR))
88 ret &= ~NFS4_ACE_DELETE_CHILD;
93 mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
97 if (!(flags & NFS4_ACL_DIR))
98 ignore |= NFS4_ACE_DELETE_CHILD; /* ignore it */
101 if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
103 if ((perm & NFS4_WRITE_MODE) == NFS4_WRITE_MODE)
105 if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
106 *mode |= ACL_EXECUTE;
107 if (!MASK_EQUAL(perm, ignore|mask_from_posix(*mode, flags)))
112 struct ace_container {
113 struct nfs4_ace *ace;
114 struct list_head ace_l;
117 static short ace2type(struct nfs4_ace *);
118 static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
119 static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
120 int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
121 int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
124 nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
127 struct nfs4_acl *acl;
131 (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
133 (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
136 acl = nfs4_acl_new();
143 error = _posix_to_nfsv4_one(pacl, acl,
144 flags & ~NFS4_ACL_TYPE_DEFAULT);
150 error = _posix_to_nfsv4_one(dpacl, acl,
151 flags | NFS4_ACL_TYPE_DEFAULT);
161 acl = ERR_PTR(error);
167 nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
168 uid_t owner, unsigned int flags)
172 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
173 eflag, mask, whotype, owner);
176 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
177 eflag, deny_mask(mask, flags), whotype, owner);
181 /* We assume the acl has been verified with posix_acl_valid. */
183 _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
186 struct posix_acl_entry *pa, *pe, *group_owner_entry;
189 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
190 NFS4_INHERITANCE_FLAGS : 0);
192 BUG_ON(pacl->a_count < 3);
193 pe = pacl->a_entries + pacl->a_count;
194 pa = pe - 2; /* if mask entry exists, it's second from the last. */
195 if (pa->e_tag == ACL_MASK)
196 mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
200 pa = pacl->a_entries;
201 BUG_ON(pa->e_tag != ACL_USER_OBJ);
202 mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
203 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
208 while (pa->e_tag == ACL_USER) {
209 mask = mask_from_posix(pa->e_perm, flags);
210 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
211 eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
216 error = nfs4_acl_add_pair(acl, eflag, mask,
217 NFS4_ACL_WHO_NAMED, pa->e_id, flags);
223 /* In the case of groups, we apply allow ACEs first, then deny ACEs,
224 * since a user can be in more than one group. */
228 if (pacl->a_count > 3) {
229 BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
230 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
231 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
232 NFS4_ACL_WHO_GROUP, 0);
236 group_owner_entry = pa;
237 mask = mask_from_posix(pa->e_perm, flags);
238 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
239 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
240 NFS4_ACL_WHO_GROUP, 0);
245 while (pa->e_tag == ACL_GROUP) {
246 mask = mask_from_posix(pa->e_perm, flags);
247 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
248 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
249 NFS4_ACL_WHO_NAMED, pa->e_id);
253 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
254 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
255 NFS4_ACL_WHO_NAMED, pa->e_id);
263 pa = group_owner_entry;
264 mask = mask_from_posix(pa->e_perm, flags);
265 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
266 NFS4_ACE_IDENTIFIER_GROUP | eflag,
267 deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
271 while (pa->e_tag == ACL_GROUP) {
272 mask = mask_from_posix(pa->e_perm, flags);
273 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
274 NFS4_ACE_IDENTIFIER_GROUP | eflag,
275 deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
281 if (pa->e_tag == ACL_MASK)
283 BUG_ON(pa->e_tag != ACL_OTHER);
284 mask = mask_from_posix(pa->e_perm, flags);
285 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
292 sort_pacl_range(struct posix_acl *pacl, int start, int end) {
294 struct posix_acl_entry tmp;
296 /* We just do a bubble sort; easy to do in place, and we're not
297 * expecting acl's to be long enough to justify anything more. */
300 for (i = start; i < end; i++) {
301 if (pacl->a_entries[i].e_id
302 > pacl->a_entries[i+1].e_id) {
304 tmp = pacl->a_entries[i];
305 pacl->a_entries[i] = pacl->a_entries[i+1];
306 pacl->a_entries[i+1] = tmp;
313 sort_pacl(struct posix_acl *pacl)
315 /* posix_acl_valid requires that users and groups be in order
319 if (pacl->a_count <= 4)
320 return; /* no users or groups */
322 while (pacl->a_entries[i].e_tag == ACL_USER)
324 sort_pacl_range(pacl, 1, i-1);
326 BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
328 while (pacl->a_entries[j].e_tag == ACL_GROUP)
330 sort_pacl_range(pacl, i, j-1);
335 write_pace(struct nfs4_ace *ace, struct posix_acl *pacl,
336 struct posix_acl_entry **pace, short tag, unsigned int flags)
338 struct posix_acl_entry *this = *pace;
340 if (*pace == pacl->a_entries + pacl->a_count)
341 return -EINVAL; /* fell off the end */
344 if (tag == ACL_USER_OBJ)
345 flags |= NFS4_ACL_OWNER;
346 if (mode_from_nfs4(ace->access_mask, &this->e_perm, flags))
348 this->e_id = (tag == ACL_USER || tag == ACL_GROUP ?
349 ace->who : ACL_UNDEFINED_ID);
353 static struct nfs4_ace *
354 get_next_v4_ace(struct list_head **p, struct list_head *head)
356 struct nfs4_ace *ace;
361 ace = list_entry(*p, struct nfs4_ace, l_ace);
367 nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
368 struct posix_acl **dpacl, unsigned int flags)
370 struct nfs4_acl *dacl;
376 dacl = nfs4_acl_new();
380 error = nfs4_acl_split(acl, dacl);
385 if (acl->naces == 0) {
390 *pacl = _nfsv4_to_posix_one(acl, flags);
392 error = PTR_ERR(*pacl);
400 if (dacl->naces == 0) {
401 if (pacl == NULL || *pacl == NULL)
407 *dpacl = _nfsv4_to_posix_one(dacl, flags);
408 if (IS_ERR(*dpacl)) {
409 error = PTR_ERR(*dpacl);
417 posix_acl_release(*pacl);
426 same_who(struct nfs4_ace *a, struct nfs4_ace *b)
428 return a->whotype == b->whotype &&
429 (a->whotype != NFS4_ACL_WHO_NAMED || a->who == b->who);
433 complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny,
437 if (!(flags & NFS4_ACL_DIR))
438 ignore |= NFS4_ACE_DELETE_CHILD;
439 return MASK_EQUAL(ignore|deny_mask(allow->access_mask, flags),
440 ignore|deny->access_mask) &&
441 allow->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
442 deny->type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE &&
443 allow->flag == deny->flag &&
444 same_who(allow, deny);
448 user_obj_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
449 struct posix_acl *pacl, struct posix_acl_entry **pace,
453 struct nfs4_ace *ace, *ace2;
455 ace = get_next_v4_ace(p, &n4acl->ace_head);
458 if (ace2type(ace) != ACL_USER_OBJ)
460 error = write_pace(ace, pacl, pace, ACL_USER_OBJ, flags);
464 ace2 = get_next_v4_ace(p, &n4acl->ace_head);
467 if (!complementary_ace_pair(ace, ace2, flags))
475 users_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
476 struct nfs4_ace **mask_ace,
477 struct posix_acl *pacl, struct posix_acl_entry **pace,
481 struct nfs4_ace *ace, *ace2;
483 ace = get_next_v4_ace(p, &n4acl->ace_head);
486 while (ace2type(ace) == ACL_USER) {
487 if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
490 !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
493 ace = get_next_v4_ace(p, &n4acl->ace_head);
496 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
498 error = write_pace(ace, pacl, pace, ACL_USER, flags);
502 ace2 = get_next_v4_ace(p, &n4acl->ace_head);
505 if (!complementary_ace_pair(ace, ace2, flags))
507 if ((*mask_ace)->flag != ace2->flag ||
508 !same_who(*mask_ace, ace2))
510 ace = get_next_v4_ace(p, &n4acl->ace_head);
520 group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
521 struct nfs4_ace **mask_ace,
522 struct posix_acl *pacl, struct posix_acl_entry **pace,
526 struct nfs4_ace *ace, *ace2;
527 struct ace_container *ac;
528 struct list_head group_l;
530 INIT_LIST_HEAD(&group_l);
531 ace = list_entry(*p, struct nfs4_ace, l_ace);
533 /* group owner (mask and allow aces) */
535 if (pacl->a_count != 3) {
536 /* then the group owner should be preceded by mask */
537 if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
540 !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
543 ace = get_next_v4_ace(p, &n4acl->ace_head);
547 if ((*mask_ace)->flag != ace->flag || !same_who(*mask_ace, ace))
551 if (ace2type(ace) != ACL_GROUP_OBJ)
554 ac = kmalloc(sizeof(*ac), GFP_KERNEL);
559 list_add_tail(&ac->ace_l, &group_l);
562 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
565 error = write_pace(ace, pacl, pace, ACL_GROUP_OBJ, flags);
570 ace = get_next_v4_ace(p, &n4acl->ace_head);
574 /* groups (mask and allow aces) */
576 while (ace2type(ace) == ACL_GROUP) {
577 if (*mask_ace == NULL)
580 if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE ||
581 !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
585 ace = get_next_v4_ace(p, &n4acl->ace_head);
588 ac = kmalloc(sizeof(*ac), GFP_KERNEL);
593 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ||
594 !same_who(ace, *mask_ace))
598 list_add_tail(&ac->ace_l, &group_l);
600 error = write_pace(ace, pacl, pace, ACL_GROUP, flags);
604 ace = get_next_v4_ace(p, &n4acl->ace_head);
609 /* group owner (deny ace) */
611 if (ace2type(ace) != ACL_GROUP_OBJ)
613 ac = list_entry(group_l.next, struct ace_container, ace_l);
615 if (!complementary_ace_pair(ace2, ace, flags))
617 list_del(group_l.next);
620 /* groups (deny aces) */
622 while (!list_empty(&group_l)) {
623 ace = get_next_v4_ace(p, &n4acl->ace_head);
626 if (ace2type(ace) != ACL_GROUP)
628 ac = list_entry(group_l.next, struct ace_container, ace_l);
630 if (!complementary_ace_pair(ace2, ace, flags))
632 list_del(group_l.next);
636 ace = get_next_v4_ace(p, &n4acl->ace_head);
639 if (ace2type(ace) != ACL_OTHER)
643 while (!list_empty(&group_l)) {
644 ac = list_entry(group_l.next, struct ace_container, ace_l);
645 list_del(group_l.next);
652 mask_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
653 struct nfs4_ace **mask_ace,
654 struct posix_acl *pacl, struct posix_acl_entry **pace,
658 struct nfs4_ace *ace;
660 ace = list_entry(*p, struct nfs4_ace, l_ace);
661 if (pacl->a_count != 3) {
662 if (*mask_ace == NULL)
664 (*mask_ace)->access_mask = deny_mask((*mask_ace)->access_mask, flags);
665 write_pace(*mask_ace, pacl, pace, ACL_MASK, flags);
673 other_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
674 struct posix_acl *pacl, struct posix_acl_entry **pace,
678 struct nfs4_ace *ace, *ace2;
680 ace = list_entry(*p, struct nfs4_ace, l_ace);
681 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
683 error = write_pace(ace, pacl, pace, ACL_OTHER, flags);
687 ace2 = get_next_v4_ace(p, &n4acl->ace_head);
690 if (!complementary_ace_pair(ace, ace2, flags))
698 calculate_posix_ace_count(struct nfs4_acl *n4acl)
700 if (n4acl->naces == 6) /* owner, owner group, and other only */
702 else { /* Otherwise there must be a mask entry. */
703 /* Also, the remaining entries are for named users and
704 * groups, and come in threes (mask, allow, deny): */
705 if (n4acl->naces < 7)
707 if ((n4acl->naces - 7) % 3)
709 return 4 + (n4acl->naces - 7)/3;
714 static struct posix_acl *
715 _nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
717 struct posix_acl *pacl;
718 int error = -EINVAL, nace = 0;
720 struct nfs4_ace *mask_ace = NULL;
721 struct posix_acl_entry *pace;
723 nace = calculate_posix_ace_count(n4acl);
727 pacl = posix_acl_alloc(nace, GFP_KERNEL);
732 pace = &pacl->a_entries[0];
733 p = &n4acl->ace_head;
735 error = user_obj_from_v4(n4acl, &p, pacl, &pace, flags);
739 error = users_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
743 error = group_obj_and_groups_from_v4(n4acl, &p, &mask_ace, pacl, &pace,
748 error = mask_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
751 error = other_from_v4(n4acl, &p, pacl, &pace, flags);
756 if (p->next != &n4acl->ace_head)
758 if (pace != pacl->a_entries + pacl->a_count)
765 posix_acl_release(pacl);
767 pacl = ERR_PTR(error);
772 nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
774 struct list_head *h, *n;
775 struct nfs4_ace *ace;
778 list_for_each_safe(h, n, &acl->ace_head) {
779 ace = list_entry(h, struct nfs4_ace, l_ace);
781 if ((ace->flag & NFS4_INHERITANCE_FLAGS)
782 != NFS4_INHERITANCE_FLAGS)
785 error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
786 ace->access_mask, ace->whotype, ace->who) == -1;
800 ace2type(struct nfs4_ace *ace)
802 switch (ace->whotype) {
803 case NFS4_ACL_WHO_NAMED:
804 return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
805 ACL_GROUP : ACL_USER);
806 case NFS4_ACL_WHO_OWNER:
808 case NFS4_ACL_WHO_GROUP:
809 return ACL_GROUP_OBJ;
810 case NFS4_ACL_WHO_EVERYONE:
817 EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
818 EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
823 struct nfs4_acl *acl;
825 if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
829 INIT_LIST_HEAD(&acl->ace_head);
835 nfs4_acl_free(struct nfs4_acl *acl)
838 struct nfs4_ace *ace;
843 while (!list_empty(&acl->ace_head)) {
844 h = acl->ace_head.next;
846 ace = list_entry(h, struct nfs4_ace, l_ace);
856 nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
857 int whotype, uid_t who)
859 struct nfs4_ace *ace;
861 if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
866 ace->access_mask = access_mask;
867 ace->whotype = whotype;
870 list_add_tail(&ace->l_ace, &acl->ace_head);
883 .stringlen = sizeof("OWNER@") - 1,
884 .type = NFS4_ACL_WHO_OWNER,
888 .stringlen = sizeof("GROUP@") - 1,
889 .type = NFS4_ACL_WHO_GROUP,
892 .string = "EVERYONE@",
893 .stringlen = sizeof("EVERYONE@") - 1,
894 .type = NFS4_ACL_WHO_EVERYONE,
899 nfs4_acl_get_whotype(char *p, u32 len)
903 for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
904 if (s2t_map[i].stringlen == len &&
905 0 == memcmp(s2t_map[i].string, p, len))
906 return s2t_map[i].type;
908 return NFS4_ACL_WHO_NAMED;
912 nfs4_acl_write_who(int who, char *p)
916 for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
917 if (s2t_map[i].type == who) {
918 memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
919 return s2t_map[i].stringlen;
927 match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
929 switch (ace->whotype) {
930 case NFS4_ACL_WHO_NAMED:
931 return who == ace->who;
932 case NFS4_ACL_WHO_OWNER:
934 case NFS4_ACL_WHO_GROUP:
936 case NFS4_ACL_WHO_EVERYONE:
943 /* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */
945 nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
948 struct nfs4_ace *ace;
951 list_for_each_entry(ace, &acl->ace_head, l_ace) {
952 if (!match_who(ace, group, owner, who))
955 case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE:
956 allowed |= ace->access_mask;
957 if ((allowed & mask) == mask)
960 case NFS4_ACE_ACCESS_DENIED_ACE_TYPE:
961 if (ace->access_mask & mask)
969 EXPORT_SYMBOL(nfs4_acl_new);
970 EXPORT_SYMBOL(nfs4_acl_free);
971 EXPORT_SYMBOL(nfs4_acl_add_ace);
972 EXPORT_SYMBOL(nfs4_acl_get_whotype);
973 EXPORT_SYMBOL(nfs4_acl_write_who);
974 EXPORT_SYMBOL(nfs4_acl_permission);