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