Back to home page

LXR

 
 

    


0001 /*
0002  * Copyright (C) 2002,2003 by Andreas Gruenbacher <a.gruenbacher@computer.org>
0003  *
0004  * Fixes from William Schumacher incorporated on 15 March 2001.
0005  *    (Reported by Charles Bertsch, <CBertsch@microtest.com>).
0006  */
0007 
0008 /*
0009  *  This file contains generic functions for manipulating
0010  *  POSIX 1003.1e draft standard 17 ACLs.
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/atomic.h>
0016 #include <linux/fs.h>
0017 #include <linux/sched.h>
0018 #include <linux/posix_acl.h>
0019 #include <linux/posix_acl_xattr.h>
0020 #include <linux/xattr.h>
0021 #include <linux/export.h>
0022 #include <linux/user_namespace.h>
0023 
0024 static struct posix_acl **acl_by_type(struct inode *inode, int type)
0025 {
0026     switch (type) {
0027     case ACL_TYPE_ACCESS:
0028         return &inode->i_acl;
0029     case ACL_TYPE_DEFAULT:
0030         return &inode->i_default_acl;
0031     default:
0032         BUG();
0033     }
0034 }
0035 
0036 struct posix_acl *get_cached_acl(struct inode *inode, int type)
0037 {
0038     struct posix_acl **p = acl_by_type(inode, type);
0039     struct posix_acl *acl;
0040 
0041     for (;;) {
0042         rcu_read_lock();
0043         acl = rcu_dereference(*p);
0044         if (!acl || is_uncached_acl(acl) ||
0045             atomic_inc_not_zero(&acl->a_refcount))
0046             break;
0047         rcu_read_unlock();
0048         cpu_relax();
0049     }
0050     rcu_read_unlock();
0051     return acl;
0052 }
0053 EXPORT_SYMBOL(get_cached_acl);
0054 
0055 struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
0056 {
0057     return rcu_dereference(*acl_by_type(inode, type));
0058 }
0059 EXPORT_SYMBOL(get_cached_acl_rcu);
0060 
0061 void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl)
0062 {
0063     struct posix_acl **p = acl_by_type(inode, type);
0064     struct posix_acl *old;
0065 
0066     old = xchg(p, posix_acl_dup(acl));
0067     if (!is_uncached_acl(old))
0068         posix_acl_release(old);
0069 }
0070 EXPORT_SYMBOL(set_cached_acl);
0071 
0072 static void __forget_cached_acl(struct posix_acl **p)
0073 {
0074     struct posix_acl *old;
0075 
0076     old = xchg(p, ACL_NOT_CACHED);
0077     if (!is_uncached_acl(old))
0078         posix_acl_release(old);
0079 }
0080 
0081 void forget_cached_acl(struct inode *inode, int type)
0082 {
0083     __forget_cached_acl(acl_by_type(inode, type));
0084 }
0085 EXPORT_SYMBOL(forget_cached_acl);
0086 
0087 void forget_all_cached_acls(struct inode *inode)
0088 {
0089     __forget_cached_acl(&inode->i_acl);
0090     __forget_cached_acl(&inode->i_default_acl);
0091 }
0092 EXPORT_SYMBOL(forget_all_cached_acls);
0093 
0094 struct posix_acl *get_acl(struct inode *inode, int type)
0095 {
0096     void *sentinel;
0097     struct posix_acl **p;
0098     struct posix_acl *acl;
0099 
0100     /*
0101      * The sentinel is used to detect when another operation like
0102      * set_cached_acl() or forget_cached_acl() races with get_acl().
0103      * It is guaranteed that is_uncached_acl(sentinel) is true.
0104      */
0105 
0106     acl = get_cached_acl(inode, type);
0107     if (!is_uncached_acl(acl))
0108         return acl;
0109 
0110     if (!IS_POSIXACL(inode))
0111         return NULL;
0112 
0113     sentinel = uncached_acl_sentinel(current);
0114     p = acl_by_type(inode, type);
0115 
0116     /*
0117      * If the ACL isn't being read yet, set our sentinel.  Otherwise, the
0118      * current value of the ACL will not be ACL_NOT_CACHED and so our own
0119      * sentinel will not be set; another task will update the cache.  We
0120      * could wait for that other task to complete its job, but it's easier
0121      * to just call ->get_acl to fetch the ACL ourself.  (This is going to
0122      * be an unlikely race.)
0123      */
0124     if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED)
0125         /* fall through */ ;
0126 
0127     /*
0128      * Normally, the ACL returned by ->get_acl will be cached.
0129      * A filesystem can prevent that by calling
0130      * forget_cached_acl(inode, type) in ->get_acl.
0131      *
0132      * If the filesystem doesn't have a get_acl() function at all, we'll
0133      * just create the negative cache entry.
0134      */
0135     if (!inode->i_op->get_acl) {
0136         set_cached_acl(inode, type, NULL);
0137         return NULL;
0138     }
0139     acl = inode->i_op->get_acl(inode, type);
0140 
0141     if (IS_ERR(acl)) {
0142         /*
0143          * Remove our sentinel so that we don't block future attempts
0144          * to cache the ACL.
0145          */
0146         cmpxchg(p, sentinel, ACL_NOT_CACHED);
0147         return acl;
0148     }
0149 
0150     /*
0151      * Cache the result, but only if our sentinel is still in place.
0152      */
0153     posix_acl_dup(acl);
0154     if (unlikely(cmpxchg(p, sentinel, acl) != sentinel))
0155         posix_acl_release(acl);
0156     return acl;
0157 }
0158 EXPORT_SYMBOL(get_acl);
0159 
0160 /*
0161  * Init a fresh posix_acl
0162  */
0163 void
0164 posix_acl_init(struct posix_acl *acl, int count)
0165 {
0166     atomic_set(&acl->a_refcount, 1);
0167     acl->a_count = count;
0168 }
0169 EXPORT_SYMBOL(posix_acl_init);
0170 
0171 /*
0172  * Allocate a new ACL with the specified number of entries.
0173  */
0174 struct posix_acl *
0175 posix_acl_alloc(int count, gfp_t flags)
0176 {
0177     const size_t size = sizeof(struct posix_acl) +
0178                         count * sizeof(struct posix_acl_entry);
0179     struct posix_acl *acl = kmalloc(size, flags);
0180     if (acl)
0181         posix_acl_init(acl, count);
0182     return acl;
0183 }
0184 EXPORT_SYMBOL(posix_acl_alloc);
0185 
0186 /*
0187  * Clone an ACL.
0188  */
0189 static struct posix_acl *
0190 posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
0191 {
0192     struct posix_acl *clone = NULL;
0193 
0194     if (acl) {
0195         int size = sizeof(struct posix_acl) + acl->a_count *
0196                    sizeof(struct posix_acl_entry);
0197         clone = kmemdup(acl, size, flags);
0198         if (clone)
0199             atomic_set(&clone->a_refcount, 1);
0200     }
0201     return clone;
0202 }
0203 
0204 /*
0205  * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
0206  */
0207 int
0208 posix_acl_valid(struct user_namespace *user_ns, const struct posix_acl *acl)
0209 {
0210     const struct posix_acl_entry *pa, *pe;
0211     int state = ACL_USER_OBJ;
0212     int needs_mask = 0;
0213 
0214     FOREACH_ACL_ENTRY(pa, acl, pe) {
0215         if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
0216             return -EINVAL;
0217         switch (pa->e_tag) {
0218             case ACL_USER_OBJ:
0219                 if (state == ACL_USER_OBJ) {
0220                     state = ACL_USER;
0221                     break;
0222                 }
0223                 return -EINVAL;
0224 
0225             case ACL_USER:
0226                 if (state != ACL_USER)
0227                     return -EINVAL;
0228                 if (!kuid_has_mapping(user_ns, pa->e_uid))
0229                     return -EINVAL;
0230                 needs_mask = 1;
0231                 break;
0232 
0233             case ACL_GROUP_OBJ:
0234                 if (state == ACL_USER) {
0235                     state = ACL_GROUP;
0236                     break;
0237                 }
0238                 return -EINVAL;
0239 
0240             case ACL_GROUP:
0241                 if (state != ACL_GROUP)
0242                     return -EINVAL;
0243                 if (!kgid_has_mapping(user_ns, pa->e_gid))
0244                     return -EINVAL;
0245                 needs_mask = 1;
0246                 break;
0247 
0248             case ACL_MASK:
0249                 if (state != ACL_GROUP)
0250                     return -EINVAL;
0251                 state = ACL_OTHER;
0252                 break;
0253 
0254             case ACL_OTHER:
0255                 if (state == ACL_OTHER ||
0256                     (state == ACL_GROUP && !needs_mask)) {
0257                     state = 0;
0258                     break;
0259                 }
0260                 return -EINVAL;
0261 
0262             default:
0263                 return -EINVAL;
0264         }
0265     }
0266     if (state == 0)
0267         return 0;
0268     return -EINVAL;
0269 }
0270 EXPORT_SYMBOL(posix_acl_valid);
0271 
0272 /*
0273  * Returns 0 if the acl can be exactly represented in the traditional
0274  * file mode permission bits, or else 1. Returns -E... on error.
0275  */
0276 int
0277 posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
0278 {
0279     const struct posix_acl_entry *pa, *pe;
0280     umode_t mode = 0;
0281     int not_equiv = 0;
0282 
0283     /*
0284      * A null ACL can always be presented as mode bits.
0285      */
0286     if (!acl)
0287         return 0;
0288 
0289     FOREACH_ACL_ENTRY(pa, acl, pe) {
0290         switch (pa->e_tag) {
0291             case ACL_USER_OBJ:
0292                 mode |= (pa->e_perm & S_IRWXO) << 6;
0293                 break;
0294             case ACL_GROUP_OBJ:
0295                 mode |= (pa->e_perm & S_IRWXO) << 3;
0296                 break;
0297             case ACL_OTHER:
0298                 mode |= pa->e_perm & S_IRWXO;
0299                 break;
0300             case ACL_MASK:
0301                 mode = (mode & ~S_IRWXG) |
0302                        ((pa->e_perm & S_IRWXO) << 3);
0303                 not_equiv = 1;
0304                 break;
0305             case ACL_USER:
0306             case ACL_GROUP:
0307                 not_equiv = 1;
0308                 break;
0309             default:
0310                 return -EINVAL;
0311         }
0312     }
0313         if (mode_p)
0314                 *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
0315         return not_equiv;
0316 }
0317 EXPORT_SYMBOL(posix_acl_equiv_mode);
0318 
0319 /*
0320  * Create an ACL representing the file mode permission bits of an inode.
0321  */
0322 struct posix_acl *
0323 posix_acl_from_mode(umode_t mode, gfp_t flags)
0324 {
0325     struct posix_acl *acl = posix_acl_alloc(3, flags);
0326     if (!acl)
0327         return ERR_PTR(-ENOMEM);
0328 
0329     acl->a_entries[0].e_tag  = ACL_USER_OBJ;
0330     acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
0331 
0332     acl->a_entries[1].e_tag  = ACL_GROUP_OBJ;
0333     acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
0334 
0335     acl->a_entries[2].e_tag  = ACL_OTHER;
0336     acl->a_entries[2].e_perm = (mode & S_IRWXO);
0337     return acl;
0338 }
0339 EXPORT_SYMBOL(posix_acl_from_mode);
0340 
0341 /*
0342  * Return 0 if current is granted want access to the inode
0343  * by the acl. Returns -E... otherwise.
0344  */
0345 int
0346 posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
0347 {
0348     const struct posix_acl_entry *pa, *pe, *mask_obj;
0349     int found = 0;
0350 
0351     want &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_NOT_BLOCK;
0352 
0353     FOREACH_ACL_ENTRY(pa, acl, pe) {
0354                 switch(pa->e_tag) {
0355                         case ACL_USER_OBJ:
0356                 /* (May have been checked already) */
0357                 if (uid_eq(inode->i_uid, current_fsuid()))
0358                                         goto check_perm;
0359                                 break;
0360                         case ACL_USER:
0361                 if (uid_eq(pa->e_uid, current_fsuid()))
0362                                         goto mask;
0363                 break;
0364                         case ACL_GROUP_OBJ:
0365                                 if (in_group_p(inode->i_gid)) {
0366                     found = 1;
0367                     if ((pa->e_perm & want) == want)
0368                         goto mask;
0369                                 }
0370                 break;
0371                         case ACL_GROUP:
0372                 if (in_group_p(pa->e_gid)) {
0373                     found = 1;
0374                     if ((pa->e_perm & want) == want)
0375                         goto mask;
0376                                 }
0377                                 break;
0378                         case ACL_MASK:
0379                                 break;
0380                         case ACL_OTHER:
0381                 if (found)
0382                     return -EACCES;
0383                 else
0384                     goto check_perm;
0385             default:
0386                 return -EIO;
0387                 }
0388         }
0389     return -EIO;
0390 
0391 mask:
0392     for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
0393         if (mask_obj->e_tag == ACL_MASK) {
0394             if ((pa->e_perm & mask_obj->e_perm & want) == want)
0395                 return 0;
0396             return -EACCES;
0397         }
0398     }
0399 
0400 check_perm:
0401     if ((pa->e_perm & want) == want)
0402         return 0;
0403     return -EACCES;
0404 }
0405 
0406 /*
0407  * Modify acl when creating a new inode. The caller must ensure the acl is
0408  * only referenced once.
0409  *
0410  * mode_p initially must contain the mode parameter to the open() / creat()
0411  * system calls. All permissions that are not granted by the acl are removed.
0412  * The permissions in the acl are changed to reflect the mode_p parameter.
0413  */
0414 static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
0415 {
0416     struct posix_acl_entry *pa, *pe;
0417     struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
0418     umode_t mode = *mode_p;
0419     int not_equiv = 0;
0420 
0421     /* assert(atomic_read(acl->a_refcount) == 1); */
0422 
0423     FOREACH_ACL_ENTRY(pa, acl, pe) {
0424                 switch(pa->e_tag) {
0425                         case ACL_USER_OBJ:
0426                 pa->e_perm &= (mode >> 6) | ~S_IRWXO;
0427                 mode &= (pa->e_perm << 6) | ~S_IRWXU;
0428                 break;
0429 
0430             case ACL_USER:
0431             case ACL_GROUP:
0432                 not_equiv = 1;
0433                 break;
0434 
0435                         case ACL_GROUP_OBJ:
0436                 group_obj = pa;
0437                                 break;
0438 
0439                         case ACL_OTHER:
0440                 pa->e_perm &= mode | ~S_IRWXO;
0441                 mode &= pa->e_perm | ~S_IRWXO;
0442                                 break;
0443 
0444                         case ACL_MASK:
0445                 mask_obj = pa;
0446                 not_equiv = 1;
0447                                 break;
0448 
0449             default:
0450                 return -EIO;
0451                 }
0452         }
0453 
0454     if (mask_obj) {
0455         mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
0456         mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
0457     } else {
0458         if (!group_obj)
0459             return -EIO;
0460         group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
0461         mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
0462     }
0463 
0464     *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
0465         return not_equiv;
0466 }
0467 
0468 /*
0469  * Modify the ACL for the chmod syscall.
0470  */
0471 static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
0472 {
0473     struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
0474     struct posix_acl_entry *pa, *pe;
0475 
0476     /* assert(atomic_read(acl->a_refcount) == 1); */
0477 
0478     FOREACH_ACL_ENTRY(pa, acl, pe) {
0479         switch(pa->e_tag) {
0480             case ACL_USER_OBJ:
0481                 pa->e_perm = (mode & S_IRWXU) >> 6;
0482                 break;
0483 
0484             case ACL_USER:
0485             case ACL_GROUP:
0486                 break;
0487 
0488             case ACL_GROUP_OBJ:
0489                 group_obj = pa;
0490                 break;
0491 
0492             case ACL_MASK:
0493                 mask_obj = pa;
0494                 break;
0495 
0496             case ACL_OTHER:
0497                 pa->e_perm = (mode & S_IRWXO);
0498                 break;
0499 
0500             default:
0501                 return -EIO;
0502         }
0503     }
0504 
0505     if (mask_obj) {
0506         mask_obj->e_perm = (mode & S_IRWXG) >> 3;
0507     } else {
0508         if (!group_obj)
0509             return -EIO;
0510         group_obj->e_perm = (mode & S_IRWXG) >> 3;
0511     }
0512 
0513     return 0;
0514 }
0515 
0516 int
0517 __posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
0518 {
0519     struct posix_acl *clone = posix_acl_clone(*acl, gfp);
0520     int err = -ENOMEM;
0521     if (clone) {
0522         err = posix_acl_create_masq(clone, mode_p);
0523         if (err < 0) {
0524             posix_acl_release(clone);
0525             clone = NULL;
0526         }
0527     }
0528     posix_acl_release(*acl);
0529     *acl = clone;
0530     return err;
0531 }
0532 EXPORT_SYMBOL(__posix_acl_create);
0533 
0534 int
0535 __posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
0536 {
0537     struct posix_acl *clone = posix_acl_clone(*acl, gfp);
0538     int err = -ENOMEM;
0539     if (clone) {
0540         err = __posix_acl_chmod_masq(clone, mode);
0541         if (err) {
0542             posix_acl_release(clone);
0543             clone = NULL;
0544         }
0545     }
0546     posix_acl_release(*acl);
0547     *acl = clone;
0548     return err;
0549 }
0550 EXPORT_SYMBOL(__posix_acl_chmod);
0551 
0552 int
0553 posix_acl_chmod(struct inode *inode, umode_t mode)
0554 {
0555     struct posix_acl *acl;
0556     int ret = 0;
0557 
0558     if (!IS_POSIXACL(inode))
0559         return 0;
0560     if (!inode->i_op->set_acl)
0561         return -EOPNOTSUPP;
0562 
0563     acl = get_acl(inode, ACL_TYPE_ACCESS);
0564     if (IS_ERR_OR_NULL(acl)) {
0565         if (acl == ERR_PTR(-EOPNOTSUPP))
0566             return 0;
0567         return PTR_ERR(acl);
0568     }
0569 
0570     ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
0571     if (ret)
0572         return ret;
0573     ret = inode->i_op->set_acl(inode, acl, ACL_TYPE_ACCESS);
0574     posix_acl_release(acl);
0575     return ret;
0576 }
0577 EXPORT_SYMBOL(posix_acl_chmod);
0578 
0579 int
0580 posix_acl_create(struct inode *dir, umode_t *mode,
0581         struct posix_acl **default_acl, struct posix_acl **acl)
0582 {
0583     struct posix_acl *p;
0584     struct posix_acl *clone;
0585     int ret;
0586 
0587     *acl = NULL;
0588     *default_acl = NULL;
0589 
0590     if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
0591         return 0;
0592 
0593     p = get_acl(dir, ACL_TYPE_DEFAULT);
0594     if (!p || p == ERR_PTR(-EOPNOTSUPP)) {
0595         *mode &= ~current_umask();
0596         return 0;
0597     }
0598     if (IS_ERR(p))
0599         return PTR_ERR(p);
0600 
0601     ret = -ENOMEM;
0602     clone = posix_acl_clone(p, GFP_NOFS);
0603     if (!clone)
0604         goto err_release;
0605 
0606     ret = posix_acl_create_masq(clone, mode);
0607     if (ret < 0)
0608         goto err_release_clone;
0609 
0610     if (ret == 0)
0611         posix_acl_release(clone);
0612     else
0613         *acl = clone;
0614 
0615     if (!S_ISDIR(*mode))
0616         posix_acl_release(p);
0617     else
0618         *default_acl = p;
0619 
0620     return 0;
0621 
0622 err_release_clone:
0623     posix_acl_release(clone);
0624 err_release:
0625     posix_acl_release(p);
0626     return ret;
0627 }
0628 EXPORT_SYMBOL_GPL(posix_acl_create);
0629 
0630 /**
0631  * posix_acl_update_mode  -  update mode in set_acl
0632  *
0633  * Update the file mode when setting an ACL: compute the new file permission
0634  * bits based on the ACL.  In addition, if the ACL is equivalent to the new
0635  * file mode, set *acl to NULL to indicate that no ACL should be set.
0636  *
0637  * As with chmod, clear the setgit bit if the caller is not in the owning group
0638  * or capable of CAP_FSETID (see inode_change_ok).
0639  *
0640  * Called from set_acl inode operations.
0641  */
0642 int posix_acl_update_mode(struct inode *inode, umode_t *mode_p,
0643               struct posix_acl **acl)
0644 {
0645     umode_t mode = inode->i_mode;
0646     int error;
0647 
0648     error = posix_acl_equiv_mode(*acl, &mode);
0649     if (error < 0)
0650         return error;
0651     if (error == 0)
0652         *acl = NULL;
0653     if (!in_group_p(inode->i_gid) &&
0654         !capable_wrt_inode_uidgid(inode, CAP_FSETID))
0655         mode &= ~S_ISGID;
0656     *mode_p = mode;
0657     return 0;
0658 }
0659 EXPORT_SYMBOL(posix_acl_update_mode);
0660 
0661 /*
0662  * Fix up the uids and gids in posix acl extended attributes in place.
0663  */
0664 static void posix_acl_fix_xattr_userns(
0665     struct user_namespace *to, struct user_namespace *from,
0666     void *value, size_t size)
0667 {
0668     struct posix_acl_xattr_header *header = value;
0669     struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
0670     int count;
0671     kuid_t uid;
0672     kgid_t gid;
0673 
0674     if (!value)
0675         return;
0676     if (size < sizeof(struct posix_acl_xattr_header))
0677         return;
0678     if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
0679         return;
0680 
0681     count = posix_acl_xattr_count(size);
0682     if (count < 0)
0683         return;
0684     if (count == 0)
0685         return;
0686 
0687     for (end = entry + count; entry != end; entry++) {
0688         switch(le16_to_cpu(entry->e_tag)) {
0689         case ACL_USER:
0690             uid = make_kuid(from, le32_to_cpu(entry->e_id));
0691             entry->e_id = cpu_to_le32(from_kuid(to, uid));
0692             break;
0693         case ACL_GROUP:
0694             gid = make_kgid(from, le32_to_cpu(entry->e_id));
0695             entry->e_id = cpu_to_le32(from_kgid(to, gid));
0696             break;
0697         default:
0698             break;
0699         }
0700     }
0701 }
0702 
0703 void posix_acl_fix_xattr_from_user(void *value, size_t size)
0704 {
0705     struct user_namespace *user_ns = current_user_ns();
0706     if (user_ns == &init_user_ns)
0707         return;
0708     posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size);
0709 }
0710 
0711 void posix_acl_fix_xattr_to_user(void *value, size_t size)
0712 {
0713     struct user_namespace *user_ns = current_user_ns();
0714     if (user_ns == &init_user_ns)
0715         return;
0716     posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size);
0717 }
0718 
0719 /*
0720  * Convert from extended attribute to in-memory representation.
0721  */
0722 struct posix_acl *
0723 posix_acl_from_xattr(struct user_namespace *user_ns,
0724              const void *value, size_t size)
0725 {
0726     const struct posix_acl_xattr_header *header = value;
0727     const struct posix_acl_xattr_entry *entry = (const void *)(header + 1), *end;
0728     int count;
0729     struct posix_acl *acl;
0730     struct posix_acl_entry *acl_e;
0731 
0732     if (!value)
0733         return NULL;
0734     if (size < sizeof(struct posix_acl_xattr_header))
0735          return ERR_PTR(-EINVAL);
0736     if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
0737         return ERR_PTR(-EOPNOTSUPP);
0738 
0739     count = posix_acl_xattr_count(size);
0740     if (count < 0)
0741         return ERR_PTR(-EINVAL);
0742     if (count == 0)
0743         return NULL;
0744     
0745     acl = posix_acl_alloc(count, GFP_NOFS);
0746     if (!acl)
0747         return ERR_PTR(-ENOMEM);
0748     acl_e = acl->a_entries;
0749     
0750     for (end = entry + count; entry != end; acl_e++, entry++) {
0751         acl_e->e_tag  = le16_to_cpu(entry->e_tag);
0752         acl_e->e_perm = le16_to_cpu(entry->e_perm);
0753 
0754         switch(acl_e->e_tag) {
0755             case ACL_USER_OBJ:
0756             case ACL_GROUP_OBJ:
0757             case ACL_MASK:
0758             case ACL_OTHER:
0759                 break;
0760 
0761             case ACL_USER:
0762                 acl_e->e_uid =
0763                     make_kuid(user_ns,
0764                           le32_to_cpu(entry->e_id));
0765                 if (!uid_valid(acl_e->e_uid))
0766                     goto fail;
0767                 break;
0768             case ACL_GROUP:
0769                 acl_e->e_gid =
0770                     make_kgid(user_ns,
0771                           le32_to_cpu(entry->e_id));
0772                 if (!gid_valid(acl_e->e_gid))
0773                     goto fail;
0774                 break;
0775 
0776             default:
0777                 goto fail;
0778         }
0779     }
0780     return acl;
0781 
0782 fail:
0783     posix_acl_release(acl);
0784     return ERR_PTR(-EINVAL);
0785 }
0786 EXPORT_SYMBOL (posix_acl_from_xattr);
0787 
0788 /*
0789  * Convert from in-memory to extended attribute representation.
0790  */
0791 int
0792 posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
0793            void *buffer, size_t size)
0794 {
0795     struct posix_acl_xattr_header *ext_acl = buffer;
0796     struct posix_acl_xattr_entry *ext_entry;
0797     int real_size, n;
0798 
0799     real_size = posix_acl_xattr_size(acl->a_count);
0800     if (!buffer)
0801         return real_size;
0802     if (real_size > size)
0803         return -ERANGE;
0804 
0805     ext_entry = (void *)(ext_acl + 1);
0806     ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
0807 
0808     for (n=0; n < acl->a_count; n++, ext_entry++) {
0809         const struct posix_acl_entry *acl_e = &acl->a_entries[n];
0810         ext_entry->e_tag  = cpu_to_le16(acl_e->e_tag);
0811         ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
0812         switch(acl_e->e_tag) {
0813         case ACL_USER:
0814             ext_entry->e_id =
0815                 cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
0816             break;
0817         case ACL_GROUP:
0818             ext_entry->e_id =
0819                 cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
0820             break;
0821         default:
0822             ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
0823             break;
0824         }
0825     }
0826     return real_size;
0827 }
0828 EXPORT_SYMBOL (posix_acl_to_xattr);
0829 
0830 static int
0831 posix_acl_xattr_get(const struct xattr_handler *handler,
0832             struct dentry *unused, struct inode *inode,
0833             const char *name, void *value, size_t size)
0834 {
0835     struct posix_acl *acl;
0836     int error;
0837 
0838     if (!IS_POSIXACL(inode))
0839         return -EOPNOTSUPP;
0840     if (S_ISLNK(inode->i_mode))
0841         return -EOPNOTSUPP;
0842 
0843     acl = get_acl(inode, handler->flags);
0844     if (IS_ERR(acl))
0845         return PTR_ERR(acl);
0846     if (acl == NULL)
0847         return -ENODATA;
0848 
0849     error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
0850     posix_acl_release(acl);
0851 
0852     return error;
0853 }
0854 
0855 int
0856 set_posix_acl(struct inode *inode, int type, struct posix_acl *acl)
0857 {
0858     if (!IS_POSIXACL(inode))
0859         return -EOPNOTSUPP;
0860     if (!inode->i_op->set_acl)
0861         return -EOPNOTSUPP;
0862 
0863     if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
0864         return acl ? -EACCES : 0;
0865     if (!inode_owner_or_capable(inode))
0866         return -EPERM;
0867 
0868     if (acl) {
0869         int ret = posix_acl_valid(inode->i_sb->s_user_ns, acl);
0870         if (ret)
0871             return ret;
0872     }
0873     return inode->i_op->set_acl(inode, acl, type);
0874 }
0875 EXPORT_SYMBOL(set_posix_acl);
0876 
0877 static int
0878 posix_acl_xattr_set(const struct xattr_handler *handler,
0879             struct dentry *unused, struct inode *inode,
0880             const char *name, const void *value,
0881             size_t size, int flags)
0882 {
0883     struct posix_acl *acl = NULL;
0884     int ret;
0885 
0886     if (value) {
0887         acl = posix_acl_from_xattr(&init_user_ns, value, size);
0888         if (IS_ERR(acl))
0889             return PTR_ERR(acl);
0890     }
0891     ret = set_posix_acl(inode, handler->flags, acl);
0892     posix_acl_release(acl);
0893     return ret;
0894 }
0895 
0896 static bool
0897 posix_acl_xattr_list(struct dentry *dentry)
0898 {
0899     return IS_POSIXACL(d_backing_inode(dentry));
0900 }
0901 
0902 const struct xattr_handler posix_acl_access_xattr_handler = {
0903     .name = XATTR_NAME_POSIX_ACL_ACCESS,
0904     .flags = ACL_TYPE_ACCESS,
0905     .list = posix_acl_xattr_list,
0906     .get = posix_acl_xattr_get,
0907     .set = posix_acl_xattr_set,
0908 };
0909 EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
0910 
0911 const struct xattr_handler posix_acl_default_xattr_handler = {
0912     .name = XATTR_NAME_POSIX_ACL_DEFAULT,
0913     .flags = ACL_TYPE_DEFAULT,
0914     .list = posix_acl_xattr_list,
0915     .get = posix_acl_xattr_get,
0916     .set = posix_acl_xattr_set,
0917 };
0918 EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
0919 
0920 int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
0921 {
0922     int error;
0923 
0924     if (type == ACL_TYPE_ACCESS) {
0925         error = posix_acl_update_mode(inode,
0926                 &inode->i_mode, &acl);
0927         if (error)
0928             return error;
0929     }
0930 
0931     inode->i_ctime = current_time(inode);
0932     set_cached_acl(inode, type, acl);
0933     return 0;
0934 }
0935 
0936 int simple_acl_create(struct inode *dir, struct inode *inode)
0937 {
0938     struct posix_acl *default_acl, *acl;
0939     int error;
0940 
0941     error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
0942     if (error)
0943         return error;
0944 
0945     set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
0946     set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
0947 
0948     if (default_acl)
0949         posix_acl_release(default_acl);
0950     if (acl)
0951         posix_acl_release(acl);
0952     return 0;
0953 }