linux/fs/posix_acl.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002,2003 by Andreas Gruenbacher <a.gruenbacher@computer.org>
   3 *
   4 * Fixes from William Schumacher incorporated on 15 March 2001.
   5 *    (Reported by Charles Bertsch, <CBertsch@microtest.com>).
   6 */
   7
   8/*
   9 *  This file contains generic functions for manipulating
  10 *  POSIX 1003.1e draft standard 17 ACLs.
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/slab.h>
  15#include <linux/atomic.h>
  16#include <linux/fs.h>
  17#include <linux/sched.h>
  18#include <linux/posix_acl.h>
  19#include <linux/posix_acl_xattr.h>
  20#include <linux/xattr.h>
  21#include <linux/export.h>
  22#include <linux/user_namespace.h>
  23
  24static struct posix_acl **acl_by_type(struct inode *inode, int type)
  25{
  26        switch (type) {
  27        case ACL_TYPE_ACCESS:
  28                return &inode->i_acl;
  29        case ACL_TYPE_DEFAULT:
  30                return &inode->i_default_acl;
  31        default:
  32                BUG();
  33        }
  34}
  35
  36struct posix_acl *get_cached_acl(struct inode *inode, int type)
  37{
  38        struct posix_acl **p = acl_by_type(inode, type);
  39        struct posix_acl *acl;
  40
  41        for (;;) {
  42                rcu_read_lock();
  43                acl = rcu_dereference(*p);
  44                if (!acl || is_uncached_acl(acl) ||
  45                    atomic_inc_not_zero(&acl->a_refcount))
  46                        break;
  47                rcu_read_unlock();
  48                cpu_relax();
  49        }
  50        rcu_read_unlock();
  51        return acl;
  52}
  53EXPORT_SYMBOL(get_cached_acl);
  54
  55struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
  56{
  57        return rcu_dereference(*acl_by_type(inode, type));
  58}
  59EXPORT_SYMBOL(get_cached_acl_rcu);
  60
  61void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl)
  62{
  63        struct posix_acl **p = acl_by_type(inode, type);
  64        struct posix_acl *old;
  65
  66        old = xchg(p, posix_acl_dup(acl));
  67        if (!is_uncached_acl(old))
  68                posix_acl_release(old);
  69}
  70EXPORT_SYMBOL(set_cached_acl);
  71
  72static void __forget_cached_acl(struct posix_acl **p)
  73{
  74        struct posix_acl *old;
  75
  76        old = xchg(p, ACL_NOT_CACHED);
  77        if (!is_uncached_acl(old))
  78                posix_acl_release(old);
  79}
  80
  81void forget_cached_acl(struct inode *inode, int type)
  82{
  83        __forget_cached_acl(acl_by_type(inode, type));
  84}
  85EXPORT_SYMBOL(forget_cached_acl);
  86
  87void forget_all_cached_acls(struct inode *inode)
  88{
  89        __forget_cached_acl(&inode->i_acl);
  90        __forget_cached_acl(&inode->i_default_acl);
  91}
  92EXPORT_SYMBOL(forget_all_cached_acls);
  93
  94struct posix_acl *get_acl(struct inode *inode, int type)
  95{
  96        void *sentinel;
  97        struct posix_acl **p;
  98        struct posix_acl *acl;
  99
 100        /*
 101         * The sentinel is used to detect when another operation like
 102         * set_cached_acl() or forget_cached_acl() races with get_acl().
 103         * It is guaranteed that is_uncached_acl(sentinel) is true.
 104         */
 105
 106        acl = get_cached_acl(inode, type);
 107        if (!is_uncached_acl(acl))
 108                return acl;
 109
 110        if (!IS_POSIXACL(inode))
 111                return NULL;
 112
 113        sentinel = uncached_acl_sentinel(current);
 114        p = acl_by_type(inode, type);
 115
 116        /*
 117         * If the ACL isn't being read yet, set our sentinel.  Otherwise, the
 118         * current value of the ACL will not be ACL_NOT_CACHED and so our own
 119         * sentinel will not be set; another task will update the cache.  We
 120         * could wait for that other task to complete its job, but it's easier
 121         * to just call ->get_acl to fetch the ACL ourself.  (This is going to
 122         * be an unlikely race.)
 123         */
 124        if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED)
 125                /* fall through */ ;
 126
 127        /*
 128         * Normally, the ACL returned by ->get_acl will be cached.
 129         * A filesystem can prevent that by calling
 130         * forget_cached_acl(inode, type) in ->get_acl.
 131         *
 132         * If the filesystem doesn't have a get_acl() function at all, we'll
 133         * just create the negative cache entry.
 134         */
 135        if (!inode->i_op->get_acl) {
 136                set_cached_acl(inode, type, NULL);
 137                return NULL;
 138        }
 139        acl = inode->i_op->get_acl(inode, type);
 140
 141        if (IS_ERR(acl)) {
 142                /*
 143                 * Remove our sentinel so that we don't block future attempts
 144                 * to cache the ACL.
 145                 */
 146                cmpxchg(p, sentinel, ACL_NOT_CACHED);
 147                return acl;
 148        }
 149
 150        /*
 151         * Cache the result, but only if our sentinel is still in place.
 152         */
 153        posix_acl_dup(acl);
 154        if (unlikely(cmpxchg(p, sentinel, acl) != sentinel))
 155                posix_acl_release(acl);
 156        return acl;
 157}
 158EXPORT_SYMBOL(get_acl);
 159
 160/*
 161 * Init a fresh posix_acl
 162 */
 163void
 164posix_acl_init(struct posix_acl *acl, int count)
 165{
 166        atomic_set(&acl->a_refcount, 1);
 167        acl->a_count = count;
 168}
 169EXPORT_SYMBOL(posix_acl_init);
 170
 171/*
 172 * Allocate a new ACL with the specified number of entries.
 173 */
 174struct posix_acl *
 175posix_acl_alloc(int count, gfp_t flags)
 176{
 177        const size_t size = sizeof(struct posix_acl) +
 178                            count * sizeof(struct posix_acl_entry);
 179        struct posix_acl *acl = kmalloc(size, flags);
 180        if (acl)
 181                posix_acl_init(acl, count);
 182        return acl;
 183}
 184EXPORT_SYMBOL(posix_acl_alloc);
 185
 186/*
 187 * Clone an ACL.
 188 */
 189static struct posix_acl *
 190posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
 191{
 192        struct posix_acl *clone = NULL;
 193
 194        if (acl) {
 195                int size = sizeof(struct posix_acl) + acl->a_count *
 196                           sizeof(struct posix_acl_entry);
 197                clone = kmemdup(acl, size, flags);
 198                if (clone)
 199                        atomic_set(&clone->a_refcount, 1);
 200        }
 201        return clone;
 202}
 203
 204/*
 205 * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
 206 */
 207int
 208posix_acl_valid(struct user_namespace *user_ns, const struct posix_acl *acl)
 209{
 210        const struct posix_acl_entry *pa, *pe;
 211        int state = ACL_USER_OBJ;
 212        int needs_mask = 0;
 213
 214        FOREACH_ACL_ENTRY(pa, acl, pe) {
 215                if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
 216                        return -EINVAL;
 217                switch (pa->e_tag) {
 218                        case ACL_USER_OBJ:
 219                                if (state == ACL_USER_OBJ) {
 220                                        state = ACL_USER;
 221                                        break;
 222                                }
 223                                return -EINVAL;
 224
 225                        case ACL_USER:
 226                                if (state != ACL_USER)
 227                                        return -EINVAL;
 228                                if (!kuid_has_mapping(user_ns, pa->e_uid))
 229                                        return -EINVAL;
 230                                needs_mask = 1;
 231                                break;
 232
 233                        case ACL_GROUP_OBJ:
 234                                if (state == ACL_USER) {
 235                                        state = ACL_GROUP;
 236                                        break;
 237                                }
 238                                return -EINVAL;
 239
 240                        case ACL_GROUP:
 241                                if (state != ACL_GROUP)
 242                                        return -EINVAL;
 243                                if (!kgid_has_mapping(user_ns, pa->e_gid))
 244                                        return -EINVAL;
 245                                needs_mask = 1;
 246                                break;
 247
 248                        case ACL_MASK:
 249                                if (state != ACL_GROUP)
 250                                        return -EINVAL;
 251                                state = ACL_OTHER;
 252                                break;
 253
 254                        case ACL_OTHER:
 255                                if (state == ACL_OTHER ||
 256                                    (state == ACL_GROUP && !needs_mask)) {
 257                                        state = 0;
 258                                        break;
 259                                }
 260                                return -EINVAL;
 261
 262                        default:
 263                                return -EINVAL;
 264                }
 265        }
 266        if (state == 0)
 267                return 0;
 268        return -EINVAL;
 269}
 270EXPORT_SYMBOL(posix_acl_valid);
 271
 272/*
 273 * Returns 0 if the acl can be exactly represented in the traditional
 274 * file mode permission bits, or else 1. Returns -E... on error.
 275 */
 276int
 277posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
 278{
 279        const struct posix_acl_entry *pa, *pe;
 280        umode_t mode = 0;
 281        int not_equiv = 0;
 282
 283        /*
 284         * A null ACL can always be presented as mode bits.
 285         */
 286        if (!acl)
 287                return 0;
 288
 289        FOREACH_ACL_ENTRY(pa, acl, pe) {
 290                switch (pa->e_tag) {
 291                        case ACL_USER_OBJ:
 292                                mode |= (pa->e_perm & S_IRWXO) << 6;
 293                                break;
 294                        case ACL_GROUP_OBJ:
 295                                mode |= (pa->e_perm & S_IRWXO) << 3;
 296                                break;
 297                        case ACL_OTHER:
 298                                mode |= pa->e_perm & S_IRWXO;
 299                                break;
 300                        case ACL_MASK:
 301                                mode = (mode & ~S_IRWXG) |
 302                                       ((pa->e_perm & S_IRWXO) << 3);
 303                                not_equiv = 1;
 304                                break;
 305                        case ACL_USER:
 306                        case ACL_GROUP:
 307                                not_equiv = 1;
 308                                break;
 309                        default:
 310                                return -EINVAL;
 311                }
 312        }
 313        if (mode_p)
 314                *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
 315        return not_equiv;
 316}
 317EXPORT_SYMBOL(posix_acl_equiv_mode);
 318
 319/*
 320 * Create an ACL representing the file mode permission bits of an inode.
 321 */
 322struct posix_acl *
 323posix_acl_from_mode(umode_t mode, gfp_t flags)
 324{
 325        struct posix_acl *acl = posix_acl_alloc(3, flags);
 326        if (!acl)
 327                return ERR_PTR(-ENOMEM);
 328
 329        acl->a_entries[0].e_tag  = ACL_USER_OBJ;
 330        acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
 331
 332        acl->a_entries[1].e_tag  = ACL_GROUP_OBJ;
 333        acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
 334
 335        acl->a_entries[2].e_tag  = ACL_OTHER;
 336        acl->a_entries[2].e_perm = (mode & S_IRWXO);
 337        return acl;
 338}
 339EXPORT_SYMBOL(posix_acl_from_mode);
 340
 341/*
 342 * Return 0 if current is granted want access to the inode
 343 * by the acl. Returns -E... otherwise.
 344 */
 345int
 346posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
 347{
 348        const struct posix_acl_entry *pa, *pe, *mask_obj;
 349        int found = 0;
 350
 351        want &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_NOT_BLOCK;
 352
 353        FOREACH_ACL_ENTRY(pa, acl, pe) {
 354                switch(pa->e_tag) {
 355                        case ACL_USER_OBJ:
 356                                /* (May have been checked already) */
 357                                if (uid_eq(inode->i_uid, current_fsuid()))
 358                                        goto check_perm;
 359                                break;
 360                        case ACL_USER:
 361                                if (uid_eq(pa->e_uid, current_fsuid()))
 362                                        goto mask;
 363                                break;
 364                        case ACL_GROUP_OBJ:
 365                                if (in_group_p(inode->i_gid)) {
 366                                        found = 1;
 367                                        if ((pa->e_perm & want) == want)
 368                                                goto mask;
 369                                }
 370                                break;
 371                        case ACL_GROUP:
 372                                if (in_group_p(pa->e_gid)) {
 373                                        found = 1;
 374                                        if ((pa->e_perm & want) == want)
 375                                                goto mask;
 376                                }
 377                                break;
 378                        case ACL_MASK:
 379                                break;
 380                        case ACL_OTHER:
 381                                if (found)
 382                                        return -EACCES;
 383                                else
 384                                        goto check_perm;
 385                        default:
 386                                return -EIO;
 387                }
 388        }
 389        return -EIO;
 390
 391mask:
 392        for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
 393                if (mask_obj->e_tag == ACL_MASK) {
 394                        if ((pa->e_perm & mask_obj->e_perm & want) == want)
 395                                return 0;
 396                        return -EACCES;
 397                }
 398        }
 399
 400check_perm:
 401        if ((pa->e_perm & want) == want)
 402                return 0;
 403        return -EACCES;
 404}
 405
 406/*
 407 * Modify acl when creating a new inode. The caller must ensure the acl is
 408 * only referenced once.
 409 *
 410 * mode_p initially must contain the mode parameter to the open() / creat()
 411 * system calls. All permissions that are not granted by the acl are removed.
 412 * The permissions in the acl are changed to reflect the mode_p parameter.
 413 */
 414static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
 415{
 416        struct posix_acl_entry *pa, *pe;
 417        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
 418        umode_t mode = *mode_p;
 419        int not_equiv = 0;
 420
 421        /* assert(atomic_read(acl->a_refcount) == 1); */
 422
 423        FOREACH_ACL_ENTRY(pa, acl, pe) {
 424                switch(pa->e_tag) {
 425                        case ACL_USER_OBJ:
 426                                pa->e_perm &= (mode >> 6) | ~S_IRWXO;
 427                                mode &= (pa->e_perm << 6) | ~S_IRWXU;
 428                                break;
 429
 430                        case ACL_USER:
 431                        case ACL_GROUP:
 432                                not_equiv = 1;
 433                                break;
 434
 435                        case ACL_GROUP_OBJ:
 436                                group_obj = pa;
 437                                break;
 438
 439                        case ACL_OTHER:
 440                                pa->e_perm &= mode | ~S_IRWXO;
 441                                mode &= pa->e_perm | ~S_IRWXO;
 442                                break;
 443
 444                        case ACL_MASK:
 445                                mask_obj = pa;
 446                                not_equiv = 1;
 447                                break;
 448
 449                        default:
 450                                return -EIO;
 451                }
 452        }
 453
 454        if (mask_obj) {
 455                mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
 456                mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
 457        } else {
 458                if (!group_obj)
 459                        return -EIO;
 460                group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
 461                mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
 462        }
 463
 464        *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
 465        return not_equiv;
 466}
 467
 468/*
 469 * Modify the ACL for the chmod syscall.
 470 */
 471static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
 472{
 473        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
 474        struct posix_acl_entry *pa, *pe;
 475
 476        /* assert(atomic_read(acl->a_refcount) == 1); */
 477
 478        FOREACH_ACL_ENTRY(pa, acl, pe) {
 479                switch(pa->e_tag) {
 480                        case ACL_USER_OBJ:
 481                                pa->e_perm = (mode & S_IRWXU) >> 6;
 482                                break;
 483
 484                        case ACL_USER:
 485                        case ACL_GROUP:
 486                                break;
 487
 488                        case ACL_GROUP_OBJ:
 489                                group_obj = pa;
 490                                break;
 491
 492                        case ACL_MASK:
 493                                mask_obj = pa;
 494                                break;
 495
 496                        case ACL_OTHER:
 497                                pa->e_perm = (mode & S_IRWXO);
 498                                break;
 499
 500                        default:
 501                                return -EIO;
 502                }
 503        }
 504
 505        if (mask_obj) {
 506                mask_obj->e_perm = (mode & S_IRWXG) >> 3;
 507        } else {
 508                if (!group_obj)
 509                        return -EIO;
 510                group_obj->e_perm = (mode & S_IRWXG) >> 3;
 511        }
 512
 513        return 0;
 514}
 515
 516int
 517__posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
 518{
 519        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
 520        int err = -ENOMEM;
 521        if (clone) {
 522                err = posix_acl_create_masq(clone, mode_p);
 523                if (err < 0) {
 524                        posix_acl_release(clone);
 525                        clone = NULL;
 526                }
 527        }
 528        posix_acl_release(*acl);
 529        *acl = clone;
 530        return err;
 531}
 532EXPORT_SYMBOL(__posix_acl_create);
 533
 534int
 535__posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
 536{
 537        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
 538        int err = -ENOMEM;
 539        if (clone) {
 540                err = __posix_acl_chmod_masq(clone, mode);
 541                if (err) {
 542                        posix_acl_release(clone);
 543                        clone = NULL;
 544                }
 545        }
 546        posix_acl_release(*acl);
 547        *acl = clone;
 548        return err;
 549}
 550EXPORT_SYMBOL(__posix_acl_chmod);
 551
 552int
 553posix_acl_chmod(struct inode *inode, umode_t mode)
 554{
 555        struct posix_acl *acl;
 556        int ret = 0;
 557
 558        if (!IS_POSIXACL(inode))
 559                return 0;
 560        if (!inode->i_op->set_acl)
 561                return -EOPNOTSUPP;
 562
 563        acl = get_acl(inode, ACL_TYPE_ACCESS);
 564        if (IS_ERR_OR_NULL(acl)) {
 565                if (acl == ERR_PTR(-EOPNOTSUPP))
 566                        return 0;
 567                return PTR_ERR(acl);
 568        }
 569
 570        ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
 571        if (ret)
 572                return ret;
 573        ret = inode->i_op->set_acl(inode, acl, ACL_TYPE_ACCESS);
 574        posix_acl_release(acl);
 575        return ret;
 576}
 577EXPORT_SYMBOL(posix_acl_chmod);
 578
 579int
 580posix_acl_create(struct inode *dir, umode_t *mode,
 581                struct posix_acl **default_acl, struct posix_acl **acl)
 582{
 583        struct posix_acl *p;
 584        struct posix_acl *clone;
 585        int ret;
 586
 587        *acl = NULL;
 588        *default_acl = NULL;
 589
 590        if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
 591                return 0;
 592
 593        p = get_acl(dir, ACL_TYPE_DEFAULT);
 594        if (!p || p == ERR_PTR(-EOPNOTSUPP)) {
 595                *mode &= ~current_umask();
 596                return 0;
 597        }
 598        if (IS_ERR(p))
 599                return PTR_ERR(p);
 600
 601        ret = -ENOMEM;
 602        clone = posix_acl_clone(p, GFP_NOFS);
 603        if (!clone)
 604                goto err_release;
 605
 606        ret = posix_acl_create_masq(clone, mode);
 607        if (ret < 0)
 608                goto err_release_clone;
 609
 610        if (ret == 0)
 611                posix_acl_release(clone);
 612        else
 613                *acl = clone;
 614
 615        if (!S_ISDIR(*mode))
 616                posix_acl_release(p);
 617        else
 618                *default_acl = p;
 619
 620        return 0;
 621
 622err_release_clone:
 623        posix_acl_release(clone);
 624err_release:
 625        posix_acl_release(p);
 626        return ret;
 627}
 628EXPORT_SYMBOL_GPL(posix_acl_create);
 629
 630/**
 631 * posix_acl_update_mode  -  update mode in set_acl
 632 *
 633 * Update the file mode when setting an ACL: compute the new file permission
 634 * bits based on the ACL.  In addition, if the ACL is equivalent to the new
 635 * file mode, set *acl to NULL to indicate that no ACL should be set.
 636 *
 637 * As with chmod, clear the setgit bit if the caller is not in the owning group
 638 * or capable of CAP_FSETID (see inode_change_ok).
 639 *
 640 * Called from set_acl inode operations.
 641 */
 642int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
 643                          struct posix_acl **acl)
 644{
 645        umode_t mode = inode->i_mode;
 646        int error;
 647
 648        error = posix_acl_equiv_mode(*acl, &mode);
 649        if (error < 0)
 650                return error;
 651        if (error == 0)
 652                *acl = NULL;
 653        if (!in_group_p(inode->i_gid) &&
 654            !capable_wrt_inode_uidgid(inode, CAP_FSETID))
 655                mode &= ~S_ISGID;
 656        *mode_p = mode;
 657        return 0;
 658}
 659EXPORT_SYMBOL(posix_acl_update_mode);
 660
 661/*
 662 * Fix up the uids and gids in posix acl extended attributes in place.
 663 */
 664static void posix_acl_fix_xattr_userns(
 665        struct user_namespace *to, struct user_namespace *from,
 666        void *value, size_t size)
 667{
 668        struct posix_acl_xattr_header *header = value;
 669        struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
 670        int count;
 671        kuid_t uid;
 672        kgid_t gid;
 673
 674        if (!value)
 675                return;
 676        if (size < sizeof(struct posix_acl_xattr_header))
 677                return;
 678        if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
 679                return;
 680
 681        count = posix_acl_xattr_count(size);
 682        if (count < 0)
 683                return;
 684        if (count == 0)
 685                return;
 686
 687        for (end = entry + count; entry != end; entry++) {
 688                switch(le16_to_cpu(entry->e_tag)) {
 689                case ACL_USER:
 690                        uid = make_kuid(from, le32_to_cpu(entry->e_id));
 691                        entry->e_id = cpu_to_le32(from_kuid(to, uid));
 692                        break;
 693                case ACL_GROUP:
 694                        gid = make_kgid(from, le32_to_cpu(entry->e_id));
 695                        entry->e_id = cpu_to_le32(from_kgid(to, gid));
 696                        break;
 697                default:
 698                        break;
 699                }
 700        }
 701}
 702
 703void posix_acl_fix_xattr_from_user(void *value, size_t size)
 704{
 705        struct user_namespace *user_ns = current_user_ns();
 706        if (user_ns == &init_user_ns)
 707                return;
 708        posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size);
 709}
 710
 711void posix_acl_fix_xattr_to_user(void *value, size_t size)
 712{
 713        struct user_namespace *user_ns = current_user_ns();
 714        if (user_ns == &init_user_ns)
 715                return;
 716        posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size);
 717}
 718
 719/*
 720 * Convert from extended attribute to in-memory representation.
 721 */
 722struct posix_acl *
 723posix_acl_from_xattr(struct user_namespace *user_ns,
 724                     const void *value, size_t size)
 725{
 726        const struct posix_acl_xattr_header *header = value;
 727        const struct posix_acl_xattr_entry *entry = (const void *)(header + 1), *end;
 728        int count;
 729        struct posix_acl *acl;
 730        struct posix_acl_entry *acl_e;
 731
 732        if (!value)
 733                return NULL;
 734        if (size < sizeof(struct posix_acl_xattr_header))
 735                 return ERR_PTR(-EINVAL);
 736        if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
 737                return ERR_PTR(-EOPNOTSUPP);
 738
 739        count = posix_acl_xattr_count(size);
 740        if (count < 0)
 741                return ERR_PTR(-EINVAL);
 742        if (count == 0)
 743                return NULL;
 744        
 745        acl = posix_acl_alloc(count, GFP_NOFS);
 746        if (!acl)
 747                return ERR_PTR(-ENOMEM);
 748        acl_e = acl->a_entries;
 749        
 750        for (end = entry + count; entry != end; acl_e++, entry++) {
 751                acl_e->e_tag  = le16_to_cpu(entry->e_tag);
 752                acl_e->e_perm = le16_to_cpu(entry->e_perm);
 753
 754                switch(acl_e->e_tag) {
 755                        case ACL_USER_OBJ:
 756                        case ACL_GROUP_OBJ:
 757                        case ACL_MASK:
 758                        case ACL_OTHER:
 759                                break;
 760
 761                        case ACL_USER:
 762                                acl_e->e_uid =
 763                                        make_kuid(user_ns,
 764                                                  le32_to_cpu(entry->e_id));
 765                                if (!uid_valid(acl_e->e_uid))
 766                                        goto fail;
 767                                break;
 768                        case ACL_GROUP:
 769                                acl_e->e_gid =
 770                                        make_kgid(user_ns,
 771                                                  le32_to_cpu(entry->e_id));
 772                                if (!gid_valid(acl_e->e_gid))
 773                                        goto fail;
 774                                break;
 775
 776                        default:
 777                                goto fail;
 778                }
 779        }
 780        return acl;
 781
 782fail:
 783        posix_acl_release(acl);
 784        return ERR_PTR(-EINVAL);
 785}
 786EXPORT_SYMBOL (posix_acl_from_xattr);
 787
 788/*
 789 * Convert from in-memory to extended attribute representation.
 790 */
 791int
 792posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
 793                   void *buffer, size_t size)
 794{
 795        struct posix_acl_xattr_header *ext_acl = buffer;
 796        struct posix_acl_xattr_entry *ext_entry;
 797        int real_size, n;
 798
 799        real_size = posix_acl_xattr_size(acl->a_count);
 800        if (!buffer)
 801                return real_size;
 802        if (real_size > size)
 803                return -ERANGE;
 804
 805        ext_entry = (void *)(ext_acl + 1);
 806        ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
 807
 808        for (n=0; n < acl->a_count; n++, ext_entry++) {
 809                const struct posix_acl_entry *acl_e = &acl->a_entries[n];
 810                ext_entry->e_tag  = cpu_to_le16(acl_e->e_tag);
 811                ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
 812                switch(acl_e->e_tag) {
 813                case ACL_USER:
 814                        ext_entry->e_id =
 815                                cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
 816                        break;
 817                case ACL_GROUP:
 818                        ext_entry->e_id =
 819                                cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
 820                        break;
 821                default:
 822                        ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
 823                        break;
 824                }
 825        }
 826        return real_size;
 827}
 828EXPORT_SYMBOL (posix_acl_to_xattr);
 829
 830static int
 831posix_acl_xattr_get(const struct xattr_handler *handler,
 832                    struct dentry *unused, struct inode *inode,
 833                    const char *name, void *value, size_t size)
 834{
 835        struct posix_acl *acl;
 836        int error;
 837
 838        if (!IS_POSIXACL(inode))
 839                return -EOPNOTSUPP;
 840        if (S_ISLNK(inode->i_mode))
 841                return -EOPNOTSUPP;
 842
 843        acl = get_acl(inode, handler->flags);
 844        if (IS_ERR(acl))
 845                return PTR_ERR(acl);
 846        if (acl == NULL)
 847                return -ENODATA;
 848
 849        error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
 850        posix_acl_release(acl);
 851
 852        return error;
 853}
 854
 855int
 856set_posix_acl(struct inode *inode, int type, struct posix_acl *acl)
 857{
 858        if (!IS_POSIXACL(inode))
 859                return -EOPNOTSUPP;
 860        if (!inode->i_op->set_acl)
 861                return -EOPNOTSUPP;
 862
 863        if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
 864                return acl ? -EACCES : 0;
 865        if (!inode_owner_or_capable(inode))
 866                return -EPERM;
 867
 868        if (acl) {
 869                int ret = posix_acl_valid(inode->i_sb->s_user_ns, acl);
 870                if (ret)
 871                        return ret;
 872        }
 873        return inode->i_op->set_acl(inode, acl, type);
 874}
 875EXPORT_SYMBOL(set_posix_acl);
 876
 877static int
 878posix_acl_xattr_set(const struct xattr_handler *handler,
 879                    struct dentry *unused, struct inode *inode,
 880                    const char *name, const void *value,
 881                    size_t size, int flags)
 882{
 883        struct posix_acl *acl = NULL;
 884        int ret;
 885
 886        if (value) {
 887                acl = posix_acl_from_xattr(&init_user_ns, value, size);
 888                if (IS_ERR(acl))
 889                        return PTR_ERR(acl);
 890        }
 891        ret = set_posix_acl(inode, handler->flags, acl);
 892        posix_acl_release(acl);
 893        return ret;
 894}
 895
 896static bool
 897posix_acl_xattr_list(struct dentry *dentry)
 898{
 899        return IS_POSIXACL(d_backing_inode(dentry));
 900}
 901
 902const struct xattr_handler posix_acl_access_xattr_handler = {
 903        .name = XATTR_NAME_POSIX_ACL_ACCESS,
 904        .flags = ACL_TYPE_ACCESS,
 905        .list = posix_acl_xattr_list,
 906        .get = posix_acl_xattr_get,
 907        .set = posix_acl_xattr_set,
 908};
 909EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
 910
 911const struct xattr_handler posix_acl_default_xattr_handler = {
 912        .name = XATTR_NAME_POSIX_ACL_DEFAULT,
 913        .flags = ACL_TYPE_DEFAULT,
 914        .list = posix_acl_xattr_list,
 915        .get = posix_acl_xattr_get,
 916        .set = posix_acl_xattr_set,
 917};
 918EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
 919
 920int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 921{
 922        int error;
 923
 924        if (type == ACL_TYPE_ACCESS) {
 925                error = posix_acl_equiv_mode(acl, &inode->i_mode);
 926                if (error < 0)
 927                        return 0;
 928                if (error == 0)
 929                        acl = NULL;
 930        }
 931
 932        inode->i_ctime = current_time(inode);
 933        set_cached_acl(inode, type, acl);
 934        return 0;
 935}
 936
 937int simple_acl_create(struct inode *dir, struct inode *inode)
 938{
 939        struct posix_acl *default_acl, *acl;
 940        int error;
 941
 942        error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
 943        if (error)
 944                return error;
 945
 946        set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
 947        set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
 948
 949        if (default_acl)
 950                posix_acl_release(default_acl);
 951        if (acl)
 952                posix_acl_release(acl);
 953        return 0;
 954}
 955