xfs: use generic Posix ACL code

This patch rips out the XFS ACL handling code and uses the generic
fs/posix_acl.c code instead. The ondisk format is of course left
unchanged.

This also introduces the same ACL caching all other Linux filesystems do
by adding pointers to the acl and default acl in struct xfs_inode.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Eric Sandeen <sandeen@sandeen.net>

authored by

Christoph Hellwig and committed by
Christoph Hellwig
ef14f0c1 8b5403a6

+598 -1103
+1
fs/xfs/Kconfig
··· 39 39 config XFS_POSIX_ACL 40 40 bool "XFS POSIX ACL support" 41 41 depends on XFS_FS 42 + select FS_POSIX_ACL 42 43 help 43 44 POSIX Access Control Lists (ACLs) support permissions for users and 44 45 groups beyond the owner/group/world scheme.
+1 -1
fs/xfs/Makefile
··· 40 40 endif 41 41 42 42 xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o 43 - xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o 43 + xfs-$(CONFIG_XFS_POSIX_ACL) += $(XFS_LINUX)/xfs_acl.o 44 44 xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o 45 45 xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o 46 46 xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o
+523
fs/xfs/linux-2.6/xfs_acl.c
··· 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 <linux/xattr.h> 25 + #include <linux/posix_acl_xattr.h> 26 + 27 + 28 + #define XFS_ACL_NOT_CACHED ((void *)-1) 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 + * - access and updates to the ip->i_acl and ip->i_default_acl pointers are 35 + * protected by inode->i_lock. 36 + */ 37 + 38 + STATIC struct posix_acl * 39 + xfs_acl_from_disk(struct xfs_acl *aclp) 40 + { 41 + struct posix_acl_entry *acl_e; 42 + struct posix_acl *acl; 43 + struct xfs_acl_entry *ace; 44 + int count, i; 45 + 46 + count = be32_to_cpu(aclp->acl_cnt); 47 + 48 + acl = posix_acl_alloc(count, GFP_KERNEL); 49 + if (!acl) 50 + return ERR_PTR(-ENOMEM); 51 + 52 + for (i = 0; i < count; i++) { 53 + acl_e = &acl->a_entries[i]; 54 + ace = &aclp->acl_entry[i]; 55 + 56 + /* 57 + * The tag is 32 bits on disk and 16 bits in core. 58 + * 59 + * Because every access to it goes through the core 60 + * format first this is not a problem. 61 + */ 62 + acl_e->e_tag = be32_to_cpu(ace->ae_tag); 63 + acl_e->e_perm = be16_to_cpu(ace->ae_perm); 64 + 65 + switch (acl_e->e_tag) { 66 + case ACL_USER: 67 + case ACL_GROUP: 68 + acl_e->e_id = be32_to_cpu(ace->ae_id); 69 + break; 70 + case ACL_USER_OBJ: 71 + case ACL_GROUP_OBJ: 72 + case ACL_MASK: 73 + case ACL_OTHER: 74 + acl_e->e_id = ACL_UNDEFINED_ID; 75 + break; 76 + default: 77 + goto fail; 78 + } 79 + } 80 + return acl; 81 + 82 + fail: 83 + posix_acl_release(acl); 84 + return ERR_PTR(-EINVAL); 85 + } 86 + 87 + STATIC void 88 + xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) 89 + { 90 + const struct posix_acl_entry *acl_e; 91 + struct xfs_acl_entry *ace; 92 + int i; 93 + 94 + aclp->acl_cnt = cpu_to_be32(acl->a_count); 95 + for (i = 0; i < acl->a_count; i++) { 96 + ace = &aclp->acl_entry[i]; 97 + acl_e = &acl->a_entries[i]; 98 + 99 + ace->ae_tag = cpu_to_be32(acl_e->e_tag); 100 + ace->ae_id = cpu_to_be32(acl_e->e_id); 101 + ace->ae_perm = cpu_to_be16(acl_e->e_perm); 102 + } 103 + } 104 + 105 + /* 106 + * Update the cached ACL pointer in the inode. 107 + * 108 + * Because we don't hold any locks while reading/writing the attribute 109 + * from/to disk another thread could have raced and updated the cached 110 + * ACL value before us. In that case we release the previous cached value 111 + * and update it with our new value. 112 + */ 113 + STATIC void 114 + xfs_update_cached_acl(struct inode *inode, struct posix_acl **p_acl, 115 + struct posix_acl *acl) 116 + { 117 + spin_lock(&inode->i_lock); 118 + if (*p_acl && *p_acl != XFS_ACL_NOT_CACHED) 119 + posix_acl_release(*p_acl); 120 + *p_acl = posix_acl_dup(acl); 121 + spin_unlock(&inode->i_lock); 122 + } 123 + 124 + struct posix_acl * 125 + xfs_get_acl(struct inode *inode, int type) 126 + { 127 + struct xfs_inode *ip = XFS_I(inode); 128 + struct posix_acl *acl = NULL, **p_acl; 129 + struct xfs_acl *xfs_acl; 130 + int len = sizeof(struct xfs_acl); 131 + char *ea_name; 132 + int error; 133 + 134 + switch (type) { 135 + case ACL_TYPE_ACCESS: 136 + ea_name = SGI_ACL_FILE; 137 + p_acl = &ip->i_acl; 138 + break; 139 + case ACL_TYPE_DEFAULT: 140 + ea_name = SGI_ACL_DEFAULT; 141 + p_acl = &ip->i_default_acl; 142 + break; 143 + default: 144 + return ERR_PTR(-EINVAL); 145 + } 146 + 147 + spin_lock(&inode->i_lock); 148 + if (*p_acl != XFS_ACL_NOT_CACHED) 149 + acl = posix_acl_dup(*p_acl); 150 + spin_unlock(&inode->i_lock); 151 + 152 + /* 153 + * If we have a cached ACLs value just return it, not need to 154 + * go out to the disk. 155 + */ 156 + if (acl) 157 + return acl; 158 + 159 + xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); 160 + if (!xfs_acl) 161 + return ERR_PTR(-ENOMEM); 162 + 163 + error = -xfs_attr_get(ip, ea_name, (char *)xfs_acl, &len, ATTR_ROOT); 164 + if (error) { 165 + /* 166 + * If the attribute doesn't exist make sure we have a negative 167 + * cache entry, for any other error assume it is transient and 168 + * leave the cache entry as XFS_ACL_NOT_CACHED. 169 + */ 170 + if (error == -ENOATTR) { 171 + acl = NULL; 172 + goto out_update_cache; 173 + } 174 + goto out; 175 + } 176 + 177 + acl = xfs_acl_from_disk(xfs_acl); 178 + if (IS_ERR(acl)) 179 + goto out; 180 + 181 + out_update_cache: 182 + xfs_update_cached_acl(inode, p_acl, acl); 183 + out: 184 + kfree(xfs_acl); 185 + return acl; 186 + } 187 + 188 + STATIC int 189 + xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 190 + { 191 + struct xfs_inode *ip = XFS_I(inode); 192 + struct posix_acl **p_acl; 193 + char *ea_name; 194 + int error; 195 + 196 + if (S_ISLNK(inode->i_mode)) 197 + return -EOPNOTSUPP; 198 + 199 + switch (type) { 200 + case ACL_TYPE_ACCESS: 201 + ea_name = SGI_ACL_FILE; 202 + p_acl = &ip->i_acl; 203 + break; 204 + case ACL_TYPE_DEFAULT: 205 + if (!S_ISDIR(inode->i_mode)) 206 + return acl ? -EACCES : 0; 207 + ea_name = SGI_ACL_DEFAULT; 208 + p_acl = &ip->i_default_acl; 209 + break; 210 + default: 211 + return -EINVAL; 212 + } 213 + 214 + if (acl) { 215 + struct xfs_acl *xfs_acl; 216 + int len; 217 + 218 + xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); 219 + if (!xfs_acl) 220 + return -ENOMEM; 221 + 222 + xfs_acl_to_disk(xfs_acl, acl); 223 + len = sizeof(struct xfs_acl) - 224 + (sizeof(struct xfs_acl_entry) * 225 + (XFS_ACL_MAX_ENTRIES - acl->a_count)); 226 + 227 + error = -xfs_attr_set(ip, ea_name, (char *)xfs_acl, 228 + len, ATTR_ROOT); 229 + 230 + kfree(xfs_acl); 231 + } else { 232 + /* 233 + * A NULL ACL argument means we want to remove the ACL. 234 + */ 235 + error = -xfs_attr_remove(ip, ea_name, ATTR_ROOT); 236 + 237 + /* 238 + * If the attribute didn't exist to start with that's fine. 239 + */ 240 + if (error == -ENOATTR) 241 + error = 0; 242 + } 243 + 244 + if (!error) 245 + xfs_update_cached_acl(inode, p_acl, acl); 246 + return error; 247 + } 248 + 249 + int 250 + xfs_check_acl(struct inode *inode, int mask) 251 + { 252 + struct xfs_inode *ip = XFS_I(inode); 253 + struct posix_acl *acl; 254 + int error = -EAGAIN; 255 + 256 + xfs_itrace_entry(ip); 257 + 258 + /* 259 + * If there is no attribute fork no ACL exists on this inode and 260 + * we can skip the whole exercise. 261 + */ 262 + if (!XFS_IFORK_Q(ip)) 263 + return -EAGAIN; 264 + 265 + acl = xfs_get_acl(inode, ACL_TYPE_ACCESS); 266 + if (IS_ERR(acl)) 267 + return PTR_ERR(acl); 268 + if (acl) { 269 + error = posix_acl_permission(inode, acl, mask); 270 + posix_acl_release(acl); 271 + } 272 + 273 + return error; 274 + } 275 + 276 + static int 277 + xfs_set_mode(struct inode *inode, mode_t mode) 278 + { 279 + int error = 0; 280 + 281 + if (mode != inode->i_mode) { 282 + struct iattr iattr; 283 + 284 + iattr.ia_valid = ATTR_MODE; 285 + iattr.ia_mode = mode; 286 + 287 + error = -xfs_setattr(XFS_I(inode), &iattr, XFS_ATTR_NOACL); 288 + } 289 + 290 + return error; 291 + } 292 + 293 + static int 294 + xfs_acl_exists(struct inode *inode, char *name) 295 + { 296 + int len = sizeof(struct xfs_acl); 297 + 298 + return (xfs_attr_get(XFS_I(inode), name, NULL, &len, 299 + ATTR_ROOT|ATTR_KERNOVAL) == 0); 300 + } 301 + 302 + int 303 + posix_acl_access_exists(struct inode *inode) 304 + { 305 + return xfs_acl_exists(inode, SGI_ACL_FILE); 306 + } 307 + 308 + int 309 + posix_acl_default_exists(struct inode *inode) 310 + { 311 + if (!S_ISDIR(inode->i_mode)) 312 + return 0; 313 + return xfs_acl_exists(inode, SGI_ACL_DEFAULT); 314 + } 315 + 316 + /* 317 + * No need for i_mutex because the inode is not yet exposed to the VFS. 318 + */ 319 + int 320 + xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl) 321 + { 322 + struct posix_acl *clone; 323 + mode_t mode; 324 + int error = 0, inherit = 0; 325 + 326 + if (S_ISDIR(inode->i_mode)) { 327 + error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl); 328 + if (error) 329 + return error; 330 + } 331 + 332 + clone = posix_acl_clone(default_acl, GFP_KERNEL); 333 + if (!clone) 334 + return -ENOMEM; 335 + 336 + mode = inode->i_mode; 337 + error = posix_acl_create_masq(clone, &mode); 338 + if (error < 0) 339 + goto out_release_clone; 340 + 341 + /* 342 + * If posix_acl_create_masq returns a positive value we need to 343 + * inherit a permission that can't be represented using the Unix 344 + * mode bits and we actually need to set an ACL. 345 + */ 346 + if (error > 0) 347 + inherit = 1; 348 + 349 + error = xfs_set_mode(inode, mode); 350 + if (error) 351 + goto out_release_clone; 352 + 353 + if (inherit) 354 + error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 355 + 356 + out_release_clone: 357 + posix_acl_release(clone); 358 + return error; 359 + } 360 + 361 + int 362 + xfs_acl_chmod(struct inode *inode) 363 + { 364 + struct posix_acl *acl, *clone; 365 + int error; 366 + 367 + if (S_ISLNK(inode->i_mode)) 368 + return -EOPNOTSUPP; 369 + 370 + acl = xfs_get_acl(inode, ACL_TYPE_ACCESS); 371 + if (IS_ERR(acl) || !acl) 372 + return PTR_ERR(acl); 373 + 374 + clone = posix_acl_clone(acl, GFP_KERNEL); 375 + posix_acl_release(acl); 376 + if (!clone) 377 + return -ENOMEM; 378 + 379 + error = posix_acl_chmod_masq(clone, inode->i_mode); 380 + if (!error) 381 + error = xfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 382 + 383 + posix_acl_release(clone); 384 + return error; 385 + } 386 + 387 + void 388 + xfs_inode_init_acls(struct xfs_inode *ip) 389 + { 390 + /* 391 + * No need for locking, inode is not live yet. 392 + */ 393 + ip->i_acl = XFS_ACL_NOT_CACHED; 394 + ip->i_default_acl = XFS_ACL_NOT_CACHED; 395 + } 396 + 397 + void 398 + xfs_inode_clear_acls(struct xfs_inode *ip) 399 + { 400 + /* 401 + * No need for locking here, the inode is not live anymore 402 + * and just about to be freed. 403 + */ 404 + if (ip->i_acl != XFS_ACL_NOT_CACHED) 405 + posix_acl_release(ip->i_acl); 406 + if (ip->i_default_acl != XFS_ACL_NOT_CACHED) 407 + posix_acl_release(ip->i_default_acl); 408 + } 409 + 410 + 411 + /* 412 + * System xattr handlers. 413 + * 414 + * Currently Posix ACLs are the only system namespace extended attribute 415 + * handlers supported by XFS, so we just implement the handlers here. 416 + * If we ever support other system extended attributes this will need 417 + * some refactoring. 418 + */ 419 + 420 + static int 421 + xfs_decode_acl(const char *name) 422 + { 423 + if (strcmp(name, "posix_acl_access") == 0) 424 + return ACL_TYPE_ACCESS; 425 + else if (strcmp(name, "posix_acl_default") == 0) 426 + return ACL_TYPE_DEFAULT; 427 + return -EINVAL; 428 + } 429 + 430 + static int 431 + xfs_xattr_system_get(struct inode *inode, const char *name, 432 + void *value, size_t size) 433 + { 434 + struct posix_acl *acl; 435 + int type, error; 436 + 437 + type = xfs_decode_acl(name); 438 + if (type < 0) 439 + return type; 440 + 441 + acl = xfs_get_acl(inode, type); 442 + if (IS_ERR(acl)) 443 + return PTR_ERR(acl); 444 + if (acl == NULL) 445 + return -ENODATA; 446 + 447 + error = posix_acl_to_xattr(acl, value, size); 448 + posix_acl_release(acl); 449 + 450 + return error; 451 + } 452 + 453 + static int 454 + xfs_xattr_system_set(struct inode *inode, const char *name, 455 + const void *value, size_t size, int flags) 456 + { 457 + struct posix_acl *acl = NULL; 458 + int error = 0, type; 459 + 460 + type = xfs_decode_acl(name); 461 + if (type < 0) 462 + return type; 463 + if (flags & XATTR_CREATE) 464 + return -EINVAL; 465 + if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) 466 + return value ? -EACCES : 0; 467 + if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) 468 + return -EPERM; 469 + 470 + if (!value) 471 + goto set_acl; 472 + 473 + acl = posix_acl_from_xattr(value, size); 474 + if (!acl) { 475 + /* 476 + * acl_set_file(3) may request that we set default ACLs with 477 + * zero length -- defend (gracefully) against that here. 478 + */ 479 + goto out; 480 + } 481 + if (IS_ERR(acl)) { 482 + error = PTR_ERR(acl); 483 + goto out; 484 + } 485 + 486 + error = posix_acl_valid(acl); 487 + if (error) 488 + goto out_release; 489 + 490 + error = -EINVAL; 491 + if (acl->a_count > XFS_ACL_MAX_ENTRIES) 492 + goto out_release; 493 + 494 + if (type == ACL_TYPE_ACCESS) { 495 + mode_t mode = inode->i_mode; 496 + error = posix_acl_equiv_mode(acl, &mode); 497 + 498 + if (error <= 0) { 499 + posix_acl_release(acl); 500 + acl = NULL; 501 + 502 + if (error < 0) 503 + return error; 504 + } 505 + 506 + error = xfs_set_mode(inode, mode); 507 + if (error) 508 + goto out_release; 509 + } 510 + 511 + set_acl: 512 + error = xfs_set_acl(inode, type, acl); 513 + out_release: 514 + posix_acl_release(acl); 515 + out: 516 + return error; 517 + } 518 + 519 + struct xattr_handler xfs_xattr_system_handler = { 520 + .prefix = XATTR_SYSTEM_PREFIX, 521 + .get = xfs_xattr_system_get, 522 + .set = xfs_xattr_system_set, 523 + };
-1
fs/xfs/linux-2.6/xfs_ioctl.c
··· 41 41 #include "xfs_itable.h" 42 42 #include "xfs_error.h" 43 43 #include "xfs_rw.h" 44 - #include "xfs_acl.h" 45 44 #include "xfs_attr.h" 46 45 #include "xfs_bmap.h" 47 46 #include "xfs_buf_item.h"
+13 -40
fs/xfs/linux-2.6/xfs_iops.c
··· 17 17 */ 18 18 #include "xfs.h" 19 19 #include "xfs_fs.h" 20 + #include "xfs_acl.h" 20 21 #include "xfs_bit.h" 21 22 #include "xfs_log.h" 22 23 #include "xfs_inum.h" ··· 52 51 #include <linux/capability.h> 53 52 #include <linux/xattr.h> 54 53 #include <linux/namei.h> 54 + #include <linux/posix_acl.h> 55 55 #include <linux/security.h> 56 56 #include <linux/falloc.h> 57 57 #include <linux/fiemap.h> ··· 204 202 { 205 203 struct inode *inode; 206 204 struct xfs_inode *ip = NULL; 207 - xfs_acl_t *default_acl = NULL; 205 + struct posix_acl *default_acl = NULL; 208 206 struct xfs_name name; 209 - int (*test_default_acl)(struct inode *) = _ACL_DEFAULT_EXISTS; 210 207 int error; 211 208 212 209 /* ··· 220 219 rdev = 0; 221 220 } 222 221 223 - if (test_default_acl && test_default_acl(dir)) { 224 - if (!_ACL_ALLOC(default_acl)) { 225 - return -ENOMEM; 226 - } 227 - if (!_ACL_GET_DEFAULT(dir, default_acl)) { 228 - _ACL_FREE(default_acl); 229 - default_acl = NULL; 230 - } 231 - } 222 + if (IS_POSIXACL(dir)) { 223 + default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); 224 + if (IS_ERR(default_acl)) 225 + return -PTR_ERR(default_acl); 232 226 233 - if (IS_POSIXACL(dir) && !default_acl) 234 - mode &= ~current->fs->umask; 227 + if (!default_acl) 228 + mode &= ~current->fs->umask; 229 + } 235 230 236 231 xfs_dentry_to_name(&name, dentry); 237 232 error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL); ··· 241 244 goto out_cleanup_inode; 242 245 243 246 if (default_acl) { 244 - error = _ACL_INHERIT(inode, mode, default_acl); 247 + error = -xfs_inherit_acl(inode, default_acl); 245 248 if (unlikely(error)) 246 249 goto out_cleanup_inode; 247 - _ACL_FREE(default_acl); 250 + posix_acl_release(default_acl); 248 251 } 249 252 250 253 ··· 254 257 out_cleanup_inode: 255 258 xfs_cleanup_inode(dir, inode, dentry); 256 259 out_free_acl: 257 - if (default_acl) 258 - _ACL_FREE(default_acl); 260 + posix_acl_release(default_acl); 259 261 return -error; 260 262 } 261 263 ··· 484 488 kfree(s); 485 489 } 486 490 487 - #ifdef CONFIG_XFS_POSIX_ACL 488 - STATIC int 489 - xfs_check_acl( 490 - struct inode *inode, 491 - int mask) 492 - { 493 - struct xfs_inode *ip = XFS_I(inode); 494 - int error; 495 - 496 - xfs_itrace_entry(ip); 497 - 498 - if (XFS_IFORK_Q(ip)) { 499 - error = xfs_acl_iaccess(ip, mask, NULL); 500 - if (error != -1) 501 - return -error; 502 - } 503 - 504 - return -EAGAIN; 505 - } 506 - 507 491 STATIC int 508 492 xfs_vn_permission( 509 493 struct inode *inode, ··· 491 515 { 492 516 return generic_permission(inode, mask, xfs_check_acl); 493 517 } 494 - #else 495 - #define xfs_vn_permission NULL 496 - #endif 497 518 498 519 STATIC int 499 520 xfs_vn_getattr(
-1
fs/xfs/linux-2.6/xfs_lrw.c
··· 42 42 #include "xfs_error.h" 43 43 #include "xfs_itable.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_inode_item.h" 48 47 #include "xfs_buf_item.h"
-14
fs/xfs/linux-2.6/xfs_super.c
··· 43 43 #include "xfs_itable.h" 44 44 #include "xfs_fsops.h" 45 45 #include "xfs_rw.h" 46 - #include "xfs_acl.h" 47 46 #include "xfs_attr.h" 48 47 #include "xfs_buf_item.h" 49 48 #include "xfs_utils.h" ··· 1734 1735 if (!xfs_ili_zone) 1735 1736 goto out_destroy_inode_zone; 1736 1737 1737 - #ifdef CONFIG_XFS_POSIX_ACL 1738 - xfs_acl_zone = kmem_zone_init(sizeof(xfs_acl_t), "xfs_acl"); 1739 - if (!xfs_acl_zone) 1740 - goto out_destroy_ili_zone; 1741 - #endif 1742 - 1743 1738 return 0; 1744 1739 1745 - #ifdef CONFIG_XFS_POSIX_ACL 1746 - out_destroy_ili_zone: 1747 - #endif 1748 - kmem_zone_destroy(xfs_ili_zone); 1749 1740 out_destroy_inode_zone: 1750 1741 kmem_zone_destroy(xfs_inode_zone); 1751 1742 out_destroy_efi_zone: ··· 1769 1780 STATIC void 1770 1781 xfs_destroy_zones(void) 1771 1782 { 1772 - #ifdef CONFIG_XFS_POSIX_ACL 1773 - kmem_zone_destroy(xfs_acl_zone); 1774 - #endif 1775 1783 kmem_zone_destroy(xfs_ili_zone); 1776 1784 kmem_zone_destroy(xfs_inode_zone); 1777 1785 kmem_zone_destroy(xfs_efi_zone);
+4 -63
fs/xfs/linux-2.6/xfs_xattr.c
··· 29 29 #include <linux/xattr.h> 30 30 31 31 32 - /* 33 - * ACL handling. Should eventually be moved into xfs_acl.c 34 - */ 35 - 36 - static int 37 - xfs_decode_acl(const char *name) 38 - { 39 - if (strcmp(name, "posix_acl_access") == 0) 40 - return _ACL_TYPE_ACCESS; 41 - else if (strcmp(name, "posix_acl_default") == 0) 42 - return _ACL_TYPE_DEFAULT; 43 - return -EINVAL; 44 - } 45 - 46 - /* 47 - * Get system extended attributes which at the moment only 48 - * includes Posix ACLs. 49 - */ 50 - static int 51 - xfs_xattr_system_get(struct inode *inode, const char *name, 52 - void *buffer, size_t size) 53 - { 54 - int acl; 55 - 56 - acl = xfs_decode_acl(name); 57 - if (acl < 0) 58 - return acl; 59 - 60 - return xfs_acl_vget(inode, buffer, size, acl); 61 - } 62 - 63 - static int 64 - xfs_xattr_system_set(struct inode *inode, const char *name, 65 - const void *value, size_t size, int flags) 66 - { 67 - int acl; 68 - 69 - acl = xfs_decode_acl(name); 70 - if (acl < 0) 71 - return acl; 72 - if (flags & XATTR_CREATE) 73 - return -EINVAL; 74 - 75 - if (!value) 76 - return xfs_acl_vremove(inode, acl); 77 - 78 - return xfs_acl_vset(inode, (void *)value, size, acl); 79 - } 80 - 81 - static struct xattr_handler xfs_xattr_system_handler = { 82 - .prefix = XATTR_SYSTEM_PREFIX, 83 - .get = xfs_xattr_system_get, 84 - .set = xfs_xattr_system_set, 85 - }; 86 - 87 - 88 - /* 89 - * Real xattr handling. The only difference between the namespaces is 90 - * a flag passed to the low-level attr code. 91 - */ 92 - 93 32 static int 94 33 __xfs_xattr_get(struct inode *inode, const char *name, 95 34 void *value, size_t size, int xflags) ··· 138 199 &xfs_xattr_user_handler, 139 200 &xfs_xattr_trusted_handler, 140 201 &xfs_xattr_security_handler, 202 + #ifdef CONFIG_XFS_POSIX_ACL 141 203 &xfs_xattr_system_handler, 204 + #endif 142 205 NULL 143 206 }; 144 207 ··· 251 310 /* 252 311 * Then add the two synthetic ACL attributes. 253 312 */ 254 - if (xfs_acl_vhasacl_access(inode)) { 313 + if (posix_acl_access_exists(inode)) { 255 314 error = list_one_attr(POSIX_ACL_XATTR_ACCESS, 256 315 strlen(POSIX_ACL_XATTR_ACCESS) + 1, 257 316 data, size, &context.count); ··· 259 318 return error; 260 319 } 261 320 262 - if (xfs_acl_vhasacl_default(inode)) { 321 + if (posix_acl_default_exists(inode)) { 263 322 error = list_one_attr(POSIX_ACL_XATTR_DEFAULT, 264 323 strlen(POSIX_ACL_XATTR_DEFAULT) + 1, 265 324 data, size, &context.count);
-1
fs/xfs/quota/xfs_dquot.c
··· 42 42 #include "xfs_error.h" 43 43 #include "xfs_itable.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_trans_space.h"
-1
fs/xfs/quota/xfs_dquot_item.c
··· 42 42 #include "xfs_error.h" 43 43 #include "xfs_itable.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_trans_priv.h"
-1
fs/xfs/quota/xfs_qm.c
··· 42 42 #include "xfs_error.h" 43 43 #include "xfs_bmap.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_trans_space.h"
-1
fs/xfs/quota/xfs_qm_bhv.c
··· 42 42 #include "xfs_rtalloc.h" 43 43 #include "xfs_error.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_qm.h"
-1
fs/xfs/quota/xfs_qm_stats.c
··· 42 42 #include "xfs_rtalloc.h" 43 43 #include "xfs_error.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_qm.h"
-1
fs/xfs/quota/xfs_qm_syscalls.c
··· 45 45 #include "xfs_rtalloc.h" 46 46 #include "xfs_error.h" 47 47 #include "xfs_rw.h" 48 - #include "xfs_acl.h" 49 48 #include "xfs_attr.h" 50 49 #include "xfs_buf_item.h" 51 50 #include "xfs_utils.h"
-1
fs/xfs/quota/xfs_trans_dquot.c
··· 42 42 #include "xfs_rtalloc.h" 43 43 #include "xfs_error.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_trans_priv.h"
-874
fs/xfs/xfs_acl.c
··· 1 - /* 2 - * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc. 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_fs.h" 20 - #include "xfs_types.h" 21 - #include "xfs_bit.h" 22 - #include "xfs_inum.h" 23 - #include "xfs_ag.h" 24 - #include "xfs_dir2.h" 25 - #include "xfs_bmap_btree.h" 26 - #include "xfs_alloc_btree.h" 27 - #include "xfs_ialloc_btree.h" 28 - #include "xfs_dir2_sf.h" 29 - #include "xfs_attr_sf.h" 30 - #include "xfs_dinode.h" 31 - #include "xfs_inode.h" 32 - #include "xfs_btree.h" 33 - #include "xfs_acl.h" 34 - #include "xfs_attr.h" 35 - #include "xfs_vnodeops.h" 36 - 37 - #include <linux/capability.h> 38 - #include <linux/posix_acl_xattr.h> 39 - 40 - STATIC int xfs_acl_setmode(struct inode *, xfs_acl_t *, int *); 41 - STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); 42 - STATIC void xfs_acl_get_endian(xfs_acl_t *); 43 - STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); 44 - STATIC int xfs_acl_invalid(xfs_acl_t *); 45 - STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); 46 - STATIC void xfs_acl_get_attr(struct inode *, xfs_acl_t *, int, int, int *); 47 - STATIC void xfs_acl_set_attr(struct inode *, xfs_acl_t *, int, int *); 48 - STATIC int xfs_acl_allow_set(struct inode *, int); 49 - 50 - kmem_zone_t *xfs_acl_zone; 51 - 52 - 53 - /* 54 - * Test for existence of access ACL attribute as efficiently as possible. 55 - */ 56 - int 57 - xfs_acl_vhasacl_access( 58 - struct inode *vp) 59 - { 60 - int error; 61 - 62 - xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error); 63 - return (error == 0); 64 - } 65 - 66 - /* 67 - * Test for existence of default ACL attribute as efficiently as possible. 68 - */ 69 - int 70 - xfs_acl_vhasacl_default( 71 - struct inode *vp) 72 - { 73 - int error; 74 - 75 - if (!S_ISDIR(vp->i_mode)) 76 - return 0; 77 - xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error); 78 - return (error == 0); 79 - } 80 - 81 - /* 82 - * Convert from extended attribute representation to in-memory for XFS. 83 - */ 84 - STATIC int 85 - posix_acl_xattr_to_xfs( 86 - posix_acl_xattr_header *src, 87 - size_t size, 88 - xfs_acl_t *dest) 89 - { 90 - posix_acl_xattr_entry *src_entry; 91 - xfs_acl_entry_t *dest_entry; 92 - int n; 93 - 94 - if (!src || !dest) 95 - return EINVAL; 96 - 97 - if (size < sizeof(posix_acl_xattr_header)) 98 - return EINVAL; 99 - 100 - if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 101 - return EOPNOTSUPP; 102 - 103 - memset(dest, 0, sizeof(xfs_acl_t)); 104 - dest->acl_cnt = posix_acl_xattr_count(size); 105 - if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES) 106 - return EINVAL; 107 - 108 - /* 109 - * acl_set_file(3) may request that we set default ACLs with 110 - * zero length -- defend (gracefully) against that here. 111 - */ 112 - if (!dest->acl_cnt) 113 - return 0; 114 - 115 - src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src)); 116 - dest_entry = &dest->acl_entry[0]; 117 - 118 - for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) { 119 - dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm); 120 - if (_ACL_PERM_INVALID(dest_entry->ae_perm)) 121 - return EINVAL; 122 - dest_entry->ae_tag = le16_to_cpu(src_entry->e_tag); 123 - switch(dest_entry->ae_tag) { 124 - case ACL_USER: 125 - case ACL_GROUP: 126 - dest_entry->ae_id = le32_to_cpu(src_entry->e_id); 127 - break; 128 - case ACL_USER_OBJ: 129 - case ACL_GROUP_OBJ: 130 - case ACL_MASK: 131 - case ACL_OTHER: 132 - dest_entry->ae_id = ACL_UNDEFINED_ID; 133 - break; 134 - default: 135 - return EINVAL; 136 - } 137 - } 138 - if (xfs_acl_invalid(dest)) 139 - return EINVAL; 140 - 141 - return 0; 142 - } 143 - 144 - /* 145 - * Comparison function called from xfs_sort(). 146 - * Primary key is ae_tag, secondary key is ae_id. 147 - */ 148 - STATIC int 149 - xfs_acl_entry_compare( 150 - const void *va, 151 - const void *vb) 152 - { 153 - xfs_acl_entry_t *a = (xfs_acl_entry_t *)va, 154 - *b = (xfs_acl_entry_t *)vb; 155 - 156 - if (a->ae_tag == b->ae_tag) 157 - return (a->ae_id - b->ae_id); 158 - return (a->ae_tag - b->ae_tag); 159 - } 160 - 161 - /* 162 - * Convert from in-memory XFS to extended attribute representation. 163 - */ 164 - STATIC int 165 - posix_acl_xfs_to_xattr( 166 - xfs_acl_t *src, 167 - posix_acl_xattr_header *dest, 168 - size_t size) 169 - { 170 - int n; 171 - size_t new_size = posix_acl_xattr_size(src->acl_cnt); 172 - posix_acl_xattr_entry *dest_entry; 173 - xfs_acl_entry_t *src_entry; 174 - 175 - if (size < new_size) 176 - return -ERANGE; 177 - 178 - /* Need to sort src XFS ACL by <ae_tag,ae_id> */ 179 - xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]), 180 - xfs_acl_entry_compare); 181 - 182 - dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); 183 - dest_entry = &dest->a_entries[0]; 184 - src_entry = &src->acl_entry[0]; 185 - for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) { 186 - dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm); 187 - if (_ACL_PERM_INVALID(src_entry->ae_perm)) 188 - return -EINVAL; 189 - dest_entry->e_tag = cpu_to_le16(src_entry->ae_tag); 190 - switch (src_entry->ae_tag) { 191 - case ACL_USER: 192 - case ACL_GROUP: 193 - dest_entry->e_id = cpu_to_le32(src_entry->ae_id); 194 - break; 195 - case ACL_USER_OBJ: 196 - case ACL_GROUP_OBJ: 197 - case ACL_MASK: 198 - case ACL_OTHER: 199 - dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); 200 - break; 201 - default: 202 - return -EINVAL; 203 - } 204 - } 205 - return new_size; 206 - } 207 - 208 - int 209 - xfs_acl_vget( 210 - struct inode *vp, 211 - void *acl, 212 - size_t size, 213 - int kind) 214 - { 215 - int error; 216 - xfs_acl_t *xfs_acl = NULL; 217 - posix_acl_xattr_header *ext_acl = acl; 218 - int flags = 0; 219 - 220 - if(size) { 221 - if (!(_ACL_ALLOC(xfs_acl))) { 222 - error = ENOMEM; 223 - goto out; 224 - } 225 - memset(xfs_acl, 0, sizeof(xfs_acl_t)); 226 - } else 227 - flags = ATTR_KERNOVAL; 228 - 229 - xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error); 230 - if (error) 231 - goto out; 232 - 233 - if (!size) { 234 - error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES); 235 - } else { 236 - if (xfs_acl_invalid(xfs_acl)) { 237 - error = EINVAL; 238 - goto out; 239 - } 240 - if (kind == _ACL_TYPE_ACCESS) 241 - xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, xfs_acl); 242 - error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size); 243 - } 244 - out: 245 - if(xfs_acl) 246 - _ACL_FREE(xfs_acl); 247 - return -error; 248 - } 249 - 250 - int 251 - xfs_acl_vremove( 252 - struct inode *vp, 253 - int kind) 254 - { 255 - int error; 256 - 257 - error = xfs_acl_allow_set(vp, kind); 258 - if (!error) { 259 - error = xfs_attr_remove(XFS_I(vp), 260 - kind == _ACL_TYPE_DEFAULT? 261 - SGI_ACL_DEFAULT: SGI_ACL_FILE, 262 - ATTR_ROOT); 263 - if (error == ENOATTR) 264 - error = 0; /* 'scool */ 265 - } 266 - return -error; 267 - } 268 - 269 - int 270 - xfs_acl_vset( 271 - struct inode *vp, 272 - void *acl, 273 - size_t size, 274 - int kind) 275 - { 276 - posix_acl_xattr_header *ext_acl = acl; 277 - xfs_acl_t *xfs_acl; 278 - int error; 279 - int basicperms = 0; /* more than std unix perms? */ 280 - 281 - if (!acl) 282 - return -EINVAL; 283 - 284 - if (!(_ACL_ALLOC(xfs_acl))) 285 - return -ENOMEM; 286 - 287 - error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl); 288 - if (error) { 289 - _ACL_FREE(xfs_acl); 290 - return -error; 291 - } 292 - if (!xfs_acl->acl_cnt) { 293 - _ACL_FREE(xfs_acl); 294 - return 0; 295 - } 296 - 297 - error = xfs_acl_allow_set(vp, kind); 298 - 299 - /* Incoming ACL exists, set file mode based on its value */ 300 - if (!error && kind == _ACL_TYPE_ACCESS) 301 - error = xfs_acl_setmode(vp, xfs_acl, &basicperms); 302 - 303 - if (error) 304 - goto out; 305 - 306 - /* 307 - * If we have more than std unix permissions, set up the actual attr. 308 - * Otherwise, delete any existing attr. This prevents us from 309 - * having actual attrs for permissions that can be stored in the 310 - * standard permission bits. 311 - */ 312 - if (!basicperms) { 313 - xfs_acl_set_attr(vp, xfs_acl, kind, &error); 314 - } else { 315 - error = -xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); 316 - } 317 - 318 - out: 319 - _ACL_FREE(xfs_acl); 320 - return -error; 321 - } 322 - 323 - int 324 - xfs_acl_iaccess( 325 - xfs_inode_t *ip, 326 - mode_t mode, 327 - cred_t *cr) 328 - { 329 - xfs_acl_t *acl; 330 - int rval; 331 - struct xfs_name acl_name = {SGI_ACL_FILE, SGI_ACL_FILE_SIZE}; 332 - 333 - if (!(_ACL_ALLOC(acl))) 334 - return -1; 335 - 336 - /* If the file has no ACL return -1. */ 337 - rval = sizeof(xfs_acl_t); 338 - if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval, ATTR_ROOT)) { 339 - _ACL_FREE(acl); 340 - return -1; 341 - } 342 - xfs_acl_get_endian(acl); 343 - 344 - /* If the file has an empty ACL return -1. */ 345 - if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) { 346 - _ACL_FREE(acl); 347 - return -1; 348 - } 349 - 350 - /* Synchronize ACL with mode bits */ 351 - xfs_acl_sync_mode(ip->i_d.di_mode, acl); 352 - 353 - rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr); 354 - _ACL_FREE(acl); 355 - return rval; 356 - } 357 - 358 - STATIC int 359 - xfs_acl_allow_set( 360 - struct inode *vp, 361 - int kind) 362 - { 363 - if (vp->i_flags & (S_IMMUTABLE|S_APPEND)) 364 - return EPERM; 365 - if (kind == _ACL_TYPE_DEFAULT && !S_ISDIR(vp->i_mode)) 366 - return ENOTDIR; 367 - if (vp->i_sb->s_flags & MS_RDONLY) 368 - return EROFS; 369 - if (XFS_I(vp)->i_d.di_uid != current_fsuid() && !capable(CAP_FOWNER)) 370 - return EPERM; 371 - return 0; 372 - } 373 - 374 - /* 375 - * Note: cr is only used here for the capability check if the ACL test fails. 376 - * It is not used to find out the credentials uid or groups etc, as was 377 - * done in IRIX. It is assumed that the uid and groups for the current 378 - * thread are taken from "current" instead of the cr parameter. 379 - */ 380 - STATIC int 381 - xfs_acl_access( 382 - uid_t fuid, 383 - gid_t fgid, 384 - xfs_acl_t *fap, 385 - mode_t md, 386 - cred_t *cr) 387 - { 388 - xfs_acl_entry_t matched; 389 - int i, allows; 390 - int maskallows = -1; /* true, but not 1, either */ 391 - int seen_userobj = 0; 392 - 393 - matched.ae_tag = 0; /* Invalid type */ 394 - matched.ae_perm = 0; 395 - 396 - for (i = 0; i < fap->acl_cnt; i++) { 397 - /* 398 - * Break out if we've got a user_obj entry or 399 - * a user entry and the mask (and have processed USER_OBJ) 400 - */ 401 - if (matched.ae_tag == ACL_USER_OBJ) 402 - break; 403 - if (matched.ae_tag == ACL_USER) { 404 - if (maskallows != -1 && seen_userobj) 405 - break; 406 - if (fap->acl_entry[i].ae_tag != ACL_MASK && 407 - fap->acl_entry[i].ae_tag != ACL_USER_OBJ) 408 - continue; 409 - } 410 - /* True if this entry allows the requested access */ 411 - allows = ((fap->acl_entry[i].ae_perm & md) == md); 412 - 413 - switch (fap->acl_entry[i].ae_tag) { 414 - case ACL_USER_OBJ: 415 - seen_userobj = 1; 416 - if (fuid != current_fsuid()) 417 - continue; 418 - matched.ae_tag = ACL_USER_OBJ; 419 - matched.ae_perm = allows; 420 - break; 421 - case ACL_USER: 422 - if (fap->acl_entry[i].ae_id != current_fsuid()) 423 - continue; 424 - matched.ae_tag = ACL_USER; 425 - matched.ae_perm = allows; 426 - break; 427 - case ACL_GROUP_OBJ: 428 - if ((matched.ae_tag == ACL_GROUP_OBJ || 429 - matched.ae_tag == ACL_GROUP) && !allows) 430 - continue; 431 - if (!in_group_p(fgid)) 432 - continue; 433 - matched.ae_tag = ACL_GROUP_OBJ; 434 - matched.ae_perm = allows; 435 - break; 436 - case ACL_GROUP: 437 - if ((matched.ae_tag == ACL_GROUP_OBJ || 438 - matched.ae_tag == ACL_GROUP) && !allows) 439 - continue; 440 - if (!in_group_p(fap->acl_entry[i].ae_id)) 441 - continue; 442 - matched.ae_tag = ACL_GROUP; 443 - matched.ae_perm = allows; 444 - break; 445 - case ACL_MASK: 446 - maskallows = allows; 447 - break; 448 - case ACL_OTHER: 449 - if (matched.ae_tag != 0) 450 - continue; 451 - matched.ae_tag = ACL_OTHER; 452 - matched.ae_perm = allows; 453 - break; 454 - } 455 - } 456 - /* 457 - * First possibility is that no matched entry allows access. 458 - * The capability to override DAC may exist, so check for it. 459 - */ 460 - switch (matched.ae_tag) { 461 - case ACL_OTHER: 462 - case ACL_USER_OBJ: 463 - if (matched.ae_perm) 464 - return 0; 465 - break; 466 - case ACL_USER: 467 - case ACL_GROUP_OBJ: 468 - case ACL_GROUP: 469 - if (maskallows && matched.ae_perm) 470 - return 0; 471 - break; 472 - case 0: 473 - break; 474 - } 475 - 476 - /* EACCES tells generic_permission to check for capability overrides */ 477 - return EACCES; 478 - } 479 - 480 - /* 481 - * ACL validity checker. 482 - * This acl validation routine checks each ACL entry read in makes sense. 483 - */ 484 - STATIC int 485 - xfs_acl_invalid( 486 - xfs_acl_t *aclp) 487 - { 488 - xfs_acl_entry_t *entry, *e; 489 - int user = 0, group = 0, other = 0, mask = 0; 490 - int mask_required = 0; 491 - int i, j; 492 - 493 - if (!aclp) 494 - goto acl_invalid; 495 - 496 - if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES) 497 - goto acl_invalid; 498 - 499 - for (i = 0; i < aclp->acl_cnt; i++) { 500 - entry = &aclp->acl_entry[i]; 501 - switch (entry->ae_tag) { 502 - case ACL_USER_OBJ: 503 - if (user++) 504 - goto acl_invalid; 505 - break; 506 - case ACL_GROUP_OBJ: 507 - if (group++) 508 - goto acl_invalid; 509 - break; 510 - case ACL_OTHER: 511 - if (other++) 512 - goto acl_invalid; 513 - break; 514 - case ACL_USER: 515 - case ACL_GROUP: 516 - for (j = i + 1; j < aclp->acl_cnt; j++) { 517 - e = &aclp->acl_entry[j]; 518 - if (e->ae_id == entry->ae_id && 519 - e->ae_tag == entry->ae_tag) 520 - goto acl_invalid; 521 - } 522 - mask_required++; 523 - break; 524 - case ACL_MASK: 525 - if (mask++) 526 - goto acl_invalid; 527 - break; 528 - default: 529 - goto acl_invalid; 530 - } 531 - } 532 - if (!user || !group || !other || (mask_required && !mask)) 533 - goto acl_invalid; 534 - else 535 - return 0; 536 - acl_invalid: 537 - return EINVAL; 538 - } 539 - 540 - /* 541 - * Do ACL endian conversion. 542 - */ 543 - STATIC void 544 - xfs_acl_get_endian( 545 - xfs_acl_t *aclp) 546 - { 547 - xfs_acl_entry_t *ace, *end; 548 - 549 - INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); 550 - end = &aclp->acl_entry[0]+aclp->acl_cnt; 551 - for (ace = &aclp->acl_entry[0]; ace < end; ace++) { 552 - INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag); 553 - INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id); 554 - INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm); 555 - } 556 - } 557 - 558 - /* 559 - * Get the ACL from the EA and do endian conversion. 560 - */ 561 - STATIC void 562 - xfs_acl_get_attr( 563 - struct inode *vp, 564 - xfs_acl_t *aclp, 565 - int kind, 566 - int flags, 567 - int *error) 568 - { 569 - int len = sizeof(xfs_acl_t); 570 - 571 - ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); 572 - flags |= ATTR_ROOT; 573 - *error = xfs_attr_get(XFS_I(vp), 574 - kind == _ACL_TYPE_ACCESS ? 575 - SGI_ACL_FILE : SGI_ACL_DEFAULT, 576 - (char *)aclp, &len, flags); 577 - if (*error || (flags & ATTR_KERNOVAL)) 578 - return; 579 - xfs_acl_get_endian(aclp); 580 - } 581 - 582 - /* 583 - * Set the EA with the ACL and do endian conversion. 584 - */ 585 - STATIC void 586 - xfs_acl_set_attr( 587 - struct inode *vp, 588 - xfs_acl_t *aclp, 589 - int kind, 590 - int *error) 591 - { 592 - xfs_acl_entry_t *ace, *newace, *end; 593 - xfs_acl_t *newacl; 594 - int len; 595 - 596 - if (!(_ACL_ALLOC(newacl))) { 597 - *error = ENOMEM; 598 - return; 599 - } 600 - 601 - len = sizeof(xfs_acl_t) - 602 - (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt)); 603 - end = &aclp->acl_entry[0]+aclp->acl_cnt; 604 - for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0]; 605 - ace < end; 606 - ace++, newace++) { 607 - INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag); 608 - INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id); 609 - INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); 610 - } 611 - INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); 612 - *error = xfs_attr_set(XFS_I(vp), 613 - kind == _ACL_TYPE_ACCESS ? 614 - SGI_ACL_FILE: SGI_ACL_DEFAULT, 615 - (char *)newacl, len, ATTR_ROOT); 616 - _ACL_FREE(newacl); 617 - } 618 - 619 - int 620 - xfs_acl_vtoacl( 621 - struct inode *vp, 622 - xfs_acl_t *access_acl, 623 - xfs_acl_t *default_acl) 624 - { 625 - int error = 0; 626 - 627 - if (access_acl) { 628 - /* 629 - * Get the Access ACL and the mode. If either cannot 630 - * be obtained for some reason, invalidate the access ACL. 631 - */ 632 - xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error); 633 - if (error) 634 - access_acl->acl_cnt = XFS_ACL_NOT_PRESENT; 635 - else /* We have a good ACL and the file mode, synchronize. */ 636 - xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, access_acl); 637 - } 638 - 639 - if (default_acl) { 640 - xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error); 641 - if (error) 642 - default_acl->acl_cnt = XFS_ACL_NOT_PRESENT; 643 - } 644 - return error; 645 - } 646 - 647 - /* 648 - * This function retrieves the parent directory's acl, processes it 649 - * and lets the child inherit the acl(s) that it should. 650 - */ 651 - int 652 - xfs_acl_inherit( 653 - struct inode *vp, 654 - mode_t mode, 655 - xfs_acl_t *pdaclp) 656 - { 657 - xfs_acl_t *cacl; 658 - int error = 0; 659 - int basicperms = 0; 660 - 661 - /* 662 - * If the parent does not have a default ACL, or it's an 663 - * invalid ACL, we're done. 664 - */ 665 - if (!vp) 666 - return 0; 667 - if (!pdaclp || xfs_acl_invalid(pdaclp)) 668 - return 0; 669 - 670 - /* 671 - * Copy the default ACL of the containing directory to 672 - * the access ACL of the new file and use the mode that 673 - * was passed in to set up the correct initial values for 674 - * the u::,g::[m::], and o:: entries. This is what makes 675 - * umask() "work" with ACL's. 676 - */ 677 - 678 - if (!(_ACL_ALLOC(cacl))) 679 - return ENOMEM; 680 - 681 - memcpy(cacl, pdaclp, sizeof(xfs_acl_t)); 682 - xfs_acl_filter_mode(mode, cacl); 683 - error = xfs_acl_setmode(vp, cacl, &basicperms); 684 - if (error) 685 - goto out_error; 686 - 687 - /* 688 - * Set the Default and Access ACL on the file. The mode is already 689 - * set on the file, so we don't need to worry about that. 690 - * 691 - * If the new file is a directory, its default ACL is a copy of 692 - * the containing directory's default ACL. 693 - */ 694 - if (S_ISDIR(vp->i_mode)) 695 - xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error); 696 - if (!error && !basicperms) 697 - xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error); 698 - out_error: 699 - _ACL_FREE(cacl); 700 - return error; 701 - } 702 - 703 - /* 704 - * Set up the correct mode on the file based on the supplied ACL. This 705 - * makes sure that the mode on the file reflects the state of the 706 - * u::,g::[m::], and o:: entries in the ACL. Since the mode is where 707 - * the ACL is going to get the permissions for these entries, we must 708 - * synchronize the mode whenever we set the ACL on a file. 709 - */ 710 - STATIC int 711 - xfs_acl_setmode( 712 - struct inode *vp, 713 - xfs_acl_t *acl, 714 - int *basicperms) 715 - { 716 - struct iattr iattr; 717 - xfs_acl_entry_t *ap; 718 - xfs_acl_entry_t *gap = NULL; 719 - int i, nomask = 1; 720 - 721 - *basicperms = 1; 722 - 723 - if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) 724 - return 0; 725 - 726 - /* 727 - * Copy the u::, g::, o::, and m:: bits from the ACL into the 728 - * mode. The m:: bits take precedence over the g:: bits. 729 - */ 730 - iattr.ia_valid = ATTR_MODE; 731 - iattr.ia_mode = XFS_I(vp)->i_d.di_mode; 732 - iattr.ia_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); 733 - ap = acl->acl_entry; 734 - for (i = 0; i < acl->acl_cnt; ++i) { 735 - switch (ap->ae_tag) { 736 - case ACL_USER_OBJ: 737 - iattr.ia_mode |= ap->ae_perm << 6; 738 - break; 739 - case ACL_GROUP_OBJ: 740 - gap = ap; 741 - break; 742 - case ACL_MASK: /* more than just standard modes */ 743 - nomask = 0; 744 - iattr.ia_mode |= ap->ae_perm << 3; 745 - *basicperms = 0; 746 - break; 747 - case ACL_OTHER: 748 - iattr.ia_mode |= ap->ae_perm; 749 - break; 750 - default: /* more than just standard modes */ 751 - *basicperms = 0; 752 - break; 753 - } 754 - ap++; 755 - } 756 - 757 - /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */ 758 - if (gap && nomask) 759 - iattr.ia_mode |= gap->ae_perm << 3; 760 - 761 - return xfs_setattr(XFS_I(vp), &iattr, 0); 762 - } 763 - 764 - /* 765 - * The permissions for the special ACL entries (u::, g::[m::], o::) are 766 - * actually stored in the file mode (if there is both a group and a mask, 767 - * the group is stored in the ACL entry and the mask is stored on the file). 768 - * This allows the mode to remain automatically in sync with the ACL without 769 - * the need for a call-back to the ACL system at every point where the mode 770 - * could change. This function takes the permissions from the specified mode 771 - * and places it in the supplied ACL. 772 - * 773 - * This implementation draws its validity from the fact that, when the ACL 774 - * was assigned, the mode was copied from the ACL. 775 - * If the mode did not change, therefore, the mode remains exactly what was 776 - * taken from the special ACL entries at assignment. 777 - * If a subsequent chmod() was done, the POSIX spec says that the change in 778 - * mode must cause an update to the ACL seen at user level and used for 779 - * access checks. Before and after a mode change, therefore, the file mode 780 - * most accurately reflects what the special ACL entries should permit/deny. 781 - * 782 - * CAVEAT: If someone sets the SGI_ACL_FILE attribute directly, 783 - * the existing mode bits will override whatever is in the 784 - * ACL. Similarly, if there is a pre-existing ACL that was 785 - * never in sync with its mode (owing to a bug in 6.5 and 786 - * before), it will now magically (or mystically) be 787 - * synchronized. This could cause slight astonishment, but 788 - * it is better than inconsistent permissions. 789 - * 790 - * The supplied ACL is a template that may contain any combination 791 - * of special entries. These are treated as place holders when we fill 792 - * out the ACL. This routine does not add or remove special entries, it 793 - * simply unites each special entry with its associated set of permissions. 794 - */ 795 - STATIC void 796 - xfs_acl_sync_mode( 797 - mode_t mode, 798 - xfs_acl_t *acl) 799 - { 800 - int i, nomask = 1; 801 - xfs_acl_entry_t *ap; 802 - xfs_acl_entry_t *gap = NULL; 803 - 804 - /* 805 - * Set ACL entries. POSIX1003.1eD16 requires that the MASK 806 - * be set instead of the GROUP entry, if there is a MASK. 807 - */ 808 - for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) { 809 - switch (ap->ae_tag) { 810 - case ACL_USER_OBJ: 811 - ap->ae_perm = (mode >> 6) & 0x7; 812 - break; 813 - case ACL_GROUP_OBJ: 814 - gap = ap; 815 - break; 816 - case ACL_MASK: 817 - nomask = 0; 818 - ap->ae_perm = (mode >> 3) & 0x7; 819 - break; 820 - case ACL_OTHER: 821 - ap->ae_perm = mode & 0x7; 822 - break; 823 - default: 824 - break; 825 - } 826 - } 827 - /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */ 828 - if (gap && nomask) 829 - gap->ae_perm = (mode >> 3) & 0x7; 830 - } 831 - 832 - /* 833 - * When inheriting an Access ACL from a directory Default ACL, 834 - * the ACL bits are set to the intersection of the ACL default 835 - * permission bits and the file permission bits in mode. If there 836 - * are no permission bits on the file then we must not give them 837 - * the ACL. This is what what makes umask() work with ACLs. 838 - */ 839 - STATIC void 840 - xfs_acl_filter_mode( 841 - mode_t mode, 842 - xfs_acl_t *acl) 843 - { 844 - int i, nomask = 1; 845 - xfs_acl_entry_t *ap; 846 - xfs_acl_entry_t *gap = NULL; 847 - 848 - /* 849 - * Set ACL entries. POSIX1003.1eD16 requires that the MASK 850 - * be merged with GROUP entry, if there is a MASK. 851 - */ 852 - for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) { 853 - switch (ap->ae_tag) { 854 - case ACL_USER_OBJ: 855 - ap->ae_perm &= (mode >> 6) & 0x7; 856 - break; 857 - case ACL_GROUP_OBJ: 858 - gap = ap; 859 - break; 860 - case ACL_MASK: 861 - nomask = 0; 862 - ap->ae_perm &= (mode >> 3) & 0x7; 863 - break; 864 - case ACL_OTHER: 865 - ap->ae_perm &= mode & 0x7; 866 - break; 867 - default: 868 - break; 869 - } 870 - } 871 - /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */ 872 - if (gap && nomask) 873 - gap->ae_perm &= (mode >> 3) & 0x7; 874 - }
+32 -65
fs/xfs/xfs_acl.h
··· 18 18 #ifndef __XFS_ACL_H__ 19 19 #define __XFS_ACL_H__ 20 20 21 - /* 22 - * Access Control Lists 23 - */ 24 - typedef __uint16_t xfs_acl_perm_t; 25 - typedef __int32_t xfs_acl_tag_t; 26 - typedef __int32_t xfs_acl_id_t; 21 + struct inode; 22 + struct posix_acl; 23 + struct xfs_inode; 27 24 28 25 #define XFS_ACL_MAX_ENTRIES 25 29 26 #define XFS_ACL_NOT_PRESENT (-1) 30 27 31 - typedef struct xfs_acl_entry { 32 - xfs_acl_tag_t ae_tag; 33 - xfs_acl_id_t ae_id; 34 - xfs_acl_perm_t ae_perm; 35 - } xfs_acl_entry_t; 36 - 37 - typedef struct xfs_acl { 38 - __int32_t acl_cnt; 39 - xfs_acl_entry_t acl_entry[XFS_ACL_MAX_ENTRIES]; 40 - } xfs_acl_t; 28 + /* On-disk XFS access control list structure */ 29 + struct xfs_acl { 30 + __be32 acl_cnt; 31 + struct xfs_acl_entry { 32 + __be32 ae_tag; 33 + __be32 ae_id; 34 + __be16 ae_perm; 35 + } acl_entry[XFS_ACL_MAX_ENTRIES]; 36 + }; 41 37 42 38 /* On-disk XFS extended attribute names */ 43 - #define SGI_ACL_FILE "SGI_ACL_FILE" 44 - #define SGI_ACL_DEFAULT "SGI_ACL_DEFAULT" 39 + #define SGI_ACL_FILE "SGI_ACL_FILE" 40 + #define SGI_ACL_DEFAULT "SGI_ACL_DEFAULT" 45 41 #define SGI_ACL_FILE_SIZE (sizeof(SGI_ACL_FILE)-1) 46 42 #define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1) 47 43 48 - #define _ACL_TYPE_ACCESS 1 49 - #define _ACL_TYPE_DEFAULT 2 50 - 51 44 #ifdef CONFIG_XFS_POSIX_ACL 45 + extern int xfs_check_acl(struct inode *inode, int mask); 46 + extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); 47 + extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl); 48 + extern int xfs_acl_chmod(struct inode *inode); 49 + extern void xfs_inode_init_acls(struct xfs_inode *ip); 50 + extern void xfs_inode_clear_acls(struct xfs_inode *ip); 51 + extern int posix_acl_access_exists(struct inode *inode); 52 + extern int posix_acl_default_exists(struct inode *inode); 52 53 53 - struct vattr; 54 - struct xfs_inode; 55 - 56 - extern struct kmem_zone *xfs_acl_zone; 57 - #define xfs_acl_zone_init(zone, name) \ 58 - (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) 59 - #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) 60 - 61 - extern int xfs_acl_inherit(struct inode *, mode_t mode, xfs_acl_t *); 62 - extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); 63 - extern int xfs_acl_vtoacl(struct inode *, xfs_acl_t *, xfs_acl_t *); 64 - extern int xfs_acl_vhasacl_access(struct inode *); 65 - extern int xfs_acl_vhasacl_default(struct inode *); 66 - extern int xfs_acl_vset(struct inode *, void *, size_t, int); 67 - extern int xfs_acl_vget(struct inode *, void *, size_t, int); 68 - extern int xfs_acl_vremove(struct inode *, int); 69 - 70 - #define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE)) 71 - 72 - #define _ACL_INHERIT(c,m,d) (xfs_acl_inherit(c,m,d)) 73 - #define _ACL_GET_ACCESS(pv,pa) (xfs_acl_vtoacl(pv,pa,NULL) == 0) 74 - #define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0) 75 - #define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access 76 - #define _ACL_DEFAULT_EXISTS xfs_acl_vhasacl_default 77 - 78 - #define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP)) 79 - #define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0) 80 - 54 + extern struct xattr_handler xfs_xattr_system_handler; 81 55 #else 82 - #define xfs_acl_zone_init(zone,name) 83 - #define xfs_acl_zone_destroy(zone) 84 - #define xfs_acl_vset(v,p,sz,t) (-EOPNOTSUPP) 85 - #define xfs_acl_vget(v,p,sz,t) (-EOPNOTSUPP) 86 - #define xfs_acl_vremove(v,t) (-EOPNOTSUPP) 87 - #define xfs_acl_vhasacl_access(v) (0) 88 - #define xfs_acl_vhasacl_default(v) (0) 89 - #define _ACL_ALLOC(a) (1) /* successfully allocate nothing */ 90 - #define _ACL_FREE(a) ((void)0) 91 - #define _ACL_INHERIT(c,m,d) (0) 92 - #define _ACL_GET_ACCESS(pv,pa) (0) 93 - #define _ACL_GET_DEFAULT(pv,pd) (0) 94 - #define _ACL_ACCESS_EXISTS (NULL) 95 - #define _ACL_DEFAULT_EXISTS (NULL) 96 - #endif 97 - 56 + # define xfs_check_acl NULL 57 + # define xfs_get_acl(inode, type) NULL 58 + # define xfs_inherit_acl(inode, default_acl) 0 59 + # define xfs_acl_chmod(inode) 0 60 + # define xfs_inode_init_acls(ip) 61 + # define xfs_inode_clear_acls(ip) 62 + # define posix_acl_access_exists(inode) 0 63 + # define posix_acl_default_exists(inode) 0 64 + #endif /* CONFIG_XFS_POSIX_ACL */ 98 65 #endif /* __XFS_ACL_H__ */
-32
fs/xfs/xfs_arch.h
··· 73 73 74 74 #endif /* __KERNEL__ */ 75 75 76 - /* do we need conversion? */ 77 - #define ARCH_NOCONVERT 1 78 - #ifdef XFS_NATIVE_HOST 79 - # define ARCH_CONVERT ARCH_NOCONVERT 80 - #else 81 - # define ARCH_CONVERT 0 82 - #endif 83 - 84 - /* generic swapping macros */ 85 - 86 - #ifndef HAVE_SWABMACROS 87 - #define INT_SWAP16(type,var) ((typeof(type))(__swab16((__u16)(var)))) 88 - #define INT_SWAP32(type,var) ((typeof(type))(__swab32((__u32)(var)))) 89 - #define INT_SWAP64(type,var) ((typeof(type))(__swab64((__u64)(var)))) 90 - #endif 91 - 92 - #define INT_SWAP(type, var) \ 93 - ((sizeof(type) == 8) ? INT_SWAP64(type,var) : \ 94 - ((sizeof(type) == 4) ? INT_SWAP32(type,var) : \ 95 - ((sizeof(type) == 2) ? INT_SWAP16(type,var) : \ 96 - (var)))) 97 - 98 76 /* 99 77 * get and set integers from potentially unaligned locations 100 78 */ ··· 84 106 ((__u8*)(pointer))[0] = (((value) >> 8) & 0xff); \ 85 107 ((__u8*)(pointer))[1] = (((value) ) & 0xff); \ 86 108 } 87 - 88 - /* does not return a value */ 89 - #define INT_SET(reference,arch,valueref) \ 90 - (__builtin_constant_p(valueref) ? \ 91 - (void)( (reference) = ( ((arch) != ARCH_NOCONVERT) ? (INT_SWAP((reference),(valueref))) : (valueref)) ) : \ 92 - (void)( \ 93 - ((reference) = (valueref)), \ 94 - ( ((arch) != ARCH_NOCONVERT) ? (reference) = INT_SWAP((reference),(reference)) : 0 ) \ 95 - ) \ 96 - ) 97 109 98 110 /* 99 111 * In directories inode numbers are stored as unaligned arrays of unsigned
-1
fs/xfs/xfs_attr.c
··· 45 45 #include "xfs_error.h" 46 46 #include "xfs_quota.h" 47 47 #include "xfs_trans_space.h" 48 - #include "xfs_acl.h" 49 48 #include "xfs_rw.h" 50 49 #include "xfs_vnodeops.h" 51 50
+3
fs/xfs/xfs_iget.c
··· 18 18 #include "xfs.h" 19 19 #include "xfs_fs.h" 20 20 #include "xfs_types.h" 21 + #include "xfs_acl.h" 21 22 #include "xfs_bit.h" 22 23 #include "xfs_log.h" 23 24 #include "xfs_inum.h" ··· 83 82 memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); 84 83 ip->i_size = 0; 85 84 ip->i_new_size = 0; 85 + xfs_inode_init_acls(ip); 86 86 87 87 /* 88 88 * Initialize inode's trace buffers. ··· 560 558 ASSERT(atomic_read(&ip->i_pincount) == 0); 561 559 ASSERT(!spin_is_locked(&ip->i_flags_lock)); 562 560 ASSERT(completion_done(&ip->i_flush)); 561 + xfs_inode_clear_acls(ip); 563 562 kmem_zone_free(xfs_inode_zone, ip); 564 563 } 565 564
-1
fs/xfs/xfs_inode.c
··· 49 49 #include "xfs_utils.h" 50 50 #include "xfs_dir2_trace.h" 51 51 #include "xfs_quota.h" 52 - #include "xfs_acl.h" 53 52 #include "xfs_filestream.h" 54 53 #include "xfs_vnodeops.h" 55 54
+6
fs/xfs/xfs_inode.h
··· 18 18 #ifndef __XFS_INODE_H__ 19 19 #define __XFS_INODE_H__ 20 20 21 + struct posix_acl; 21 22 struct xfs_dinode; 22 23 struct xfs_inode; 23 24 ··· 272 271 273 272 /* VFS inode */ 274 273 struct inode i_vnode; /* embedded VFS inode */ 274 + 275 + #ifdef CONFIG_XFS_POSIX_ACL 276 + struct posix_acl *i_acl; 277 + struct posix_acl *i_default_acl; 278 + #endif 275 279 276 280 /* Trace buffers per inode. */ 277 281 #ifdef XFS_INODE_TRACE
-1
fs/xfs/xfs_iomap.c
··· 42 42 #include "xfs_error.h" 43 43 #include "xfs_itable.h" 44 44 #include "xfs_rw.h" 45 - #include "xfs_acl.h" 46 45 #include "xfs_attr.h" 47 46 #include "xfs_buf_item.h" 48 47 #include "xfs_trans_space.h"
-1
fs/xfs/xfs_rw.c
··· 41 41 #include "xfs_ialloc.h" 42 42 #include "xfs_attr.h" 43 43 #include "xfs_bmap.h" 44 - #include "xfs_acl.h" 45 44 #include "xfs_error.h" 46 45 #include "xfs_buf_item.h" 47 46 #include "xfs_rw.h"
+14 -1
fs/xfs/xfs_vnodeops.c
··· 42 42 #include "xfs_ialloc.h" 43 43 #include "xfs_alloc.h" 44 44 #include "xfs_bmap.h" 45 + #include "xfs_acl.h" 45 46 #include "xfs_attr.h" 46 47 #include "xfs_rw.h" 47 48 #include "xfs_error.h" ··· 468 467 xfs_qm_dqrele(udqp); 469 468 xfs_qm_dqrele(gdqp); 470 469 471 - if (code) { 470 + if (code) 472 471 return code; 472 + 473 + /* 474 + * XXX(hch): Updating the ACL entries is not atomic vs the i_mode 475 + * update. We could avoid this with linked transactions 476 + * and passing down the transaction pointer all the way 477 + * to attr_set. No previous user of the generic 478 + * Posix ACL code seems to care about this issue either. 479 + */ 480 + if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) { 481 + code = -xfs_acl_chmod(inode); 482 + if (code) 483 + return XFS_ERROR(code); 473 484 } 474 485 475 486 if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) &&
+1
fs/xfs/xfs_vnodeops.h
··· 18 18 #define XFS_ATTR_DMI 0x01 /* invocation from a DMI function */ 19 19 #define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if operation would block */ 20 20 #define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */ 21 + #define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */ 21 22 22 23 int xfs_readlink(struct xfs_inode *ip, char *link); 23 24 int xfs_fsync(struct xfs_inode *ip);