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/fs.h>
  38#include <linux/slab.h>
  39#include <linux/posix_acl.h>
  40
  41#include "nfsfh.h"
  42#include "nfsd.h"
  43#include "acl.h"
  44#include "vfs.h"
  45
  46#define NFS4_ACL_TYPE_DEFAULT   0x01
  47#define NFS4_ACL_DIR            0x02
  48#define NFS4_ACL_OWNER          0x04
  49
  50/* mode bit translations: */
  51#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
  52#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
  53#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
  54#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
  55#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
  56
  57/* flags used to simulate posix default ACLs */
  58#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
  59                | NFS4_ACE_DIRECTORY_INHERIT_ACE)
  60
  61#define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
  62                | NFS4_ACE_INHERIT_ONLY_ACE \
  63                | NFS4_ACE_IDENTIFIER_GROUP)
  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 expect 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
 124static short ace2type(struct nfs4_ace *);
 125static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
 126                                unsigned int);
 127
 128int
 129nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
 130                struct nfs4_acl **acl)
 131{
 132        struct inode *inode = d_inode(dentry);
 133        int error = 0;
 134        struct posix_acl *pacl = NULL, *dpacl = NULL;
 135        unsigned int flags = 0;
 136        int size = 0;
 137
 138        pacl = get_acl(inode, ACL_TYPE_ACCESS);
 139        if (!pacl)
 140                pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 141
 142        if (IS_ERR(pacl))
 143                return PTR_ERR(pacl);
 144
 145        /* allocate for worst case: one (deny, allow) pair each: */
 146        size += 2 * pacl->a_count;
 147
 148        if (S_ISDIR(inode->i_mode)) {
 149                flags = NFS4_ACL_DIR;
 150                dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
 151                if (IS_ERR(dpacl)) {
 152                        error = PTR_ERR(dpacl);
 153                        goto rel_pacl;
 154                }
 155
 156                if (dpacl)
 157                        size += 2 * dpacl->a_count;
 158        }
 159
 160        *acl = kmalloc(nfs4_acl_bytes(size), GFP_KERNEL);
 161        if (*acl == NULL) {
 162                error = -ENOMEM;
 163                goto out;
 164        }
 165        (*acl)->naces = 0;
 166
 167        _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
 168
 169        if (dpacl)
 170                _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
 171
 172out:
 173        posix_acl_release(dpacl);
 174rel_pacl:
 175        posix_acl_release(pacl);
 176        return error;
 177}
 178
 179struct posix_acl_summary {
 180        unsigned short owner;
 181        unsigned short users;
 182        unsigned short group;
 183        unsigned short groups;
 184        unsigned short other;
 185        unsigned short mask;
 186};
 187
 188static void
 189summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
 190{
 191        struct posix_acl_entry *pa, *pe;
 192
 193        /*
 194         * Only pas.users and pas.groups need initialization; previous
 195         * posix_acl_valid() calls ensure that the other fields will be
 196         * initialized in the following loop.  But, just to placate gcc:
 197         */
 198        memset(pas, 0, sizeof(*pas));
 199        pas->mask = 07;
 200
 201        pe = acl->a_entries + acl->a_count;
 202
 203        FOREACH_ACL_ENTRY(pa, acl, pe) {
 204                switch (pa->e_tag) {
 205                        case ACL_USER_OBJ:
 206                                pas->owner = pa->e_perm;
 207                                break;
 208                        case ACL_GROUP_OBJ:
 209                                pas->group = pa->e_perm;
 210                                break;
 211                        case ACL_USER:
 212                                pas->users |= pa->e_perm;
 213                                break;
 214                        case ACL_GROUP:
 215                                pas->groups |= pa->e_perm;
 216                                break;
 217                        case ACL_OTHER:
 218                                pas->other = pa->e_perm;
 219                                break;
 220                        case ACL_MASK:
 221                                pas->mask = pa->e_perm;
 222                                break;
 223                }
 224        }
 225        /* We'll only care about effective permissions: */
 226        pas->users &= pas->mask;
 227        pas->group &= pas->mask;
 228        pas->groups &= pas->mask;
 229}
 230
 231/* We assume the acl has been verified with posix_acl_valid. */
 232static void
 233_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
 234                                                unsigned int flags)
 235{
 236        struct posix_acl_entry *pa, *group_owner_entry;
 237        struct nfs4_ace *ace;
 238        struct posix_acl_summary pas;
 239        unsigned short deny;
 240        int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
 241                NFS4_INHERITANCE_FLAGS | NFS4_ACE_INHERIT_ONLY_ACE : 0);
 242
 243        BUG_ON(pacl->a_count < 3);
 244        summarize_posix_acl(pacl, &pas);
 245
 246        pa = pacl->a_entries;
 247        ace = acl->aces + acl->naces;
 248
 249        /* We could deny everything not granted by the owner: */
 250        deny = ~pas.owner;
 251        /*
 252         * but it is equivalent (and simpler) to deny only what is not
 253         * granted by later entries:
 254         */
 255        deny &= pas.users | pas.group | pas.groups | pas.other;
 256        if (deny) {
 257                ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
 258                ace->flag = eflag;
 259                ace->access_mask = deny_mask_from_posix(deny, flags);
 260                ace->whotype = NFS4_ACL_WHO_OWNER;
 261                ace++;
 262                acl->naces++;
 263        }
 264
 265        ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
 266        ace->flag = eflag;
 267        ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
 268        ace->whotype = NFS4_ACL_WHO_OWNER;
 269        ace++;
 270        acl->naces++;
 271        pa++;
 272
 273        while (pa->e_tag == ACL_USER) {
 274                deny = ~(pa->e_perm & pas.mask);
 275                deny &= pas.groups | pas.group | pas.other;
 276                if (deny) {
 277                        ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
 278                        ace->flag = eflag;
 279                        ace->access_mask = deny_mask_from_posix(deny, flags);
 280                        ace->whotype = NFS4_ACL_WHO_NAMED;
 281                        ace->who_uid = pa->e_uid;
 282                        ace++;
 283                        acl->naces++;
 284                }
 285                ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
 286                ace->flag = eflag;
 287                ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
 288                                                   flags);
 289                ace->whotype = NFS4_ACL_WHO_NAMED;
 290                ace->who_uid = pa->e_uid;
 291                ace++;
 292                acl->naces++;
 293                pa++;
 294        }
 295
 296        /* In the case of groups, we apply allow ACEs first, then deny ACEs,
 297         * since a user can be in more than one group.  */
 298
 299        /* allow ACEs */
 300
 301        group_owner_entry = pa;
 302
 303        ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
 304        ace->flag = eflag;
 305        ace->access_mask = mask_from_posix(pas.group, flags);
 306        ace->whotype = NFS4_ACL_WHO_GROUP;
 307        ace++;
 308        acl->naces++;
 309        pa++;
 310
 311        while (pa->e_tag == ACL_GROUP) {
 312                ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
 313                ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
 314                ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
 315                                                   flags);
 316                ace->whotype = NFS4_ACL_WHO_NAMED;
 317                ace->who_gid = pa->e_gid;
 318                ace++;
 319                acl->naces++;
 320                pa++;
 321        }
 322
 323        /* deny ACEs */
 324
 325        pa = group_owner_entry;
 326
 327        deny = ~pas.group & pas.other;
 328        if (deny) {
 329                ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
 330                ace->flag = eflag;
 331                ace->access_mask = deny_mask_from_posix(deny, flags);
 332                ace->whotype = NFS4_ACL_WHO_GROUP;
 333                ace++;
 334                acl->naces++;
 335        }
 336        pa++;
 337
 338        while (pa->e_tag == ACL_GROUP) {
 339                deny = ~(pa->e_perm & pas.mask);
 340                deny &= pas.other;
 341                if (deny) {
 342                        ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
 343                        ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
 344                        ace->access_mask = deny_mask_from_posix(deny, flags);
 345                        ace->whotype = NFS4_ACL_WHO_NAMED;
 346                        ace->who_gid = pa->e_gid;
 347                        ace++;
 348                        acl->naces++;
 349                }
 350                pa++;
 351        }
 352
 353        if (pa->e_tag == ACL_MASK)
 354                pa++;
 355        ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
 356        ace->flag = eflag;
 357        ace->access_mask = mask_from_posix(pa->e_perm, flags);
 358        ace->whotype = NFS4_ACL_WHO_EVERYONE;
 359        acl->naces++;
 360}
 361
 362static bool
 363pace_gt(struct posix_acl_entry *pace1, struct posix_acl_entry *pace2)
 364{
 365        if (pace1->e_tag != pace2->e_tag)
 366                return pace1->e_tag > pace2->e_tag;
 367        if (pace1->e_tag == ACL_USER)
 368                return uid_gt(pace1->e_uid, pace2->e_uid);
 369        if (pace1->e_tag == ACL_GROUP)
 370                return gid_gt(pace1->e_gid, pace2->e_gid);
 371        return false;
 372}
 373
 374static void
 375sort_pacl_range(struct posix_acl *pacl, int start, int end) {
 376        int sorted = 0, i;
 377
 378        /* We just do a bubble sort; easy to do in place, and we're not
 379         * expecting acl's to be long enough to justify anything more. */
 380        while (!sorted) {
 381                sorted = 1;
 382                for (i = start; i < end; i++) {
 383                        if (pace_gt(&pacl->a_entries[i],
 384                                    &pacl->a_entries[i+1])) {
 385                                sorted = 0;
 386                                swap(pacl->a_entries[i],
 387                                     pacl->a_entries[i + 1]);
 388                        }
 389                }
 390        }
 391}
 392
 393static void
 394sort_pacl(struct posix_acl *pacl)
 395{
 396        /* posix_acl_valid requires that users and groups be in order
 397         * by uid/gid. */
 398        int i, j;
 399
 400        /* no users or groups */
 401        if (!pacl || pacl->a_count <= 4)
 402                return;
 403
 404        i = 1;
 405        while (pacl->a_entries[i].e_tag == ACL_USER)
 406                i++;
 407        sort_pacl_range(pacl, 1, i-1);
 408
 409        BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
 410        j = ++i;
 411        while (pacl->a_entries[j].e_tag == ACL_GROUP)
 412                j++;
 413        sort_pacl_range(pacl, i, j-1);
 414        return;
 415}
 416
 417/*
 418 * While processing the NFSv4 ACE, this maintains bitmasks representing
 419 * which permission bits have been allowed and which denied to a given
 420 * entity: */
 421struct posix_ace_state {
 422        u32 allow;
 423        u32 deny;
 424};
 425
 426struct posix_user_ace_state {
 427        union {
 428                kuid_t uid;
 429                kgid_t gid;
 430        };
 431        struct posix_ace_state perms;
 432};
 433
 434struct posix_ace_state_array {
 435        int n;
 436        struct posix_user_ace_state aces[];
 437};
 438
 439/*
 440 * While processing the NFSv4 ACE, this maintains the partial permissions
 441 * calculated so far: */
 442
 443struct posix_acl_state {
 444        int empty;
 445        struct posix_ace_state owner;
 446        struct posix_ace_state group;
 447        struct posix_ace_state other;
 448        struct posix_ace_state everyone;
 449        struct posix_ace_state mask; /* Deny unused in this case */
 450        struct posix_ace_state_array *users;
 451        struct posix_ace_state_array *groups;
 452};
 453
 454static int
 455init_state(struct posix_acl_state *state, int cnt)
 456{
 457        int alloc;
 458
 459        memset(state, 0, sizeof(struct posix_acl_state));
 460        state->empty = 1;
 461        /*
 462         * In the worst case, each individual acl could be for a distinct
 463         * named user or group, but we don't know which, so we allocate
 464         * enough space for either:
 465         */
 466        alloc = sizeof(struct posix_ace_state_array)
 467                + cnt*sizeof(struct posix_user_ace_state);
 468        state->users = kzalloc(alloc, GFP_KERNEL);
 469        if (!state->users)
 470                return -ENOMEM;
 471        state->groups = kzalloc(alloc, GFP_KERNEL);
 472        if (!state->groups) {
 473                kfree(state->users);
 474                return -ENOMEM;
 475        }
 476        return 0;
 477}
 478
 479static void
 480free_state(struct posix_acl_state *state) {
 481        kfree(state->users);
 482        kfree(state->groups);
 483}
 484
 485static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_state *astate)
 486{
 487        state->mask.allow |= astate->allow;
 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;
 497
 498        /*
 499         * ACLs with no ACEs are treated differently in the inheritable
 500         * and effective cases: when there are no inheritable ACEs,
 501         * calls ->set_acl with a NULL ACL structure.
 502         */
 503        if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT))
 504                return NULL;
 505
 506        /*
 507         * When there are no effective ACEs, the following will end
 508         * up setting a 3-element effective posix ACL with all
 509         * permissions zero.
 510         */
 511        if (!state->users->n && !state->groups->n)
 512                nace = 3;
 513        else /* Note we also include a MASK ACE in this case: */
 514                nace = 4 + state->users->n + state->groups->n;
 515        pacl = posix_acl_alloc(nace, GFP_KERNEL);
 516        if (!pacl)
 517                return ERR_PTR(-ENOMEM);
 518
 519        pace = pacl->a_entries;
 520        pace->e_tag = ACL_USER_OBJ;
 521        low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
 522
 523        for (i=0; i < state->users->n; i++) {
 524                pace++;
 525                pace->e_tag = ACL_USER;
 526                low_mode_from_nfs4(state->users->aces[i].perms.allow,
 527                                        &pace->e_perm, flags);
 528                pace->e_uid = state->users->aces[i].uid;
 529                add_to_mask(state, &state->users->aces[i].perms);
 530        }
 531
 532        pace++;
 533        pace->e_tag = ACL_GROUP_OBJ;
 534        low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
 535        add_to_mask(state, &state->group);
 536
 537        for (i=0; i < state->groups->n; i++) {
 538                pace++;
 539                pace->e_tag = ACL_GROUP;
 540                low_mode_from_nfs4(state->groups->aces[i].perms.allow,
 541                                        &pace->e_perm, flags);
 542                pace->e_gid = state->groups->aces[i].gid;
 543                add_to_mask(state, &state->groups->aces[i].perms);
 544        }
 545
 546        if (state->users->n || state->groups->n) {
 547                pace++;
 548                pace->e_tag = ACL_MASK;
 549                low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
 550        }
 551
 552        pace++;
 553        pace->e_tag = ACL_OTHER;
 554        low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
 555
 556        return pacl;
 557}
 558
 559static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
 560{
 561        /* Allow all bits in the mask not already denied: */
 562        astate->allow |= mask & ~astate->deny;
 563}
 564
 565static inline void deny_bits(struct posix_ace_state *astate, u32 mask)
 566{
 567        /* Deny all bits in the mask not already allowed: */
 568        astate->deny |= mask & ~astate->allow;
 569}
 570
 571static int find_uid(struct posix_acl_state *state, kuid_t uid)
 572{
 573        struct posix_ace_state_array *a = state->users;
 574        int i;
 575
 576        for (i = 0; i < a->n; i++)
 577                if (uid_eq(a->aces[i].uid, uid))
 578                        return i;
 579        /* Not found: */
 580        a->n++;
 581        a->aces[i].uid = uid;
 582        a->aces[i].perms.allow = state->everyone.allow;
 583        a->aces[i].perms.deny  = state->everyone.deny;
 584
 585        return i;
 586}
 587
 588static int find_gid(struct posix_acl_state *state, kgid_t gid)
 589{
 590        struct posix_ace_state_array *a = state->groups;
 591        int i;
 592
 593        for (i = 0; i < a->n; i++)
 594                if (gid_eq(a->aces[i].gid, gid))
 595                        return i;
 596        /* Not found: */
 597        a->n++;
 598        a->aces[i].gid = gid;
 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, ace->who_uid);
 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_gid(state, ace->who_gid);
 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
 692static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
 693                struct posix_acl **pacl, struct posix_acl **dpacl,
 694                unsigned int flags)
 695{
 696        struct posix_acl_state effective_acl_state, default_acl_state;
 697        struct nfs4_ace *ace;
 698        int ret;
 699
 700        ret = init_state(&effective_acl_state, acl->naces);
 701        if (ret)
 702                return ret;
 703        ret = init_state(&default_acl_state, acl->naces);
 704        if (ret)
 705                goto out_estate;
 706        ret = -EINVAL;
 707        for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
 708                if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
 709                    ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
 710                        goto out_dstate;
 711                if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
 712                        goto out_dstate;
 713                if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
 714                        process_one_v4_ace(&effective_acl_state, ace);
 715                        continue;
 716                }
 717                if (!(flags & NFS4_ACL_DIR))
 718                        goto out_dstate;
 719                /*
 720                 * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT
 721                 * is set, we're effectively turning on the other.  That's OK,
 722                 * according to rfc 3530.
 723                 */
 724                process_one_v4_ace(&default_acl_state, ace);
 725
 726                if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
 727                        process_one_v4_ace(&effective_acl_state, ace);
 728        }
 729        *pacl = posix_state_to_acl(&effective_acl_state, flags);
 730        if (IS_ERR(*pacl)) {
 731                ret = PTR_ERR(*pacl);
 732                *pacl = NULL;
 733                goto out_dstate;
 734        }
 735        *dpacl = posix_state_to_acl(&default_acl_state,
 736                                                flags | NFS4_ACL_TYPE_DEFAULT);
 737        if (IS_ERR(*dpacl)) {
 738                ret = PTR_ERR(*dpacl);
 739                *dpacl = NULL;
 740                posix_acl_release(*pacl);
 741                *pacl = NULL;
 742                goto out_dstate;
 743        }
 744        sort_pacl(*pacl);
 745        sort_pacl(*dpacl);
 746        ret = 0;
 747out_dstate:
 748        free_state(&default_acl_state);
 749out_estate:
 750        free_state(&effective_acl_state);
 751        return ret;
 752}
 753
 754__be32
 755nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
 756                struct nfs4_acl *acl)
 757{
 758        __be32 error;
 759        int host_error;
 760        struct dentry *dentry;
 761        struct inode *inode;
 762        struct posix_acl *pacl = NULL, *dpacl = NULL;
 763        unsigned int flags = 0;
 764
 765        /* Get inode */
 766        error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
 767        if (error)
 768                return error;
 769
 770        dentry = fhp->fh_dentry;
 771        inode = d_inode(dentry);
 772
 773        if (S_ISDIR(inode->i_mode))
 774                flags = NFS4_ACL_DIR;
 775
 776        host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
 777        if (host_error == -EINVAL)
 778                return nfserr_attrnotsupp;
 779        if (host_error < 0)
 780                goto out_nfserr;
 781
 782        fh_lock(fhp);
 783
 784        host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl);
 785        if (host_error < 0)
 786                goto out_drop_lock;
 787
 788        if (S_ISDIR(inode->i_mode)) {
 789                host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl);
 790        }
 791
 792out_drop_lock:
 793        fh_unlock(fhp);
 794
 795        posix_acl_release(pacl);
 796        posix_acl_release(dpacl);
 797out_nfserr:
 798        if (host_error == -EOPNOTSUPP)
 799                return nfserr_attrnotsupp;
 800        else
 801                return nfserrno(host_error);
 802}
 803
 804
 805static short
 806ace2type(struct nfs4_ace *ace)
 807{
 808        switch (ace->whotype) {
 809                case NFS4_ACL_WHO_NAMED:
 810                        return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
 811                                        ACL_GROUP : ACL_USER);
 812                case NFS4_ACL_WHO_OWNER:
 813                        return ACL_USER_OBJ;
 814                case NFS4_ACL_WHO_GROUP:
 815                        return ACL_GROUP_OBJ;
 816                case NFS4_ACL_WHO_EVERYONE:
 817                        return ACL_OTHER;
 818        }
 819        BUG();
 820        return -1;
 821}
 822
 823/*
 824 * return the size of the struct nfs4_acl required to represent an acl
 825 * with @entries entries.
 826 */
 827int nfs4_acl_bytes(int entries)
 828{
 829        return sizeof(struct nfs4_acl) + entries * sizeof(struct nfs4_ace);
 830}
 831
 832static struct {
 833        char *string;
 834        int   stringlen;
 835        int type;
 836} s2t_map[] = {
 837        {
 838                .string    = "OWNER@",
 839                .stringlen = sizeof("OWNER@") - 1,
 840                .type      = NFS4_ACL_WHO_OWNER,
 841        },
 842        {
 843                .string    = "GROUP@",
 844                .stringlen = sizeof("GROUP@") - 1,
 845                .type      = NFS4_ACL_WHO_GROUP,
 846        },
 847        {
 848                .string    = "EVERYONE@",
 849                .stringlen = sizeof("EVERYONE@") - 1,
 850                .type      = NFS4_ACL_WHO_EVERYONE,
 851        },
 852};
 853
 854int
 855nfs4_acl_get_whotype(char *p, u32 len)
 856{
 857        int i;
 858
 859        for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
 860                if (s2t_map[i].stringlen == len &&
 861                                0 == memcmp(s2t_map[i].string, p, len))
 862                        return s2t_map[i].type;
 863        }
 864        return NFS4_ACL_WHO_NAMED;
 865}
 866
 867__be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who)
 868{
 869        __be32 *p;
 870        int i;
 871
 872        for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
 873                if (s2t_map[i].type != who)
 874                        continue;
 875                p = xdr_reserve_space(xdr, s2t_map[i].stringlen + 4);
 876                if (!p)
 877                        return nfserr_resource;
 878                p = xdr_encode_opaque(p, s2t_map[i].string,
 879                                        s2t_map[i].stringlen);
 880                return 0;
 881        }
 882        WARN_ON_ONCE(1);
 883        return nfserr_serverfault;
 884}
 885