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