root/fs/posix_acl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acl_by_type
  2. get_cached_acl
  3. get_cached_acl_rcu
  4. set_cached_acl
  5. __forget_cached_acl
  6. forget_cached_acl
  7. forget_all_cached_acls
  8. get_acl
  9. posix_acl_init
  10. posix_acl_alloc
  11. posix_acl_clone
  12. posix_acl_valid
  13. posix_acl_equiv_mode
  14. posix_acl_from_mode
  15. posix_acl_permission
  16. posix_acl_create_masq
  17. __posix_acl_chmod_masq
  18. __posix_acl_create
  19. __posix_acl_chmod
  20. posix_acl_chmod
  21. posix_acl_create
  22. posix_acl_update_mode
  23. posix_acl_fix_xattr_userns
  24. posix_acl_fix_xattr_from_user
  25. posix_acl_fix_xattr_to_user
  26. posix_acl_from_xattr
  27. posix_acl_to_xattr
  28. posix_acl_xattr_get
  29. set_posix_acl
  30. posix_acl_xattr_set
  31. posix_acl_xattr_list
  32. simple_set_acl
  33. simple_acl_create

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

/* [<][>][^][v][top][bottom][index][help] */