0001
0002
0003
0004
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
0026
0027
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
0065
0066
0067
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
0160
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
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
0269
0270
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
0280
0281
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 }