1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24 * Copyright 2023 RackTop Systems, Inc. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/errno.h> 30 #include <sys/avl.h> 31 #if defined(_KERNEL) || defined(_FAKE_KERNEL) 32 #include <sys/debug.h> 33 #include <sys/kmem.h> 34 #include <sys/systm.h> 35 #include <sys/sysmacros.h> 36 #include <acl/acl_common.h> 37 #else 38 #include <errno.h> 39 #include <stdlib.h> 40 #include <stddef.h> 41 #include <strings.h> 42 #include <unistd.h> 43 #include <assert.h> 44 #include <grp.h> 45 #include <pwd.h> 46 #include <acl_common.h> 47 #define ASSERT assert 48 #endif 49 50 #define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \ 51 ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \ 52 ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL) 53 54 55 #define ACL_SYNCHRONIZE_SET_DENY 0x0000001 56 #define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002 57 #define ACL_SYNCHRONIZE_ERR_DENY 0x0000004 58 #define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008 59 60 #define ACL_WRITE_OWNER_SET_DENY 0x0000010 61 #define ACL_WRITE_OWNER_SET_ALLOW 0x0000020 62 #define ACL_WRITE_OWNER_ERR_DENY 0x0000040 63 #define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080 64 65 #define ACL_DELETE_SET_DENY 0x0000100 66 #define ACL_DELETE_SET_ALLOW 0x0000200 67 #define ACL_DELETE_ERR_DENY 0x0000400 68 #define ACL_DELETE_ERR_ALLOW 0x0000800 69 70 #define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000 71 #define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 72 #define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000 73 #define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000 74 75 #define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000 76 #define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000 77 #define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000 78 #define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000 79 80 #define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000 81 #define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000 82 #define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000 83 #define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000 84 85 #define ACL_READ_NAMED_READER_SET_DENY 0x1000000 86 #define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000 87 #define ACL_READ_NAMED_READER_ERR_DENY 0x4000000 88 #define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000 89 90 91 #define ACE_VALID_MASK_BITS (\ 92 ACE_READ_DATA | \ 93 ACE_LIST_DIRECTORY | \ 94 ACE_WRITE_DATA | \ 95 ACE_ADD_FILE | \ 96 ACE_APPEND_DATA | \ 97 ACE_ADD_SUBDIRECTORY | \ 98 ACE_READ_NAMED_ATTRS | \ 99 ACE_WRITE_NAMED_ATTRS | \ 100 ACE_EXECUTE | \ 101 ACE_DELETE_CHILD | \ 102 ACE_READ_ATTRIBUTES | \ 103 ACE_WRITE_ATTRIBUTES | \ 104 ACE_DELETE | \ 105 ACE_READ_ACL | \ 106 ACE_WRITE_ACL | \ 107 ACE_WRITE_OWNER | \ 108 ACE_SYNCHRONIZE) 109 110 #define ACE_MASK_UNDEFINED 0x80000000 111 112 #define ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \ 113 ACE_DIRECTORY_INHERIT_ACE | \ 114 ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \ 115 ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \ 116 ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE) 117 118 /* 119 * ACL conversion helpers 120 */ 121 122 typedef enum { 123 ace_unused, 124 ace_user_obj, 125 ace_user, 126 ace_group, /* includes GROUP and GROUP_OBJ */ 127 ace_other_obj 128 } ace_to_aent_state_t; 129 130 typedef struct acevals { 131 uid_t key; 132 avl_node_t avl; 133 uint32_t mask; 134 uint32_t allowed; 135 uint32_t denied; 136 int aent_type; 137 } acevals_t; 138 139 typedef struct ace_list { 140 acevals_t user_obj; 141 avl_tree_t user; 142 int numusers; 143 acevals_t group_obj; 144 avl_tree_t group; 145 int numgroups; 146 acevals_t other_obj; 147 uint32_t acl_mask; 148 int hasmask; 149 int dfacl_flag; 150 ace_to_aent_state_t state; 151 int seen; /* bitmask of all aclent_t a_type values seen */ 152 } ace_list_t; 153 154 /* 155 * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified. 156 * v = Ptr to array/vector of objs 157 * n = # objs in the array 158 * s = size of each obj (must be multiples of a word size) 159 * f = ptr to function to compare two objs 160 * returns (-1 = less than, 0 = equal, 1 = greater than 161 */ 162 void 163 ksort(caddr_t v, int n, int s, int (*f)()) 164 { 165 int g, i, j, ii; 166 unsigned int *p1, *p2; 167 unsigned int tmp; 168 169 /* No work to do */ 170 if (v == NULL || n <= 1) 171 return; 172 173 /* Sanity check on arguments */ 174 ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0); 175 ASSERT(s > 0); 176 for (g = n / 2; g > 0; g /= 2) { 177 for (i = g; i < n; i++) { 178 for (j = i - g; j >= 0 && 179 (*f)(v + j * s, v + (j + g) * s) == 1; 180 j -= g) { 181 p1 = (void *)(v + j * s); 182 p2 = (void *)(v + (j + g) * s); 183 for (ii = 0; ii < s / 4; ii++) { 184 tmp = *p1; 185 *p1++ = *p2; 186 *p2++ = tmp; 187 } 188 } 189 } 190 } 191 } 192 193 /* 194 * Compare two acls, all fields. Returns: 195 * -1 (less than) 196 * 0 (equal) 197 * +1 (greater than) 198 */ 199 int 200 cmp2acls(void *a, void *b) 201 { 202 aclent_t *x = (aclent_t *)a; 203 aclent_t *y = (aclent_t *)b; 204 205 /* Compare types */ 206 if (x->a_type < y->a_type) 207 return (-1); 208 if (x->a_type > y->a_type) 209 return (1); 210 /* Equal types; compare id's */ 211 if (x->a_id < y->a_id) 212 return (-1); 213 if (x->a_id > y->a_id) 214 return (1); 215 /* Equal ids; compare perms */ 216 if (x->a_perm < y->a_perm) 217 return (-1); 218 if (x->a_perm > y->a_perm) 219 return (1); 220 /* Totally equal */ 221 return (0); 222 } 223 224 /*ARGSUSED*/ 225 static void * 226 cacl_realloc(void *ptr, size_t size, size_t new_size) 227 { 228 #if defined(_KERNEL) || defined(_FAKE_KERNEL) 229 void *tmp; 230 231 tmp = kmem_alloc(new_size, KM_SLEEP); 232 (void) memcpy(tmp, ptr, (size < new_size) ? size : new_size); 233 kmem_free(ptr, size); 234 return (tmp); 235 #else 236 return (realloc(ptr, new_size)); 237 #endif 238 } 239 240 static int 241 cacl_malloc(void **ptr, size_t size) 242 { 243 #if defined(_KERNEL) || defined(_FAKE_KERNEL) 244 *ptr = kmem_zalloc(size, KM_SLEEP); 245 return (0); 246 #else 247 *ptr = calloc(1, size); 248 if (*ptr == NULL) 249 return (errno); 250 251 return (0); 252 #endif 253 } 254 255 /*ARGSUSED*/ 256 static void 257 cacl_free(void *ptr, size_t size) 258 { 259 #if defined(_KERNEL) || defined(_FAKE_KERNEL) 260 kmem_free(ptr, size); 261 #else 262 free(ptr); 263 #endif 264 } 265 266 acl_t * 267 acl_alloc(enum acl_type type) 268 { 269 acl_t *aclp; 270 271 if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0) 272 return (NULL); 273 274 aclp->acl_aclp = NULL; 275 aclp->acl_cnt = 0; 276 277 switch (type) { 278 case ACE_T: 279 aclp->acl_type = ACE_T; 280 aclp->acl_entry_size = sizeof (ace_t); 281 break; 282 case ACLENT_T: 283 aclp->acl_type = ACLENT_T; 284 aclp->acl_entry_size = sizeof (aclent_t); 285 break; 286 default: 287 acl_free(aclp); 288 aclp = NULL; 289 } 290 return (aclp); 291 } 292 293 /* 294 * Free acl_t structure 295 */ 296 void 297 acl_free(acl_t *aclp) 298 { 299 int acl_size; 300 301 if (aclp == NULL) 302 return; 303 304 if (aclp->acl_aclp) { 305 acl_size = aclp->acl_cnt * aclp->acl_entry_size; 306 cacl_free(aclp->acl_aclp, acl_size); 307 } 308 309 cacl_free(aclp, sizeof (acl_t)); 310 } 311 312 static uint32_t 313 access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow) 314 { 315 uint32_t access_mask = 0; 316 int acl_produce; 317 int synchronize_set = 0, write_owner_set = 0; 318 int delete_set = 0, write_attrs_set = 0; 319 int read_named_set = 0, write_named_set = 0; 320 321 acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW | 322 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 323 ACL_WRITE_ATTRS_WRITER_SET_DENY); 324 325 if (isallow) { 326 synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; 327 write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; 328 delete_set = ACL_DELETE_SET_ALLOW; 329 if (hasreadperm) 330 read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; 331 if (haswriteperm) 332 write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 333 if (isowner) 334 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 335 else if (haswriteperm) 336 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 337 } else { 338 339 synchronize_set = ACL_SYNCHRONIZE_SET_DENY; 340 write_owner_set = ACL_WRITE_OWNER_SET_DENY; 341 delete_set = ACL_DELETE_SET_DENY; 342 if (hasreadperm) 343 read_named_set = ACL_READ_NAMED_READER_SET_DENY; 344 if (haswriteperm) 345 write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; 346 if (isowner) 347 write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; 348 else if (haswriteperm) 349 write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; 350 else 351 /* 352 * If the entity is not the owner and does not 353 * have write permissions ACE_WRITE_ATTRIBUTES will 354 * always go in the DENY ACE. 355 */ 356 access_mask |= ACE_WRITE_ATTRIBUTES; 357 } 358 359 if (acl_produce & synchronize_set) 360 access_mask |= ACE_SYNCHRONIZE; 361 if (acl_produce & write_owner_set) 362 access_mask |= ACE_WRITE_OWNER; 363 if (acl_produce & delete_set) 364 access_mask |= ACE_DELETE; 365 if (acl_produce & write_attrs_set) 366 access_mask |= ACE_WRITE_ATTRIBUTES; 367 if (acl_produce & read_named_set) 368 access_mask |= ACE_READ_NAMED_ATTRS; 369 if (acl_produce & write_named_set) 370 access_mask |= ACE_WRITE_NAMED_ATTRS; 371 372 return (access_mask); 373 } 374 375 /* 376 * Given an mode_t, convert it into an access_mask as used 377 * by nfsace, assuming aclent_t -> nfsace semantics. 378 */ 379 static uint32_t 380 mode_to_ace_access(mode_t mode, boolean_t isdir, int isowner, int isallow) 381 { 382 uint32_t access = 0; 383 int haswriteperm = 0; 384 int hasreadperm = 0; 385 386 if (isallow) { 387 haswriteperm = (mode & S_IWOTH); 388 hasreadperm = (mode & S_IROTH); 389 } else { 390 haswriteperm = !(mode & S_IWOTH); 391 hasreadperm = !(mode & S_IROTH); 392 } 393 394 /* 395 * The following call takes care of correctly setting the following 396 * mask bits in the access_mask: 397 * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE, 398 * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS 399 */ 400 access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow); 401 402 if (isallow) { 403 access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES; 404 if (isowner) 405 access |= ACE_WRITE_ACL; 406 } else { 407 if (! isowner) 408 access |= ACE_WRITE_ACL; 409 } 410 411 /* read */ 412 if (mode & S_IROTH) { 413 access |= ACE_READ_DATA; 414 } 415 /* write */ 416 if (mode & S_IWOTH) { 417 access |= ACE_WRITE_DATA | 418 ACE_APPEND_DATA; 419 if (isdir) 420 access |= ACE_DELETE_CHILD; 421 } 422 /* exec */ 423 if (mode & S_IXOTH) { 424 access |= ACE_EXECUTE; 425 } 426 427 return (access); 428 } 429 430 /* 431 * Given an nfsace (presumably an ALLOW entry), make a 432 * corresponding DENY entry at the address given. 433 */ 434 static void 435 ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner) 436 { 437 (void) memcpy(deny, allow, sizeof (ace_t)); 438 439 deny->a_who = allow->a_who; 440 441 deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 442 deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS; 443 if (isdir) 444 deny->a_access_mask ^= ACE_DELETE_CHILD; 445 446 deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER | 447 ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS | 448 ACE_WRITE_NAMED_ATTRS); 449 deny->a_access_mask |= access_mask_set((allow->a_access_mask & 450 ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner, 451 B_FALSE); 452 } 453 /* 454 * Make an initial pass over an array of aclent_t's. Gather 455 * information such as an ACL_MASK (if any), number of users, 456 * number of groups, and whether the array needs to be sorted. 457 */ 458 static int 459 ln_aent_preprocess(aclent_t *aclent, int n, 460 int *hasmask, mode_t *mask, 461 int *numuser, int *numgroup, int *needsort) 462 { 463 int error = 0; 464 int i; 465 int curtype = 0; 466 467 *hasmask = 0; 468 *mask = 07; 469 *needsort = 0; 470 *numuser = 0; 471 *numgroup = 0; 472 473 for (i = 0; i < n; i++) { 474 if (aclent[i].a_type < curtype) 475 *needsort = 1; 476 else if (aclent[i].a_type > curtype) 477 curtype = aclent[i].a_type; 478 if (aclent[i].a_type & USER) 479 (*numuser)++; 480 if (aclent[i].a_type & (GROUP | GROUP_OBJ)) 481 (*numgroup)++; 482 if (aclent[i].a_type & CLASS_OBJ) { 483 if (*hasmask) { 484 error = EINVAL; 485 goto out; 486 } else { 487 *hasmask = 1; 488 *mask = aclent[i].a_perm; 489 } 490 } 491 } 492 493 if ((! *hasmask) && (*numuser + *numgroup > 1)) { 494 error = EINVAL; 495 goto out; 496 } 497 498 out: 499 return (error); 500 } 501 502 /* 503 * Convert an array of aclent_t into an array of nfsace entries, 504 * following POSIX draft -> nfsv4 conversion semantics as outlined in 505 * the IETF draft. 506 */ 507 static int 508 ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir) 509 { 510 int error = 0; 511 mode_t mask; 512 int numuser, numgroup, needsort; 513 int resultsize = 0; 514 int i, groupi = 0, skip; 515 ace_t *acep, *result = NULL; 516 int hasmask; 517 518 error = ln_aent_preprocess(aclent, n, &hasmask, &mask, 519 &numuser, &numgroup, &needsort); 520 if (error != 0) 521 goto out; 522 523 /* allow + deny for each aclent */ 524 resultsize = n * 2; 525 if (hasmask) { 526 /* 527 * stick extra deny on the group_obj and on each 528 * user|group for the mask (the group_obj was added 529 * into the count for numgroup) 530 */ 531 resultsize += numuser + numgroup; 532 /* ... and don't count the mask itself */ 533 resultsize -= 2; 534 } 535 536 /* sort the source if necessary */ 537 if (needsort) 538 ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); 539 540 if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0) 541 goto out; 542 543 acep = result; 544 545 for (i = 0; i < n; i++) { 546 /* 547 * don't process CLASS_OBJ (mask); mask was grabbed in 548 * ln_aent_preprocess() 549 */ 550 if (aclent[i].a_type & CLASS_OBJ) 551 continue; 552 553 /* If we need an ACL_MASK emulator, prepend it now */ 554 if ((hasmask) && 555 (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { 556 acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 557 acep->a_flags = 0; 558 if (aclent[i].a_type & GROUP_OBJ) { 559 acep->a_who = (uid_t)-1; 560 acep->a_flags |= 561 (ACE_IDENTIFIER_GROUP|ACE_GROUP); 562 } else if (aclent[i].a_type & USER) { 563 acep->a_who = aclent[i].a_id; 564 } else { 565 acep->a_who = aclent[i].a_id; 566 acep->a_flags |= ACE_IDENTIFIER_GROUP; 567 } 568 if (aclent[i].a_type & ACL_DEFAULT) { 569 acep->a_flags |= ACE_INHERIT_ONLY_ACE | 570 ACE_FILE_INHERIT_ACE | 571 ACE_DIRECTORY_INHERIT_ACE; 572 } 573 /* 574 * Set the access mask for the prepended deny 575 * ace. To do this, we invert the mask (found 576 * in ln_aent_preprocess()) then convert it to an 577 * DENY ace access_mask. 578 */ 579 acep->a_access_mask = mode_to_ace_access((mask ^ 07), 580 isdir, 0, 0); 581 acep += 1; 582 } 583 584 /* handle a_perm -> access_mask */ 585 acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm, 586 isdir, aclent[i].a_type & USER_OBJ, 1); 587 588 /* emulate a default aclent */ 589 if (aclent[i].a_type & ACL_DEFAULT) { 590 acep->a_flags |= ACE_INHERIT_ONLY_ACE | 591 ACE_FILE_INHERIT_ACE | 592 ACE_DIRECTORY_INHERIT_ACE; 593 } 594 595 /* 596 * handle a_perm and a_id 597 * 598 * this must be done last, since it involves the 599 * corresponding deny aces, which are handled 600 * differently for each different a_type. 601 */ 602 if (aclent[i].a_type & USER_OBJ) { 603 acep->a_who = (uid_t)-1; 604 acep->a_flags |= ACE_OWNER; 605 ace_make_deny(acep, acep + 1, isdir, B_TRUE); 606 acep += 2; 607 } else if (aclent[i].a_type & USER) { 608 acep->a_who = aclent[i].a_id; 609 ace_make_deny(acep, acep + 1, isdir, B_FALSE); 610 acep += 2; 611 } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { 612 if (aclent[i].a_type & GROUP_OBJ) { 613 acep->a_who = (uid_t)-1; 614 acep->a_flags |= ACE_GROUP; 615 } else { 616 acep->a_who = aclent[i].a_id; 617 } 618 acep->a_flags |= ACE_IDENTIFIER_GROUP; 619 /* 620 * Set the corresponding deny for the group ace. 621 * 622 * The deny aces go after all of the groups, unlike 623 * everything else, where they immediately follow 624 * the allow ace. 625 * 626 * We calculate "skip", the number of slots to 627 * skip ahead for the deny ace, here. 628 * 629 * The pattern is: 630 * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 631 * thus, skip is 632 * (2 * numgroup) - 1 - groupi 633 * (2 * numgroup) to account for MD + A 634 * - 1 to account for the fact that we're on the 635 * access (A), not the mask (MD) 636 * - groupi to account for the fact that we have 637 * passed up groupi number of MD's. 638 */ 639 skip = (2 * numgroup) - 1 - groupi; 640 ace_make_deny(acep, acep + skip, isdir, B_FALSE); 641 /* 642 * If we just did the last group, skip acep past 643 * all of the denies; else, just move ahead one. 644 */ 645 if (++groupi >= numgroup) 646 acep += numgroup + 1; 647 else 648 acep += 1; 649 } else if (aclent[i].a_type & OTHER_OBJ) { 650 acep->a_who = (uid_t)-1; 651 acep->a_flags |= ACE_EVERYONE; 652 ace_make_deny(acep, acep + 1, isdir, B_FALSE); 653 acep += 2; 654 } else { 655 error = EINVAL; 656 goto out; 657 } 658 } 659 660 *acepp = result; 661 *rescount = resultsize; 662 663 out: 664 if (error != 0) { 665 if ((result != NULL) && (resultsize > 0)) { 666 cacl_free(result, resultsize * sizeof (ace_t)); 667 } 668 } 669 670 return (error); 671 } 672 673 static int 674 convert_aent_to_ace(aclent_t *aclentp, int aclcnt, boolean_t isdir, 675 ace_t **retacep, int *retacecnt) 676 { 677 ace_t *acep; 678 ace_t *dfacep; 679 int acecnt = 0; 680 int dfacecnt = 0; 681 int dfaclstart = 0; 682 int dfaclcnt = 0; 683 aclent_t *aclp; 684 int i; 685 int error; 686 int acesz, dfacesz; 687 688 ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls); 689 690 for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) { 691 if (aclp->a_type & ACL_DEFAULT) 692 break; 693 } 694 695 if (i < aclcnt) { 696 dfaclstart = i; 697 dfaclcnt = aclcnt - i; 698 } 699 700 if (dfaclcnt && !isdir) { 701 return (EINVAL); 702 } 703 704 error = ln_aent_to_ace(aclentp, i, &acep, &acecnt, isdir); 705 if (error) 706 return (error); 707 708 if (dfaclcnt) { 709 error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt, 710 &dfacep, &dfacecnt, isdir); 711 if (error) { 712 if (acep) { 713 cacl_free(acep, acecnt * sizeof (ace_t)); 714 } 715 return (error); 716 } 717 } 718 719 if (dfacecnt != 0) { 720 acesz = sizeof (ace_t) * acecnt; 721 dfacesz = sizeof (ace_t) * dfacecnt; 722 acep = cacl_realloc(acep, acesz, acesz + dfacesz); 723 if (acep == NULL) 724 return (ENOMEM); 725 if (dfaclcnt) { 726 (void) memcpy(acep + acecnt, dfacep, dfacesz); 727 } 728 } 729 if (dfaclcnt) 730 cacl_free(dfacep, dfacecnt * sizeof (ace_t)); 731 732 *retacecnt = acecnt + dfacecnt; 733 *retacep = acep; 734 return (0); 735 } 736 737 static int 738 ace_mask_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir) 739 { 740 int error = 0; 741 o_mode_t mode = 0; 742 uint32_t bits, wantbits; 743 744 /* read */ 745 if (mask & ACE_READ_DATA) 746 mode |= S_IROTH; 747 748 /* write */ 749 wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA); 750 if (isdir) 751 wantbits |= ACE_DELETE_CHILD; 752 bits = mask & wantbits; 753 if (bits != 0) { 754 if (bits != wantbits) { 755 error = ENOTSUP; 756 goto out; 757 } 758 mode |= S_IWOTH; 759 } 760 761 /* exec */ 762 if (mask & ACE_EXECUTE) { 763 mode |= S_IXOTH; 764 } 765 766 *modep = mode; 767 768 out: 769 return (error); 770 } 771 772 static void 773 acevals_init(acevals_t *vals, uid_t key) 774 { 775 bzero(vals, sizeof (*vals)); 776 vals->allowed = ACE_MASK_UNDEFINED; 777 vals->denied = ACE_MASK_UNDEFINED; 778 vals->mask = ACE_MASK_UNDEFINED; 779 vals->key = key; 780 } 781 782 static void 783 ace_list_init(ace_list_t *al, int dfacl_flag) 784 { 785 acevals_init(&al->user_obj, 0); 786 acevals_init(&al->group_obj, 0); 787 acevals_init(&al->other_obj, 0); 788 al->numusers = 0; 789 al->numgroups = 0; 790 al->acl_mask = 0; 791 al->hasmask = 0; 792 al->state = ace_unused; 793 al->seen = 0; 794 al->dfacl_flag = dfacl_flag; 795 } 796 797 /* 798 * Find or create an acevals holder for a given id and avl tree. 799 * 800 * Note that only one thread will ever touch these avl trees, so 801 * there is no need for locking. 802 */ 803 static acevals_t * 804 acevals_find(ace_t *ace, avl_tree_t *avl, int *num) 805 { 806 acevals_t key, *rc; 807 avl_index_t where; 808 809 key.key = ace->a_who; 810 rc = avl_find(avl, &key, &where); 811 if (rc != NULL) 812 return (rc); 813 814 /* this memory is freed by ln_ace_to_aent()->ace_list_free() */ 815 if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0) 816 return (NULL); 817 818 acevals_init(rc, ace->a_who); 819 avl_insert(avl, rc, where); 820 (*num)++; 821 822 return (rc); 823 } 824 825 static int 826 access_mask_check(ace_t *acep, int mask_bit, int isowner) 827 { 828 int set_deny, err_deny; 829 int set_allow, err_allow; 830 int acl_consume; 831 int haswriteperm, hasreadperm; 832 833 if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { 834 haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1; 835 hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1; 836 } else { 837 haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0; 838 hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0; 839 } 840 841 acl_consume = (ACL_SYNCHRONIZE_ERR_DENY | 842 ACL_DELETE_ERR_DENY | 843 ACL_WRITE_OWNER_ERR_DENY | 844 ACL_WRITE_OWNER_ERR_ALLOW | 845 ACL_WRITE_ATTRS_OWNER_SET_ALLOW | 846 ACL_WRITE_ATTRS_OWNER_ERR_DENY | 847 ACL_WRITE_ATTRS_WRITER_SET_DENY | 848 ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | 849 ACL_WRITE_NAMED_WRITER_ERR_DENY | 850 ACL_READ_NAMED_READER_ERR_DENY); 851 852 if (mask_bit == ACE_SYNCHRONIZE) { 853 set_deny = ACL_SYNCHRONIZE_SET_DENY; 854 err_deny = ACL_SYNCHRONIZE_ERR_DENY; 855 set_allow = ACL_SYNCHRONIZE_SET_ALLOW; 856 err_allow = ACL_SYNCHRONIZE_ERR_ALLOW; 857 } else if (mask_bit == ACE_WRITE_OWNER) { 858 set_deny = ACL_WRITE_OWNER_SET_DENY; 859 err_deny = ACL_WRITE_OWNER_ERR_DENY; 860 set_allow = ACL_WRITE_OWNER_SET_ALLOW; 861 err_allow = ACL_WRITE_OWNER_ERR_ALLOW; 862 } else if (mask_bit == ACE_DELETE) { 863 set_deny = ACL_DELETE_SET_DENY; 864 err_deny = ACL_DELETE_ERR_DENY; 865 set_allow = ACL_DELETE_SET_ALLOW; 866 err_allow = ACL_DELETE_ERR_ALLOW; 867 } else if (mask_bit == ACE_WRITE_ATTRIBUTES) { 868 if (isowner) { 869 set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY; 870 err_deny = ACL_WRITE_ATTRS_OWNER_ERR_DENY; 871 set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; 872 err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW; 873 } else if (haswriteperm) { 874 set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY; 875 err_deny = ACL_WRITE_ATTRS_WRITER_ERR_DENY; 876 set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; 877 err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW; 878 } else { 879 if (((acep->a_access_mask & mask_bit) != 0) && 880 (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE)) { 881 return (ENOTSUP); 882 } 883 return (0); 884 } 885 } else if (mask_bit == ACE_READ_NAMED_ATTRS) { 886 if (!hasreadperm) 887 return (0); 888 889 set_deny = ACL_READ_NAMED_READER_SET_DENY; 890 err_deny = ACL_READ_NAMED_READER_ERR_DENY; 891 set_allow = ACL_READ_NAMED_READER_SET_ALLOW; 892 err_allow = ACL_READ_NAMED_READER_ERR_ALLOW; 893 } else if (mask_bit == ACE_WRITE_NAMED_ATTRS) { 894 if (!haswriteperm) 895 return (0); 896 897 set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY; 898 err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY; 899 set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW; 900 err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW; 901 } else { 902 return (EINVAL); 903 } 904 905 if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { 906 if (acl_consume & set_deny) { 907 if (!(acep->a_access_mask & mask_bit)) { 908 return (ENOTSUP); 909 } 910 } else if (acl_consume & err_deny) { 911 if (acep->a_access_mask & mask_bit) { 912 return (ENOTSUP); 913 } 914 } 915 } else { 916 /* ACE_ACCESS_ALLOWED_ACE_TYPE */ 917 if (acl_consume & set_allow) { 918 if (!(acep->a_access_mask & mask_bit)) { 919 return (ENOTSUP); 920 } 921 } else if (acl_consume & err_allow) { 922 if (acep->a_access_mask & mask_bit) { 923 return (ENOTSUP); 924 } 925 } 926 } 927 return (0); 928 } 929 930 static int 931 ace_to_aent_legal(ace_t *acep) 932 { 933 int error = 0; 934 int isowner; 935 936 /* only ALLOW or DENY */ 937 if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) && 938 (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) { 939 error = ENOTSUP; 940 goto out; 941 } 942 943 /* check for invalid flags */ 944 if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) { 945 error = EINVAL; 946 goto out; 947 } 948 949 /* some flags are illegal */ 950 if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG | 951 ACE_FAILED_ACCESS_ACE_FLAG | 952 ACE_NO_PROPAGATE_INHERIT_ACE)) { 953 error = ENOTSUP; 954 goto out; 955 } 956 957 /* check for invalid masks */ 958 if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) { 959 error = EINVAL; 960 goto out; 961 } 962 963 if ((acep->a_flags & ACE_OWNER)) { 964 isowner = 1; 965 } else { 966 isowner = 0; 967 } 968 969 error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner); 970 if (error) 971 goto out; 972 973 error = access_mask_check(acep, ACE_WRITE_OWNER, isowner); 974 if (error) 975 goto out; 976 977 error = access_mask_check(acep, ACE_DELETE, isowner); 978 if (error) 979 goto out; 980 981 error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner); 982 if (error) 983 goto out; 984 985 error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner); 986 if (error) 987 goto out; 988 989 error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner); 990 if (error) 991 goto out; 992 993 /* more detailed checking of masks */ 994 if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 995 if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) { 996 error = ENOTSUP; 997 goto out; 998 } 999 if ((acep->a_access_mask & ACE_WRITE_DATA) && 1000 (! (acep->a_access_mask & ACE_APPEND_DATA))) { 1001 error = ENOTSUP; 1002 goto out; 1003 } 1004 if ((! (acep->a_access_mask & ACE_WRITE_DATA)) && 1005 (acep->a_access_mask & ACE_APPEND_DATA)) { 1006 error = ENOTSUP; 1007 goto out; 1008 } 1009 } 1010 1011 /* ACL enforcement */ 1012 if ((acep->a_access_mask & ACE_READ_ACL) && 1013 (acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE)) { 1014 error = ENOTSUP; 1015 goto out; 1016 } 1017 if (acep->a_access_mask & ACE_WRITE_ACL) { 1018 if ((acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) && 1019 (isowner)) { 1020 error = ENOTSUP; 1021 goto out; 1022 } 1023 if ((acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) && 1024 (! isowner)) { 1025 error = ENOTSUP; 1026 goto out; 1027 } 1028 } 1029 1030 out: 1031 return (error); 1032 } 1033 1034 static int 1035 ace_allow_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir) 1036 { 1037 /* ACE_READ_ACL and ACE_READ_ATTRIBUTES must both be set */ 1038 if ((mask & (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) != 1039 (ACE_READ_ACL | ACE_READ_ATTRIBUTES)) { 1040 return (ENOTSUP); 1041 } 1042 1043 return (ace_mask_to_mode(mask, modep, isdir)); 1044 } 1045 1046 static int 1047 acevals_to_aent(acevals_t *vals, aclent_t *dest, ace_list_t *list, 1048 uid_t owner, gid_t group, boolean_t isdir) 1049 { 1050 int error; 1051 uint32_t flips = ACE_POSIX_SUPPORTED_BITS; 1052 1053 if (isdir) 1054 flips |= ACE_DELETE_CHILD; 1055 if (vals->allowed != (vals->denied ^ flips)) { 1056 error = ENOTSUP; 1057 goto out; 1058 } 1059 if ((list->hasmask) && (list->acl_mask != vals->mask) && 1060 (vals->aent_type & (USER | GROUP | GROUP_OBJ))) { 1061 error = ENOTSUP; 1062 goto out; 1063 } 1064 error = ace_allow_to_mode(vals->allowed, &dest->a_perm, isdir); 1065 if (error != 0) 1066 goto out; 1067 dest->a_type = vals->aent_type; 1068 if (dest->a_type & (USER | GROUP)) { 1069 dest->a_id = vals->key; 1070 } else if (dest->a_type & USER_OBJ) { 1071 dest->a_id = owner; 1072 } else if (dest->a_type & GROUP_OBJ) { 1073 dest->a_id = group; 1074 } else if (dest->a_type & OTHER_OBJ) { 1075 dest->a_id = 0; 1076 } else { 1077 error = EINVAL; 1078 goto out; 1079 } 1080 1081 out: 1082 return (error); 1083 } 1084 1085 1086 static int 1087 ace_list_to_aent(ace_list_t *list, aclent_t **aclentp, int *aclcnt, 1088 uid_t owner, gid_t group, boolean_t isdir) 1089 { 1090 int error = 0; 1091 aclent_t *aent, *result = NULL; 1092 acevals_t *vals; 1093 int resultcount; 1094 1095 if ((list->seen & (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) != 1096 (USER_OBJ | GROUP_OBJ | OTHER_OBJ)) { 1097 return (ENOTSUP); 1098 } 1099 1100 if ((! list->hasmask) && (list->numusers + list->numgroups > 0)) { 1101 return (ENOTSUP); 1102 } 1103 1104 resultcount = 3 + list->numusers + list->numgroups; 1105 /* 1106 * This must be the same condition as below, when we add the CLASS_OBJ 1107 * (aka ACL mask) 1108 */ 1109 if ((list->hasmask) || (! list->dfacl_flag)) 1110 resultcount += 1; 1111 1112 if (cacl_malloc((void **)&result, 1113 resultcount * sizeof (aclent_t)) != 0) { 1114 error = ENOMEM; 1115 goto out; 1116 } 1117 aent = result; 1118 1119 /* USER_OBJ */ 1120 if (!(list->user_obj.aent_type & USER_OBJ)) { 1121 error = EINVAL; 1122 goto out; 1123 } 1124 1125 error = acevals_to_aent(&list->user_obj, aent, list, owner, group, 1126 isdir); 1127 1128 if (error != 0) 1129 goto out; 1130 ++aent; 1131 /* USER */ 1132 vals = NULL; 1133 for (vals = avl_first(&list->user); vals != NULL; 1134 vals = AVL_NEXT(&list->user, vals)) { 1135 if (!(vals->aent_type & USER)) { 1136 error = EINVAL; 1137 goto out; 1138 } 1139 error = acevals_to_aent(vals, aent, list, owner, group, 1140 isdir); 1141 if (error != 0) 1142 goto out; 1143 ++aent; 1144 } 1145 /* GROUP_OBJ */ 1146 if (!(list->group_obj.aent_type & GROUP_OBJ)) { 1147 error = EINVAL; 1148 goto out; 1149 } 1150 error = acevals_to_aent(&list->group_obj, aent, list, owner, group, 1151 isdir); 1152 if (error != 0) 1153 goto out; 1154 ++aent; 1155 /* GROUP */ 1156 vals = NULL; 1157 for (vals = avl_first(&list->group); vals != NULL; 1158 vals = AVL_NEXT(&list->group, vals)) { 1159 if (!(vals->aent_type & GROUP)) { 1160 error = EINVAL; 1161 goto out; 1162 } 1163 error = acevals_to_aent(vals, aent, list, owner, group, 1164 isdir); 1165 if (error != 0) 1166 goto out; 1167 ++aent; 1168 } 1169 /* 1170 * CLASS_OBJ (aka ACL_MASK) 1171 * 1172 * An ACL_MASK is not fabricated if the ACL is a default ACL. 1173 * This is to follow UFS's behavior. 1174 */ 1175 if ((list->hasmask) || (! list->dfacl_flag)) { 1176 if (list->hasmask) { 1177 uint32_t flips = ACE_POSIX_SUPPORTED_BITS; 1178 if (isdir) 1179 flips |= ACE_DELETE_CHILD; 1180 error = ace_mask_to_mode(list->acl_mask ^ flips, 1181 &aent->a_perm, isdir); 1182 if (error != 0) 1183 goto out; 1184 } else { 1185 /* fabricate the ACL_MASK from the group permissions */ 1186 error = ace_mask_to_mode(list->group_obj.allowed, 1187 &aent->a_perm, isdir); 1188 if (error != 0) 1189 goto out; 1190 } 1191 aent->a_id = 0; 1192 aent->a_type = CLASS_OBJ | list->dfacl_flag; 1193 ++aent; 1194 } 1195 /* OTHER_OBJ */ 1196 if (!(list->other_obj.aent_type & OTHER_OBJ)) { 1197 error = EINVAL; 1198 goto out; 1199 } 1200 error = acevals_to_aent(&list->other_obj, aent, list, owner, group, 1201 isdir); 1202 if (error != 0) 1203 goto out; 1204 ++aent; 1205 1206 *aclentp = result; 1207 *aclcnt = resultcount; 1208 1209 out: 1210 if (error != 0) { 1211 if (result != NULL) 1212 cacl_free(result, resultcount * sizeof (aclent_t)); 1213 } 1214 1215 return (error); 1216 } 1217 1218 1219 /* 1220 * free all data associated with an ace_list 1221 */ 1222 static void 1223 ace_list_free(ace_list_t *al) 1224 { 1225 acevals_t *node; 1226 void *cookie; 1227 1228 if (al == NULL) 1229 return; 1230 1231 cookie = NULL; 1232 while ((node = avl_destroy_nodes(&al->user, &cookie)) != NULL) 1233 cacl_free(node, sizeof (acevals_t)); 1234 cookie = NULL; 1235 while ((node = avl_destroy_nodes(&al->group, &cookie)) != NULL) 1236 cacl_free(node, sizeof (acevals_t)); 1237 1238 avl_destroy(&al->user); 1239 avl_destroy(&al->group); 1240 1241 /* free the container itself */ 1242 cacl_free(al, sizeof (ace_list_t)); 1243 } 1244 1245 static int 1246 acevals_compare(const void *va, const void *vb) 1247 { 1248 const acevals_t *a = va, *b = vb; 1249 1250 if (a->key == b->key) 1251 return (0); 1252 1253 if (a->key > b->key) 1254 return (1); 1255 1256 else 1257 return (-1); 1258 } 1259 1260 /* 1261 * Convert a list of ace_t entries to equivalent regular and default 1262 * aclent_t lists. Return error (ENOTSUP) when conversion is not possible. 1263 */ 1264 static int 1265 ln_ace_to_aent(ace_t *ace, int n, uid_t owner, gid_t group, 1266 aclent_t **aclentp, int *aclcnt, aclent_t **dfaclentp, int *dfaclcnt, 1267 boolean_t isdir) 1268 { 1269 int error = 0; 1270 ace_t *acep; 1271 uint32_t bits; 1272 int i; 1273 ace_list_t *normacl = NULL, *dfacl = NULL, *acl; 1274 acevals_t *vals; 1275 1276 *aclentp = NULL; 1277 *aclcnt = 0; 1278 *dfaclentp = NULL; 1279 *dfaclcnt = 0; 1280 1281 /* we need at least user_obj, group_obj, and other_obj */ 1282 if (n < 6) { 1283 error = ENOTSUP; 1284 goto out; 1285 } 1286 if (ace == NULL) { 1287 error = EINVAL; 1288 goto out; 1289 } 1290 1291 error = cacl_malloc((void **)&normacl, sizeof (ace_list_t)); 1292 if (error != 0) 1293 goto out; 1294 1295 avl_create(&normacl->user, acevals_compare, sizeof (acevals_t), 1296 offsetof(acevals_t, avl)); 1297 avl_create(&normacl->group, acevals_compare, sizeof (acevals_t), 1298 offsetof(acevals_t, avl)); 1299 1300 ace_list_init(normacl, 0); 1301 1302 error = cacl_malloc((void **)&dfacl, sizeof (ace_list_t)); 1303 if (error != 0) 1304 goto out; 1305 1306 avl_create(&dfacl->user, acevals_compare, sizeof (acevals_t), 1307 offsetof(acevals_t, avl)); 1308 avl_create(&dfacl->group, acevals_compare, sizeof (acevals_t), 1309 offsetof(acevals_t, avl)); 1310 ace_list_init(dfacl, ACL_DEFAULT); 1311 1312 /* process every ace_t... */ 1313 for (i = 0; i < n; i++) { 1314 acep = &ace[i]; 1315 1316 /* rule out certain cases quickly */ 1317 error = ace_to_aent_legal(acep); 1318 if (error != 0) 1319 goto out; 1320 1321 /* 1322 * Turn off these bits in order to not have to worry about 1323 * them when doing the checks for compliments. 1324 */ 1325 acep->a_access_mask &= ~(ACE_WRITE_OWNER | ACE_DELETE | 1326 ACE_SYNCHRONIZE | ACE_WRITE_ATTRIBUTES | 1327 ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS); 1328 1329 /* see if this should be a regular or default acl */ 1330 bits = acep->a_flags & 1331 (ACE_INHERIT_ONLY_ACE | 1332 ACE_FILE_INHERIT_ACE | 1333 ACE_DIRECTORY_INHERIT_ACE); 1334 if (bits != 0) { 1335 /* all or nothing on these inherit bits */ 1336 if (bits != (ACE_INHERIT_ONLY_ACE | 1337 ACE_FILE_INHERIT_ACE | 1338 ACE_DIRECTORY_INHERIT_ACE)) { 1339 error = ENOTSUP; 1340 goto out; 1341 } 1342 acl = dfacl; 1343 } else { 1344 acl = normacl; 1345 } 1346 1347 if ((acep->a_flags & ACE_OWNER)) { 1348 if (acl->state > ace_user_obj) { 1349 error = ENOTSUP; 1350 goto out; 1351 } 1352 acl->state = ace_user_obj; 1353 acl->seen |= USER_OBJ; 1354 vals = &acl->user_obj; 1355 vals->aent_type = USER_OBJ | acl->dfacl_flag; 1356 } else if ((acep->a_flags & ACE_EVERYONE)) { 1357 acl->state = ace_other_obj; 1358 acl->seen |= OTHER_OBJ; 1359 vals = &acl->other_obj; 1360 vals->aent_type = OTHER_OBJ | acl->dfacl_flag; 1361 } else if (acep->a_flags & ACE_IDENTIFIER_GROUP) { 1362 if (acl->state > ace_group) { 1363 error = ENOTSUP; 1364 goto out; 1365 } 1366 if ((acep->a_flags & ACE_GROUP)) { 1367 acl->seen |= GROUP_OBJ; 1368 vals = &acl->group_obj; 1369 vals->aent_type = GROUP_OBJ | acl->dfacl_flag; 1370 } else { 1371 acl->seen |= GROUP; 1372 vals = acevals_find(acep, &acl->group, 1373 &acl->numgroups); 1374 if (vals == NULL) { 1375 error = ENOMEM; 1376 goto out; 1377 } 1378 vals->aent_type = GROUP | acl->dfacl_flag; 1379 } 1380 acl->state = ace_group; 1381 } else { 1382 if (acl->state > ace_user) { 1383 error = ENOTSUP; 1384 goto out; 1385 } 1386 acl->state = ace_user; 1387 acl->seen |= USER; 1388 vals = acevals_find(acep, &acl->user, 1389 &acl->numusers); 1390 if (vals == NULL) { 1391 error = ENOMEM; 1392 goto out; 1393 } 1394 vals->aent_type = USER | acl->dfacl_flag; 1395 } 1396 1397 if (!(acl->state > ace_unused)) { 1398 error = EINVAL; 1399 goto out; 1400 } 1401 1402 if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { 1403 /* no more than one allowed per aclent_t */ 1404 if (vals->allowed != ACE_MASK_UNDEFINED) { 1405 error = ENOTSUP; 1406 goto out; 1407 } 1408 vals->allowed = acep->a_access_mask; 1409 } else { 1410 /* 1411 * it's a DENY; if there was a previous DENY, it 1412 * must have been an ACL_MASK. 1413 */ 1414 if (vals->denied != ACE_MASK_UNDEFINED) { 1415 /* ACL_MASK is for USER and GROUP only */ 1416 if ((acl->state != ace_user) && 1417 (acl->state != ace_group)) { 1418 error = ENOTSUP; 1419 goto out; 1420 } 1421 1422 if (! acl->hasmask) { 1423 acl->hasmask = 1; 1424 acl->acl_mask = vals->denied; 1425 /* check for mismatched ACL_MASK emulations */ 1426 } else if (acl->acl_mask != vals->denied) { 1427 error = ENOTSUP; 1428 goto out; 1429 } 1430 vals->mask = vals->denied; 1431 } 1432 vals->denied = acep->a_access_mask; 1433 } 1434 } 1435 1436 /* done collating; produce the aclent_t lists */ 1437 if (normacl->state != ace_unused) { 1438 error = ace_list_to_aent(normacl, aclentp, aclcnt, 1439 owner, group, isdir); 1440 if (error != 0) { 1441 goto out; 1442 } 1443 } 1444 if (dfacl->state != ace_unused) { 1445 error = ace_list_to_aent(dfacl, dfaclentp, dfaclcnt, 1446 owner, group, isdir); 1447 if (error != 0) { 1448 goto out; 1449 } 1450 } 1451 1452 out: 1453 if (normacl != NULL) 1454 ace_list_free(normacl); 1455 if (dfacl != NULL) 1456 ace_list_free(dfacl); 1457 1458 return (error); 1459 } 1460 1461 static int 1462 convert_ace_to_aent(ace_t *acebufp, int acecnt, boolean_t isdir, 1463 uid_t owner, gid_t group, aclent_t **retaclentp, int *retaclcnt) 1464 { 1465 int error = 0; 1466 aclent_t *aclentp, *dfaclentp; 1467 int aclcnt, dfaclcnt; 1468 int aclsz, dfaclsz = 0; 1469 1470 error = ln_ace_to_aent(acebufp, acecnt, owner, group, 1471 &aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir); 1472 1473 if (error) 1474 return (error); 1475 1476 1477 if (dfaclcnt != 0) { 1478 /* 1479 * Slap aclentp and dfaclentp into a single array. 1480 */ 1481 aclsz = sizeof (aclent_t) * aclcnt; 1482 dfaclsz = sizeof (aclent_t) * dfaclcnt; 1483 aclentp = cacl_realloc(aclentp, aclsz, aclsz + dfaclsz); 1484 if (aclentp != NULL) { 1485 (void) memcpy(aclentp + aclcnt, dfaclentp, dfaclsz); 1486 } else { 1487 error = ENOMEM; 1488 } 1489 } 1490 1491 if (aclentp) { 1492 *retaclentp = aclentp; 1493 *retaclcnt = aclcnt + dfaclcnt; 1494 } 1495 1496 if (dfaclentp) 1497 cacl_free(dfaclentp, dfaclsz); 1498 1499 return (error); 1500 } 1501 1502 1503 int 1504 acl_translate(acl_t *aclp, int target_flavor, boolean_t isdir, uid_t owner, 1505 gid_t group) 1506 { 1507 int aclcnt; 1508 void *acldata; 1509 int error; 1510 1511 /* 1512 * See if we need to translate 1513 */ 1514 if ((target_flavor == _ACL_ACE_ENABLED && aclp->acl_type == ACE_T) || 1515 (target_flavor == _ACL_ACLENT_ENABLED && 1516 aclp->acl_type == ACLENT_T)) 1517 return (0); 1518 1519 if (target_flavor == -1) { 1520 error = EINVAL; 1521 goto out; 1522 } 1523 1524 if (target_flavor == _ACL_ACE_ENABLED && 1525 aclp->acl_type == ACLENT_T) { 1526 error = convert_aent_to_ace(aclp->acl_aclp, 1527 aclp->acl_cnt, isdir, (ace_t **)&acldata, &aclcnt); 1528 if (error) 1529 goto out; 1530 1531 } else if (target_flavor == _ACL_ACLENT_ENABLED && 1532 aclp->acl_type == ACE_T) { 1533 error = convert_ace_to_aent(aclp->acl_aclp, aclp->acl_cnt, 1534 isdir, owner, group, (aclent_t **)&acldata, &aclcnt); 1535 if (error) 1536 goto out; 1537 } else { 1538 error = ENOTSUP; 1539 goto out; 1540 } 1541 1542 /* 1543 * replace old acl with newly translated acl 1544 */ 1545 cacl_free(aclp->acl_aclp, aclp->acl_cnt * aclp->acl_entry_size); 1546 aclp->acl_aclp = acldata; 1547 aclp->acl_cnt = aclcnt; 1548 if (target_flavor == _ACL_ACE_ENABLED) { 1549 aclp->acl_type = ACE_T; 1550 aclp->acl_entry_size = sizeof (ace_t); 1551 } else { 1552 aclp->acl_type = ACLENT_T; 1553 aclp->acl_entry_size = sizeof (aclent_t); 1554 } 1555 return (0); 1556 1557 out: 1558 1559 #if defined(_KERNEL) || defined(_FAKE_KERNEL) 1560 return (error); 1561 #else 1562 errno = error; 1563 return (-1); 1564 #endif 1565 } 1566 1567 #define SET_ACE(acl, index, who, mask, type, flags) { \ 1568 acl[0][index].a_who = (uint32_t)who; \ 1569 acl[0][index].a_type = type; \ 1570 acl[0][index].a_flags = flags; \ 1571 acl[0][index++].a_access_mask = mask; \ 1572 } 1573 1574 void 1575 acl_trivial_access_masks(mode_t mode, boolean_t isdir, trivial_acl_t *masks) 1576 { 1577 uint32_t read_mask = ACE_READ_DATA; 1578 uint32_t write_mask = ACE_WRITE_DATA|ACE_APPEND_DATA; 1579 uint32_t execute_mask = ACE_EXECUTE; 1580 1581 if (isdir) 1582 write_mask |= ACE_DELETE_CHILD; 1583 1584 masks->deny1 = 0; 1585 if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH))) 1586 masks->deny1 |= read_mask; 1587 if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH))) 1588 masks->deny1 |= write_mask; 1589 if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH))) 1590 masks->deny1 |= execute_mask; 1591 1592 masks->deny2 = 0; 1593 if (!(mode & S_IRGRP) && (mode & S_IROTH)) 1594 masks->deny2 |= read_mask; 1595 if (!(mode & S_IWGRP) && (mode & S_IWOTH)) 1596 masks->deny2 |= write_mask; 1597 if (!(mode & S_IXGRP) && (mode & S_IXOTH)) 1598 masks->deny2 |= execute_mask; 1599 1600 masks->allow0 = 0; 1601 if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH))) 1602 masks->allow0 |= read_mask; 1603 if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH))) 1604 masks->allow0 |= write_mask; 1605 if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH))) 1606 masks->allow0 |= execute_mask; 1607 1608 masks->owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL| 1609 ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES| 1610 ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE; 1611 if (mode & S_IRUSR) 1612 masks->owner |= read_mask; 1613 if (mode & S_IWUSR) 1614 masks->owner |= write_mask; 1615 if (mode & S_IXUSR) 1616 masks->owner |= execute_mask; 1617 1618 masks->group = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS| 1619 ACE_SYNCHRONIZE; 1620 if (mode & S_IRGRP) 1621 masks->group |= read_mask; 1622 if (mode & S_IWGRP) 1623 masks->group |= write_mask; 1624 if (mode & S_IXGRP) 1625 masks->group |= execute_mask; 1626 1627 masks->everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_READ_NAMED_ATTRS| 1628 ACE_SYNCHRONIZE; 1629 if (mode & S_IROTH) 1630 masks->everyone |= read_mask; 1631 if (mode & S_IWOTH) 1632 masks->everyone |= write_mask; 1633 if (mode & S_IXOTH) 1634 masks->everyone |= execute_mask; 1635 } 1636 1637 int 1638 acl_trivial_create(mode_t mode, boolean_t isdir, ace_t **acl, int *count) 1639 { 1640 int index = 0; 1641 int error; 1642 trivial_acl_t masks; 1643 1644 *count = 3; 1645 acl_trivial_access_masks(mode, isdir, &masks); 1646 1647 if (masks.allow0) 1648 (*count)++; 1649 if (masks.deny1) 1650 (*count)++; 1651 if (masks.deny2) 1652 (*count)++; 1653 1654 if ((error = cacl_malloc((void **)acl, *count * sizeof (ace_t))) != 0) 1655 return (error); 1656 1657 if (masks.allow0) { 1658 SET_ACE(acl, index, -1, masks.allow0, 1659 ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_OWNER); 1660 } 1661 if (masks.deny1) { 1662 SET_ACE(acl, index, -1, masks.deny1, 1663 ACE_ACCESS_DENIED_ACE_TYPE, ACE_OWNER); 1664 } 1665 if (masks.deny2) { 1666 SET_ACE(acl, index, -1, masks.deny2, 1667 ACE_ACCESS_DENIED_ACE_TYPE, ACE_GROUP|ACE_IDENTIFIER_GROUP); 1668 } 1669 1670 SET_ACE(acl, index, -1, masks.owner, ACE_ACCESS_ALLOWED_ACE_TYPE, 1671 ACE_OWNER); 1672 SET_ACE(acl, index, -1, masks.group, ACE_ACCESS_ALLOWED_ACE_TYPE, 1673 ACE_IDENTIFIER_GROUP|ACE_GROUP); 1674 SET_ACE(acl, index, -1, masks.everyone, ACE_ACCESS_ALLOWED_ACE_TYPE, 1675 ACE_EVERYONE); 1676 1677 return (0); 1678 } 1679 1680 /* 1681 * Convenience macro for ACE rights implied for owner in a trivial ACL: 1682 * write_owner/write_acl/write_attributes/write_xattr 1683 */ 1684 #define ACE_OWNER_MASK (\ 1685 ACE_WRITE_OWNER|\ 1686 ACE_WRITE_ACL|\ 1687 ACE_WRITE_ATTRIBUTES|\ 1688 ACE_WRITE_NAMED_ATTRS) 1689 1690 /* 1691 * ace_trivial: 1692 * determine whether an ace_t acl is trivial 1693 * 1694 * Trivialness implies that the acl is composed of only 1695 * owner, group, everyone entries. ACL can't 1696 * have read_acl denied, and write_owner/write_acl/write_attributes 1697 * can only be owner@ entry. 1698 * 1699 * Returns zero if this is a "trivial" ACL, else 1. 1700 */ 1701 int 1702 ace_trivial_common(void *acep, int aclcnt, 1703 uint64_t (*walk)(void *, uint64_t, int aclcnt, 1704 uint16_t *, uint16_t *, uint32_t *)) 1705 { 1706 uint16_t flags; 1707 uint32_t mask; 1708 uint16_t type; 1709 uint64_t cookie = 0; 1710 uint32_t owner_allow = 0; 1711 uint32_t owner_deny = 0; 1712 1713 while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask)) 1714 != 0) { 1715 switch (flags & ACE_TYPE_FLAGS) { 1716 case ACE_OWNER: 1717 case ACE_GROUP|ACE_IDENTIFIER_GROUP: 1718 case ACE_EVERYONE: 1719 break; 1720 default: 1721 return (1); 1722 1723 } 1724 1725 if (flags & (ACE_FILE_INHERIT_ACE| 1726 ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE| 1727 ACE_INHERIT_ONLY_ACE)) 1728 return (1); 1729 1730 /* 1731 * Special check for some special bits 1732 * 1733 * Don't allow anybody to deny reading basic 1734 * attributes or a files ACL. 1735 */ 1736 if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) && 1737 (type == ACE_ACCESS_DENIED_ACE_TYPE)) 1738 return (1); 1739 1740 /* 1741 * Delete permission is never set by default 1742 */ 1743 if (mask & ACE_DELETE) 1744 return (1); 1745 1746 /* 1747 * Child delete permission should be accompanied by write 1748 */ 1749 if ((mask & ACE_DELETE_CHILD) && !(mask & ACE_WRITE_DATA)) 1750 return (1); 1751 1752 /* 1753 * only allow owner@ to have 1754 * write_acl/write_owner/write_attributes/write_xattr/ 1755 */ 1756 if (type == ACE_ACCESS_ALLOWED_ACE_TYPE && 1757 (flags & ACE_OWNER) == 0 && 1758 (mask & ACE_OWNER_MASK) != 0) 1759 return (1); 1760 1761 /* Accumulate owner masks */ 1762 if ((flags & ACE_OWNER) != 0) { 1763 if (type == ACE_ACCESS_ALLOWED_ACE_TYPE) 1764 owner_allow |= mask; 1765 if (type == ACE_ACCESS_DENIED_ACE_TYPE) 1766 owner_deny |= mask; 1767 } 1768 } 1769 1770 /* 1771 * If owner was not allowed the usual implied rights, 1772 * then this should not be considered a trivial ACL. 1773 * In cases like mode 0745 we may have owner@ on 1774 * multiple ACEs, so we have to check the combined 1775 * access masks. 1776 */ 1777 if ((owner_deny & ACE_OWNER_MASK) != 0) 1778 return (1); 1779 if ((owner_allow & ACE_OWNER_MASK) != ACE_OWNER_MASK) 1780 return (1); 1781 1782 return (0); 1783 } 1784 1785 uint64_t 1786 ace_walk(void *datap, uint64_t cookie, int aclcnt, uint16_t *flags, 1787 uint16_t *type, uint32_t *mask) 1788 { 1789 ace_t *acep = datap; 1790 1791 if (cookie >= aclcnt) 1792 return (0); 1793 1794 *flags = acep[cookie].a_flags; 1795 *type = acep[cookie].a_type; 1796 *mask = acep[cookie++].a_access_mask; 1797 1798 return (cookie); 1799 } 1800 1801 int 1802 ace_trivial(ace_t *acep, int aclcnt) 1803 { 1804 return (ace_trivial_common(acep, aclcnt, ace_walk)); 1805 } 1806