Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2008, Christoph Hellwig
0004  * All Rights Reserved.
0005  */
0006 #include "xfs.h"
0007 #include "xfs_shared.h"
0008 #include "xfs_format.h"
0009 #include "xfs_log_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_mount.h"
0012 #include "xfs_inode.h"
0013 #include "xfs_da_format.h"
0014 #include "xfs_da_btree.h"
0015 #include "xfs_attr.h"
0016 #include "xfs_trace.h"
0017 #include "xfs_error.h"
0018 #include "xfs_acl.h"
0019 #include "xfs_trans.h"
0020 #include "xfs_xattr.h"
0021 
0022 #include <linux/posix_acl_xattr.h>
0023 
0024 /*
0025  * Locking scheme:
0026  *  - all ACL updates are protected by inode->i_mutex, which is taken before
0027  *    calling into this file.
0028  */
0029 
0030 STATIC struct posix_acl *
0031 xfs_acl_from_disk(
0032     struct xfs_mount    *mp,
0033     const struct xfs_acl    *aclp,
0034     int         len,
0035     int         max_entries)
0036 {
0037     struct posix_acl_entry *acl_e;
0038     struct posix_acl *acl;
0039     const struct xfs_acl_entry *ace;
0040     unsigned int count, i;
0041 
0042     if (len < sizeof(*aclp)) {
0043         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
0044                 len);
0045         return ERR_PTR(-EFSCORRUPTED);
0046     }
0047 
0048     count = be32_to_cpu(aclp->acl_cnt);
0049     if (count > max_entries || XFS_ACL_SIZE(count) != len) {
0050         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
0051                 len);
0052         return ERR_PTR(-EFSCORRUPTED);
0053     }
0054 
0055     acl = posix_acl_alloc(count, GFP_KERNEL);
0056     if (!acl)
0057         return ERR_PTR(-ENOMEM);
0058 
0059     for (i = 0; i < count; i++) {
0060         acl_e = &acl->a_entries[i];
0061         ace = &aclp->acl_entry[i];
0062 
0063         /*
0064          * The tag is 32 bits on disk and 16 bits in core.
0065          *
0066          * Because every access to it goes through the core
0067          * format first this is not a problem.
0068          */
0069         acl_e->e_tag = be32_to_cpu(ace->ae_tag);
0070         acl_e->e_perm = be16_to_cpu(ace->ae_perm);
0071 
0072         switch (acl_e->e_tag) {
0073         case ACL_USER:
0074             acl_e->e_uid = make_kuid(&init_user_ns,
0075                          be32_to_cpu(ace->ae_id));
0076             break;
0077         case ACL_GROUP:
0078             acl_e->e_gid = make_kgid(&init_user_ns,
0079                          be32_to_cpu(ace->ae_id));
0080             break;
0081         case ACL_USER_OBJ:
0082         case ACL_GROUP_OBJ:
0083         case ACL_MASK:
0084         case ACL_OTHER:
0085             break;
0086         default:
0087             goto fail;
0088         }
0089     }
0090     return acl;
0091 
0092 fail:
0093     posix_acl_release(acl);
0094     return ERR_PTR(-EINVAL);
0095 }
0096 
0097 STATIC void
0098 xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl)
0099 {
0100     const struct posix_acl_entry *acl_e;
0101     struct xfs_acl_entry *ace;
0102     int i;
0103 
0104     aclp->acl_cnt = cpu_to_be32(acl->a_count);
0105     for (i = 0; i < acl->a_count; i++) {
0106         ace = &aclp->acl_entry[i];
0107         acl_e = &acl->a_entries[i];
0108 
0109         ace->ae_tag = cpu_to_be32(acl_e->e_tag);
0110         switch (acl_e->e_tag) {
0111         case ACL_USER:
0112             ace->ae_id = cpu_to_be32(
0113                     from_kuid(&init_user_ns, acl_e->e_uid));
0114             break;
0115         case ACL_GROUP:
0116             ace->ae_id = cpu_to_be32(
0117                     from_kgid(&init_user_ns, acl_e->e_gid));
0118             break;
0119         default:
0120             ace->ae_id = cpu_to_be32(ACL_UNDEFINED_ID);
0121             break;
0122         }
0123 
0124         ace->ae_perm = cpu_to_be16(acl_e->e_perm);
0125     }
0126 }
0127 
0128 struct posix_acl *
0129 xfs_get_acl(struct inode *inode, int type, bool rcu)
0130 {
0131     struct xfs_inode    *ip = XFS_I(inode);
0132     struct xfs_mount    *mp = ip->i_mount;
0133     struct posix_acl    *acl = NULL;
0134     struct xfs_da_args  args = {
0135         .dp     = ip,
0136         .attr_filter    = XFS_ATTR_ROOT,
0137         .valuelen   = XFS_ACL_MAX_SIZE(mp),
0138     };
0139     int         error;
0140 
0141     if (rcu)
0142         return ERR_PTR(-ECHILD);
0143 
0144     trace_xfs_get_acl(ip);
0145 
0146     switch (type) {
0147     case ACL_TYPE_ACCESS:
0148         args.name = SGI_ACL_FILE;
0149         break;
0150     case ACL_TYPE_DEFAULT:
0151         args.name = SGI_ACL_DEFAULT;
0152         break;
0153     default:
0154         BUG();
0155     }
0156     args.namelen = strlen(args.name);
0157 
0158     /*
0159      * If the attribute doesn't exist make sure we have a negative cache
0160      * entry, for any other error assume it is transient.
0161      */
0162     error = xfs_attr_get(&args);
0163     if (!error) {
0164         acl = xfs_acl_from_disk(mp, args.value, args.valuelen,
0165                     XFS_ACL_MAX_ENTRIES(mp));
0166     } else if (error != -ENOATTR) {
0167         acl = ERR_PTR(error);
0168     }
0169 
0170     kmem_free(args.value);
0171     return acl;
0172 }
0173 
0174 int
0175 __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
0176 {
0177     struct xfs_inode    *ip = XFS_I(inode);
0178     struct xfs_da_args  args = {
0179         .dp     = ip,
0180         .attr_filter    = XFS_ATTR_ROOT,
0181     };
0182     int         error;
0183 
0184     switch (type) {
0185     case ACL_TYPE_ACCESS:
0186         args.name = SGI_ACL_FILE;
0187         break;
0188     case ACL_TYPE_DEFAULT:
0189         if (!S_ISDIR(inode->i_mode))
0190             return acl ? -EACCES : 0;
0191         args.name = SGI_ACL_DEFAULT;
0192         break;
0193     default:
0194         return -EINVAL;
0195     }
0196     args.namelen = strlen(args.name);
0197 
0198     if (acl) {
0199         args.valuelen = XFS_ACL_SIZE(acl->a_count);
0200         args.value = kvzalloc(args.valuelen, GFP_KERNEL);
0201         if (!args.value)
0202             return -ENOMEM;
0203         xfs_acl_to_disk(args.value, acl);
0204     }
0205 
0206     error = xfs_attr_change(&args);
0207     kmem_free(args.value);
0208 
0209     /*
0210      * If the attribute didn't exist to start with that's fine.
0211      */
0212     if (!acl && error == -ENOATTR)
0213         error = 0;
0214     if (!error)
0215         set_cached_acl(inode, type, acl);
0216     return error;
0217 }
0218 
0219 static int
0220 xfs_acl_set_mode(
0221     struct inode        *inode,
0222     umode_t         mode)
0223 {
0224     struct xfs_inode    *ip = XFS_I(inode);
0225     struct xfs_mount    *mp = ip->i_mount;
0226     struct xfs_trans    *tp;
0227     int         error;
0228 
0229     error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
0230     if (error)
0231         return error;
0232 
0233     xfs_ilock(ip, XFS_ILOCK_EXCL);
0234     xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
0235     inode->i_mode = mode;
0236     inode->i_ctime = current_time(inode);
0237     xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
0238 
0239     if (xfs_has_wsync(mp))
0240         xfs_trans_set_sync(tp);
0241     return xfs_trans_commit(tp);
0242 }
0243 
0244 int
0245 xfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
0246         struct posix_acl *acl, int type)
0247 {
0248     umode_t mode;
0249     bool set_mode = false;
0250     int error = 0;
0251 
0252     if (!acl)
0253         goto set_acl;
0254 
0255     error = -E2BIG;
0256     if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
0257         return error;
0258 
0259     if (type == ACL_TYPE_ACCESS) {
0260         error = posix_acl_update_mode(mnt_userns, inode, &mode, &acl);
0261         if (error)
0262             return error;
0263         set_mode = true;
0264     }
0265 
0266  set_acl:
0267     /*
0268      * We set the mode after successfully updating the ACL xattr because the
0269      * xattr update can fail at ENOSPC and we don't want to change the mode
0270      * if the ACL update hasn't been applied.
0271      */
0272     error =  __xfs_set_acl(inode, acl, type);
0273     if (!error && set_mode && mode != inode->i_mode)
0274         error = xfs_acl_set_mode(inode, mode);
0275     return error;
0276 }
0277 
0278 /*
0279  * Invalidate any cached ACLs if the user has bypassed the ACL interface.
0280  * We don't validate the content whatsoever so it is caller responsibility to
0281  * provide data in valid format and ensure i_mode is consistent.
0282  */
0283 void
0284 xfs_forget_acl(
0285     struct inode        *inode,
0286     const char      *name)
0287 {
0288     if (!strcmp(name, SGI_ACL_FILE))
0289         forget_cached_acl(inode, ACL_TYPE_ACCESS);
0290     else if (!strcmp(name, SGI_ACL_DEFAULT))
0291         forget_cached_acl(inode, ACL_TYPE_DEFAULT);
0292 }