Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  Common NFSv4 ACL handling code.
0003  *
0004  *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
0005  *  All rights reserved.
0006  *
0007  *  Marius Aamodt Eriksen <marius@umich.edu>
0008  *  Jeff Sedlak <jsedlak@umich.edu>
0009  *  J. Bruce Fields <bfields@umich.edu>
0010  *
0011  *  Redistribution and use in source and binary forms, with or without
0012  *  modification, are permitted provided that the following conditions
0013  *  are met:
0014  *
0015  *  1. Redistributions of source code must retain the above copyright
0016  *     notice, this list of conditions and the following disclaimer.
0017  *  2. Redistributions in binary form must reproduce the above copyright
0018  *     notice, this list of conditions and the following disclaimer in the
0019  *     documentation and/or other materials provided with the distribution.
0020  *  3. Neither the name of the University nor the names of its
0021  *     contributors may be used to endorse or promote products derived
0022  *     from this software without specific prior written permission.
0023  *
0024  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
0025  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0026  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0027  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0028  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0031  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0032  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0033  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0034  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <linux/fs.h>
0038 #include <linux/slab.h>
0039 #include <linux/posix_acl.h>
0040 
0041 #include "nfsfh.h"
0042 #include "nfsd.h"
0043 #include "acl.h"
0044 #include "vfs.h"
0045 
0046 #define NFS4_ACL_TYPE_DEFAULT   0x01
0047 #define NFS4_ACL_DIR        0x02
0048 #define NFS4_ACL_OWNER      0x04
0049 
0050 /* mode bit translations: */
0051 #define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
0052 #define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
0053 #define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
0054 #define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
0055 #define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
0056 
0057 /* flags used to simulate posix default ACLs */
0058 #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
0059         | NFS4_ACE_DIRECTORY_INHERIT_ACE)
0060 
0061 #define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
0062         | NFS4_ACE_INHERIT_ONLY_ACE \
0063         | NFS4_ACE_IDENTIFIER_GROUP)
0064 
0065 static u32
0066 mask_from_posix(unsigned short perm, unsigned int flags)
0067 {
0068     int mask = NFS4_ANYONE_MODE;
0069 
0070     if (flags & NFS4_ACL_OWNER)
0071         mask |= NFS4_OWNER_MODE;
0072     if (perm & ACL_READ)
0073         mask |= NFS4_READ_MODE;
0074     if (perm & ACL_WRITE)
0075         mask |= NFS4_WRITE_MODE;
0076     if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
0077         mask |= NFS4_ACE_DELETE_CHILD;
0078     if (perm & ACL_EXECUTE)
0079         mask |= NFS4_EXECUTE_MODE;
0080     return mask;
0081 }
0082 
0083 static u32
0084 deny_mask_from_posix(unsigned short perm, u32 flags)
0085 {
0086     u32 mask = 0;
0087 
0088     if (perm & ACL_READ)
0089         mask |= NFS4_READ_MODE;
0090     if (perm & ACL_WRITE)
0091         mask |= NFS4_WRITE_MODE;
0092     if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
0093         mask |= NFS4_ACE_DELETE_CHILD;
0094     if (perm & ACL_EXECUTE)
0095         mask |= NFS4_EXECUTE_MODE;
0096     return mask;
0097 }
0098 
0099 /* XXX: modify functions to return NFS errors; they're only ever
0100  * used by nfs code, after all.... */
0101 
0102 /* We only map from NFSv4 to POSIX ACLs when setting ACLs, when we err on the
0103  * side of being more restrictive, so the mode bit mapping below is
0104  * pessimistic.  An optimistic version would be needed to handle DENY's,
0105  * but we expect to coalesce all ALLOWs and DENYs before mapping to mode
0106  * bits. */
0107 
0108 static void
0109 low_mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
0110 {
0111     u32 write_mode = NFS4_WRITE_MODE;
0112 
0113     if (flags & NFS4_ACL_DIR)
0114         write_mode |= NFS4_ACE_DELETE_CHILD;
0115     *mode = 0;
0116     if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
0117         *mode |= ACL_READ;
0118     if ((perm & write_mode) == write_mode)
0119         *mode |= ACL_WRITE;
0120     if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
0121         *mode |= ACL_EXECUTE;
0122 }
0123 
0124 static short ace2type(struct nfs4_ace *);
0125 static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
0126                 unsigned int);
0127 
0128 int
0129 nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
0130         struct nfs4_acl **acl)
0131 {
0132     struct inode *inode = d_inode(dentry);
0133     int error = 0;
0134     struct posix_acl *pacl = NULL, *dpacl = NULL;
0135     unsigned int flags = 0;
0136     int size = 0;
0137 
0138     pacl = get_acl(inode, ACL_TYPE_ACCESS);
0139     if (!pacl)
0140         pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
0141 
0142     if (IS_ERR(pacl))
0143         return PTR_ERR(pacl);
0144 
0145     /* allocate for worst case: one (deny, allow) pair each: */
0146     size += 2 * pacl->a_count;
0147 
0148     if (S_ISDIR(inode->i_mode)) {
0149         flags = NFS4_ACL_DIR;
0150         dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
0151         if (IS_ERR(dpacl)) {
0152             error = PTR_ERR(dpacl);
0153             goto rel_pacl;
0154         }
0155 
0156         if (dpacl)
0157             size += 2 * dpacl->a_count;
0158     }
0159 
0160     *acl = kmalloc(nfs4_acl_bytes(size), GFP_KERNEL);
0161     if (*acl == NULL) {
0162         error = -ENOMEM;
0163         goto out;
0164     }
0165     (*acl)->naces = 0;
0166 
0167     _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
0168 
0169     if (dpacl)
0170         _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
0171 
0172 out:
0173     posix_acl_release(dpacl);
0174 rel_pacl:
0175     posix_acl_release(pacl);
0176     return error;
0177 }
0178 
0179 struct posix_acl_summary {
0180     unsigned short owner;
0181     unsigned short users;
0182     unsigned short group;
0183     unsigned short groups;
0184     unsigned short other;
0185     unsigned short mask;
0186 };
0187 
0188 static void
0189 summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
0190 {
0191     struct posix_acl_entry *pa, *pe;
0192 
0193     /*
0194      * Only pas.users and pas.groups need initialization; previous
0195      * posix_acl_valid() calls ensure that the other fields will be
0196      * initialized in the following loop.  But, just to placate gcc:
0197      */
0198     memset(pas, 0, sizeof(*pas));
0199     pas->mask = 07;
0200 
0201     pe = acl->a_entries + acl->a_count;
0202 
0203     FOREACH_ACL_ENTRY(pa, acl, pe) {
0204         switch (pa->e_tag) {
0205             case ACL_USER_OBJ:
0206                 pas->owner = pa->e_perm;
0207                 break;
0208             case ACL_GROUP_OBJ:
0209                 pas->group = pa->e_perm;
0210                 break;
0211             case ACL_USER:
0212                 pas->users |= pa->e_perm;
0213                 break;
0214             case ACL_GROUP:
0215                 pas->groups |= pa->e_perm;
0216                 break;
0217             case ACL_OTHER:
0218                 pas->other = pa->e_perm;
0219                 break;
0220             case ACL_MASK:
0221                 pas->mask = pa->e_perm;
0222                 break;
0223         }
0224     }
0225     /* We'll only care about effective permissions: */
0226     pas->users &= pas->mask;
0227     pas->group &= pas->mask;
0228     pas->groups &= pas->mask;
0229 }
0230 
0231 /* We assume the acl has been verified with posix_acl_valid. */
0232 static void
0233 _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
0234                         unsigned int flags)
0235 {
0236     struct posix_acl_entry *pa, *group_owner_entry;
0237     struct nfs4_ace *ace;
0238     struct posix_acl_summary pas;
0239     unsigned short deny;
0240     int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
0241         NFS4_INHERITANCE_FLAGS | NFS4_ACE_INHERIT_ONLY_ACE : 0);
0242 
0243     BUG_ON(pacl->a_count < 3);
0244     summarize_posix_acl(pacl, &pas);
0245 
0246     pa = pacl->a_entries;
0247     ace = acl->aces + acl->naces;
0248 
0249     /* We could deny everything not granted by the owner: */
0250     deny = ~pas.owner;
0251     /*
0252      * but it is equivalent (and simpler) to deny only what is not
0253      * granted by later entries:
0254      */
0255     deny &= pas.users | pas.group | pas.groups | pas.other;
0256     if (deny) {
0257         ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0258         ace->flag = eflag;
0259         ace->access_mask = deny_mask_from_posix(deny, flags);
0260         ace->whotype = NFS4_ACL_WHO_OWNER;
0261         ace++;
0262         acl->naces++;
0263     }
0264 
0265     ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0266     ace->flag = eflag;
0267     ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
0268     ace->whotype = NFS4_ACL_WHO_OWNER;
0269     ace++;
0270     acl->naces++;
0271     pa++;
0272 
0273     while (pa->e_tag == ACL_USER) {
0274         deny = ~(pa->e_perm & pas.mask);
0275         deny &= pas.groups | pas.group | pas.other;
0276         if (deny) {
0277             ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0278             ace->flag = eflag;
0279             ace->access_mask = deny_mask_from_posix(deny, flags);
0280             ace->whotype = NFS4_ACL_WHO_NAMED;
0281             ace->who_uid = pa->e_uid;
0282             ace++;
0283             acl->naces++;
0284         }
0285         ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0286         ace->flag = eflag;
0287         ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
0288                            flags);
0289         ace->whotype = NFS4_ACL_WHO_NAMED;
0290         ace->who_uid = pa->e_uid;
0291         ace++;
0292         acl->naces++;
0293         pa++;
0294     }
0295 
0296     /* In the case of groups, we apply allow ACEs first, then deny ACEs,
0297      * since a user can be in more than one group.  */
0298 
0299     /* allow ACEs */
0300 
0301     group_owner_entry = pa;
0302 
0303     ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0304     ace->flag = eflag;
0305     ace->access_mask = mask_from_posix(pas.group, flags);
0306     ace->whotype = NFS4_ACL_WHO_GROUP;
0307     ace++;
0308     acl->naces++;
0309     pa++;
0310 
0311     while (pa->e_tag == ACL_GROUP) {
0312         ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0313         ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
0314         ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
0315                            flags);
0316         ace->whotype = NFS4_ACL_WHO_NAMED;
0317         ace->who_gid = pa->e_gid;
0318         ace++;
0319         acl->naces++;
0320         pa++;
0321     }
0322 
0323     /* deny ACEs */
0324 
0325     pa = group_owner_entry;
0326 
0327     deny = ~pas.group & pas.other;
0328     if (deny) {
0329         ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0330         ace->flag = eflag;
0331         ace->access_mask = deny_mask_from_posix(deny, flags);
0332         ace->whotype = NFS4_ACL_WHO_GROUP;
0333         ace++;
0334         acl->naces++;
0335     }
0336     pa++;
0337 
0338     while (pa->e_tag == ACL_GROUP) {
0339         deny = ~(pa->e_perm & pas.mask);
0340         deny &= pas.other;
0341         if (deny) {
0342             ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0343             ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
0344             ace->access_mask = deny_mask_from_posix(deny, flags);
0345             ace->whotype = NFS4_ACL_WHO_NAMED;
0346             ace->who_gid = pa->e_gid;
0347             ace++;
0348             acl->naces++;
0349         }
0350         pa++;
0351     }
0352 
0353     if (pa->e_tag == ACL_MASK)
0354         pa++;
0355     ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0356     ace->flag = eflag;
0357     ace->access_mask = mask_from_posix(pa->e_perm, flags);
0358     ace->whotype = NFS4_ACL_WHO_EVERYONE;
0359     acl->naces++;
0360 }
0361 
0362 static bool
0363 pace_gt(struct posix_acl_entry *pace1, struct posix_acl_entry *pace2)
0364 {
0365     if (pace1->e_tag != pace2->e_tag)
0366         return pace1->e_tag > pace2->e_tag;
0367     if (pace1->e_tag == ACL_USER)
0368         return uid_gt(pace1->e_uid, pace2->e_uid);
0369     if (pace1->e_tag == ACL_GROUP)
0370         return gid_gt(pace1->e_gid, pace2->e_gid);
0371     return false;
0372 }
0373 
0374 static void
0375 sort_pacl_range(struct posix_acl *pacl, int start, int end) {
0376     int sorted = 0, i;
0377 
0378     /* We just do a bubble sort; easy to do in place, and we're not
0379      * expecting acl's to be long enough to justify anything more. */
0380     while (!sorted) {
0381         sorted = 1;
0382         for (i = start; i < end; i++) {
0383             if (pace_gt(&pacl->a_entries[i],
0384                     &pacl->a_entries[i+1])) {
0385                 sorted = 0;
0386                 swap(pacl->a_entries[i],
0387                      pacl->a_entries[i + 1]);
0388             }
0389         }
0390     }
0391 }
0392 
0393 static void
0394 sort_pacl(struct posix_acl *pacl)
0395 {
0396     /* posix_acl_valid requires that users and groups be in order
0397      * by uid/gid. */
0398     int i, j;
0399 
0400     /* no users or groups */
0401     if (!pacl || pacl->a_count <= 4)
0402         return;
0403 
0404     i = 1;
0405     while (pacl->a_entries[i].e_tag == ACL_USER)
0406         i++;
0407     sort_pacl_range(pacl, 1, i-1);
0408 
0409     BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
0410     j = ++i;
0411     while (pacl->a_entries[j].e_tag == ACL_GROUP)
0412         j++;
0413     sort_pacl_range(pacl, i, j-1);
0414     return;
0415 }
0416 
0417 /*
0418  * While processing the NFSv4 ACE, this maintains bitmasks representing
0419  * which permission bits have been allowed and which denied to a given
0420  * entity: */
0421 struct posix_ace_state {
0422     u32 allow;
0423     u32 deny;
0424 };
0425 
0426 struct posix_user_ace_state {
0427     union {
0428         kuid_t uid;
0429         kgid_t gid;
0430     };
0431     struct posix_ace_state perms;
0432 };
0433 
0434 struct posix_ace_state_array {
0435     int n;
0436     struct posix_user_ace_state aces[];
0437 };
0438 
0439 /*
0440  * While processing the NFSv4 ACE, this maintains the partial permissions
0441  * calculated so far: */
0442 
0443 struct posix_acl_state {
0444     int empty;
0445     struct posix_ace_state owner;
0446     struct posix_ace_state group;
0447     struct posix_ace_state other;
0448     struct posix_ace_state everyone;
0449     struct posix_ace_state mask; /* Deny unused in this case */
0450     struct posix_ace_state_array *users;
0451     struct posix_ace_state_array *groups;
0452 };
0453 
0454 static int
0455 init_state(struct posix_acl_state *state, int cnt)
0456 {
0457     int alloc;
0458 
0459     memset(state, 0, sizeof(struct posix_acl_state));
0460     state->empty = 1;
0461     /*
0462      * In the worst case, each individual acl could be for a distinct
0463      * named user or group, but we don't know which, so we allocate
0464      * enough space for either:
0465      */
0466     alloc = sizeof(struct posix_ace_state_array)
0467         + cnt*sizeof(struct posix_user_ace_state);
0468     state->users = kzalloc(alloc, GFP_KERNEL);
0469     if (!state->users)
0470         return -ENOMEM;
0471     state->groups = kzalloc(alloc, GFP_KERNEL);
0472     if (!state->groups) {
0473         kfree(state->users);
0474         return -ENOMEM;
0475     }
0476     return 0;
0477 }
0478 
0479 static void
0480 free_state(struct posix_acl_state *state) {
0481     kfree(state->users);
0482     kfree(state->groups);
0483 }
0484 
0485 static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_state *astate)
0486 {
0487     state->mask.allow |= astate->allow;
0488 }
0489 
0490 static struct posix_acl *
0491 posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
0492 {
0493     struct posix_acl_entry *pace;
0494     struct posix_acl *pacl;
0495     int nace;
0496     int i;
0497 
0498     /*
0499      * ACLs with no ACEs are treated differently in the inheritable
0500      * and effective cases: when there are no inheritable ACEs,
0501      * calls ->set_acl with a NULL ACL structure.
0502      */
0503     if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT))
0504         return NULL;
0505 
0506     /*
0507      * When there are no effective ACEs, the following will end
0508      * up setting a 3-element effective posix ACL with all
0509      * permissions zero.
0510      */
0511     if (!state->users->n && !state->groups->n)
0512         nace = 3;
0513     else /* Note we also include a MASK ACE in this case: */
0514         nace = 4 + state->users->n + state->groups->n;
0515     pacl = posix_acl_alloc(nace, GFP_KERNEL);
0516     if (!pacl)
0517         return ERR_PTR(-ENOMEM);
0518 
0519     pace = pacl->a_entries;
0520     pace->e_tag = ACL_USER_OBJ;
0521     low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
0522 
0523     for (i=0; i < state->users->n; i++) {
0524         pace++;
0525         pace->e_tag = ACL_USER;
0526         low_mode_from_nfs4(state->users->aces[i].perms.allow,
0527                     &pace->e_perm, flags);
0528         pace->e_uid = state->users->aces[i].uid;
0529         add_to_mask(state, &state->users->aces[i].perms);
0530     }
0531 
0532     pace++;
0533     pace->e_tag = ACL_GROUP_OBJ;
0534     low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
0535     add_to_mask(state, &state->group);
0536 
0537     for (i=0; i < state->groups->n; i++) {
0538         pace++;
0539         pace->e_tag = ACL_GROUP;
0540         low_mode_from_nfs4(state->groups->aces[i].perms.allow,
0541                     &pace->e_perm, flags);
0542         pace->e_gid = state->groups->aces[i].gid;
0543         add_to_mask(state, &state->groups->aces[i].perms);
0544     }
0545 
0546     if (state->users->n || state->groups->n) {
0547         pace++;
0548         pace->e_tag = ACL_MASK;
0549         low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
0550     }
0551 
0552     pace++;
0553     pace->e_tag = ACL_OTHER;
0554     low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
0555 
0556     return pacl;
0557 }
0558 
0559 static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
0560 {
0561     /* Allow all bits in the mask not already denied: */
0562     astate->allow |= mask & ~astate->deny;
0563 }
0564 
0565 static inline void deny_bits(struct posix_ace_state *astate, u32 mask)
0566 {
0567     /* Deny all bits in the mask not already allowed: */
0568     astate->deny |= mask & ~astate->allow;
0569 }
0570 
0571 static int find_uid(struct posix_acl_state *state, kuid_t uid)
0572 {
0573     struct posix_ace_state_array *a = state->users;
0574     int i;
0575 
0576     for (i = 0; i < a->n; i++)
0577         if (uid_eq(a->aces[i].uid, uid))
0578             return i;
0579     /* Not found: */
0580     a->n++;
0581     a->aces[i].uid = uid;
0582     a->aces[i].perms.allow = state->everyone.allow;
0583     a->aces[i].perms.deny  = state->everyone.deny;
0584 
0585     return i;
0586 }
0587 
0588 static int find_gid(struct posix_acl_state *state, kgid_t gid)
0589 {
0590     struct posix_ace_state_array *a = state->groups;
0591     int i;
0592 
0593     for (i = 0; i < a->n; i++)
0594         if (gid_eq(a->aces[i].gid, gid))
0595             return i;
0596     /* Not found: */
0597     a->n++;
0598     a->aces[i].gid = gid;
0599     a->aces[i].perms.allow = state->everyone.allow;
0600     a->aces[i].perms.deny  = state->everyone.deny;
0601 
0602     return i;
0603 }
0604 
0605 static void deny_bits_array(struct posix_ace_state_array *a, u32 mask)
0606 {
0607     int i;
0608 
0609     for (i=0; i < a->n; i++)
0610         deny_bits(&a->aces[i].perms, mask);
0611 }
0612 
0613 static void allow_bits_array(struct posix_ace_state_array *a, u32 mask)
0614 {
0615     int i;
0616 
0617     for (i=0; i < a->n; i++)
0618         allow_bits(&a->aces[i].perms, mask);
0619 }
0620 
0621 static void process_one_v4_ace(struct posix_acl_state *state,
0622                 struct nfs4_ace *ace)
0623 {
0624     u32 mask = ace->access_mask;
0625     int i;
0626 
0627     state->empty = 0;
0628 
0629     switch (ace2type(ace)) {
0630     case ACL_USER_OBJ:
0631         if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0632             allow_bits(&state->owner, mask);
0633         } else {
0634             deny_bits(&state->owner, mask);
0635         }
0636         break;
0637     case ACL_USER:
0638         i = find_uid(state, ace->who_uid);
0639         if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0640             allow_bits(&state->users->aces[i].perms, mask);
0641         } else {
0642             deny_bits(&state->users->aces[i].perms, mask);
0643             mask = state->users->aces[i].perms.deny;
0644             deny_bits(&state->owner, mask);
0645         }
0646         break;
0647     case ACL_GROUP_OBJ:
0648         if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0649             allow_bits(&state->group, mask);
0650         } else {
0651             deny_bits(&state->group, mask);
0652             mask = state->group.deny;
0653             deny_bits(&state->owner, mask);
0654             deny_bits(&state->everyone, mask);
0655             deny_bits_array(state->users, mask);
0656             deny_bits_array(state->groups, mask);
0657         }
0658         break;
0659     case ACL_GROUP:
0660         i = find_gid(state, ace->who_gid);
0661         if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0662             allow_bits(&state->groups->aces[i].perms, mask);
0663         } else {
0664             deny_bits(&state->groups->aces[i].perms, mask);
0665             mask = state->groups->aces[i].perms.deny;
0666             deny_bits(&state->owner, mask);
0667             deny_bits(&state->group, mask);
0668             deny_bits(&state->everyone, mask);
0669             deny_bits_array(state->users, mask);
0670             deny_bits_array(state->groups, mask);
0671         }
0672         break;
0673     case ACL_OTHER:
0674         if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0675             allow_bits(&state->owner, mask);
0676             allow_bits(&state->group, mask);
0677             allow_bits(&state->other, mask);
0678             allow_bits(&state->everyone, mask);
0679             allow_bits_array(state->users, mask);
0680             allow_bits_array(state->groups, mask);
0681         } else {
0682             deny_bits(&state->owner, mask);
0683             deny_bits(&state->group, mask);
0684             deny_bits(&state->other, mask);
0685             deny_bits(&state->everyone, mask);
0686             deny_bits_array(state->users, mask);
0687             deny_bits_array(state->groups, mask);
0688         }
0689     }
0690 }
0691 
0692 static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
0693         struct posix_acl **pacl, struct posix_acl **dpacl,
0694         unsigned int flags)
0695 {
0696     struct posix_acl_state effective_acl_state, default_acl_state;
0697     struct nfs4_ace *ace;
0698     int ret;
0699 
0700     ret = init_state(&effective_acl_state, acl->naces);
0701     if (ret)
0702         return ret;
0703     ret = init_state(&default_acl_state, acl->naces);
0704     if (ret)
0705         goto out_estate;
0706     ret = -EINVAL;
0707     for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
0708         if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
0709             ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
0710             goto out_dstate;
0711         if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
0712             goto out_dstate;
0713         if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
0714             process_one_v4_ace(&effective_acl_state, ace);
0715             continue;
0716         }
0717         if (!(flags & NFS4_ACL_DIR))
0718             goto out_dstate;
0719         /*
0720          * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
0721          * is set, we're effectively turning on the other.  That's OK,
0722          * according to rfc 3530.
0723          */
0724         process_one_v4_ace(&default_acl_state, ace);
0725 
0726         if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
0727             process_one_v4_ace(&effective_acl_state, ace);
0728     }
0729     *pacl = posix_state_to_acl(&effective_acl_state, flags);
0730     if (IS_ERR(*pacl)) {
0731         ret = PTR_ERR(*pacl);
0732         *pacl = NULL;
0733         goto out_dstate;
0734     }
0735     *dpacl = posix_state_to_acl(&default_acl_state,
0736                         flags | NFS4_ACL_TYPE_DEFAULT);
0737     if (IS_ERR(*dpacl)) {
0738         ret = PTR_ERR(*dpacl);
0739         *dpacl = NULL;
0740         posix_acl_release(*pacl);
0741         *pacl = NULL;
0742         goto out_dstate;
0743     }
0744     sort_pacl(*pacl);
0745     sort_pacl(*dpacl);
0746     ret = 0;
0747 out_dstate:
0748     free_state(&default_acl_state);
0749 out_estate:
0750     free_state(&effective_acl_state);
0751     return ret;
0752 }
0753 
0754 __be32 nfsd4_acl_to_attr(enum nfs_ftype4 type, struct nfs4_acl *acl,
0755              struct nfsd_attrs *attr)
0756 {
0757     int host_error;
0758     unsigned int flags = 0;
0759 
0760     if (!acl)
0761         return nfs_ok;
0762 
0763     if (type == NF4DIR)
0764         flags = NFS4_ACL_DIR;
0765 
0766     host_error = nfs4_acl_nfsv4_to_posix(acl, &attr->na_pacl,
0767                          &attr->na_dpacl, flags);
0768     if (host_error == -EINVAL)
0769         return nfserr_attrnotsupp;
0770     else
0771         return nfserrno(host_error);
0772 }
0773 
0774 static short
0775 ace2type(struct nfs4_ace *ace)
0776 {
0777     switch (ace->whotype) {
0778         case NFS4_ACL_WHO_NAMED:
0779             return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
0780                     ACL_GROUP : ACL_USER);
0781         case NFS4_ACL_WHO_OWNER:
0782             return ACL_USER_OBJ;
0783         case NFS4_ACL_WHO_GROUP:
0784             return ACL_GROUP_OBJ;
0785         case NFS4_ACL_WHO_EVERYONE:
0786             return ACL_OTHER;
0787     }
0788     BUG();
0789     return -1;
0790 }
0791 
0792 /*
0793  * return the size of the struct nfs4_acl required to represent an acl
0794  * with @entries entries.
0795  */
0796 int nfs4_acl_bytes(int entries)
0797 {
0798     return sizeof(struct nfs4_acl) + entries * sizeof(struct nfs4_ace);
0799 }
0800 
0801 static struct {
0802     char *string;
0803     int   stringlen;
0804     int type;
0805 } s2t_map[] = {
0806     {
0807         .string    = "OWNER@",
0808         .stringlen = sizeof("OWNER@") - 1,
0809         .type      = NFS4_ACL_WHO_OWNER,
0810     },
0811     {
0812         .string    = "GROUP@",
0813         .stringlen = sizeof("GROUP@") - 1,
0814         .type      = NFS4_ACL_WHO_GROUP,
0815     },
0816     {
0817         .string    = "EVERYONE@",
0818         .stringlen = sizeof("EVERYONE@") - 1,
0819         .type      = NFS4_ACL_WHO_EVERYONE,
0820     },
0821 };
0822 
0823 int
0824 nfs4_acl_get_whotype(char *p, u32 len)
0825 {
0826     int i;
0827 
0828     for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
0829         if (s2t_map[i].stringlen == len &&
0830                 0 == memcmp(s2t_map[i].string, p, len))
0831             return s2t_map[i].type;
0832     }
0833     return NFS4_ACL_WHO_NAMED;
0834 }
0835 
0836 __be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who)
0837 {
0838     __be32 *p;
0839     int i;
0840 
0841     for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
0842         if (s2t_map[i].type != who)
0843             continue;
0844         p = xdr_reserve_space(xdr, s2t_map[i].stringlen + 4);
0845         if (!p)
0846             return nfserr_resource;
0847         p = xdr_encode_opaque(p, s2t_map[i].string,
0848                     s2t_map[i].stringlen);
0849         return 0;
0850     }
0851     WARN_ON_ONCE(1);
0852     return nfserr_serverfault;
0853 }