1 /*- 2 * Copyright (c) 2008-2010 Edward Tomasz Napierała <trasz@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * ACL support routines specific to NFSv4 access control lists. These are 29 * utility routines for code common across file systems implementing NFSv4 30 * ACLs. 31 */ 32 33 #ifdef _KERNEL 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/kernel.h> 39 #include <sys/module.h> 40 #include <sys/systm.h> 41 #include <sys/mount.h> 42 #include <sys/priv.h> 43 #include <sys/vnode.h> 44 #include <sys/errno.h> 45 #include <sys/stat.h> 46 #include <sys/sysctl.h> 47 #include <sys/acl.h> 48 #else 49 #include <errno.h> 50 #include <assert.h> 51 #include <sys/acl.h> 52 #include <sys/stat.h> 53 #define KASSERT(a, b) assert(a) 54 #define CTASSERT(a) 55 56 #endif /* !_KERNEL */ 57 58 #ifdef _KERNEL 59 60 static void acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode); 61 62 static int acl_nfs4_old_semantics = 0; 63 64 SYSCTL_INT(_vfs, OID_AUTO, acl_nfs4_old_semantics, CTLFLAG_RW, 65 &acl_nfs4_old_semantics, 0, "Use pre-PSARC/2010/029 NFSv4 ACL semantics"); 66 67 static struct { 68 accmode_t accmode; 69 int mask; 70 } accmode2mask[] = {{VREAD, ACL_READ_DATA}, 71 {VWRITE, ACL_WRITE_DATA}, 72 {VAPPEND, ACL_APPEND_DATA}, 73 {VEXEC, ACL_EXECUTE}, 74 {VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 75 {VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 76 {VDELETE_CHILD, ACL_DELETE_CHILD}, 77 {VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 78 {VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 79 {VDELETE, ACL_DELETE}, 80 {VREAD_ACL, ACL_READ_ACL}, 81 {VWRITE_ACL, ACL_WRITE_ACL}, 82 {VWRITE_OWNER, ACL_WRITE_OWNER}, 83 {VSYNCHRONIZE, ACL_SYNCHRONIZE}, 84 {0, 0}}; 85 86 static int 87 _access_mask_from_accmode(accmode_t accmode) 88 { 89 int access_mask = 0, i; 90 91 for (i = 0; accmode2mask[i].accmode != 0; i++) { 92 if (accmode & accmode2mask[i].accmode) 93 access_mask |= accmode2mask[i].mask; 94 } 95 96 /* 97 * VAPPEND is just a modifier for VWRITE; if the caller asked 98 * for 'VAPPEND | VWRITE', we want to check for ACL_APPEND_DATA only. 99 */ 100 if (access_mask & ACL_APPEND_DATA) 101 access_mask &= ~ACL_WRITE_DATA; 102 103 return (access_mask); 104 } 105 106 /* 107 * Return 0, iff access is allowed, 1 otherwise. 108 */ 109 static int 110 _acl_denies(const struct acl *aclp, int access_mask, struct ucred *cred, 111 int file_uid, int file_gid, int *denied_explicitly) 112 { 113 int i; 114 const struct acl_entry *entry; 115 116 if (denied_explicitly != NULL) 117 *denied_explicitly = 0; 118 119 KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, 120 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 121 122 for (i = 0; i < aclp->acl_cnt; i++) { 123 entry = &(aclp->acl_entry[i]); 124 125 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 126 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 127 continue; 128 if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) 129 continue; 130 switch (entry->ae_tag) { 131 case ACL_USER_OBJ: 132 if (file_uid != cred->cr_uid) 133 continue; 134 break; 135 case ACL_USER: 136 if (entry->ae_id != cred->cr_uid) 137 continue; 138 break; 139 case ACL_GROUP_OBJ: 140 if (!groupmember(file_gid, cred)) 141 continue; 142 break; 143 case ACL_GROUP: 144 if (!groupmember(entry->ae_id, cred)) 145 continue; 146 break; 147 default: 148 KASSERT(entry->ae_tag == ACL_EVERYONE, 149 ("entry->ae_tag == ACL_EVERYONE")); 150 } 151 152 if (entry->ae_entry_type == ACL_ENTRY_TYPE_DENY) { 153 if (entry->ae_perm & access_mask) { 154 if (denied_explicitly != NULL) 155 *denied_explicitly = 1; 156 return (1); 157 } 158 } 159 160 access_mask &= ~(entry->ae_perm); 161 if (access_mask == 0) 162 return (0); 163 } 164 165 if (access_mask == 0) 166 return (0); 167 168 return (1); 169 } 170 171 int 172 vaccess_acl_nfs4(enum vtype type, uid_t file_uid, gid_t file_gid, 173 struct acl *aclp, accmode_t accmode, struct ucred *cred, int *privused) 174 { 175 accmode_t priv_granted = 0; 176 int denied, explicitly_denied, access_mask, is_directory, 177 must_be_owner = 0; 178 mode_t file_mode = 0; 179 180 KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND | 181 VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS | 182 VDELETE_CHILD | VREAD_ATTRIBUTES | VWRITE_ATTRIBUTES | VDELETE | 183 VREAD_ACL | VWRITE_ACL | VWRITE_OWNER | VSYNCHRONIZE)) == 0, 184 ("invalid bit in accmode")); 185 KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE), 186 ("VAPPEND without VWRITE")); 187 188 if (privused != NULL) 189 *privused = 0; 190 191 if (accmode & VADMIN) 192 must_be_owner = 1; 193 194 /* 195 * Ignore VSYNCHRONIZE permission. 196 */ 197 accmode &= ~VSYNCHRONIZE; 198 199 access_mask = _access_mask_from_accmode(accmode); 200 201 if (type == VDIR) 202 is_directory = 1; 203 else 204 is_directory = 0; 205 206 /* 207 * File owner is always allowed to read and write the ACL 208 * and basic attributes. This is to prevent a situation 209 * where user would change ACL in a way that prevents him 210 * from undoing the change. 211 */ 212 if (file_uid == cred->cr_uid) 213 access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL | 214 ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES); 215 216 /* 217 * Ignore append permission for regular files; use write 218 * permission instead. 219 */ 220 if (!is_directory && (access_mask & ACL_APPEND_DATA)) { 221 access_mask &= ~ACL_APPEND_DATA; 222 access_mask |= ACL_WRITE_DATA; 223 } 224 225 denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid, 226 &explicitly_denied); 227 228 if (must_be_owner) { 229 if (file_uid != cred->cr_uid) 230 denied = EPERM; 231 } 232 233 /* 234 * For VEXEC, ensure that at least one execute bit is set for 235 * non-directories. We have to check the mode here to stay 236 * consistent with execve(2). See the test in 237 * exec_check_permissions(). 238 */ 239 acl_nfs4_sync_mode_from_acl(&file_mode, aclp); 240 if (!denied && !is_directory && (accmode & VEXEC) && 241 (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) 242 denied = EACCES; 243 244 if (!denied) 245 return (0); 246 247 /* 248 * Access failed. Iff it was not denied explicitly and 249 * VEXPLICIT_DENY flag was specified, allow access. 250 */ 251 if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0) 252 return (0); 253 254 accmode &= ~VEXPLICIT_DENY; 255 256 /* 257 * No match. Try to use privileges, if there are any. 258 */ 259 if (is_directory) { 260 if ((accmode & VEXEC) && !priv_check_cred(cred, 261 PRIV_VFS_LOOKUP, 0)) 262 priv_granted |= VEXEC; 263 } else { 264 /* 265 * Ensure that at least one execute bit is on. Otherwise, 266 * a privileged user will always succeed, and we don't want 267 * this to happen unless the file really is executable. 268 */ 269 if ((accmode & VEXEC) && (file_mode & 270 (S_IXUSR | S_IXGRP | S_IXOTH)) != 0 && 271 !priv_check_cred(cred, PRIV_VFS_EXEC, 0)) 272 priv_granted |= VEXEC; 273 } 274 275 if ((accmode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ, 0)) 276 priv_granted |= VREAD; 277 278 if ((accmode & (VWRITE | VAPPEND | VDELETE_CHILD)) && 279 !priv_check_cred(cred, PRIV_VFS_WRITE, 0)) 280 priv_granted |= (VWRITE | VAPPEND | VDELETE_CHILD); 281 282 if ((accmode & VADMIN_PERMS) && 283 !priv_check_cred(cred, PRIV_VFS_ADMIN, 0)) 284 priv_granted |= VADMIN_PERMS; 285 286 if ((accmode & VSTAT_PERMS) && 287 !priv_check_cred(cred, PRIV_VFS_STAT, 0)) 288 priv_granted |= VSTAT_PERMS; 289 290 if ((accmode & priv_granted) == accmode) { 291 if (privused != NULL) 292 *privused = 1; 293 294 return (0); 295 } 296 297 if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE)) 298 denied = EPERM; 299 else 300 denied = EACCES; 301 302 return (denied); 303 } 304 #endif /* _KERNEL */ 305 306 static int 307 _acl_entry_matches(struct acl_entry *entry, acl_tag_t tag, acl_perm_t perm, 308 acl_entry_type_t entry_type) 309 { 310 if (entry->ae_tag != tag) 311 return (0); 312 313 if (entry->ae_id != ACL_UNDEFINED_ID) 314 return (0); 315 316 if (entry->ae_perm != perm) 317 return (0); 318 319 if (entry->ae_entry_type != entry_type) 320 return (0); 321 322 if (entry->ae_flags != 0) 323 return (0); 324 325 return (1); 326 } 327 328 static struct acl_entry * 329 _acl_append(struct acl *aclp, acl_tag_t tag, acl_perm_t perm, 330 acl_entry_type_t entry_type) 331 { 332 struct acl_entry *entry; 333 334 KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 335 ("aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 336 337 entry = &(aclp->acl_entry[aclp->acl_cnt]); 338 aclp->acl_cnt++; 339 340 entry->ae_tag = tag; 341 entry->ae_id = ACL_UNDEFINED_ID; 342 entry->ae_perm = perm; 343 entry->ae_entry_type = entry_type; 344 entry->ae_flags = 0; 345 346 return (entry); 347 } 348 349 static struct acl_entry * 350 _acl_duplicate_entry(struct acl *aclp, int entry_index) 351 { 352 int i; 353 354 KASSERT(aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 355 ("aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 356 357 for (i = aclp->acl_cnt; i > entry_index; i--) 358 aclp->acl_entry[i] = aclp->acl_entry[i - 1]; 359 360 aclp->acl_cnt++; 361 362 return (&(aclp->acl_entry[entry_index + 1])); 363 } 364 365 static void 366 acl_nfs4_sync_acl_from_mode_draft(struct acl *aclp, mode_t mode, 367 int file_owner_id) 368 { 369 int i, meets, must_append; 370 struct acl_entry *entry, *copy, *previous, 371 *a1, *a2, *a3, *a4, *a5, *a6; 372 mode_t amode; 373 const int READ = 04; 374 const int WRITE = 02; 375 const int EXEC = 01; 376 377 KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, 378 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 379 380 /* 381 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 382 * 383 * 3.16.6.3. Applying a Mode to an Existing ACL 384 */ 385 386 /* 387 * 1. For each ACE: 388 */ 389 for (i = 0; i < aclp->acl_cnt; i++) { 390 entry = &(aclp->acl_entry[i]); 391 392 /* 393 * 1.1. If the type is neither ALLOW or DENY - skip. 394 */ 395 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 396 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 397 continue; 398 399 /* 400 * 1.2. If ACL_ENTRY_INHERIT_ONLY is set - skip. 401 */ 402 if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) 403 continue; 404 405 /* 406 * 1.3. If ACL_ENTRY_FILE_INHERIT or ACL_ENTRY_DIRECTORY_INHERIT 407 * are set: 408 */ 409 if (entry->ae_flags & 410 (ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT)) { 411 /* 412 * 1.3.1. A copy of the current ACE is made, and placed 413 * in the ACL immediately following the current 414 * ACE. 415 */ 416 copy = _acl_duplicate_entry(aclp, i); 417 418 /* 419 * 1.3.2. In the first ACE, the flag 420 * ACL_ENTRY_INHERIT_ONLY is set. 421 */ 422 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 423 424 /* 425 * 1.3.3. In the second ACE, the following flags 426 * are cleared: 427 * ACL_ENTRY_FILE_INHERIT, 428 * ACL_ENTRY_DIRECTORY_INHERIT, 429 * ACL_ENTRY_NO_PROPAGATE_INHERIT. 430 */ 431 copy->ae_flags &= ~(ACL_ENTRY_FILE_INHERIT | 432 ACL_ENTRY_DIRECTORY_INHERIT | 433 ACL_ENTRY_NO_PROPAGATE_INHERIT); 434 435 /* 436 * The algorithm continues on with the second ACE. 437 */ 438 i++; 439 entry = copy; 440 } 441 442 /* 443 * 1.4. If it's owner@, group@ or everyone@ entry, clear 444 * ACL_READ_DATA, ACL_WRITE_DATA, ACL_APPEND_DATA 445 * and ACL_EXECUTE. Continue to the next entry. 446 */ 447 if (entry->ae_tag == ACL_USER_OBJ || 448 entry->ae_tag == ACL_GROUP_OBJ || 449 entry->ae_tag == ACL_EVERYONE) { 450 entry->ae_perm &= ~(ACL_READ_DATA | ACL_WRITE_DATA | 451 ACL_APPEND_DATA | ACL_EXECUTE); 452 continue; 453 } 454 455 /* 456 * 1.5. Otherwise, if the "who" field did not match one 457 * of OWNER@, GROUP@, EVERYONE@: 458 * 459 * 1.5.1. If the type is ALLOW, check the preceding ACE. 460 * If it does not meet all of the following criteria: 461 */ 462 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW) 463 continue; 464 465 meets = 0; 466 if (i > 0) { 467 meets = 1; 468 previous = &(aclp->acl_entry[i - 1]); 469 470 /* 471 * 1.5.1.1. The type field is DENY, 472 */ 473 if (previous->ae_entry_type != ACL_ENTRY_TYPE_DENY) 474 meets = 0; 475 476 /* 477 * 1.5.1.2. The "who" field is the same as the current 478 * ACE, 479 * 480 * 1.5.1.3. The flag bit ACE4_IDENTIFIER_GROUP 481 * is the same as it is in the current ACE, 482 * and no other flag bits are set, 483 */ 484 if (previous->ae_id != entry->ae_id || 485 previous->ae_tag != entry->ae_tag) 486 meets = 0; 487 488 if (previous->ae_flags) 489 meets = 0; 490 491 /* 492 * 1.5.1.4. The mask bits are a subset of the mask bits 493 * of the current ACE, and are also subset of 494 * the following: ACL_READ_DATA, 495 * ACL_WRITE_DATA, ACL_APPEND_DATA, ACL_EXECUTE 496 */ 497 if (previous->ae_perm & ~(entry->ae_perm)) 498 meets = 0; 499 500 if (previous->ae_perm & ~(ACL_READ_DATA | 501 ACL_WRITE_DATA | ACL_APPEND_DATA | ACL_EXECUTE)) 502 meets = 0; 503 } 504 505 if (!meets) { 506 /* 507 * Then the ACE of type DENY, with a who equal 508 * to the current ACE, flag bits equal to 509 * (<current ACE flags> & <ACE_IDENTIFIER_GROUP>) 510 * and no mask bits, is prepended. 511 */ 512 previous = entry; 513 entry = _acl_duplicate_entry(aclp, i); 514 515 /* Adjust counter, as we've just added an entry. */ 516 i++; 517 518 previous->ae_tag = entry->ae_tag; 519 previous->ae_id = entry->ae_id; 520 previous->ae_flags = entry->ae_flags; 521 previous->ae_perm = 0; 522 previous->ae_entry_type = ACL_ENTRY_TYPE_DENY; 523 } 524 525 /* 526 * 1.5.2. The following modifications are made to the prepended 527 * ACE. The intent is to mask the following ACE 528 * to disallow ACL_READ_DATA, ACL_WRITE_DATA, 529 * ACL_APPEND_DATA, or ACL_EXECUTE, based upon the group 530 * permissions of the new mode. As a special case, 531 * if the ACE matches the current owner of the file, 532 * the owner bits are used, rather than the group bits. 533 * This is reflected in the algorithm below. 534 */ 535 amode = mode >> 3; 536 537 /* 538 * If ACE4_IDENTIFIER_GROUP is not set, and the "who" field 539 * in ACE matches the owner of the file, we shift amode three 540 * more bits, in order to have the owner permission bits 541 * placed in the three low order bits of amode. 542 */ 543 if (entry->ae_tag == ACL_USER && entry->ae_id == file_owner_id) 544 amode = amode >> 3; 545 546 if (entry->ae_perm & ACL_READ_DATA) { 547 if (amode & READ) 548 previous->ae_perm &= ~ACL_READ_DATA; 549 else 550 previous->ae_perm |= ACL_READ_DATA; 551 } 552 553 if (entry->ae_perm & ACL_WRITE_DATA) { 554 if (amode & WRITE) 555 previous->ae_perm &= ~ACL_WRITE_DATA; 556 else 557 previous->ae_perm |= ACL_WRITE_DATA; 558 } 559 560 if (entry->ae_perm & ACL_APPEND_DATA) { 561 if (amode & WRITE) 562 previous->ae_perm &= ~ACL_APPEND_DATA; 563 else 564 previous->ae_perm |= ACL_APPEND_DATA; 565 } 566 567 if (entry->ae_perm & ACL_EXECUTE) { 568 if (amode & EXEC) 569 previous->ae_perm &= ~ACL_EXECUTE; 570 else 571 previous->ae_perm |= ACL_EXECUTE; 572 } 573 574 /* 575 * 1.5.3. If ACE4_IDENTIFIER_GROUP is set in the flags 576 * of the ALLOW ace: 577 * 578 * XXX: This point is not there in the Falkner's draft. 579 */ 580 if (entry->ae_tag == ACL_GROUP && 581 entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) { 582 mode_t extramode, ownermode; 583 extramode = (mode >> 3) & 07; 584 ownermode = mode >> 6; 585 extramode &= ~ownermode; 586 587 if (extramode) { 588 if (extramode & READ) { 589 entry->ae_perm &= ~ACL_READ_DATA; 590 previous->ae_perm &= ~ACL_READ_DATA; 591 } 592 593 if (extramode & WRITE) { 594 entry->ae_perm &= 595 ~(ACL_WRITE_DATA | ACL_APPEND_DATA); 596 previous->ae_perm &= 597 ~(ACL_WRITE_DATA | ACL_APPEND_DATA); 598 } 599 600 if (extramode & EXEC) { 601 entry->ae_perm &= ~ACL_EXECUTE; 602 previous->ae_perm &= ~ACL_EXECUTE; 603 } 604 } 605 } 606 } 607 608 /* 609 * 2. If there at least six ACEs, the final six ACEs are examined. 610 * If they are not equal to what we want, append six ACEs. 611 */ 612 must_append = 0; 613 if (aclp->acl_cnt < 6) { 614 must_append = 1; 615 } else { 616 a6 = &(aclp->acl_entry[aclp->acl_cnt - 1]); 617 a5 = &(aclp->acl_entry[aclp->acl_cnt - 2]); 618 a4 = &(aclp->acl_entry[aclp->acl_cnt - 3]); 619 a3 = &(aclp->acl_entry[aclp->acl_cnt - 4]); 620 a2 = &(aclp->acl_entry[aclp->acl_cnt - 5]); 621 a1 = &(aclp->acl_entry[aclp->acl_cnt - 6]); 622 623 if (!_acl_entry_matches(a1, ACL_USER_OBJ, 0, 624 ACL_ENTRY_TYPE_DENY)) 625 must_append = 1; 626 if (!_acl_entry_matches(a2, ACL_USER_OBJ, ACL_WRITE_ACL | 627 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 628 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_ALLOW)) 629 must_append = 1; 630 if (!_acl_entry_matches(a3, ACL_GROUP_OBJ, 0, 631 ACL_ENTRY_TYPE_DENY)) 632 must_append = 1; 633 if (!_acl_entry_matches(a4, ACL_GROUP_OBJ, 0, 634 ACL_ENTRY_TYPE_ALLOW)) 635 must_append = 1; 636 if (!_acl_entry_matches(a5, ACL_EVERYONE, ACL_WRITE_ACL | 637 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 638 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_DENY)) 639 must_append = 1; 640 if (!_acl_entry_matches(a6, ACL_EVERYONE, ACL_READ_ACL | 641 ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | 642 ACL_SYNCHRONIZE, ACL_ENTRY_TYPE_ALLOW)) 643 must_append = 1; 644 } 645 646 if (must_append) { 647 KASSERT(aclp->acl_cnt + 6 <= ACL_MAX_ENTRIES, 648 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 649 650 a1 = _acl_append(aclp, ACL_USER_OBJ, 0, ACL_ENTRY_TYPE_DENY); 651 a2 = _acl_append(aclp, ACL_USER_OBJ, ACL_WRITE_ACL | 652 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 653 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_ALLOW); 654 a3 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_ENTRY_TYPE_DENY); 655 a4 = _acl_append(aclp, ACL_GROUP_OBJ, 0, ACL_ENTRY_TYPE_ALLOW); 656 a5 = _acl_append(aclp, ACL_EVERYONE, ACL_WRITE_ACL | 657 ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 658 ACL_WRITE_NAMED_ATTRS, ACL_ENTRY_TYPE_DENY); 659 a6 = _acl_append(aclp, ACL_EVERYONE, ACL_READ_ACL | 660 ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | 661 ACL_SYNCHRONIZE, ACL_ENTRY_TYPE_ALLOW); 662 663 KASSERT(a1 != NULL && a2 != NULL && a3 != NULL && a4 != NULL && 664 a5 != NULL && a6 != NULL, ("couldn't append to ACL.")); 665 } 666 667 /* 668 * 3. The final six ACEs are adjusted according to the incoming mode. 669 */ 670 if (mode & S_IRUSR) 671 a2->ae_perm |= ACL_READ_DATA; 672 else 673 a1->ae_perm |= ACL_READ_DATA; 674 if (mode & S_IWUSR) 675 a2->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 676 else 677 a1->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 678 if (mode & S_IXUSR) 679 a2->ae_perm |= ACL_EXECUTE; 680 else 681 a1->ae_perm |= ACL_EXECUTE; 682 683 if (mode & S_IRGRP) 684 a4->ae_perm |= ACL_READ_DATA; 685 else 686 a3->ae_perm |= ACL_READ_DATA; 687 if (mode & S_IWGRP) 688 a4->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 689 else 690 a3->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 691 if (mode & S_IXGRP) 692 a4->ae_perm |= ACL_EXECUTE; 693 else 694 a3->ae_perm |= ACL_EXECUTE; 695 696 if (mode & S_IROTH) 697 a6->ae_perm |= ACL_READ_DATA; 698 else 699 a5->ae_perm |= ACL_READ_DATA; 700 if (mode & S_IWOTH) 701 a6->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 702 else 703 a5->ae_perm |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 704 if (mode & S_IXOTH) 705 a6->ae_perm |= ACL_EXECUTE; 706 else 707 a5->ae_perm |= ACL_EXECUTE; 708 } 709 710 #ifdef _KERNEL 711 void 712 acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode, 713 int file_owner_id) 714 { 715 716 if (acl_nfs4_old_semantics) 717 acl_nfs4_sync_acl_from_mode_draft(aclp, mode, file_owner_id); 718 else 719 acl_nfs4_trivial_from_mode(aclp, mode); 720 } 721 #endif /* _KERNEL */ 722 723 void 724 acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp) 725 { 726 int i; 727 mode_t old_mode = *_mode, mode = 0, seen = 0; 728 const struct acl_entry *entry; 729 730 KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES, 731 ("aclp->acl_cnt <= ACL_MAX_ENTRIES")); 732 733 /* 734 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 735 * 736 * 3.16.6.1. Recomputing mode upon SETATTR of ACL 737 */ 738 739 for (i = 0; i < aclp->acl_cnt; i++) { 740 entry = &(aclp->acl_entry[i]); 741 742 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 743 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 744 continue; 745 746 if (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) 747 continue; 748 749 if (entry->ae_tag == ACL_USER_OBJ) { 750 if ((entry->ae_perm & ACL_READ_DATA) && 751 ((seen & S_IRUSR) == 0)) { 752 seen |= S_IRUSR; 753 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 754 mode |= S_IRUSR; 755 } 756 if ((entry->ae_perm & ACL_WRITE_DATA) && 757 ((seen & S_IWUSR) == 0)) { 758 seen |= S_IWUSR; 759 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 760 mode |= S_IWUSR; 761 } 762 if ((entry->ae_perm & ACL_EXECUTE) && 763 ((seen & S_IXUSR) == 0)) { 764 seen |= S_IXUSR; 765 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 766 mode |= S_IXUSR; 767 } 768 } else if (entry->ae_tag == ACL_GROUP_OBJ) { 769 if ((entry->ae_perm & ACL_READ_DATA) && 770 ((seen & S_IRGRP) == 0)) { 771 seen |= S_IRGRP; 772 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 773 mode |= S_IRGRP; 774 } 775 if ((entry->ae_perm & ACL_WRITE_DATA) && 776 ((seen & S_IWGRP) == 0)) { 777 seen |= S_IWGRP; 778 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 779 mode |= S_IWGRP; 780 } 781 if ((entry->ae_perm & ACL_EXECUTE) && 782 ((seen & S_IXGRP) == 0)) { 783 seen |= S_IXGRP; 784 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 785 mode |= S_IXGRP; 786 } 787 } else if (entry->ae_tag == ACL_EVERYONE) { 788 if (entry->ae_perm & ACL_READ_DATA) { 789 if ((seen & S_IRUSR) == 0) { 790 seen |= S_IRUSR; 791 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 792 mode |= S_IRUSR; 793 } 794 if ((seen & S_IRGRP) == 0) { 795 seen |= S_IRGRP; 796 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 797 mode |= S_IRGRP; 798 } 799 if ((seen & S_IROTH) == 0) { 800 seen |= S_IROTH; 801 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 802 mode |= S_IROTH; 803 } 804 } 805 if (entry->ae_perm & ACL_WRITE_DATA) { 806 if ((seen & S_IWUSR) == 0) { 807 seen |= S_IWUSR; 808 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 809 mode |= S_IWUSR; 810 } 811 if ((seen & S_IWGRP) == 0) { 812 seen |= S_IWGRP; 813 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 814 mode |= S_IWGRP; 815 } 816 if ((seen & S_IWOTH) == 0) { 817 seen |= S_IWOTH; 818 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 819 mode |= S_IWOTH; 820 } 821 } 822 if (entry->ae_perm & ACL_EXECUTE) { 823 if ((seen & S_IXUSR) == 0) { 824 seen |= S_IXUSR; 825 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 826 mode |= S_IXUSR; 827 } 828 if ((seen & S_IXGRP) == 0) { 829 seen |= S_IXGRP; 830 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 831 mode |= S_IXGRP; 832 } 833 if ((seen & S_IXOTH) == 0) { 834 seen |= S_IXOTH; 835 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 836 mode |= S_IXOTH; 837 } 838 } 839 } 840 } 841 842 *_mode = mode | (old_mode & ACL_PRESERVE_MASK); 843 } 844 845 #ifdef _KERNEL 846 /* 847 * Calculate inherited ACL in a manner compatible with NFSv4 Minor Version 1, 848 * draft-ietf-nfsv4-minorversion1-03.txt. 849 */ 850 static void 851 acl_nfs4_compute_inherited_acl_draft(const struct acl *parent_aclp, 852 struct acl *child_aclp, mode_t mode, int file_owner_id, 853 int is_directory) 854 { 855 int i, flags; 856 const struct acl_entry *parent_entry; 857 struct acl_entry *entry, *copy; 858 859 KASSERT(child_aclp->acl_cnt == 0, ("child_aclp->acl_cnt == 0")); 860 KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES, 861 ("parent_aclp->acl_cnt <= ACL_MAX_ENTRIES")); 862 863 /* 864 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 865 * 866 * 3.16.6.2. Applying the mode given to CREATE or OPEN 867 * to an inherited ACL 868 */ 869 870 /* 871 * 1. Form an ACL that is the concatenation of all inheritable ACEs. 872 */ 873 for (i = 0; i < parent_aclp->acl_cnt; i++) { 874 parent_entry = &(parent_aclp->acl_entry[i]); 875 flags = parent_entry->ae_flags; 876 877 /* 878 * Entry is not inheritable at all. 879 */ 880 if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT | 881 ACL_ENTRY_FILE_INHERIT)) == 0) 882 continue; 883 884 /* 885 * We're creating a file, but entry is not inheritable 886 * by files. 887 */ 888 if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0) 889 continue; 890 891 /* 892 * Entry is inheritable only by files, but has NO_PROPAGATE 893 * flag set, and we're creating a directory, so it wouldn't 894 * propagate to any file in that directory anyway. 895 */ 896 if (is_directory && 897 (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 && 898 (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)) 899 continue; 900 901 KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 902 ("child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 903 child_aclp->acl_entry[child_aclp->acl_cnt] = *parent_entry; 904 child_aclp->acl_cnt++; 905 } 906 907 /* 908 * 2. For each entry in the new ACL, adjust its flags, possibly 909 * creating two entries in place of one. 910 */ 911 for (i = 0; i < child_aclp->acl_cnt; i++) { 912 entry = &(child_aclp->acl_entry[i]); 913 914 /* 915 * This is not in the specification, but SunOS 916 * apparently does that. 917 */ 918 if (((entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT) || 919 !is_directory) && 920 entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 921 entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER); 922 923 /* 924 * 2.A. If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if the object 925 * being created is not a directory, then clear the 926 * following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT, 927 * ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT, 928 * ACL_ENTRY_INHERIT_ONLY. 929 */ 930 if (entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT || 931 !is_directory) { 932 entry->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | 933 ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | 934 ACL_ENTRY_INHERIT_ONLY); 935 936 /* 937 * Continue on to the next ACE. 938 */ 939 continue; 940 } 941 942 /* 943 * 2.B. If the object is a directory and ACL_ENTRY_FILE_INHERIT 944 * is set, but ACL_ENTRY_NO_PROPAGATE_INHERIT is not set, ensure 945 * that ACL_ENTRY_INHERIT_ONLY is set. Continue to the 946 * next ACE. Otherwise... 947 */ 948 /* 949 * XXX: Read it again and make sure what does the "otherwise" 950 * apply to. 951 */ 952 if (is_directory && 953 (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) && 954 ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) { 955 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 956 continue; 957 } 958 959 /* 960 * 2.C. If the type of the ACE is neither ALLOW nor deny, 961 * then continue. 962 */ 963 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 964 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 965 continue; 966 967 /* 968 * 2.D. Copy the original ACE into a second, adjacent ACE. 969 */ 970 copy = _acl_duplicate_entry(child_aclp, i); 971 972 /* 973 * 2.E. On the first ACE, ensure that ACL_ENTRY_INHERIT_ONLY 974 * is set. 975 */ 976 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 977 978 /* 979 * 2.F. On the second ACE, clear the following flags: 980 * ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_FILE_INHERIT, 981 * ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_INHERIT_ONLY. 982 */ 983 copy->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | 984 ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | 985 ACL_ENTRY_INHERIT_ONLY); 986 987 /* 988 * 2.G. On the second ACE, if the type is ALLOW, 989 * an implementation MAY clear the following 990 * mask bits: ACL_WRITE_ACL, ACL_WRITE_OWNER. 991 */ 992 if (copy->ae_entry_type == ACL_ENTRY_TYPE_ALLOW) 993 copy->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER); 994 995 /* 996 * Increment the counter to skip the copied entry. 997 */ 998 i++; 999 } 1000 1001 /* 1002 * 3. To ensure that the mode is honored, apply the algorithm describe 1003 * in Section 2.16.6.3, using the mode that is to be used for file 1004 * creation. 1005 */ 1006 acl_nfs4_sync_acl_from_mode(child_aclp, mode, file_owner_id); 1007 } 1008 #endif /* _KERNEL */ 1009 1010 /* 1011 * Populate the ACL with entries inherited from parent_aclp. 1012 */ 1013 static void 1014 acl_nfs4_inherit_entries(const struct acl *parent_aclp, 1015 struct acl *child_aclp, mode_t mode, int file_owner_id, 1016 int is_directory) 1017 { 1018 int i, flags, tag; 1019 const struct acl_entry *parent_entry; 1020 struct acl_entry *entry; 1021 1022 KASSERT(parent_aclp->acl_cnt <= ACL_MAX_ENTRIES, 1023 ("parent_aclp->acl_cnt <= ACL_MAX_ENTRIES")); 1024 1025 for (i = 0; i < parent_aclp->acl_cnt; i++) { 1026 parent_entry = &(parent_aclp->acl_entry[i]); 1027 flags = parent_entry->ae_flags; 1028 tag = parent_entry->ae_tag; 1029 1030 /* 1031 * Don't inherit owner@, group@, or everyone@ entries. 1032 */ 1033 if (tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || 1034 tag == ACL_EVERYONE) 1035 continue; 1036 1037 /* 1038 * Entry is not inheritable at all. 1039 */ 1040 if ((flags & (ACL_ENTRY_DIRECTORY_INHERIT | 1041 ACL_ENTRY_FILE_INHERIT)) == 0) 1042 continue; 1043 1044 /* 1045 * We're creating a file, but entry is not inheritable 1046 * by files. 1047 */ 1048 if (!is_directory && (flags & ACL_ENTRY_FILE_INHERIT) == 0) 1049 continue; 1050 1051 /* 1052 * Entry is inheritable only by files, but has NO_PROPAGATE 1053 * flag set, and we're creating a directory, so it wouldn't 1054 * propagate to any file in that directory anyway. 1055 */ 1056 if (is_directory && 1057 (flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0 && 1058 (flags & ACL_ENTRY_NO_PROPAGATE_INHERIT)) 1059 continue; 1060 1061 /* 1062 * Entry qualifies for being inherited. 1063 */ 1064 KASSERT(child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES, 1065 ("child_aclp->acl_cnt + 1 <= ACL_MAX_ENTRIES")); 1066 entry = &(child_aclp->acl_entry[child_aclp->acl_cnt]); 1067 *entry = *parent_entry; 1068 child_aclp->acl_cnt++; 1069 1070 entry->ae_flags &= ~ACL_ENTRY_INHERIT_ONLY; 1071 1072 /* 1073 * If the type of the ACE is neither ALLOW nor DENY, 1074 * then leave it as it is and proceed to the next one. 1075 */ 1076 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 1077 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 1078 continue; 1079 1080 /* 1081 * If the ACL_ENTRY_NO_PROPAGATE_INHERIT is set, or if 1082 * the object being created is not a directory, then clear 1083 * the following flags: ACL_ENTRY_NO_PROPAGATE_INHERIT, 1084 * ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT, 1085 * ACL_ENTRY_INHERIT_ONLY. 1086 */ 1087 if (entry->ae_flags & ACL_ENTRY_NO_PROPAGATE_INHERIT || 1088 !is_directory) { 1089 entry->ae_flags &= ~(ACL_ENTRY_NO_PROPAGATE_INHERIT | 1090 ACL_ENTRY_FILE_INHERIT | ACL_ENTRY_DIRECTORY_INHERIT | 1091 ACL_ENTRY_INHERIT_ONLY); 1092 } 1093 1094 /* 1095 * If the object is a directory and ACL_ENTRY_FILE_INHERIT 1096 * is set, but ACL_ENTRY_DIRECTORY_INHERIT is not set, ensure 1097 * that ACL_ENTRY_INHERIT_ONLY is set. 1098 */ 1099 if (is_directory && 1100 (entry->ae_flags & ACL_ENTRY_FILE_INHERIT) && 1101 ((entry->ae_flags & ACL_ENTRY_DIRECTORY_INHERIT) == 0)) { 1102 entry->ae_flags |= ACL_ENTRY_INHERIT_ONLY; 1103 } 1104 1105 if (entry->ae_entry_type == ACL_ENTRY_TYPE_ALLOW && 1106 (entry->ae_flags & ACL_ENTRY_INHERIT_ONLY) == 0) { 1107 /* 1108 * Some permissions must never be inherited. 1109 */ 1110 entry->ae_perm &= ~(ACL_WRITE_ACL | ACL_WRITE_OWNER | 1111 ACL_WRITE_NAMED_ATTRS | ACL_WRITE_ATTRIBUTES); 1112 1113 /* 1114 * Others must be masked according to the file mode. 1115 */ 1116 if ((mode & S_IRGRP) == 0) 1117 entry->ae_perm &= ~ACL_READ_DATA; 1118 if ((mode & S_IWGRP) == 0) 1119 entry->ae_perm &= 1120 ~(ACL_WRITE_DATA | ACL_APPEND_DATA); 1121 if ((mode & S_IXGRP) == 0) 1122 entry->ae_perm &= ~ACL_EXECUTE; 1123 } 1124 } 1125 } 1126 1127 /* 1128 * Calculate inherited ACL in a manner compatible with PSARC/2010/029. 1129 * It's also being used to calculate a trivial ACL, by inheriting from 1130 * a NULL ACL. 1131 */ 1132 static void 1133 acl_nfs4_compute_inherited_acl_psarc(const struct acl *parent_aclp, 1134 struct acl *aclp, mode_t mode, int file_owner_id, int is_directory) 1135 { 1136 acl_perm_t user_allow_first = 0, user_deny = 0, group_deny = 0; 1137 acl_perm_t user_allow, group_allow, everyone_allow; 1138 1139 KASSERT(aclp->acl_cnt == 0, ("aclp->acl_cnt == 0")); 1140 1141 user_allow = group_allow = everyone_allow = ACL_READ_ACL | 1142 ACL_READ_ATTRIBUTES | ACL_READ_NAMED_ATTRS | ACL_SYNCHRONIZE; 1143 user_allow |= ACL_WRITE_ACL | ACL_WRITE_OWNER | ACL_WRITE_ATTRIBUTES | 1144 ACL_WRITE_NAMED_ATTRS; 1145 1146 if (mode & S_IRUSR) 1147 user_allow |= ACL_READ_DATA; 1148 if (mode & S_IWUSR) 1149 user_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 1150 if (mode & S_IXUSR) 1151 user_allow |= ACL_EXECUTE; 1152 1153 if (mode & S_IRGRP) 1154 group_allow |= ACL_READ_DATA; 1155 if (mode & S_IWGRP) 1156 group_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 1157 if (mode & S_IXGRP) 1158 group_allow |= ACL_EXECUTE; 1159 1160 if (mode & S_IROTH) 1161 everyone_allow |= ACL_READ_DATA; 1162 if (mode & S_IWOTH) 1163 everyone_allow |= (ACL_WRITE_DATA | ACL_APPEND_DATA); 1164 if (mode & S_IXOTH) 1165 everyone_allow |= ACL_EXECUTE; 1166 1167 user_deny = ((group_allow | everyone_allow) & ~user_allow); 1168 group_deny = everyone_allow & ~group_allow; 1169 user_allow_first = group_deny & ~user_deny; 1170 1171 if (user_allow_first != 0) 1172 _acl_append(aclp, ACL_USER_OBJ, user_allow_first, 1173 ACL_ENTRY_TYPE_ALLOW); 1174 if (user_deny != 0) 1175 _acl_append(aclp, ACL_USER_OBJ, user_deny, 1176 ACL_ENTRY_TYPE_DENY); 1177 if (group_deny != 0) 1178 _acl_append(aclp, ACL_GROUP_OBJ, group_deny, 1179 ACL_ENTRY_TYPE_DENY); 1180 1181 if (parent_aclp != NULL) 1182 acl_nfs4_inherit_entries(parent_aclp, aclp, mode, 1183 file_owner_id, is_directory); 1184 1185 _acl_append(aclp, ACL_USER_OBJ, user_allow, ACL_ENTRY_TYPE_ALLOW); 1186 _acl_append(aclp, ACL_GROUP_OBJ, group_allow, ACL_ENTRY_TYPE_ALLOW); 1187 _acl_append(aclp, ACL_EVERYONE, everyone_allow, ACL_ENTRY_TYPE_ALLOW); 1188 } 1189 1190 #ifdef _KERNEL 1191 void 1192 acl_nfs4_compute_inherited_acl(const struct acl *parent_aclp, 1193 struct acl *child_aclp, mode_t mode, int file_owner_id, 1194 int is_directory) 1195 { 1196 1197 if (acl_nfs4_old_semantics) 1198 acl_nfs4_compute_inherited_acl_draft(parent_aclp, child_aclp, 1199 mode, file_owner_id, is_directory); 1200 else 1201 acl_nfs4_compute_inherited_acl_psarc(parent_aclp, child_aclp, 1202 mode, file_owner_id, is_directory); 1203 } 1204 #endif /* _KERNEL */ 1205 1206 /* 1207 * Calculate trivial ACL in a manner compatible with PSARC/2010/029. 1208 * Note that this results in an ACL different from (but semantically 1209 * equal to) the "canonical six" trivial ACL computed using algorithm 1210 * described in draft-ietf-nfsv4-minorversion1-03.txt, 3.16.6.2. 1211 */ 1212 static void 1213 acl_nfs4_trivial_from_mode(struct acl *aclp, mode_t mode) 1214 { 1215 1216 aclp->acl_cnt = 0; 1217 acl_nfs4_compute_inherited_acl_psarc(NULL, aclp, mode, -1, -1); 1218 } 1219 1220 #ifndef _KERNEL 1221 /* 1222 * This routine is used by libc to implement acl_strip_np(3) 1223 * and acl_is_trivial_np(3). 1224 */ 1225 void 1226 acl_nfs4_trivial_from_mode_libc(struct acl *aclp, int mode, int canonical_six) 1227 { 1228 1229 aclp->acl_cnt = 0; 1230 if (canonical_six) 1231 acl_nfs4_sync_acl_from_mode_draft(aclp, mode, -1); 1232 else 1233 acl_nfs4_trivial_from_mode(aclp, mode); 1234 } 1235 #endif /* !_KERNEL */ 1236 1237 #ifdef _KERNEL 1238 static int 1239 _acls_are_equal(const struct acl *a, const struct acl *b) 1240 { 1241 int i; 1242 const struct acl_entry *entrya, *entryb; 1243 1244 if (a->acl_cnt != b->acl_cnt) 1245 return (0); 1246 1247 for (i = 0; i < b->acl_cnt; i++) { 1248 entrya = &(a->acl_entry[i]); 1249 entryb = &(b->acl_entry[i]); 1250 1251 if (entrya->ae_tag != entryb->ae_tag || 1252 entrya->ae_id != entryb->ae_id || 1253 entrya->ae_perm != entryb->ae_perm || 1254 entrya->ae_entry_type != entryb->ae_entry_type || 1255 entrya->ae_flags != entryb->ae_flags) 1256 return (0); 1257 } 1258 1259 return (1); 1260 } 1261 1262 /* 1263 * This routine is used to determine whether to remove extended attribute 1264 * that stores ACL contents. 1265 */ 1266 int 1267 acl_nfs4_is_trivial(const struct acl *aclp, int file_owner_id) 1268 { 1269 int trivial; 1270 mode_t tmpmode = 0; 1271 struct acl *tmpaclp; 1272 1273 if (aclp->acl_cnt > 6) 1274 return (0); 1275 1276 /* 1277 * Compute the mode from the ACL, then compute new ACL from that mode. 1278 * If the ACLs are identical, then the ACL is trivial. 1279 * 1280 * XXX: I guess there is a faster way to do this. However, even 1281 * this slow implementation significantly speeds things up 1282 * for files that don't have non-trivial ACLs - it's critical 1283 * for performance to not use EA when they are not needed. 1284 * 1285 * First try the PSARC/2010/029 semantics. 1286 */ 1287 tmpaclp = acl_alloc(M_WAITOK | M_ZERO); 1288 acl_nfs4_sync_mode_from_acl(&tmpmode, aclp); 1289 acl_nfs4_trivial_from_mode(tmpaclp, tmpmode); 1290 trivial = _acls_are_equal(aclp, tmpaclp); 1291 if (trivial) { 1292 acl_free(tmpaclp); 1293 return (trivial); 1294 } 1295 1296 /* 1297 * Check if it's a draft-ietf-nfsv4-minorversion1-03.txt trivial ACL. 1298 */ 1299 tmpaclp->acl_cnt = 0; 1300 acl_nfs4_sync_acl_from_mode_draft(tmpaclp, tmpmode, file_owner_id); 1301 trivial = _acls_are_equal(aclp, tmpaclp); 1302 acl_free(tmpaclp); 1303 1304 return (trivial); 1305 } 1306 #endif /* _KERNEL */ 1307 1308 int 1309 acl_nfs4_check(const struct acl *aclp, int is_directory) 1310 { 1311 int i; 1312 const struct acl_entry *entry; 1313 1314 /* 1315 * The spec doesn't seem to say anything about ACL validity. 1316 * It seems there is not much to do here. There is even no need 1317 * to count "owner@" or "everyone@" (ACL_USER_OBJ and ACL_EVERYONE) 1318 * entries, as there can be several of them and that's perfectly 1319 * valid. There can be none of them too. Really. 1320 */ 1321 1322 if (aclp->acl_cnt > ACL_MAX_ENTRIES || aclp->acl_cnt <= 0) 1323 return (EINVAL); 1324 1325 for (i = 0; i < aclp->acl_cnt; i++) { 1326 entry = &(aclp->acl_entry[i]); 1327 1328 switch (entry->ae_tag) { 1329 case ACL_USER_OBJ: 1330 case ACL_GROUP_OBJ: 1331 case ACL_EVERYONE: 1332 if (entry->ae_id != ACL_UNDEFINED_ID) 1333 return (EINVAL); 1334 break; 1335 1336 case ACL_USER: 1337 case ACL_GROUP: 1338 if (entry->ae_id == ACL_UNDEFINED_ID) 1339 return (EINVAL); 1340 break; 1341 1342 default: 1343 return (EINVAL); 1344 } 1345 1346 if ((entry->ae_perm | ACL_NFS4_PERM_BITS) != ACL_NFS4_PERM_BITS) 1347 return (EINVAL); 1348 1349 /* 1350 * Disallow ACL_ENTRY_TYPE_AUDIT and ACL_ENTRY_TYPE_ALARM for now. 1351 */ 1352 if (entry->ae_entry_type != ACL_ENTRY_TYPE_ALLOW && 1353 entry->ae_entry_type != ACL_ENTRY_TYPE_DENY) 1354 return (EINVAL); 1355 1356 if ((entry->ae_flags | ACL_FLAGS_BITS) != ACL_FLAGS_BITS) 1357 return (EINVAL); 1358 1359 /* Disallow unimplemented flags. */ 1360 if (entry->ae_flags & (ACL_ENTRY_SUCCESSFUL_ACCESS | 1361 ACL_ENTRY_FAILED_ACCESS)) 1362 return (EINVAL); 1363 1364 /* Disallow flags not allowed for ordinary files. */ 1365 if (!is_directory) { 1366 if (entry->ae_flags & (ACL_ENTRY_FILE_INHERIT | 1367 ACL_ENTRY_DIRECTORY_INHERIT | 1368 ACL_ENTRY_NO_PROPAGATE_INHERIT | ACL_ENTRY_INHERIT_ONLY)) 1369 return (EINVAL); 1370 } 1371 } 1372 1373 return (0); 1374 } 1375 1376 #ifdef _KERNEL 1377 static int 1378 acl_nfs4_modload(module_t module, int what, void *arg) 1379 { 1380 int ret; 1381 1382 ret = 0; 1383 1384 switch (what) { 1385 case MOD_LOAD: 1386 case MOD_SHUTDOWN: 1387 break; 1388 1389 case MOD_QUIESCE: 1390 /* XXX TODO */ 1391 ret = 0; 1392 break; 1393 1394 case MOD_UNLOAD: 1395 /* XXX TODO */ 1396 ret = 0; 1397 break; 1398 default: 1399 ret = EINVAL; 1400 break; 1401 } 1402 1403 return (ret); 1404 } 1405 1406 static moduledata_t acl_nfs4_mod = { 1407 "acl_nfs4", 1408 acl_nfs4_modload, 1409 NULL 1410 }; 1411 1412 /* 1413 * XXX TODO: which subsystem, order? 1414 */ 1415 DECLARE_MODULE(acl_nfs4, acl_nfs4_mod, SI_SUB_VFS, SI_ORDER_FIRST); 1416 MODULE_VERSION(acl_nfs4, 1); 1417 #endif /* _KERNEL */ 1418