Root/fs/nfsd/nfs4acl.c

1/*
2 * Common NFSv4 ACL handling code.
3 *
4 * Copyright (c) 2002, 2003 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Marius Aamodt Eriksen <marius@umich.edu>
8 * Jeff Sedlak <jsedlak@umich.edu>
9 * J. Bruce Fields <bfields@umich.edu>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <linux/slab.h>
38#include <linux/nfs_fs.h>
39#include "acl.h"
40
41
42/* mode bit translations: */
43#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
44#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
45#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
46#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
47#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
48
49/* We don't support these bits; insist they be neither allowed nor denied */
50#define NFS4_MASK_UNSUPP (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
51        | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
52
53/* flags used to simulate posix default ACLs */
54#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
55        | NFS4_ACE_DIRECTORY_INHERIT_ACE)
56
57#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
58        | NFS4_ACE_INHERIT_ONLY_ACE \
59        | NFS4_ACE_IDENTIFIER_GROUP)
60
61#define MASK_EQUAL(mask1, mask2) \
62    ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
63
64static u32
65mask_from_posix(unsigned short perm, unsigned int flags)
66{
67    int mask = NFS4_ANYONE_MODE;
68
69    if (flags & NFS4_ACL_OWNER)
70        mask |= NFS4_OWNER_MODE;
71    if (perm & ACL_READ)
72        mask |= NFS4_READ_MODE;
73    if (perm & ACL_WRITE)
74        mask |= NFS4_WRITE_MODE;
75    if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
76        mask |= NFS4_ACE_DELETE_CHILD;
77    if (perm & ACL_EXECUTE)
78        mask |= NFS4_EXECUTE_MODE;
79    return mask;
80}
81
82static u32
83deny_mask_from_posix(unsigned short perm, u32 flags)
84{
85    u32 mask = 0;
86
87    if (perm & ACL_READ)
88        mask |= NFS4_READ_MODE;
89    if (perm & ACL_WRITE)
90        mask |= NFS4_WRITE_MODE;
91    if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
92        mask |= NFS4_ACE_DELETE_CHILD;
93    if (perm & ACL_EXECUTE)
94        mask |= NFS4_EXECUTE_MODE;
95    return mask;
96}
97
98/* XXX: modify functions to return NFS errors; they're only ever
99 * used by nfs code, after all.... */
100
101/* We only map from NFSv4 to POSIX ACLs when setting ACLs, when we err on the
102 * side of being more restrictive, so the mode bit mapping below is
103 * pessimistic. An optimistic version would be needed to handle DENY's,
104 * but we espect to coalesce all ALLOWs and DENYs before mapping to mode
105 * bits. */
106
107static void
108low_mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
109{
110    u32 write_mode = NFS4_WRITE_MODE;
111
112    if (flags & NFS4_ACL_DIR)
113        write_mode |= NFS4_ACE_DELETE_CHILD;
114    *mode = 0;
115    if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
116        *mode |= ACL_READ;
117    if ((perm & write_mode) == write_mode)
118        *mode |= ACL_WRITE;
119    if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
120        *mode |= ACL_EXECUTE;
121}
122
123struct ace_container {
124    struct nfs4_ace *ace;
125    struct list_head ace_l;
126};
127
128static short ace2type(struct nfs4_ace *);
129static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
130                unsigned int);
131
132struct nfs4_acl *
133nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
134            unsigned int flags)
135{
136    struct nfs4_acl *acl;
137    int size = 0;
138
139    if (pacl) {
140        if (posix_acl_valid(pacl) < 0)
141            return ERR_PTR(-EINVAL);
142        size += 2*pacl->a_count;
143    }
144    if (dpacl) {
145        if (posix_acl_valid(dpacl) < 0)
146            return ERR_PTR(-EINVAL);
147        size += 2*dpacl->a_count;
148    }
149
150    /* Allocate for worst case: one (deny, allow) pair each: */
151    acl = nfs4_acl_new(size);
152    if (acl == NULL)
153        return ERR_PTR(-ENOMEM);
154
155    if (pacl)
156        _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
157
158    if (dpacl)
159        _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
160
161    return acl;
162}
163
164struct posix_acl_summary {
165    unsigned short owner;
166    unsigned short users;
167    unsigned short group;
168    unsigned short groups;
169    unsigned short other;
170    unsigned short mask;
171};
172
173static void
174summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
175{
176    struct posix_acl_entry *pa, *pe;
177
178    /*
179     * Only pas.users and pas.groups need initialization; previous
180     * posix_acl_valid() calls ensure that the other fields will be
181     * initialized in the following loop. But, just to placate gcc:
182     */
183    memset(pas, 0, sizeof(*pas));
184    pas->mask = 07;
185
186    pe = acl->a_entries + acl->a_count;
187
188    FOREACH_ACL_ENTRY(pa, acl, pe) {
189        switch (pa->e_tag) {
190            case ACL_USER_OBJ:
191                pas->owner = pa->e_perm;
192                break;
193            case ACL_GROUP_OBJ:
194                pas->group = pa->e_perm;
195                break;
196            case ACL_USER:
197                pas->users |= pa->e_perm;
198                break;
199            case ACL_GROUP:
200                pas->groups |= pa->e_perm;
201                break;
202            case ACL_OTHER:
203                pas->other = pa->e_perm;
204                break;
205            case ACL_MASK:
206                pas->mask = pa->e_perm;
207                break;
208        }
209    }
210    /* We'll only care about effective permissions: */
211    pas->users &= pas->mask;
212    pas->group &= pas->mask;
213    pas->groups &= pas->mask;
214}
215
216/* We assume the acl has been verified with posix_acl_valid. */
217static void
218_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
219                        unsigned int flags)
220{
221    struct posix_acl_entry *pa, *group_owner_entry;
222    struct nfs4_ace *ace;
223    struct posix_acl_summary pas;
224    unsigned short deny;
225    int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
226        NFS4_INHERITANCE_FLAGS | NFS4_ACE_INHERIT_ONLY_ACE : 0);
227
228    BUG_ON(pacl->a_count < 3);
229    summarize_posix_acl(pacl, &pas);
230
231    pa = pacl->a_entries;
232    ace = acl->aces + acl->naces;
233
234    /* We could deny everything not granted by the owner: */
235    deny = ~pas.owner;
236    /*
237     * but it is equivalent (and simpler) to deny only what is not
238     * granted by later entries:
239     */
240    deny &= pas.users | pas.group | pas.groups | pas.other;
241    if (deny) {
242        ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
243        ace->flag = eflag;
244        ace->access_mask = deny_mask_from_posix(deny, flags);
245        ace->whotype = NFS4_ACL_WHO_OWNER;
246        ace++;
247        acl->naces++;
248    }
249
250    ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
251    ace->flag = eflag;
252    ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
253    ace->whotype = NFS4_ACL_WHO_OWNER;
254    ace++;
255    acl->naces++;
256    pa++;
257
258    while (pa->e_tag == ACL_USER) {
259        deny = ~(pa->e_perm & pas.mask);
260        deny &= pas.groups | pas.group | pas.other;
261        if (deny) {
262            ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
263            ace->flag = eflag;
264            ace->access_mask = deny_mask_from_posix(deny, flags);
265            ace->whotype = NFS4_ACL_WHO_NAMED;
266            ace->who = pa->e_id;
267            ace++;
268            acl->naces++;
269        }
270        ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
271        ace->flag = eflag;
272        ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
273                           flags);
274        ace->whotype = NFS4_ACL_WHO_NAMED;
275        ace->who = pa->e_id;
276        ace++;
277        acl->naces++;
278        pa++;
279    }
280
281    /* In the case of groups, we apply allow ACEs first, then deny ACEs,
282     * since a user can be in more than one group. */
283
284    /* allow ACEs */
285
286    group_owner_entry = pa;
287
288    ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
289    ace->flag = eflag;
290    ace->access_mask = mask_from_posix(pas.group, flags);
291    ace->whotype = NFS4_ACL_WHO_GROUP;
292    ace++;
293    acl->naces++;
294    pa++;
295
296    while (pa->e_tag == ACL_GROUP) {
297        ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
298        ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
299        ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
300                           flags);
301        ace->whotype = NFS4_ACL_WHO_NAMED;
302        ace->who = pa->e_id;
303        ace++;
304        acl->naces++;
305        pa++;
306    }
307
308    /* deny ACEs */
309
310    pa = group_owner_entry;
311
312    deny = ~pas.group & pas.other;
313    if (deny) {
314        ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
315        ace->flag = eflag;
316        ace->access_mask = deny_mask_from_posix(deny, flags);
317        ace->whotype = NFS4_ACL_WHO_GROUP;
318        ace++;
319        acl->naces++;
320    }
321    pa++;
322
323    while (pa->e_tag == ACL_GROUP) {
324        deny = ~(pa->e_perm & pas.mask);
325        deny &= pas.other;
326        if (deny) {
327            ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
328            ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
329            ace->access_mask = deny_mask_from_posix(deny, flags);
330            ace->whotype = NFS4_ACL_WHO_NAMED;
331            ace->who = pa->e_id;
332            ace++;
333            acl->naces++;
334        }
335        pa++;
336    }
337
338    if (pa->e_tag == ACL_MASK)
339        pa++;
340    ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
341    ace->flag = eflag;
342    ace->access_mask = mask_from_posix(pa->e_perm, flags);
343    ace->whotype = NFS4_ACL_WHO_EVERYONE;
344    acl->naces++;
345}
346
347static void
348sort_pacl_range(struct posix_acl *pacl, int start, int end) {
349    int sorted = 0, i;
350    struct posix_acl_entry tmp;
351
352    /* We just do a bubble sort; easy to do in place, and we're not
353     * expecting acl's to be long enough to justify anything more. */
354    while (!sorted) {
355        sorted = 1;
356        for (i = start; i < end; i++) {
357            if (pacl->a_entries[i].e_id
358                    > pacl->a_entries[i+1].e_id) {
359                sorted = 0;
360                tmp = pacl->a_entries[i];
361                pacl->a_entries[i] = pacl->a_entries[i+1];
362                pacl->a_entries[i+1] = tmp;
363            }
364        }
365    }
366}
367
368static void
369sort_pacl(struct posix_acl *pacl)
370{
371    /* posix_acl_valid requires that users and groups be in order
372     * by uid/gid. */
373    int i, j;
374
375    if (pacl->a_count <= 4)
376        return; /* no users or groups */
377    i = 1;
378    while (pacl->a_entries[i].e_tag == ACL_USER)
379        i++;
380    sort_pacl_range(pacl, 1, i-1);
381
382    BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
383    j = ++i;
384    while (pacl->a_entries[j].e_tag == ACL_GROUP)
385        j++;
386    sort_pacl_range(pacl, i, j-1);
387    return;
388}
389
390/*
391 * While processing the NFSv4 ACE, this maintains bitmasks representing
392 * which permission bits have been allowed and which denied to a given
393 * entity: */
394struct posix_ace_state {
395    u32 allow;
396    u32 deny;
397};
398
399struct posix_user_ace_state {
400    uid_t uid;
401    struct posix_ace_state perms;
402};
403
404struct posix_ace_state_array {
405    int n;
406    struct posix_user_ace_state aces[];
407};
408
409/*
410 * While processing the NFSv4 ACE, this maintains the partial permissions
411 * calculated so far: */
412
413struct posix_acl_state {
414    int empty;
415    struct posix_ace_state owner;
416    struct posix_ace_state group;
417    struct posix_ace_state other;
418    struct posix_ace_state everyone;
419    struct posix_ace_state mask; /* Deny unused in this case */
420    struct posix_ace_state_array *users;
421    struct posix_ace_state_array *groups;
422};
423
424static int
425init_state(struct posix_acl_state *state, int cnt)
426{
427    int alloc;
428
429    memset(state, 0, sizeof(struct posix_acl_state));
430    state->empty = 1;
431    /*
432     * In the worst case, each individual acl could be for a distinct
433     * named user or group, but we don't no which, so we allocate
434     * enough space for either:
435     */
436    alloc = sizeof(struct posix_ace_state_array)
437        + cnt*sizeof(struct posix_user_ace_state);
438    state->users = kzalloc(alloc, GFP_KERNEL);
439    if (!state->users)
440        return -ENOMEM;
441    state->groups = kzalloc(alloc, GFP_KERNEL);
442    if (!state->groups) {
443        kfree(state->users);
444        return -ENOMEM;
445    }
446    return 0;
447}
448
449static void
450free_state(struct posix_acl_state *state) {
451    kfree(state->users);
452    kfree(state->groups);
453}
454
455static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_state *astate)
456{
457    state->mask.allow |= astate->allow;
458}
459
460/*
461 * Certain bits (SYNCHRONIZE, DELETE, WRITE_OWNER, READ/WRITE_NAMED_ATTRS,
462 * READ_ATTRIBUTES, READ_ACL) are currently unenforceable and don't translate
463 * to traditional read/write/execute permissions.
464 *
465 * It's problematic to reject acls that use certain mode bits, because it
466 * places the burden on users to learn the rules about which bits one
467 * particular server sets, without giving the user a lot of help--we return an
468 * error that could mean any number of different things. To make matters
469 * worse, the problematic bits might be introduced by some application that's
470 * automatically mapping from some other acl model.
471 *
472 * So wherever possible we accept anything, possibly erring on the side of
473 * denying more permissions than necessary.
474 *
475 * However we do reject *explicit* DENY's of a few bits representing
476 * permissions we could never deny:
477 */
478
479static inline int check_deny(u32 mask, int isowner)
480{
481    if (mask & (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL))
482        return -EINVAL;
483    if (!isowner)
484        return 0;
485    if (mask & (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL))
486        return -EINVAL;
487    return 0;
488}
489
490static struct posix_acl *
491posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
492{
493    struct posix_acl_entry *pace;
494    struct posix_acl *pacl;
495    int nace;
496    int i, error = 0;
497
498    /*
499     * ACLs with no ACEs are treated differently in the inheritable
500     * and effective cases: when there are no inheritable ACEs, we
501     * set a zero-length default posix acl:
502     */
503    if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {
504        pacl = posix_acl_alloc(0, GFP_KERNEL);
505        return pacl ? pacl : ERR_PTR(-ENOMEM);
506    }
507    /*
508     * When there are no effective ACEs, the following will end
509     * up setting a 3-element effective posix ACL with all
510     * permissions zero.
511     */
512    nace = 4 + state->users->n + state->groups->n;
513    pacl = posix_acl_alloc(nace, GFP_KERNEL);
514    if (!pacl)
515        return ERR_PTR(-ENOMEM);
516
517    pace = pacl->a_entries;
518    pace->e_tag = ACL_USER_OBJ;
519    error = check_deny(state->owner.deny, 1);
520    if (error)
521        goto out_err;
522    low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
523    pace->e_id = ACL_UNDEFINED_ID;
524
525    for (i=0; i < state->users->n; i++) {
526        pace++;
527        pace->e_tag = ACL_USER;
528        error = check_deny(state->users->aces[i].perms.deny, 0);
529        if (error)
530            goto out_err;
531        low_mode_from_nfs4(state->users->aces[i].perms.allow,
532                    &pace->e_perm, flags);
533        pace->e_id = state->users->aces[i].uid;
534        add_to_mask(state, &state->users->aces[i].perms);
535    }
536
537    pace++;
538    pace->e_tag = ACL_GROUP_OBJ;
539    error = check_deny(state->group.deny, 0);
540    if (error)
541        goto out_err;
542    low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
543    pace->e_id = ACL_UNDEFINED_ID;
544    add_to_mask(state, &state->group);
545
546    for (i=0; i < state->groups->n; i++) {
547        pace++;
548        pace->e_tag = ACL_GROUP;
549        error = check_deny(state->groups->aces[i].perms.deny, 0);
550        if (error)
551            goto out_err;
552        low_mode_from_nfs4(state->groups->aces[i].perms.allow,
553                    &pace->e_perm, flags);
554        pace->e_id = state->groups->aces[i].uid;
555        add_to_mask(state, &state->groups->aces[i].perms);
556    }
557
558    pace++;
559    pace->e_tag = ACL_MASK;
560    low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
561    pace->e_id = ACL_UNDEFINED_ID;
562
563    pace++;
564    pace->e_tag = ACL_OTHER;
565    error = check_deny(state->other.deny, 0);
566    if (error)
567        goto out_err;
568    low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
569    pace->e_id = ACL_UNDEFINED_ID;
570
571    return pacl;
572out_err:
573    posix_acl_release(pacl);
574    return ERR_PTR(error);
575}
576
577static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
578{
579    /* Allow all bits in the mask not already denied: */
580    astate->allow |= mask & ~astate->deny;
581}
582
583static inline void deny_bits(struct posix_ace_state *astate, u32 mask)
584{
585    /* Deny all bits in the mask not already allowed: */
586    astate->deny |= mask & ~astate->allow;
587}
588
589static int find_uid(struct posix_acl_state *state, struct posix_ace_state_array *a, uid_t uid)
590{
591    int i;
592
593    for (i = 0; i < a->n; i++)
594        if (a->aces[i].uid == uid)
595            return i;
596    /* Not found: */
597    a->n++;
598    a->aces[i].uid = uid;
599    a->aces[i].perms.allow = state->everyone.allow;
600    a->aces[i].perms.deny = state->everyone.deny;
601
602    return i;
603}
604
605static void deny_bits_array(struct posix_ace_state_array *a, u32 mask)
606{
607    int i;
608
609    for (i=0; i < a->n; i++)
610        deny_bits(&a->aces[i].perms, mask);
611}
612
613static void allow_bits_array(struct posix_ace_state_array *a, u32 mask)
614{
615    int i;
616
617    for (i=0; i < a->n; i++)
618        allow_bits(&a->aces[i].perms, mask);
619}
620
621static void process_one_v4_ace(struct posix_acl_state *state,
622                struct nfs4_ace *ace)
623{
624    u32 mask = ace->access_mask;
625    int i;
626
627    state->empty = 0;
628
629    switch (ace2type(ace)) {
630    case ACL_USER_OBJ:
631        if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
632            allow_bits(&state->owner, mask);
633        } else {
634            deny_bits(&state->owner, mask);
635        }
636        break;
637    case ACL_USER:
638        i = find_uid(state, state->users, ace->who);
639        if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
640            allow_bits(&state->users->aces[i].perms, mask);
641        } else {
642            deny_bits(&state->users->aces[i].perms, mask);
643            mask = state->users->aces[i].perms.deny;
644            deny_bits(&state->owner, mask);
645        }
646        break;
647    case ACL_GROUP_OBJ:
648        if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
649            allow_bits(&state->group, mask);
650        } else {
651            deny_bits(&state->group, mask);
652            mask = state->group.deny;
653            deny_bits(&state->owner, mask);
654            deny_bits(&state->everyone, mask);
655            deny_bits_array(state->users, mask);
656            deny_bits_array(state->groups, mask);
657        }
658        break;
659    case ACL_GROUP:
660        i = find_uid(state, state->groups, ace->who);
661        if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
662            allow_bits(&state->groups->aces[i].perms, mask);
663        } else {
664            deny_bits(&state->groups->aces[i].perms, mask);
665            mask = state->groups->aces[i].perms.deny;
666            deny_bits(&state->owner, mask);
667            deny_bits(&state->group, mask);
668            deny_bits(&state->everyone, mask);
669            deny_bits_array(state->users, mask);
670            deny_bits_array(state->groups, mask);
671        }
672        break;
673    case ACL_OTHER:
674        if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
675            allow_bits(&state->owner, mask);
676            allow_bits(&state->group, mask);
677            allow_bits(&state->other, mask);
678            allow_bits(&state->everyone, mask);
679            allow_bits_array(state->users, mask);
680            allow_bits_array(state->groups, mask);
681        } else {
682            deny_bits(&state->owner, mask);
683            deny_bits(&state->group, mask);
684            deny_bits(&state->other, mask);
685            deny_bits(&state->everyone, mask);
686            deny_bits_array(state->users, mask);
687            deny_bits_array(state->groups, mask);
688        }
689    }
690}
691
692int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
693                struct posix_acl **dpacl, unsigned int flags)
694{
695    struct posix_acl_state effective_acl_state, default_acl_state;
696    struct nfs4_ace *ace;
697    int ret;
698
699    ret = init_state(&effective_acl_state, acl->naces);
700    if (ret)
701        return ret;
702    ret = init_state(&default_acl_state, acl->naces);
703    if (ret)
704        goto out_estate;
705    ret = -EINVAL;
706    for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
707        if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
708            ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
709            goto out_dstate;
710        if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
711            goto out_dstate;
712        if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
713            process_one_v4_ace(&effective_acl_state, ace);
714            continue;
715        }
716        if (!(flags & NFS4_ACL_DIR))
717            goto out_dstate;
718        /*
719         * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
720         * is set, we're effectively turning on the other. That's OK,
721         * according to rfc 3530.
722         */
723        process_one_v4_ace(&default_acl_state, ace);
724
725        if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
726            process_one_v4_ace(&effective_acl_state, ace);
727    }
728    *pacl = posix_state_to_acl(&effective_acl_state, flags);
729    if (IS_ERR(*pacl)) {
730        ret = PTR_ERR(*pacl);
731        *pacl = NULL;
732        goto out_dstate;
733    }
734    *dpacl = posix_state_to_acl(&default_acl_state,
735                        flags | NFS4_ACL_TYPE_DEFAULT);
736    if (IS_ERR(*dpacl)) {
737        ret = PTR_ERR(*dpacl);
738        *dpacl = NULL;
739        posix_acl_release(*pacl);
740        *pacl = NULL;
741        goto out_dstate;
742    }
743    sort_pacl(*pacl);
744    sort_pacl(*dpacl);
745    ret = 0;
746out_dstate:
747    free_state(&default_acl_state);
748out_estate:
749    free_state(&effective_acl_state);
750    return ret;
751}
752
753static short
754ace2type(struct nfs4_ace *ace)
755{
756    switch (ace->whotype) {
757        case NFS4_ACL_WHO_NAMED:
758            return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
759                    ACL_GROUP : ACL_USER);
760        case NFS4_ACL_WHO_OWNER:
761            return ACL_USER_OBJ;
762        case NFS4_ACL_WHO_GROUP:
763            return ACL_GROUP_OBJ;
764        case NFS4_ACL_WHO_EVERYONE:
765            return ACL_OTHER;
766    }
767    BUG();
768    return -1;
769}
770
771EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
772EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
773
774struct nfs4_acl *
775nfs4_acl_new(int n)
776{
777    struct nfs4_acl *acl;
778
779    acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
780    if (acl == NULL)
781        return NULL;
782    acl->naces = 0;
783    return acl;
784}
785
786static struct {
787    char *string;
788    int stringlen;
789    int type;
790} s2t_map[] = {
791    {
792        .string = "OWNER@",
793        .stringlen = sizeof("OWNER@") - 1,
794        .type = NFS4_ACL_WHO_OWNER,
795    },
796    {
797        .string = "GROUP@",
798        .stringlen = sizeof("GROUP@") - 1,
799        .type = NFS4_ACL_WHO_GROUP,
800    },
801    {
802        .string = "EVERYONE@",
803        .stringlen = sizeof("EVERYONE@") - 1,
804        .type = NFS4_ACL_WHO_EVERYONE,
805    },
806};
807
808int
809nfs4_acl_get_whotype(char *p, u32 len)
810{
811    int i;
812
813    for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
814        if (s2t_map[i].stringlen == len &&
815                0 == memcmp(s2t_map[i].string, p, len))
816            return s2t_map[i].type;
817    }
818    return NFS4_ACL_WHO_NAMED;
819}
820
821int
822nfs4_acl_write_who(int who, char *p)
823{
824    int i;
825
826    for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
827        if (s2t_map[i].type == who) {
828            memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
829            return s2t_map[i].stringlen;
830        }
831    }
832    BUG();
833    return -1;
834}
835
836EXPORT_SYMBOL(nfs4_acl_new);
837EXPORT_SYMBOL(nfs4_acl_get_whotype);
838EXPORT_SYMBOL(nfs4_acl_write_who);
839

Archive Download this file



interactive