1 /* 2 * Copyright (c) 2008, Christoph Hellwig 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 #include "xfs.h" 19 #include "xfs_acl.h" 20 #include "xfs_attr.h" 21 #include "xfs_bmap_btree.h" 22 #include "xfs_inode.h" 23 #include "xfs_vnodeops.h" 24 #include "xfs_trace.h" 25 #include <linux/slab.h> 26 #include <linux/xattr.h> 27 #include <linux/posix_acl_xattr.h> 28 29 30 /* 31 * Locking scheme: 32 * - all ACL updates are protected by inode->i_mutex, which is taken before 33 * calling into this file. 34 */ 35 36 STATIC struct posix_acl * 37 xfs_acl_from_disk(struct xfs_acl *aclp) 38 { 39 struct posix_acl_entry *acl_e; 40 struct posix_acl *acl; 41 struct xfs_acl_entry *ace; 42 int count, i; 43 44 count = be32_to_cpu(aclp->acl_cnt); 45 46 acl = posix_acl_alloc(count, GFP_KERNEL); 47 if (!acl) 48 return ERR_PTR(-ENOMEM); 49 50 for (i = 0; i < count; i++) { 51 acl_e = &acl->a_entries[i]; 52 ace = &aclp->acl_entry[i]; 53 54 /* 55 * The tag is 32 bits on disk and 16 bits in core. 56 * 57 * Because every access to it goes through the core 58 * format first this is not a problem. 59 */ 60 acl_e->e_tag = be32_to_cpu(ace->ae_tag); 61 acl_e->e_perm = be16_to_cpu(ace->ae_perm); 62 63 switch (acl_e->e_tag) { 64 case ACL_USER: 65 case ACL_GROUP: 66 acl_e->e_id = be32_to_cpu(ace->ae_id); 67 break; 68 case ACL_USER_OBJ: 69 case ACL_GROUP_OBJ: 70 case ACL_MASK: 71 case ACL_OTHER: 72 acl_e->e_id = ACL_UNDEFINED_ID; 73 break; 74 default: 75 goto fail; 76 } 77 } 78 return acl; 79 80 fail: 81 posix_acl_release(acl); 82 return ERR_PTR(-EINVAL); 83 } 84 85 STATIC void 86 xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) 87 { 88 const struct posix_acl_entry *acl_e; 89 struct xfs_acl_entry *ace; 90 int i; 91 92 aclp->acl_cnt = cpu_to_be32(acl->a_count); 93 for (i = 0; i < acl->a_count; i++) { 94 ace = &aclp->acl_entry[i]; 95 acl_e = &acl->a_entries[i]; 96 97 ace->ae_tag = cpu_to_be32(acl_e->e_tag); 98 ace->ae_id = cpu_to_be32(acl_e->e_id); 99 ace->ae_perm = cpu_to_be16(acl_e->e_perm); 100 } 101 } 102 103 struct posix_acl * 104 xfs_get_acl(struct inode *inode, int type) 105 { 106 struct xfs_inode *ip = XFS_I(inode); 107 struct posix_acl *acl; 108 struct xfs_acl *xfs_acl; 109 int len = sizeof(struct xfs_acl); 110 unsigned char *ea_name; 111 int error; 112 113 acl = get_cached_acl(inode, type); 114 if (acl != ACL_NOT_CACHED) 115 return acl; 116 117 trace_xfs_get_acl(ip); 118 119 switch (type) { 120 case ACL_TYPE_ACCESS: 121 ea_name = SGI_ACL_FILE; 122 break; 123 case ACL_TYPE_DEFAULT: 124 ea_name = SGI_ACL_DEFAULT; 125 break; 126 default: 127 BUG(); 128 } 129 130 /* 131 * If we have a cached ACLs value just return it, not need to 132 * go out to the disk. 133 */ 134 135 xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); 136 if (!xfs_acl) 137 return ERR_PTR(-ENOMEM); 138 139 error = -xfs_attr_get(ip, ea_name, (unsigned char *)xfs_acl, 140 &len, ATTR_ROOT); 141 if (error) { 142 /* 143 * If the attribute doesn't exist make sure we have a negative 144 * cache entry, for any other error assume it is transient and 145 * leave the cache entry as ACL_NOT_CACHED. 146 */ 147 if (error == -ENOATTR) { 148 acl = NULL; 149 goto out_update_cache; 150 } 151 goto out; 152 } 153 154 acl = xfs_acl_from_disk(xfs_acl); 155 if (IS_ERR(acl)) 156 goto out; 157 158 out_update_cache: 159 set_cached_acl(inode, type, acl); 160 out: 161 kfree(xfs_acl); 162 return acl; 163 } 164 165 STATIC int 166 xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 167 { 168 struct xfs_inode *ip = XFS_I(inode); 169 unsigned char *ea_name; 170 int error; 171 172 if (S_ISLNK(inode->i_mode)) 173 return -EOPNOTSUPP; 174 175 switch (type) { 176 case ACL_TYPE_ACCESS: 177 ea_name = SGI_ACL_FILE; 178 break; 179 case ACL_TYPE_DEFAULT: 180 if (!S_ISDIR(inode->i_mode)) 181 return acl ? -EACCES : 0; 182 ea_name = SGI_ACL_DEFAULT; 183 break; 184 default: 185 return -EINVAL; 186 } 187 188 if (acl) { 189 struct xfs_acl *xfs_acl; 190 int len; 191 192 xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); 193 if (!xfs_acl) 194 return -ENOMEM; 195 196 xfs_acl_to_disk(xfs_acl, acl); 197 len = sizeof(struct xfs_acl) - 198 (sizeof(struct xfs_acl_entry) * 199 (XFS_ACL_MAX_ENTRIES - acl->a_count)); 200 201 error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, 202 len, ATTR_ROOT); 203 204 kfree(xfs_acl); 205 } else { 206 /* 207 * A NULL ACL argument means we want to remove the ACL. 208 */ 209 error = -xfs_attr_remove(ip, ea_name, ATTR_ROOT); 210 211 /* 212 * If the attribute didn't exist to start with that's fine. 213 */ 214 if (error == -ENOATTR) 215 error = 0; 216 } 217 218 if (!error) 219 set_cached_acl(inode, type, acl); 220 return error; 221 } 222 223 static int 224 xfs_set_mode(struct inode *inode, umode_t mode) 225 { 226 int error = 0; 227 228 if (mode != inode->i_mode) { 229 struct iattr iattr; 230 231 iattr.ia_valid = ATTR_MODE | ATTR_CTIME; 232 iattr.ia_mode = mode; 233 iattr.ia_ctime = current_fs_time(inode->i_sb); 234 235 error = -xfs_setattr_nonsize(XFS_I(inode), &iattr, XFS_ATTR_NOACL); 236 } 237 238 return error; 239 } 240 241 static int 242 xfs_acl_exists(struct inode *inode, unsigned char *name) 243 { 244 int len = sizeof(struct xfs_acl); 245 246 return (xfs_attr_get(XFS_I(inode), name, NULL, &len, 247 ATTR_ROOT|ATTR_KERNOVAL) == 0); 248 } 249 250 int 251 posix_acl_access_exists(struct inode *inode) 252 { 253 return xfs_acl_exists(inode, SGI_ACL_FILE); 254 } 255 256 int 257 posix_acl_default_exists(struct inode *inode) 258 { 259 if (!S_ISDIR(inode->i_mode)) 260 return 0; 261 return xfs_acl_exists(inode, SGI_ACL_DEFAULT); 262 } 263 264 /* 265 * No need for i_mutex because the inode is not yet exposed to the VFS. 266 */ 267 int 268 xfs_inherit_acl(struct inode *inode, struct posix_acl *acl) 269 { 270 umode_t mode = inode->i_mode; 271 int error = 0, inherit = 0; 272 273 if (S_ISDIR(inode->i_mode)) { 274 error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); 275 if (error) 276 goto out; 277 } 278 279 error = posix_acl_create(&acl, GFP_KERNEL, &mode); 280 if (error < 0) 281 return error; 282 283 /* 284 * If posix_acl_create returns a positive value we need to 285 * inherit a permission that can't be represented using the Unix 286 * mode bits and we actually need to set an ACL. 287 */ 288 if (error > 0) 289 inherit = 1; 290 291 error = xfs_set_mode(inode, mode); 292 if (error) 293 goto out; 294 295 if (inherit) 296 error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl); 297 298 out: 299 posix_acl_release(acl); 300 return error; 301 } 302 303 int 304 xfs_acl_chmod(struct inode *inode) 305 { 306 struct posix_acl *acl; 307 int error; 308 309 if (S_ISLNK(inode->i_mode)) 310 return -EOPNOTSUPP; 311 312 acl = xfs_get_acl(inode, ACL_TYPE_ACCESS); 313 if (IS_ERR(acl) || !acl) 314 return PTR_ERR(acl); 315 316 error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); 317 if (error) 318 return error; 319 320 error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl); 321 posix_acl_release(acl); 322 return error; 323 } 324 325 static int 326 xfs_xattr_acl_get(struct dentry *dentry, const char *name, 327 void *value, size_t size, int type) 328 { 329 struct posix_acl *acl; 330 int error; 331 332 acl = xfs_get_acl(dentry->d_inode, type); 333 if (IS_ERR(acl)) 334 return PTR_ERR(acl); 335 if (acl == NULL) 336 return -ENODATA; 337 338 error = posix_acl_to_xattr(acl, value, size); 339 posix_acl_release(acl); 340 341 return error; 342 } 343 344 static int 345 xfs_xattr_acl_set(struct dentry *dentry, const char *name, 346 const void *value, size_t size, int flags, int type) 347 { 348 struct inode *inode = dentry->d_inode; 349 struct posix_acl *acl = NULL; 350 int error = 0; 351 352 if (flags & XATTR_CREATE) 353 return -EINVAL; 354 if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) 355 return value ? -EACCES : 0; 356 if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) 357 return -EPERM; 358 359 if (!value) 360 goto set_acl; 361 362 acl = posix_acl_from_xattr(value, size); 363 if (!acl) { 364 /* 365 * acl_set_file(3) may request that we set default ACLs with 366 * zero length -- defend (gracefully) against that here. 367 */ 368 goto out; 369 } 370 if (IS_ERR(acl)) { 371 error = PTR_ERR(acl); 372 goto out; 373 } 374 375 error = posix_acl_valid(acl); 376 if (error) 377 goto out_release; 378 379 error = -EINVAL; 380 if (acl->a_count > XFS_ACL_MAX_ENTRIES) 381 goto out_release; 382 383 if (type == ACL_TYPE_ACCESS) { 384 umode_t mode = inode->i_mode; 385 error = posix_acl_equiv_mode(acl, &mode); 386 387 if (error <= 0) { 388 posix_acl_release(acl); 389 acl = NULL; 390 391 if (error < 0) 392 return error; 393 } 394 395 error = xfs_set_mode(inode, mode); 396 if (error) 397 goto out_release; 398 } 399 400 set_acl: 401 error = xfs_set_acl(inode, type, acl); 402 out_release: 403 posix_acl_release(acl); 404 out: 405 return error; 406 } 407 408 const struct xattr_handler xfs_xattr_acl_access_handler = { 409 .prefix = POSIX_ACL_XATTR_ACCESS, 410 .flags = ACL_TYPE_ACCESS, 411 .get = xfs_xattr_acl_get, 412 .set = xfs_xattr_acl_set, 413 }; 414 415 const struct xattr_handler xfs_xattr_acl_default_handler = { 416 .prefix = POSIX_ACL_XATTR_DEFAULT, 417 .flags = ACL_TYPE_DEFAULT, 418 .get = xfs_xattr_acl_get, 419 .set = xfs_xattr_acl_set, 420 }; 421