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