1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2008, Christoph Hellwig 4 * All Rights Reserved. 5 */ 6 #include "xfs.h" 7 #include "xfs_shared.h" 8 #include "xfs_format.h" 9 #include "xfs_log_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_inode.h" 13 #include "xfs_attr.h" 14 #include "xfs_trace.h" 15 #include "xfs_error.h" 16 #include "xfs_acl.h" 17 #include "xfs_da_format.h" 18 #include "xfs_da_btree.h" 19 #include "xfs_trans.h" 20 21 #include <linux/posix_acl_xattr.h> 22 23 /* 24 * Locking scheme: 25 * - all ACL updates are protected by inode->i_mutex, which is taken before 26 * calling into this file. 27 */ 28 29 STATIC struct posix_acl * 30 xfs_acl_from_disk( 31 struct xfs_mount *mp, 32 const struct xfs_acl *aclp, 33 int len, 34 int max_entries) 35 { 36 struct posix_acl_entry *acl_e; 37 struct posix_acl *acl; 38 const struct xfs_acl_entry *ace; 39 unsigned int count, i; 40 41 if (len < sizeof(*aclp)) { 42 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp, 43 len); 44 return ERR_PTR(-EFSCORRUPTED); 45 } 46 47 count = be32_to_cpu(aclp->acl_cnt); 48 if (count > max_entries || XFS_ACL_SIZE(count) != len) { 49 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp, 50 len); 51 return ERR_PTR(-EFSCORRUPTED); 52 } 53 54 acl = posix_acl_alloc(count, GFP_KERNEL); 55 if (!acl) 56 return ERR_PTR(-ENOMEM); 57 58 for (i = 0; i < count; i++) { 59 acl_e = &acl->a_entries[i]; 60 ace = &aclp->acl_entry[i]; 61 62 /* 63 * The tag is 32 bits on disk and 16 bits in core. 64 * 65 * Because every access to it goes through the core 66 * format first this is not a problem. 67 */ 68 acl_e->e_tag = be32_to_cpu(ace->ae_tag); 69 acl_e->e_perm = be16_to_cpu(ace->ae_perm); 70 71 switch (acl_e->e_tag) { 72 case ACL_USER: 73 acl_e->e_uid = make_kuid(&init_user_ns, 74 be32_to_cpu(ace->ae_id)); 75 break; 76 case ACL_GROUP: 77 acl_e->e_gid = make_kgid(&init_user_ns, 78 be32_to_cpu(ace->ae_id)); 79 break; 80 case ACL_USER_OBJ: 81 case ACL_GROUP_OBJ: 82 case ACL_MASK: 83 case ACL_OTHER: 84 break; 85 default: 86 goto fail; 87 } 88 } 89 return acl; 90 91 fail: 92 posix_acl_release(acl); 93 return ERR_PTR(-EINVAL); 94 } 95 96 STATIC void 97 xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) 98 { 99 const struct posix_acl_entry *acl_e; 100 struct xfs_acl_entry *ace; 101 int i; 102 103 aclp->acl_cnt = cpu_to_be32(acl->a_count); 104 for (i = 0; i < acl->a_count; i++) { 105 ace = &aclp->acl_entry[i]; 106 acl_e = &acl->a_entries[i]; 107 108 ace->ae_tag = cpu_to_be32(acl_e->e_tag); 109 switch (acl_e->e_tag) { 110 case ACL_USER: 111 ace->ae_id = cpu_to_be32( 112 from_kuid(&init_user_ns, acl_e->e_uid)); 113 break; 114 case ACL_GROUP: 115 ace->ae_id = cpu_to_be32( 116 from_kgid(&init_user_ns, acl_e->e_gid)); 117 break; 118 default: 119 ace->ae_id = cpu_to_be32(ACL_UNDEFINED_ID); 120 break; 121 } 122 123 ace->ae_perm = cpu_to_be16(acl_e->e_perm); 124 } 125 } 126 127 struct posix_acl * 128 xfs_get_acl(struct inode *inode, int type) 129 { 130 struct xfs_inode *ip = XFS_I(inode); 131 struct xfs_mount *mp = ip->i_mount; 132 struct posix_acl *acl = NULL; 133 struct xfs_da_args args = { 134 .dp = ip, 135 .attr_filter = XFS_ATTR_ROOT, 136 .valuelen = XFS_ACL_MAX_SIZE(mp), 137 }; 138 int error; 139 140 trace_xfs_get_acl(ip); 141 142 switch (type) { 143 case ACL_TYPE_ACCESS: 144 args.name = SGI_ACL_FILE; 145 break; 146 case ACL_TYPE_DEFAULT: 147 args.name = SGI_ACL_DEFAULT; 148 break; 149 default: 150 BUG(); 151 } 152 args.namelen = strlen(args.name); 153 154 /* 155 * If the attribute doesn't exist make sure we have a negative cache 156 * entry, for any other error assume it is transient. 157 */ 158 error = xfs_attr_get(&args); 159 if (!error) { 160 acl = xfs_acl_from_disk(mp, args.value, args.valuelen, 161 XFS_ACL_MAX_ENTRIES(mp)); 162 } else if (error != -ENOATTR) { 163 acl = ERR_PTR(error); 164 } 165 166 kmem_free(args.value); 167 return acl; 168 } 169 170 int 171 __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 172 { 173 struct xfs_inode *ip = XFS_I(inode); 174 struct xfs_da_args args = { 175 .dp = ip, 176 .attr_filter = XFS_ATTR_ROOT, 177 }; 178 int error; 179 180 switch (type) { 181 case ACL_TYPE_ACCESS: 182 args.name = SGI_ACL_FILE; 183 break; 184 case ACL_TYPE_DEFAULT: 185 if (!S_ISDIR(inode->i_mode)) 186 return acl ? -EACCES : 0; 187 args.name = SGI_ACL_DEFAULT; 188 break; 189 default: 190 return -EINVAL; 191 } 192 args.namelen = strlen(args.name); 193 194 if (acl) { 195 args.valuelen = XFS_ACL_SIZE(acl->a_count); 196 args.value = kvzalloc(args.valuelen, GFP_KERNEL); 197 if (!args.value) 198 return -ENOMEM; 199 xfs_acl_to_disk(args.value, acl); 200 } 201 202 error = xfs_attr_set(&args); 203 kmem_free(args.value); 204 205 /* 206 * If the attribute didn't exist to start with that's fine. 207 */ 208 if (!acl && error == -ENOATTR) 209 error = 0; 210 if (!error) 211 set_cached_acl(inode, type, acl); 212 return error; 213 } 214 215 static int 216 xfs_acl_set_mode( 217 struct inode *inode, 218 umode_t mode) 219 { 220 struct xfs_inode *ip = XFS_I(inode); 221 struct xfs_mount *mp = ip->i_mount; 222 struct xfs_trans *tp; 223 int error; 224 225 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); 226 if (error) 227 return error; 228 229 xfs_ilock(ip, XFS_ILOCK_EXCL); 230 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 231 inode->i_mode = mode; 232 inode->i_ctime = current_time(inode); 233 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 234 235 if (mp->m_flags & XFS_MOUNT_WSYNC) 236 xfs_trans_set_sync(tp); 237 return xfs_trans_commit(tp); 238 } 239 240 int 241 xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 242 { 243 umode_t mode; 244 bool set_mode = false; 245 int error = 0; 246 247 if (!acl) 248 goto set_acl; 249 250 error = -E2BIG; 251 if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb))) 252 return error; 253 254 if (type == ACL_TYPE_ACCESS) { 255 error = posix_acl_update_mode(inode, &mode, &acl); 256 if (error) 257 return error; 258 set_mode = true; 259 } 260 261 set_acl: 262 /* 263 * We set the mode after successfully updating the ACL xattr because the 264 * xattr update can fail at ENOSPC and we don't want to change the mode 265 * if the ACL update hasn't been applied. 266 */ 267 error = __xfs_set_acl(inode, acl, type); 268 if (!error && set_mode && mode != inode->i_mode) 269 error = xfs_acl_set_mode(inode, mode); 270 return error; 271 } 272 273 /* 274 * Invalidate any cached ACLs if the user has bypassed the ACL interface. 275 * We don't validate the content whatsoever so it is caller responsibility to 276 * provide data in valid format and ensure i_mode is consistent. 277 */ 278 void 279 xfs_forget_acl( 280 struct inode *inode, 281 const char *name) 282 { 283 if (!strcmp(name, SGI_ACL_FILE)) 284 forget_cached_acl(inode, ACL_TYPE_ACCESS); 285 else if (!strcmp(name, SGI_ACL_DEFAULT)) 286 forget_cached_acl(inode, ACL_TYPE_DEFAULT); 287 } 288