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 36 #include <linux/capability.h> 37 #include <linux/posix_acl_xattr.h> 38 39 STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *); 40 STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); 41 STATIC void xfs_acl_get_endian(xfs_acl_t *); 42 STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); 43 STATIC int xfs_acl_invalid(xfs_acl_t *); 44 STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); 45 STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *); 46 STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *); 47 STATIC int xfs_acl_allow_set(bhv_vnode_t *, int); 48 49 kmem_zone_t *xfs_acl_zone; 50 51 52 /* 53 * Test for existence of access ACL attribute as efficiently as possible. 54 */ 55 int 56 xfs_acl_vhasacl_access( 57 bhv_vnode_t *vp) 58 { 59 int error; 60 61 xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error); 62 return (error == 0); 63 } 64 65 /* 66 * Test for existence of default ACL attribute as efficiently as possible. 67 */ 68 int 69 xfs_acl_vhasacl_default( 70 bhv_vnode_t *vp) 71 { 72 int error; 73 74 if (!VN_ISDIR(vp)) 75 return 0; 76 xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error); 77 return (error == 0); 78 } 79 80 /* 81 * Convert from extended attribute representation to in-memory for XFS. 82 */ 83 STATIC int 84 posix_acl_xattr_to_xfs( 85 posix_acl_xattr_header *src, 86 size_t size, 87 xfs_acl_t *dest) 88 { 89 posix_acl_xattr_entry *src_entry; 90 xfs_acl_entry_t *dest_entry; 91 int n; 92 93 if (!src || !dest) 94 return EINVAL; 95 96 if (size < sizeof(posix_acl_xattr_header)) 97 return EINVAL; 98 99 if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 100 return EOPNOTSUPP; 101 102 memset(dest, 0, sizeof(xfs_acl_t)); 103 dest->acl_cnt = posix_acl_xattr_count(size); 104 if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES) 105 return EINVAL; 106 107 /* 108 * acl_set_file(3) may request that we set default ACLs with 109 * zero length -- defend (gracefully) against that here. 110 */ 111 if (!dest->acl_cnt) 112 return 0; 113 114 src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src)); 115 dest_entry = &dest->acl_entry[0]; 116 117 for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) { 118 dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm); 119 if (_ACL_PERM_INVALID(dest_entry->ae_perm)) 120 return EINVAL; 121 dest_entry->ae_tag = le16_to_cpu(src_entry->e_tag); 122 switch(dest_entry->ae_tag) { 123 case ACL_USER: 124 case ACL_GROUP: 125 dest_entry->ae_id = le32_to_cpu(src_entry->e_id); 126 break; 127 case ACL_USER_OBJ: 128 case ACL_GROUP_OBJ: 129 case ACL_MASK: 130 case ACL_OTHER: 131 dest_entry->ae_id = ACL_UNDEFINED_ID; 132 break; 133 default: 134 return EINVAL; 135 } 136 } 137 if (xfs_acl_invalid(dest)) 138 return EINVAL; 139 140 return 0; 141 } 142 143 /* 144 * Comparison function called from xfs_sort(). 145 * Primary key is ae_tag, secondary key is ae_id. 146 */ 147 STATIC int 148 xfs_acl_entry_compare( 149 const void *va, 150 const void *vb) 151 { 152 xfs_acl_entry_t *a = (xfs_acl_entry_t *)va, 153 *b = (xfs_acl_entry_t *)vb; 154 155 if (a->ae_tag == b->ae_tag) 156 return (a->ae_id - b->ae_id); 157 return (a->ae_tag - b->ae_tag); 158 } 159 160 /* 161 * Convert from in-memory XFS to extended attribute representation. 162 */ 163 STATIC int 164 posix_acl_xfs_to_xattr( 165 xfs_acl_t *src, 166 posix_acl_xattr_header *dest, 167 size_t size) 168 { 169 int n; 170 size_t new_size = posix_acl_xattr_size(src->acl_cnt); 171 posix_acl_xattr_entry *dest_entry; 172 xfs_acl_entry_t *src_entry; 173 174 if (size < new_size) 175 return -ERANGE; 176 177 /* Need to sort src XFS ACL by <ae_tag,ae_id> */ 178 xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]), 179 xfs_acl_entry_compare); 180 181 dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); 182 dest_entry = &dest->a_entries[0]; 183 src_entry = &src->acl_entry[0]; 184 for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) { 185 dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm); 186 if (_ACL_PERM_INVALID(src_entry->ae_perm)) 187 return -EINVAL; 188 dest_entry->e_tag = cpu_to_le16(src_entry->ae_tag); 189 switch (src_entry->ae_tag) { 190 case ACL_USER: 191 case ACL_GROUP: 192 dest_entry->e_id = cpu_to_le32(src_entry->ae_id); 193 break; 194 case ACL_USER_OBJ: 195 case ACL_GROUP_OBJ: 196 case ACL_MASK: 197 case ACL_OTHER: 198 dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); 199 break; 200 default: 201 return -EINVAL; 202 } 203 } 204 return new_size; 205 } 206 207 int 208 xfs_acl_vget( 209 bhv_vnode_t *vp, 210 void *acl, 211 size_t size, 212 int kind) 213 { 214 int error; 215 xfs_acl_t *xfs_acl = NULL; 216 posix_acl_xattr_header *ext_acl = acl; 217 int flags = 0; 218 219 VN_HOLD(vp); 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 bhv_vattr_t va; 242 243 va.va_mask = XFS_AT_MODE; 244 error = bhv_vop_getattr(vp, &va, 0, sys_cred); 245 if (error) 246 goto out; 247 xfs_acl_sync_mode(va.va_mode, xfs_acl); 248 } 249 error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size); 250 } 251 out: 252 VN_RELE(vp); 253 if(xfs_acl) 254 _ACL_FREE(xfs_acl); 255 return -error; 256 } 257 258 int 259 xfs_acl_vremove( 260 bhv_vnode_t *vp, 261 int kind) 262 { 263 int error; 264 265 VN_HOLD(vp); 266 error = xfs_acl_allow_set(vp, kind); 267 if (!error) { 268 error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT? 269 SGI_ACL_DEFAULT: SGI_ACL_FILE, 270 ATTR_ROOT, sys_cred); 271 if (error == ENOATTR) 272 error = 0; /* 'scool */ 273 } 274 VN_RELE(vp); 275 return -error; 276 } 277 278 int 279 xfs_acl_vset( 280 bhv_vnode_t *vp, 281 void *acl, 282 size_t size, 283 int kind) 284 { 285 posix_acl_xattr_header *ext_acl = acl; 286 xfs_acl_t *xfs_acl; 287 int error; 288 int basicperms = 0; /* more than std unix perms? */ 289 290 if (!acl) 291 return -EINVAL; 292 293 if (!(_ACL_ALLOC(xfs_acl))) 294 return -ENOMEM; 295 296 error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl); 297 if (error) { 298 _ACL_FREE(xfs_acl); 299 return -error; 300 } 301 if (!xfs_acl->acl_cnt) { 302 _ACL_FREE(xfs_acl); 303 return 0; 304 } 305 306 VN_HOLD(vp); 307 error = xfs_acl_allow_set(vp, kind); 308 if (error) 309 goto out; 310 311 /* Incoming ACL exists, set file mode based on its value */ 312 if (kind == _ACL_TYPE_ACCESS) 313 xfs_acl_setmode(vp, xfs_acl, &basicperms); 314 315 /* 316 * If we have more than std unix permissions, set up the actual attr. 317 * Otherwise, delete any existing attr. This prevents us from 318 * having actual attrs for permissions that can be stored in the 319 * standard permission bits. 320 */ 321 if (!basicperms) { 322 xfs_acl_set_attr(vp, xfs_acl, kind, &error); 323 } else { 324 xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); 325 } 326 327 out: 328 VN_RELE(vp); 329 _ACL_FREE(xfs_acl); 330 return -error; 331 } 332 333 int 334 xfs_acl_iaccess( 335 xfs_inode_t *ip, 336 mode_t mode, 337 cred_t *cr) 338 { 339 xfs_acl_t *acl; 340 int rval; 341 342 if (!(_ACL_ALLOC(acl))) 343 return -1; 344 345 /* If the file has no ACL return -1. */ 346 rval = sizeof(xfs_acl_t); 347 if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE, 348 (char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) { 349 _ACL_FREE(acl); 350 return -1; 351 } 352 xfs_acl_get_endian(acl); 353 354 /* If the file has an empty ACL return -1. */ 355 if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) { 356 _ACL_FREE(acl); 357 return -1; 358 } 359 360 /* Synchronize ACL with mode bits */ 361 xfs_acl_sync_mode(ip->i_d.di_mode, acl); 362 363 rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr); 364 _ACL_FREE(acl); 365 return rval; 366 } 367 368 STATIC int 369 xfs_acl_allow_set( 370 bhv_vnode_t *vp, 371 int kind) 372 { 373 bhv_vattr_t va; 374 int error; 375 376 if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) 377 return EPERM; 378 if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp)) 379 return ENOTDIR; 380 if (vp->v_vfsp->vfs_flag & VFS_RDONLY) 381 return EROFS; 382 va.va_mask = XFS_AT_UID; 383 error = bhv_vop_getattr(vp, &va, 0, NULL); 384 if (error) 385 return error; 386 if (va.va_uid != current->fsuid && !capable(CAP_FOWNER)) 387 return EPERM; 388 return error; 389 } 390 391 /* 392 * The access control process to determine the access permission: 393 * if uid == file owner id, use the file owner bits. 394 * if gid == file owner group id, use the file group bits. 395 * scan ACL for a matching user or group, and use matched entry 396 * permission. Use total permissions of all matching group entries, 397 * until all acl entries are exhausted. The final permission produced 398 * by matching acl entry or entries needs to be & with group permission. 399 * if not owner, owning group, or matching entry in ACL, use file 400 * other bits. 401 */ 402 STATIC int 403 xfs_acl_capability_check( 404 mode_t mode, 405 cred_t *cr) 406 { 407 if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH)) 408 return EACCES; 409 if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE)) 410 return EACCES; 411 if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE)) 412 return EACCES; 413 414 return 0; 415 } 416 417 /* 418 * Note: cr is only used here for the capability check if the ACL test fails. 419 * It is not used to find out the credentials uid or groups etc, as was 420 * done in IRIX. It is assumed that the uid and groups for the current 421 * thread are taken from "current" instead of the cr parameter. 422 */ 423 STATIC int 424 xfs_acl_access( 425 uid_t fuid, 426 gid_t fgid, 427 xfs_acl_t *fap, 428 mode_t md, 429 cred_t *cr) 430 { 431 xfs_acl_entry_t matched; 432 int i, allows; 433 int maskallows = -1; /* true, but not 1, either */ 434 int seen_userobj = 0; 435 436 matched.ae_tag = 0; /* Invalid type */ 437 matched.ae_perm = 0; 438 md >>= 6; /* Normalize the bits for comparison */ 439 440 for (i = 0; i < fap->acl_cnt; i++) { 441 /* 442 * Break out if we've got a user_obj entry or 443 * a user entry and the mask (and have processed USER_OBJ) 444 */ 445 if (matched.ae_tag == ACL_USER_OBJ) 446 break; 447 if (matched.ae_tag == ACL_USER) { 448 if (maskallows != -1 && seen_userobj) 449 break; 450 if (fap->acl_entry[i].ae_tag != ACL_MASK && 451 fap->acl_entry[i].ae_tag != ACL_USER_OBJ) 452 continue; 453 } 454 /* True if this entry allows the requested access */ 455 allows = ((fap->acl_entry[i].ae_perm & md) == md); 456 457 switch (fap->acl_entry[i].ae_tag) { 458 case ACL_USER_OBJ: 459 seen_userobj = 1; 460 if (fuid != current->fsuid) 461 continue; 462 matched.ae_tag = ACL_USER_OBJ; 463 matched.ae_perm = allows; 464 break; 465 case ACL_USER: 466 if (fap->acl_entry[i].ae_id != current->fsuid) 467 continue; 468 matched.ae_tag = ACL_USER; 469 matched.ae_perm = allows; 470 break; 471 case ACL_GROUP_OBJ: 472 if ((matched.ae_tag == ACL_GROUP_OBJ || 473 matched.ae_tag == ACL_GROUP) && !allows) 474 continue; 475 if (!in_group_p(fgid)) 476 continue; 477 matched.ae_tag = ACL_GROUP_OBJ; 478 matched.ae_perm = allows; 479 break; 480 case ACL_GROUP: 481 if ((matched.ae_tag == ACL_GROUP_OBJ || 482 matched.ae_tag == ACL_GROUP) && !allows) 483 continue; 484 if (!in_group_p(fap->acl_entry[i].ae_id)) 485 continue; 486 matched.ae_tag = ACL_GROUP; 487 matched.ae_perm = allows; 488 break; 489 case ACL_MASK: 490 maskallows = allows; 491 break; 492 case ACL_OTHER: 493 if (matched.ae_tag != 0) 494 continue; 495 matched.ae_tag = ACL_OTHER; 496 matched.ae_perm = allows; 497 break; 498 } 499 } 500 /* 501 * First possibility is that no matched entry allows access. 502 * The capability to override DAC may exist, so check for it. 503 */ 504 switch (matched.ae_tag) { 505 case ACL_OTHER: 506 case ACL_USER_OBJ: 507 if (matched.ae_perm) 508 return 0; 509 break; 510 case ACL_USER: 511 case ACL_GROUP_OBJ: 512 case ACL_GROUP: 513 if (maskallows && matched.ae_perm) 514 return 0; 515 break; 516 case 0: 517 break; 518 } 519 520 return xfs_acl_capability_check(md, cr); 521 } 522 523 /* 524 * ACL validity checker. 525 * This acl validation routine checks each ACL entry read in makes sense. 526 */ 527 STATIC int 528 xfs_acl_invalid( 529 xfs_acl_t *aclp) 530 { 531 xfs_acl_entry_t *entry, *e; 532 int user = 0, group = 0, other = 0, mask = 0; 533 int mask_required = 0; 534 int i, j; 535 536 if (!aclp) 537 goto acl_invalid; 538 539 if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES) 540 goto acl_invalid; 541 542 for (i = 0; i < aclp->acl_cnt; i++) { 543 entry = &aclp->acl_entry[i]; 544 switch (entry->ae_tag) { 545 case ACL_USER_OBJ: 546 if (user++) 547 goto acl_invalid; 548 break; 549 case ACL_GROUP_OBJ: 550 if (group++) 551 goto acl_invalid; 552 break; 553 case ACL_OTHER: 554 if (other++) 555 goto acl_invalid; 556 break; 557 case ACL_USER: 558 case ACL_GROUP: 559 for (j = i + 1; j < aclp->acl_cnt; j++) { 560 e = &aclp->acl_entry[j]; 561 if (e->ae_id == entry->ae_id && 562 e->ae_tag == entry->ae_tag) 563 goto acl_invalid; 564 } 565 mask_required++; 566 break; 567 case ACL_MASK: 568 if (mask++) 569 goto acl_invalid; 570 break; 571 default: 572 goto acl_invalid; 573 } 574 } 575 if (!user || !group || !other || (mask_required && !mask)) 576 goto acl_invalid; 577 else 578 return 0; 579 acl_invalid: 580 return EINVAL; 581 } 582 583 /* 584 * Do ACL endian conversion. 585 */ 586 STATIC void 587 xfs_acl_get_endian( 588 xfs_acl_t *aclp) 589 { 590 xfs_acl_entry_t *ace, *end; 591 592 INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); 593 end = &aclp->acl_entry[0]+aclp->acl_cnt; 594 for (ace = &aclp->acl_entry[0]; ace < end; ace++) { 595 INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag); 596 INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id); 597 INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm); 598 } 599 } 600 601 /* 602 * Get the ACL from the EA and do endian conversion. 603 */ 604 STATIC void 605 xfs_acl_get_attr( 606 bhv_vnode_t *vp, 607 xfs_acl_t *aclp, 608 int kind, 609 int flags, 610 int *error) 611 { 612 int len = sizeof(xfs_acl_t); 613 614 ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); 615 flags |= ATTR_ROOT; 616 *error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ? 617 SGI_ACL_FILE : SGI_ACL_DEFAULT, 618 (char *)aclp, &len, flags, sys_cred); 619 if (*error || (flags & ATTR_KERNOVAL)) 620 return; 621 xfs_acl_get_endian(aclp); 622 } 623 624 /* 625 * Set the EA with the ACL and do endian conversion. 626 */ 627 STATIC void 628 xfs_acl_set_attr( 629 bhv_vnode_t *vp, 630 xfs_acl_t *aclp, 631 int kind, 632 int *error) 633 { 634 xfs_acl_entry_t *ace, *newace, *end; 635 xfs_acl_t *newacl; 636 int len; 637 638 if (!(_ACL_ALLOC(newacl))) { 639 *error = ENOMEM; 640 return; 641 } 642 643 len = sizeof(xfs_acl_t) - 644 (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt)); 645 end = &aclp->acl_entry[0]+aclp->acl_cnt; 646 for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0]; 647 ace < end; 648 ace++, newace++) { 649 INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag); 650 INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id); 651 INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); 652 } 653 INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); 654 *error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ? 655 SGI_ACL_FILE: SGI_ACL_DEFAULT, 656 (char *)newacl, len, ATTR_ROOT, sys_cred); 657 _ACL_FREE(newacl); 658 } 659 660 int 661 xfs_acl_vtoacl( 662 bhv_vnode_t *vp, 663 xfs_acl_t *access_acl, 664 xfs_acl_t *default_acl) 665 { 666 bhv_vattr_t va; 667 int error = 0; 668 669 if (access_acl) { 670 /* 671 * Get the Access ACL and the mode. If either cannot 672 * be obtained for some reason, invalidate the access ACL. 673 */ 674 xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error); 675 if (!error) { 676 /* Got the ACL, need the mode... */ 677 va.va_mask = XFS_AT_MODE; 678 error = bhv_vop_getattr(vp, &va, 0, sys_cred); 679 } 680 681 if (error) 682 access_acl->acl_cnt = XFS_ACL_NOT_PRESENT; 683 else /* We have a good ACL and the file mode, synchronize. */ 684 xfs_acl_sync_mode(va.va_mode, access_acl); 685 } 686 687 if (default_acl) { 688 xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error); 689 if (error) 690 default_acl->acl_cnt = XFS_ACL_NOT_PRESENT; 691 } 692 return error; 693 } 694 695 /* 696 * This function retrieves the parent directory's acl, processes it 697 * and lets the child inherit the acl(s) that it should. 698 */ 699 int 700 xfs_acl_inherit( 701 bhv_vnode_t *vp, 702 bhv_vattr_t *vap, 703 xfs_acl_t *pdaclp) 704 { 705 xfs_acl_t *cacl; 706 int error = 0; 707 int basicperms = 0; 708 709 /* 710 * If the parent does not have a default ACL, or it's an 711 * invalid ACL, we're done. 712 */ 713 if (!vp) 714 return 0; 715 if (!pdaclp || xfs_acl_invalid(pdaclp)) 716 return 0; 717 718 /* 719 * Copy the default ACL of the containing directory to 720 * the access ACL of the new file and use the mode that 721 * was passed in to set up the correct initial values for 722 * the u::,g::[m::], and o:: entries. This is what makes 723 * umask() "work" with ACL's. 724 */ 725 726 if (!(_ACL_ALLOC(cacl))) 727 return ENOMEM; 728 729 memcpy(cacl, pdaclp, sizeof(xfs_acl_t)); 730 xfs_acl_filter_mode(vap->va_mode, cacl); 731 xfs_acl_setmode(vp, cacl, &basicperms); 732 733 /* 734 * Set the Default and Access ACL on the file. The mode is already 735 * set on the file, so we don't need to worry about that. 736 * 737 * If the new file is a directory, its default ACL is a copy of 738 * the containing directory's default ACL. 739 */ 740 if (VN_ISDIR(vp)) 741 xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error); 742 if (!error && !basicperms) 743 xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error); 744 _ACL_FREE(cacl); 745 return error; 746 } 747 748 /* 749 * Set up the correct mode on the file based on the supplied ACL. This 750 * makes sure that the mode on the file reflects the state of the 751 * u::,g::[m::], and o:: entries in the ACL. Since the mode is where 752 * the ACL is going to get the permissions for these entries, we must 753 * synchronize the mode whenever we set the ACL on a file. 754 */ 755 STATIC int 756 xfs_acl_setmode( 757 bhv_vnode_t *vp, 758 xfs_acl_t *acl, 759 int *basicperms) 760 { 761 bhv_vattr_t va; 762 xfs_acl_entry_t *ap; 763 xfs_acl_entry_t *gap = NULL; 764 int i, error, nomask = 1; 765 766 *basicperms = 1; 767 768 if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) 769 return 0; 770 771 /* 772 * Copy the u::, g::, o::, and m:: bits from the ACL into the 773 * mode. The m:: bits take precedence over the g:: bits. 774 */ 775 va.va_mask = XFS_AT_MODE; 776 error = bhv_vop_getattr(vp, &va, 0, sys_cred); 777 if (error) 778 return error; 779 780 va.va_mask = XFS_AT_MODE; 781 va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); 782 ap = acl->acl_entry; 783 for (i = 0; i < acl->acl_cnt; ++i) { 784 switch (ap->ae_tag) { 785 case ACL_USER_OBJ: 786 va.va_mode |= ap->ae_perm << 6; 787 break; 788 case ACL_GROUP_OBJ: 789 gap = ap; 790 break; 791 case ACL_MASK: /* more than just standard modes */ 792 nomask = 0; 793 va.va_mode |= ap->ae_perm << 3; 794 *basicperms = 0; 795 break; 796 case ACL_OTHER: 797 va.va_mode |= ap->ae_perm; 798 break; 799 default: /* more than just standard modes */ 800 *basicperms = 0; 801 break; 802 } 803 ap++; 804 } 805 806 /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */ 807 if (gap && nomask) 808 va.va_mode |= gap->ae_perm << 3; 809 810 return bhv_vop_setattr(vp, &va, 0, sys_cred); 811 } 812 813 /* 814 * The permissions for the special ACL entries (u::, g::[m::], o::) are 815 * actually stored in the file mode (if there is both a group and a mask, 816 * the group is stored in the ACL entry and the mask is stored on the file). 817 * This allows the mode to remain automatically in sync with the ACL without 818 * the need for a call-back to the ACL system at every point where the mode 819 * could change. This function takes the permissions from the specified mode 820 * and places it in the supplied ACL. 821 * 822 * This implementation draws its validity from the fact that, when the ACL 823 * was assigned, the mode was copied from the ACL. 824 * If the mode did not change, therefore, the mode remains exactly what was 825 * taken from the special ACL entries at assignment. 826 * If a subsequent chmod() was done, the POSIX spec says that the change in 827 * mode must cause an update to the ACL seen at user level and used for 828 * access checks. Before and after a mode change, therefore, the file mode 829 * most accurately reflects what the special ACL entries should permit/deny. 830 * 831 * CAVEAT: If someone sets the SGI_ACL_FILE attribute directly, 832 * the existing mode bits will override whatever is in the 833 * ACL. Similarly, if there is a pre-existing ACL that was 834 * never in sync with its mode (owing to a bug in 6.5 and 835 * before), it will now magically (or mystically) be 836 * synchronized. This could cause slight astonishment, but 837 * it is better than inconsistent permissions. 838 * 839 * The supplied ACL is a template that may contain any combination 840 * of special entries. These are treated as place holders when we fill 841 * out the ACL. This routine does not add or remove special entries, it 842 * simply unites each special entry with its associated set of permissions. 843 */ 844 STATIC void 845 xfs_acl_sync_mode( 846 mode_t mode, 847 xfs_acl_t *acl) 848 { 849 int i, nomask = 1; 850 xfs_acl_entry_t *ap; 851 xfs_acl_entry_t *gap = NULL; 852 853 /* 854 * Set ACL entries. POSIX1003.1eD16 requires that the MASK 855 * be set instead of the GROUP entry, if there is a MASK. 856 */ 857 for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) { 858 switch (ap->ae_tag) { 859 case ACL_USER_OBJ: 860 ap->ae_perm = (mode >> 6) & 0x7; 861 break; 862 case ACL_GROUP_OBJ: 863 gap = ap; 864 break; 865 case ACL_MASK: 866 nomask = 0; 867 ap->ae_perm = (mode >> 3) & 0x7; 868 break; 869 case ACL_OTHER: 870 ap->ae_perm = mode & 0x7; 871 break; 872 default: 873 break; 874 } 875 } 876 /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */ 877 if (gap && nomask) 878 gap->ae_perm = (mode >> 3) & 0x7; 879 } 880 881 /* 882 * When inheriting an Access ACL from a directory Default ACL, 883 * the ACL bits are set to the intersection of the ACL default 884 * permission bits and the file permission bits in mode. If there 885 * are no permission bits on the file then we must not give them 886 * the ACL. This is what what makes umask() work with ACLs. 887 */ 888 STATIC void 889 xfs_acl_filter_mode( 890 mode_t mode, 891 xfs_acl_t *acl) 892 { 893 int i, nomask = 1; 894 xfs_acl_entry_t *ap; 895 xfs_acl_entry_t *gap = NULL; 896 897 /* 898 * Set ACL entries. POSIX1003.1eD16 requires that the MASK 899 * be merged with GROUP entry, if there is a MASK. 900 */ 901 for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) { 902 switch (ap->ae_tag) { 903 case ACL_USER_OBJ: 904 ap->ae_perm &= (mode >> 6) & 0x7; 905 break; 906 case ACL_GROUP_OBJ: 907 gap = ap; 908 break; 909 case ACL_MASK: 910 nomask = 0; 911 ap->ae_perm &= (mode >> 3) & 0x7; 912 break; 913 case ACL_OTHER: 914 ap->ae_perm &= mode & 0x7; 915 break; 916 default: 917 break; 918 } 919 } 920 /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */ 921 if (gap && nomask) 922 gap->ae_perm &= (mode >> 3) & 0x7; 923 } 924