1 /*- 2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 4 * All rights reserved. 5 * 6 * This software was developed by Robert Watson for the TrustedBSD Project. 7 * 8 * This software was developed for the FreeBSD Project in part by NAI Labs, 9 * the Security Research Division of Network Associates, Inc. under 10 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 11 * CHATS research program. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. The names of the authors may not be used to endorse or promote 22 * products derived from this software without specific prior written 23 * permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * $FreeBSD$ 38 */ 39 40 /* 41 * Developed by the TrustedBSD Project. 42 * MLS fixed label mandatory confidentiality policy. 43 */ 44 45 #include <sys/types.h> 46 #include <sys/param.h> 47 #include <sys/acl.h> 48 #include <sys/conf.h> 49 #include <sys/kernel.h> 50 #include <sys/mac.h> 51 #include <sys/malloc.h> 52 #include <sys/mount.h> 53 #include <sys/proc.h> 54 #include <sys/systm.h> 55 #include <sys/sysproto.h> 56 #include <sys/sysent.h> 57 #include <sys/systm.h> 58 #include <sys/vnode.h> 59 #include <sys/file.h> 60 #include <sys/socket.h> 61 #include <sys/socketvar.h> 62 #include <sys/pipe.h> 63 #include <sys/sysctl.h> 64 65 #include <fs/devfs/devfs.h> 66 67 #include <net/bpfdesc.h> 68 #include <net/if.h> 69 #include <net/if_types.h> 70 #include <net/if_var.h> 71 72 #include <netinet/in.h> 73 #include <netinet/ip_var.h> 74 75 #include <vm/vm.h> 76 77 #include <sys/mac_policy.h> 78 79 #include <security/mac_mls/mac_mls.h> 80 81 SYSCTL_DECL(_security_mac); 82 83 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0, 84 "TrustedBSD mac_mls policy controls"); 85 86 static int mac_mls_enabled = 0; 87 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, 88 &mac_mls_enabled, 0, "Enforce MAC/MLS policy"); 89 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled); 90 91 static int destroyed_not_inited; 92 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 93 &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 94 95 static int ptys_equal = 0; 96 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW, 97 &ptys_equal, 0, "Label pty devices as mls/equal on create"); 98 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal); 99 100 static int revocation_enabled = 0; 101 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW, 102 &revocation_enabled, 0, "Revoke access to objects on relabel"); 103 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled); 104 105 static int max_compartments = MAC_MLS_MAX_COMPARTMENTS; 106 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD, 107 &max_compartments, 0, "Maximum compartments the policy supports"); 108 109 static int mac_mls_slot; 110 #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr) 111 112 MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels"); 113 114 static __inline int 115 mls_bit_set_empty(u_char *set) { 116 int i; 117 118 for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++) 119 if (set[i] != 0) 120 return (0); 121 return (1); 122 } 123 124 static struct mac_mls * 125 mls_alloc(int flag) 126 { 127 struct mac_mls *mac_mls; 128 129 mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag); 130 131 return (mac_mls); 132 } 133 134 static void 135 mls_free(struct mac_mls *mac_mls) 136 { 137 138 if (mac_mls != NULL) 139 free(mac_mls, M_MACMLS); 140 else 141 atomic_add_int(&destroyed_not_inited, 1); 142 } 143 144 static int 145 mls_atmostflags(struct mac_mls *mac_mls, int flags) 146 { 147 148 if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags) 149 return (EINVAL); 150 return (0); 151 } 152 153 static int 154 mac_mls_dominate_element(struct mac_mls_element *a, 155 struct mac_mls_element *b) 156 { 157 int bit; 158 159 switch (a->mme_type) { 160 case MAC_MLS_TYPE_EQUAL: 161 case MAC_MLS_TYPE_HIGH: 162 return (1); 163 164 case MAC_MLS_TYPE_LOW: 165 switch (b->mme_type) { 166 case MAC_MLS_TYPE_LEVEL: 167 case MAC_MLS_TYPE_HIGH: 168 return (0); 169 170 case MAC_MLS_TYPE_EQUAL: 171 case MAC_MLS_TYPE_LOW: 172 return (1); 173 174 default: 175 panic("mac_mls_dominate_element: b->mme_type invalid"); 176 } 177 178 case MAC_MLS_TYPE_LEVEL: 179 switch (b->mme_type) { 180 case MAC_MLS_TYPE_EQUAL: 181 case MAC_MLS_TYPE_LOW: 182 return (1); 183 184 case MAC_MLS_TYPE_HIGH: 185 return (0); 186 187 case MAC_MLS_TYPE_LEVEL: 188 for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) 189 if (!MAC_MLS_BIT_TEST(bit, 190 a->mme_compartments) && 191 MAC_MLS_BIT_TEST(bit, b->mme_compartments)) 192 return (0); 193 return (a->mme_level >= b->mme_level); 194 195 default: 196 panic("mac_mls_dominate_element: b->mme_type invalid"); 197 } 198 199 default: 200 panic("mac_mls_dominate_element: a->mme_type invalid"); 201 } 202 203 return (0); 204 } 205 206 static int 207 mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb) 208 { 209 210 return (mac_mls_dominate_element(&rangeb->mm_rangehigh, 211 &rangea->mm_rangehigh) && 212 mac_mls_dominate_element(&rangea->mm_rangelow, 213 &rangeb->mm_rangelow)); 214 } 215 216 static int 217 mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range) 218 { 219 220 KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, 221 ("mac_mls_single_in_range: a not single")); 222 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0, 223 ("mac_mls_single_in_range: b not range")); 224 225 return (mac_mls_dominate_element(&range->mm_rangehigh, 226 &single->mm_single) && 227 mac_mls_dominate_element(&single->mm_single, 228 &range->mm_rangelow)); 229 230 return (1); 231 } 232 233 static int 234 mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b) 235 { 236 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, 237 ("mac_mls_dominate_single: a not single")); 238 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, 239 ("mac_mls_dominate_single: b not single")); 240 241 return (mac_mls_dominate_element(&a->mm_single, &b->mm_single)); 242 } 243 244 static int 245 mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b) 246 { 247 248 if (a->mme_type == MAC_MLS_TYPE_EQUAL || 249 b->mme_type == MAC_MLS_TYPE_EQUAL) 250 return (1); 251 252 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level); 253 } 254 255 static int 256 mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b) 257 { 258 259 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, 260 ("mac_mls_equal_single: a not single")); 261 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, 262 ("mac_mls_equal_single: b not single")); 263 264 return (mac_mls_equal_element(&a->mm_single, &b->mm_single)); 265 } 266 267 static int 268 mac_mls_contains_equal(struct mac_mls *mac_mls) 269 { 270 271 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) 272 if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL) 273 return (1); 274 275 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { 276 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL) 277 return (1); 278 if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) 279 return (1); 280 } 281 282 return (0); 283 } 284 285 static int 286 mac_mls_subject_equal_ok(struct mac_mls *mac_mls) 287 { 288 289 KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH, 290 ("mac_mls_subject_equal_ok: subject doesn't have both labels")); 291 292 /* If the single is EQUAL, it's ok. */ 293 if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL) 294 return (0); 295 296 /* If either range endpoint is EQUAL, it's ok. */ 297 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL || 298 mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) 299 return (0); 300 301 /* If the range is low-high, it's ok. */ 302 if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW && 303 mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH) 304 return (0); 305 306 /* It's not ok. */ 307 return (EPERM); 308 } 309 310 static int 311 mac_mls_valid(struct mac_mls *mac_mls) 312 { 313 314 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) { 315 switch (mac_mls->mm_single.mme_type) { 316 case MAC_MLS_TYPE_LEVEL: 317 break; 318 319 case MAC_MLS_TYPE_EQUAL: 320 case MAC_MLS_TYPE_HIGH: 321 case MAC_MLS_TYPE_LOW: 322 if (mac_mls->mm_single.mme_level != 0 || 323 !MAC_MLS_BIT_SET_EMPTY( 324 mac_mls->mm_single.mme_compartments)) 325 return (EINVAL); 326 break; 327 328 default: 329 return (EINVAL); 330 } 331 } else { 332 if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF) 333 return (EINVAL); 334 } 335 336 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { 337 switch (mac_mls->mm_rangelow.mme_type) { 338 case MAC_MLS_TYPE_LEVEL: 339 break; 340 341 case MAC_MLS_TYPE_EQUAL: 342 case MAC_MLS_TYPE_HIGH: 343 case MAC_MLS_TYPE_LOW: 344 if (mac_mls->mm_rangelow.mme_level != 0 || 345 !MAC_MLS_BIT_SET_EMPTY( 346 mac_mls->mm_rangelow.mme_compartments)) 347 return (EINVAL); 348 break; 349 350 default: 351 return (EINVAL); 352 } 353 354 switch (mac_mls->mm_rangehigh.mme_type) { 355 case MAC_MLS_TYPE_LEVEL: 356 break; 357 358 case MAC_MLS_TYPE_EQUAL: 359 case MAC_MLS_TYPE_HIGH: 360 case MAC_MLS_TYPE_LOW: 361 if (mac_mls->mm_rangehigh.mme_level != 0 || 362 !MAC_MLS_BIT_SET_EMPTY( 363 mac_mls->mm_rangehigh.mme_compartments)) 364 return (EINVAL); 365 break; 366 367 default: 368 return (EINVAL); 369 } 370 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh, 371 &mac_mls->mm_rangelow)) 372 return (EINVAL); 373 } else { 374 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF || 375 mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF) 376 return (EINVAL); 377 } 378 379 return (0); 380 } 381 382 static void 383 mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow, 384 u_short levellow, u_char *compartmentslow, u_short typehigh, 385 u_short levelhigh, u_char *compartmentshigh) 386 { 387 388 mac_mls->mm_rangelow.mme_type = typelow; 389 mac_mls->mm_rangelow.mme_level = levellow; 390 if (compartmentslow != NULL) 391 memcpy(mac_mls->mm_rangelow.mme_compartments, 392 compartmentslow, 393 sizeof(mac_mls->mm_rangelow.mme_compartments)); 394 mac_mls->mm_rangehigh.mme_type = typehigh; 395 mac_mls->mm_rangehigh.mme_level = levelhigh; 396 if (compartmentshigh != NULL) 397 memcpy(mac_mls->mm_rangehigh.mme_compartments, 398 compartmentshigh, 399 sizeof(mac_mls->mm_rangehigh.mme_compartments)); 400 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE; 401 } 402 403 static void 404 mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level, 405 u_char *compartments) 406 { 407 408 mac_mls->mm_single.mme_type = type; 409 mac_mls->mm_single.mme_level = level; 410 if (compartments != NULL) 411 memcpy(mac_mls->mm_single.mme_compartments, compartments, 412 sizeof(mac_mls->mm_single.mme_compartments)); 413 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE; 414 } 415 416 static void 417 mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto) 418 { 419 420 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0, 421 ("mac_mls_copy_range: labelfrom not range")); 422 423 labelto->mm_rangelow = labelfrom->mm_rangelow; 424 labelto->mm_rangehigh = labelfrom->mm_rangehigh; 425 labelto->mm_flags |= MAC_MLS_FLAG_RANGE; 426 } 427 428 static void 429 mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto) 430 { 431 432 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0, 433 ("mac_mls_copy_single: labelfrom not single")); 434 435 labelto->mm_single = labelfrom->mm_single; 436 labelto->mm_flags |= MAC_MLS_FLAG_SINGLE; 437 } 438 439 static void 440 mac_mls_copy(struct mac_mls *source, struct mac_mls *dest) 441 { 442 443 if (source->mm_flags & MAC_MLS_FLAG_SINGLE) 444 mac_mls_copy_single(source, dest); 445 if (source->mm_flags & MAC_MLS_FLAG_RANGE) 446 mac_mls_copy_range(source, dest); 447 } 448 449 /* 450 * Policy module operations. 451 */ 452 static void 453 mac_mls_destroy(struct mac_policy_conf *conf) 454 { 455 456 } 457 458 static void 459 mac_mls_init(struct mac_policy_conf *conf) 460 { 461 462 } 463 464 /* 465 * Label operations. 466 */ 467 static void 468 mac_mls_init_label(struct label *label) 469 { 470 471 SLOT(label) = mls_alloc(M_WAITOK); 472 } 473 474 static int 475 mac_mls_init_label_waitcheck(struct label *label, int flag) 476 { 477 478 SLOT(label) = mls_alloc(flag); 479 if (SLOT(label) == NULL) 480 return (ENOMEM); 481 482 return (0); 483 } 484 485 static void 486 mac_mls_destroy_label(struct label *label) 487 { 488 489 mls_free(SLOT(label)); 490 SLOT(label) = NULL; 491 } 492 493 /* 494 * mac_mls_element_to_string() is basically an snprintf wrapper with 495 * the same properties as snprintf(). It returns the length it would 496 * have added to the string in the event the string is too short. 497 */ 498 static size_t 499 mac_mls_element_to_string(char *string, size_t size, 500 struct mac_mls_element *element) 501 { 502 int pos, bit = 1; 503 504 switch (element->mme_type) { 505 case MAC_MLS_TYPE_HIGH: 506 return (snprintf(string, size, "high")); 507 508 case MAC_MLS_TYPE_LOW: 509 return (snprintf(string, size, "low")); 510 511 case MAC_MLS_TYPE_EQUAL: 512 return (snprintf(string, size, "equal")); 513 514 case MAC_MLS_TYPE_LEVEL: 515 pos = snprintf(string, size, "%d:", element->mme_level); 516 for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) { 517 if (MAC_MLS_BIT_TEST(bit, element->mme_compartments)) 518 pos += snprintf(string + pos, size - pos, 519 "%d+", bit); 520 } 521 if (string[pos - 1] == '+' || string[pos - 1] == ':') 522 string[--pos] = NULL; 523 return (pos); 524 525 default: 526 panic("mac_mls_element_to_string: invalid type (%d)", 527 element->mme_type); 528 } 529 } 530 531 static size_t 532 mac_mls_to_string(char *string, size_t size, size_t *caller_len, 533 struct mac_mls *mac_mls) 534 { 535 size_t left, len; 536 char *curptr; 537 538 bzero(string, size); 539 curptr = string; 540 left = size; 541 542 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) { 543 len = mac_mls_element_to_string(curptr, left, 544 &mac_mls->mm_single); 545 if (len >= left) 546 return (EINVAL); 547 left -= len; 548 curptr += len; 549 } 550 551 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) { 552 len = snprintf(curptr, left, "("); 553 if (len >= left) 554 return (EINVAL); 555 left -= len; 556 curptr += len; 557 558 len = mac_mls_element_to_string(curptr, left, 559 &mac_mls->mm_rangelow); 560 if (len >= left) 561 return (EINVAL); 562 left -= len; 563 curptr += len; 564 565 len = snprintf(curptr, left, "-"); 566 if (len >= left) 567 return (EINVAL); 568 left -= len; 569 curptr += len; 570 571 len = mac_mls_element_to_string(curptr, left, 572 &mac_mls->mm_rangehigh); 573 if (len >= left) 574 return (EINVAL); 575 left -= len; 576 curptr += len; 577 578 len = snprintf(curptr, left, ")"); 579 if (len >= left) 580 return (EINVAL); 581 left -= len; 582 curptr += len; 583 } 584 585 *caller_len = strlen(string); 586 return (0); 587 } 588 589 static int 590 mac_mls_externalize_label(struct label *label, char *element_name, 591 char *element_data, size_t size, size_t *len, int *claimed) 592 { 593 struct mac_mls *mac_mls; 594 int error; 595 596 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0) 597 return (0); 598 599 (*claimed)++; 600 601 mac_mls = SLOT(label); 602 603 error = mac_mls_to_string(element_data, size, len, mac_mls); 604 if (error) 605 return (error); 606 607 *len = strlen(element_data); 608 return (0); 609 } 610 611 static int 612 mac_mls_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) 613 { 614 struct mac_mls *mac_mls; 615 616 mac_mls = SLOT(label); 617 618 if (mac_mls == NULL) { 619 printf("mac_mls_externalize: NULL pointer\n"); 620 return (0); 621 } 622 623 extmac->m_mls = *mac_mls; 624 625 return (0); 626 } 627 628 static int 629 mac_mls_parse_element(struct mac_mls_element *element, char *string) 630 { 631 632 if (strcmp(string, "high") == 0 || 633 strcmp(string, "hi") == 0) { 634 element->mme_type = MAC_MLS_TYPE_HIGH; 635 element->mme_level = MAC_MLS_TYPE_UNDEF; 636 } else if (strcmp(string, "low") == 0 || 637 strcmp(string, "lo") == 0) { 638 element->mme_type = MAC_MLS_TYPE_LOW; 639 element->mme_level = MAC_MLS_TYPE_UNDEF; 640 } else if (strcmp(string, "equal") == 0 || 641 strcmp(string, "eq") == 0) { 642 element->mme_type = MAC_MLS_TYPE_EQUAL; 643 element->mme_level = MAC_MLS_TYPE_UNDEF; 644 } else { 645 char *p0, *p1; 646 int d; 647 648 p0 = string; 649 d = strtol(p0, &p1, 10); 650 651 if (d < 0 || d > 65535) 652 return (EINVAL); 653 element->mme_type = MAC_MLS_TYPE_LEVEL; 654 element->mme_level = d; 655 656 if (*p1 != ':') { 657 if (p1 == p0 || *p1 != '\0') 658 return (EINVAL); 659 else 660 return (0); 661 } 662 else 663 if (*(p1 + 1) == '\0') 664 return (0); 665 666 while ((p0 = ++p1)) { 667 d = strtol(p0, &p1, 10); 668 if (d < 1 || d > MAC_MLS_MAX_COMPARTMENTS) 669 return (EINVAL); 670 671 MAC_MLS_BIT_SET(d, element->mme_compartments); 672 673 if (*p1 == '\0') 674 break; 675 if (p1 == p0 || *p1 != '+') 676 return (EINVAL); 677 } 678 } 679 680 return (0); 681 } 682 683 /* 684 * Note: destructively consumes the string, make a local copy before 685 * calling if that's a problem. 686 */ 687 static int 688 mac_mls_parse(struct mac_mls *mac_mls, char *string) 689 { 690 char *range, *rangeend, *rangehigh, *rangelow, *single; 691 int error; 692 693 /* Do we have a range? */ 694 single = string; 695 range = index(string, '('); 696 if (range == single) 697 single = NULL; 698 rangelow = rangehigh = NULL; 699 if (range != NULL) { 700 /* Nul terminate the end of the single string. */ 701 *range = '\0'; 702 range++; 703 rangelow = range; 704 rangehigh = index(rangelow, '-'); 705 if (rangehigh == NULL) 706 return (EINVAL); 707 rangehigh++; 708 if (*rangelow == '\0' || *rangehigh == '\0') 709 return (EINVAL); 710 rangeend = index(rangehigh, ')'); 711 if (rangeend == NULL) 712 return (EINVAL); 713 if (*(rangeend + 1) != '\0') 714 return (EINVAL); 715 /* Nul terminate the ends of the ranges. */ 716 *(rangehigh - 1) = '\0'; 717 *rangeend = '\0'; 718 } 719 KASSERT((rangelow != NULL && rangehigh != NULL) || 720 (rangelow == NULL && rangehigh == NULL), 721 ("mac_mls_internalize_label: range mismatch")); 722 723 bzero(mac_mls, sizeof(*mac_mls)); 724 if (single != NULL) { 725 error = mac_mls_parse_element(&mac_mls->mm_single, single); 726 if (error) 727 return (error); 728 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE; 729 } 730 731 if (rangelow != NULL) { 732 error = mac_mls_parse_element(&mac_mls->mm_rangelow, 733 rangelow); 734 if (error) 735 return (error); 736 error = mac_mls_parse_element(&mac_mls->mm_rangehigh, 737 rangehigh); 738 if (error) 739 return (error); 740 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE; 741 } 742 743 error = mac_mls_valid(mac_mls); 744 if (error) 745 return (error); 746 747 return (0); 748 } 749 750 static int 751 mac_mls_internalize_label(struct label *label, char *element_name, 752 char *element_data, int *claimed) 753 { 754 struct mac_mls *mac_mls, mac_mls_temp; 755 int error; 756 757 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0) 758 return (0); 759 760 (*claimed)++; 761 762 error = mac_mls_parse(&mac_mls_temp, element_data); 763 if (error) 764 return (error); 765 766 mac_mls = SLOT(label); 767 *mac_mls = mac_mls_temp; 768 769 return (0); 770 } 771 772 static void 773 mac_mls_copy_label(struct label *src, struct label *dest) 774 { 775 776 *SLOT(dest) = *SLOT(src); 777 } 778 779 /* 780 * Labeling event operations: file system objects, and things that look 781 * a lot like file system objects. 782 */ 783 static void 784 mac_mls_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent, 785 struct label *label) 786 { 787 struct mac_mls *mac_mls; 788 int mls_type; 789 790 mac_mls = SLOT(label); 791 if (strcmp(dev->si_name, "null") == 0 || 792 strcmp(dev->si_name, "zero") == 0 || 793 strcmp(dev->si_name, "random") == 0 || 794 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) 795 mls_type = MAC_MLS_TYPE_EQUAL; 796 else if (strcmp(dev->si_name, "kmem") == 0 || 797 strcmp(dev->si_name, "mem") == 0) 798 mls_type = MAC_MLS_TYPE_HIGH; 799 else if (ptys_equal && 800 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || 801 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) 802 mls_type = MAC_MLS_TYPE_EQUAL; 803 else 804 mls_type = MAC_MLS_TYPE_LOW; 805 mac_mls_set_single(mac_mls, mls_type, 0, NULL); 806 } 807 808 static void 809 mac_mls_create_devfs_directory(char *dirname, int dirnamelen, 810 struct devfs_dirent *devfs_dirent, struct label *label) 811 { 812 struct mac_mls *mac_mls; 813 814 mac_mls = SLOT(label); 815 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); 816 } 817 818 static void 819 mac_mls_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, 820 struct label *ddlabel, struct devfs_dirent *de, struct label *delabel) 821 { 822 struct mac_mls *source, *dest; 823 824 source = SLOT(&cred->cr_label); 825 dest = SLOT(delabel); 826 827 mac_mls_copy_single(source, dest); 828 } 829 830 static void 831 mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent, 832 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) 833 { 834 struct mac_mls *source, *dest; 835 836 source = SLOT(direntlabel); 837 dest = SLOT(vnodelabel); 838 mac_mls_copy_single(source, dest); 839 } 840 841 static void 842 mac_mls_create_vnode(struct ucred *cred, struct vnode *parent, 843 struct label *parentlabel, struct vnode *child, struct label *childlabel) 844 { 845 struct mac_mls *source, *dest; 846 847 source = SLOT(&cred->cr_label); 848 dest = SLOT(childlabel); 849 850 mac_mls_copy_single(source, dest); 851 } 852 853 static void 854 mac_mls_create_mount(struct ucred *cred, struct mount *mp, 855 struct label *mntlabel, struct label *fslabel) 856 { 857 struct mac_mls *source, *dest; 858 859 source = SLOT(&cred->cr_label); 860 dest = SLOT(mntlabel); 861 mac_mls_copy_single(source, dest); 862 dest = SLOT(fslabel); 863 mac_mls_copy_single(source, dest); 864 } 865 866 static void 867 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp, 868 struct label *mntlabel, struct label *fslabel) 869 { 870 struct mac_mls *mac_mls; 871 872 /* Always mount root as high integrity. */ 873 mac_mls = SLOT(fslabel); 874 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); 875 mac_mls = SLOT(mntlabel); 876 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); 877 } 878 879 static void 880 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp, 881 struct label *vnodelabel, struct label *label) 882 { 883 struct mac_mls *source, *dest; 884 885 source = SLOT(label); 886 dest = SLOT(vnodelabel); 887 888 mac_mls_copy(source, dest); 889 } 890 891 static void 892 mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent, 893 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) 894 { 895 struct mac_mls *source, *dest; 896 897 source = SLOT(vnodelabel); 898 dest = SLOT(direntlabel); 899 900 mac_mls_copy_single(source, dest); 901 } 902 903 static void 904 mac_mls_update_procfsvnode(struct vnode *vp, struct label *vnodelabel, 905 struct ucred *cred) 906 { 907 struct mac_mls *source, *dest; 908 909 source = SLOT(&cred->cr_label); 910 dest = SLOT(vnodelabel); 911 912 /* 913 * Only copy the single, not the range, since vnodes only have 914 * a single. 915 */ 916 mac_mls_copy_single(source, dest); 917 } 918 919 static int 920 mac_mls_update_vnode_from_externalized(struct vnode *vp, 921 struct label *vnodelabel, struct oldmac *extmac) 922 { 923 struct mac_mls *source, *dest; 924 int error; 925 926 source = &extmac->m_mls; 927 dest = SLOT(vnodelabel); 928 929 error = mac_mls_valid(source); 930 if (error) 931 return (error); 932 933 if ((source->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) 934 return (EINVAL); 935 936 mac_mls_copy_single(source, dest); 937 938 return (0); 939 } 940 941 static void 942 mac_mls_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel, 943 struct mount *mp, struct label *fslabel) 944 { 945 struct mac_mls *source, *dest; 946 947 source = SLOT(fslabel); 948 dest = SLOT(vnodelabel); 949 950 mac_mls_copy_single(source, dest); 951 } 952 953 /* 954 * Labeling event operations: IPC object. 955 */ 956 static void 957 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, 958 struct mbuf *m, struct label *mbuflabel) 959 { 960 struct mac_mls *source, *dest; 961 962 source = SLOT(socketlabel); 963 dest = SLOT(mbuflabel); 964 965 mac_mls_copy_single(source, dest); 966 } 967 968 static void 969 mac_mls_create_socket(struct ucred *cred, struct socket *socket, 970 struct label *socketlabel) 971 { 972 struct mac_mls *source, *dest; 973 974 source = SLOT(&cred->cr_label); 975 dest = SLOT(socketlabel); 976 977 mac_mls_copy_single(source, dest); 978 } 979 980 static void 981 mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe, 982 struct label *pipelabel) 983 { 984 struct mac_mls *source, *dest; 985 986 source = SLOT(&cred->cr_label); 987 dest = SLOT(pipelabel); 988 989 mac_mls_copy_single(source, dest); 990 } 991 992 static void 993 mac_mls_create_socket_from_socket(struct socket *oldsocket, 994 struct label *oldsocketlabel, struct socket *newsocket, 995 struct label *newsocketlabel) 996 { 997 struct mac_mls *source, *dest; 998 999 source = SLOT(oldsocketlabel); 1000 dest = SLOT(newsocketlabel); 1001 1002 mac_mls_copy_single(source, dest); 1003 } 1004 1005 static void 1006 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket, 1007 struct label *socketlabel, struct label *newlabel) 1008 { 1009 struct mac_mls *source, *dest; 1010 1011 source = SLOT(newlabel); 1012 dest = SLOT(socketlabel); 1013 1014 mac_mls_copy(source, dest); 1015 } 1016 1017 static void 1018 mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe, 1019 struct label *pipelabel, struct label *newlabel) 1020 { 1021 struct mac_mls *source, *dest; 1022 1023 source = SLOT(newlabel); 1024 dest = SLOT(pipelabel); 1025 1026 mac_mls_copy(source, dest); 1027 } 1028 1029 static void 1030 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, 1031 struct socket *socket, struct label *socketpeerlabel) 1032 { 1033 struct mac_mls *source, *dest; 1034 1035 source = SLOT(mbuflabel); 1036 dest = SLOT(socketpeerlabel); 1037 1038 mac_mls_copy_single(source, dest); 1039 } 1040 1041 /* 1042 * Labeling event operations: network objects. 1043 */ 1044 static void 1045 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket, 1046 struct label *oldsocketlabel, struct socket *newsocket, 1047 struct label *newsocketpeerlabel) 1048 { 1049 struct mac_mls *source, *dest; 1050 1051 source = SLOT(oldsocketlabel); 1052 dest = SLOT(newsocketpeerlabel); 1053 1054 mac_mls_copy_single(source, dest); 1055 } 1056 1057 static void 1058 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, 1059 struct label *bpflabel) 1060 { 1061 struct mac_mls *source, *dest; 1062 1063 source = SLOT(&cred->cr_label); 1064 dest = SLOT(bpflabel); 1065 1066 mac_mls_copy_single(source, dest); 1067 } 1068 1069 static void 1070 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) 1071 { 1072 struct mac_mls *dest; 1073 int level; 1074 1075 dest = SLOT(ifnetlabel); 1076 1077 if (ifnet->if_type == IFT_LOOP) 1078 level = MAC_MLS_TYPE_EQUAL; 1079 else 1080 level = MAC_MLS_TYPE_LOW; 1081 1082 mac_mls_set_single(dest, level, 0, NULL); 1083 mac_mls_set_range(dest, level, 0, NULL, level, 0, NULL); 1084 } 1085 1086 static void 1087 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, 1088 struct ipq *ipq, struct label *ipqlabel) 1089 { 1090 struct mac_mls *source, *dest; 1091 1092 source = SLOT(fragmentlabel); 1093 dest = SLOT(ipqlabel); 1094 1095 mac_mls_copy_single(source, dest); 1096 } 1097 1098 static void 1099 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, 1100 struct mbuf *datagram, struct label *datagramlabel) 1101 { 1102 struct mac_mls *source, *dest; 1103 1104 source = SLOT(ipqlabel); 1105 dest = SLOT(datagramlabel); 1106 1107 /* Just use the head, since we require them all to match. */ 1108 mac_mls_copy_single(source, dest); 1109 } 1110 1111 static void 1112 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel, 1113 struct mbuf *fragment, struct label *fragmentlabel) 1114 { 1115 struct mac_mls *source, *dest; 1116 1117 source = SLOT(datagramlabel); 1118 dest = SLOT(fragmentlabel); 1119 1120 mac_mls_copy_single(source, dest); 1121 } 1122 1123 static void 1124 mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf, 1125 struct label *oldmbuflabel, struct mbuf *newmbuf, 1126 struct label *newmbuflabel) 1127 { 1128 struct mac_mls *source, *dest; 1129 1130 source = SLOT(oldmbuflabel); 1131 dest = SLOT(newmbuflabel); 1132 1133 /* 1134 * Because the source mbuf may not yet have been "created", 1135 * just initialized, we do a conditional copy. Since we don't 1136 * allow mbufs to have ranges, do a KASSERT to make sure that 1137 * doesn't happen. 1138 */ 1139 KASSERT((source->mm_flags & MAC_MLS_FLAG_RANGE) == 0, 1140 ("mac_mls_create_mbuf_from_mbuf: source mbuf has range")); 1141 mac_mls_copy(source, dest); 1142 } 1143 1144 static void 1145 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, 1146 struct mbuf *mbuf, struct label *mbuflabel) 1147 { 1148 struct mac_mls *dest; 1149 1150 dest = SLOT(mbuflabel); 1151 1152 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 1153 } 1154 1155 static void 1156 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, 1157 struct mbuf *mbuf, struct label *mbuflabel) 1158 { 1159 struct mac_mls *source, *dest; 1160 1161 source = SLOT(bpflabel); 1162 dest = SLOT(mbuflabel); 1163 1164 mac_mls_copy_single(source, dest); 1165 } 1166 1167 static void 1168 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, 1169 struct mbuf *m, struct label *mbuflabel) 1170 { 1171 struct mac_mls *source, *dest; 1172 1173 source = SLOT(ifnetlabel); 1174 dest = SLOT(mbuflabel); 1175 1176 mac_mls_copy_single(source, dest); 1177 } 1178 1179 static void 1180 mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf, 1181 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, 1182 struct mbuf *newmbuf, struct label *newmbuflabel) 1183 { 1184 struct mac_mls *source, *dest; 1185 1186 source = SLOT(oldmbuflabel); 1187 dest = SLOT(newmbuflabel); 1188 1189 mac_mls_copy_single(source, dest); 1190 } 1191 1192 static void 1193 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, 1194 struct mbuf *newmbuf, struct label *newmbuflabel) 1195 { 1196 struct mac_mls *source, *dest; 1197 1198 source = SLOT(oldmbuflabel); 1199 dest = SLOT(newmbuflabel); 1200 1201 mac_mls_copy_single(source, dest); 1202 } 1203 1204 static int 1205 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, 1206 struct ipq *ipq, struct label *ipqlabel) 1207 { 1208 struct mac_mls *a, *b; 1209 1210 a = SLOT(ipqlabel); 1211 b = SLOT(fragmentlabel); 1212 1213 return (mac_mls_equal_single(a, b)); 1214 } 1215 1216 static void 1217 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, 1218 struct label *ifnetlabel, struct label *newlabel) 1219 { 1220 struct mac_mls *source, *dest; 1221 1222 source = SLOT(newlabel); 1223 dest = SLOT(ifnetlabel); 1224 1225 mac_mls_copy(source, dest); 1226 } 1227 1228 static void 1229 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, 1230 struct ipq *ipq, struct label *ipqlabel) 1231 { 1232 1233 /* NOOP: we only accept matching labels, so no need to update */ 1234 } 1235 1236 /* 1237 * Labeling event operations: processes. 1238 */ 1239 static void 1240 mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child) 1241 { 1242 struct mac_mls *source, *dest; 1243 1244 source = SLOT(&cred_parent->cr_label); 1245 dest = SLOT(&cred_child->cr_label); 1246 1247 mac_mls_copy_single(source, dest); 1248 mac_mls_copy_range(source, dest); 1249 } 1250 1251 static void 1252 mac_mls_execve_transition(struct ucred *old, struct ucred *new, 1253 struct vnode *vp, struct label *vnodelabel) 1254 { 1255 struct mac_mls *source, *dest; 1256 1257 source = SLOT(&old->cr_label); 1258 dest = SLOT(&new->cr_label); 1259 1260 mac_mls_copy_single(source, dest); 1261 mac_mls_copy_range(source, dest); 1262 } 1263 1264 static int 1265 mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp, 1266 struct label *vnodelabel) 1267 { 1268 1269 return (0); 1270 } 1271 1272 static void 1273 mac_mls_create_proc0(struct ucred *cred) 1274 { 1275 struct mac_mls *dest; 1276 1277 dest = SLOT(&cred->cr_label); 1278 1279 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 1280 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 1281 0, NULL); 1282 } 1283 1284 static void 1285 mac_mls_create_proc1(struct ucred *cred) 1286 { 1287 struct mac_mls *dest; 1288 1289 dest = SLOT(&cred->cr_label); 1290 1291 mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0, NULL); 1292 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 1293 0, NULL); 1294 } 1295 1296 static void 1297 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel) 1298 { 1299 struct mac_mls *source, *dest; 1300 1301 source = SLOT(newlabel); 1302 dest = SLOT(&cred->cr_label); 1303 1304 mac_mls_copy(source, dest); 1305 } 1306 1307 /* 1308 * Access control checks. 1309 */ 1310 static int 1311 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, 1312 struct ifnet *ifnet, struct label *ifnetlabel) 1313 { 1314 struct mac_mls *a, *b; 1315 1316 if (!mac_mls_enabled) 1317 return (0); 1318 1319 a = SLOT(bpflabel); 1320 b = SLOT(ifnetlabel); 1321 1322 if (mac_mls_equal_single(a, b)) 1323 return (0); 1324 return (EACCES); 1325 } 1326 1327 static int 1328 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel) 1329 { 1330 struct mac_mls *subj, *new; 1331 int error; 1332 1333 subj = SLOT(&cred->cr_label); 1334 new = SLOT(newlabel); 1335 1336 /* 1337 * If there is an MLS label update for the credential, it may be 1338 * an update of single, range, or both. 1339 */ 1340 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); 1341 if (error) 1342 return (error); 1343 1344 /* 1345 * If the MLS label is to be changed, authorize as appropriate. 1346 */ 1347 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { 1348 /* 1349 * To change the MLS single label on a credential, the 1350 * new single label must be in the current range. 1351 */ 1352 if (new->mm_flags & MAC_MLS_FLAG_SINGLE && 1353 !mac_mls_single_in_range(new, subj)) 1354 return (EPERM); 1355 1356 /* 1357 * To change the MLS range label on a credential, the 1358 * new range label must be in the current range. 1359 */ 1360 if (new->mm_flags & MAC_MLS_FLAG_RANGE && 1361 !mac_mls_range_in_range(new, subj)) 1362 return (EPERM); 1363 1364 /* 1365 * To have EQUAL in any component of the new credential 1366 * MLS label, the subject must already have EQUAL in 1367 * their label. 1368 */ 1369 if (mac_mls_contains_equal(new)) { 1370 error = mac_mls_subject_equal_ok(subj); 1371 if (error) 1372 return (error); 1373 } 1374 1375 /* 1376 * XXXMAC: Additional consistency tests regarding the single 1377 * and range of the new label might be performed here. 1378 */ 1379 } 1380 1381 return (0); 1382 } 1383 1384 static int 1385 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2) 1386 { 1387 struct mac_mls *subj, *obj; 1388 1389 if (!mac_mls_enabled) 1390 return (0); 1391 1392 subj = SLOT(&u1->cr_label); 1393 obj = SLOT(&u2->cr_label); 1394 1395 /* XXX: range */ 1396 if (!mac_mls_dominate_single(subj, obj)) 1397 return (ESRCH); 1398 1399 return (0); 1400 } 1401 1402 static int 1403 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, 1404 struct label *ifnetlabel, struct label *newlabel) 1405 { 1406 struct mac_mls *subj, *new; 1407 int error; 1408 1409 subj = SLOT(&cred->cr_label); 1410 new = SLOT(newlabel); 1411 1412 /* 1413 * If there is an MLS label update for the interface, it may 1414 * be an update of single, range, or both. 1415 */ 1416 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); 1417 if (error) 1418 return (error); 1419 1420 /* 1421 * If the MLS label is to be changed, authorize as appropriate. 1422 */ 1423 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { 1424 /* 1425 * Rely on traditional superuser status for the MLS 1426 * interface relabel requirements. XXX: This will go 1427 * away. 1428 */ 1429 error = suser_cred(cred, 0); 1430 if (error) 1431 return (EPERM); 1432 1433 /* 1434 * XXXMAC: Additional consistency tests regarding the single 1435 * and the range of the new label might be performed here. 1436 */ 1437 } 1438 1439 return (0); 1440 } 1441 1442 static int 1443 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, 1444 struct mbuf *m, struct label *mbuflabel) 1445 { 1446 struct mac_mls *p, *i; 1447 1448 if (!mac_mls_enabled) 1449 return (0); 1450 1451 p = SLOT(mbuflabel); 1452 i = SLOT(ifnetlabel); 1453 1454 return (mac_mls_single_in_range(p, i) ? 0 : EACCES); 1455 } 1456 1457 static int 1458 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp, 1459 struct label *mntlabel) 1460 { 1461 struct mac_mls *subj, *obj; 1462 1463 if (!mac_mls_enabled) 1464 return (0); 1465 1466 subj = SLOT(&cred->cr_label); 1467 obj = SLOT(mntlabel); 1468 1469 if (!mac_mls_dominate_single(subj, obj)) 1470 return (EACCES); 1471 1472 return (0); 1473 } 1474 1475 static int 1476 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, 1477 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) 1478 { 1479 1480 if(!mac_mls_enabled) 1481 return (0); 1482 1483 /* XXX: This will be implemented soon... */ 1484 1485 return (0); 1486 } 1487 1488 static int 1489 mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe, 1490 struct label *pipelabel) 1491 { 1492 struct mac_mls *subj, *obj; 1493 1494 if (!mac_mls_enabled) 1495 return (0); 1496 1497 subj = SLOT(&cred->cr_label); 1498 obj = SLOT((pipelabel)); 1499 1500 if (!mac_mls_dominate_single(subj, obj)) 1501 return (EACCES); 1502 1503 return (0); 1504 } 1505 1506 static int 1507 mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe, 1508 struct label *pipelabel) 1509 { 1510 struct mac_mls *subj, *obj; 1511 1512 if (!mac_mls_enabled) 1513 return (0); 1514 1515 subj = SLOT(&cred->cr_label); 1516 obj = SLOT((pipelabel)); 1517 1518 if (!mac_mls_dominate_single(subj, obj)) 1519 return (EACCES); 1520 1521 return (0); 1522 } 1523 1524 static int 1525 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 1526 struct label *pipelabel, struct label *newlabel) 1527 { 1528 struct mac_mls *subj, *obj, *new; 1529 int error; 1530 1531 new = SLOT(newlabel); 1532 subj = SLOT(&cred->cr_label); 1533 obj = SLOT(pipelabel); 1534 1535 /* 1536 * If there is an MLS label update for a pipe, it must be a 1537 * single update. 1538 */ 1539 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); 1540 if (error) 1541 return (error); 1542 1543 /* 1544 * To perform a relabel of a pipe (MLS label or not), MLS must 1545 * authorize the relabel. 1546 */ 1547 if (!mac_mls_single_in_range(obj, subj)) 1548 return (EPERM); 1549 1550 /* 1551 * If the MLS label is to be changed, authorize as appropriate. 1552 */ 1553 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { 1554 /* 1555 * To change the MLS label on a pipe, the new pipe label 1556 * must be in the subject range. 1557 */ 1558 if (!mac_mls_single_in_range(new, subj)) 1559 return (EPERM); 1560 1561 /* 1562 * To change the MLS label on a pipe to be EQUAL, the 1563 * subject must have appropriate privilege. 1564 */ 1565 if (mac_mls_contains_equal(new)) { 1566 error = mac_mls_subject_equal_ok(subj); 1567 if (error) 1568 return (error); 1569 } 1570 } 1571 1572 return (0); 1573 } 1574 1575 static int 1576 mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe, 1577 struct label *pipelabel) 1578 { 1579 struct mac_mls *subj, *obj; 1580 1581 if (!mac_mls_enabled) 1582 return (0); 1583 1584 subj = SLOT(&cred->cr_label); 1585 obj = SLOT((pipelabel)); 1586 1587 if (!mac_mls_dominate_single(subj, obj)) 1588 return (EACCES); 1589 1590 return (0); 1591 } 1592 1593 static int 1594 mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe, 1595 struct label *pipelabel) 1596 { 1597 struct mac_mls *subj, *obj; 1598 1599 if (!mac_mls_enabled) 1600 return (0); 1601 1602 subj = SLOT(&cred->cr_label); 1603 obj = SLOT((pipelabel)); 1604 1605 if (!mac_mls_dominate_single(obj, subj)) 1606 return (EACCES); 1607 1608 return (0); 1609 } 1610 1611 static int 1612 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc) 1613 { 1614 struct mac_mls *subj, *obj; 1615 1616 if (!mac_mls_enabled) 1617 return (0); 1618 1619 subj = SLOT(&cred->cr_label); 1620 obj = SLOT(&proc->p_ucred->cr_label); 1621 1622 /* XXX: range checks */ 1623 if (!mac_mls_dominate_single(subj, obj)) 1624 return (ESRCH); 1625 if (!mac_mls_dominate_single(obj, subj)) 1626 return (EACCES); 1627 1628 return (0); 1629 } 1630 1631 static int 1632 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc) 1633 { 1634 struct mac_mls *subj, *obj; 1635 1636 if (!mac_mls_enabled) 1637 return (0); 1638 1639 subj = SLOT(&cred->cr_label); 1640 obj = SLOT(&proc->p_ucred->cr_label); 1641 1642 /* XXX: range checks */ 1643 if (!mac_mls_dominate_single(subj, obj)) 1644 return (ESRCH); 1645 if (!mac_mls_dominate_single(obj, subj)) 1646 return (EACCES); 1647 1648 return (0); 1649 } 1650 1651 static int 1652 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 1653 { 1654 struct mac_mls *subj, *obj; 1655 1656 if (!mac_mls_enabled) 1657 return (0); 1658 1659 subj = SLOT(&cred->cr_label); 1660 obj = SLOT(&proc->p_ucred->cr_label); 1661 1662 /* XXX: range checks */ 1663 if (!mac_mls_dominate_single(subj, obj)) 1664 return (ESRCH); 1665 if (!mac_mls_dominate_single(obj, subj)) 1666 return (EACCES); 1667 1668 return (0); 1669 } 1670 1671 static int 1672 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel, 1673 struct mbuf *m, struct label *mbuflabel) 1674 { 1675 struct mac_mls *p, *s; 1676 1677 if (!mac_mls_enabled) 1678 return (0); 1679 1680 p = SLOT(mbuflabel); 1681 s = SLOT(socketlabel); 1682 1683 return (mac_mls_equal_single(p, s) ? 0 : EACCES); 1684 } 1685 1686 static int 1687 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket, 1688 struct label *socketlabel, struct label *newlabel) 1689 { 1690 struct mac_mls *subj, *obj, *new; 1691 int error; 1692 1693 new = SLOT(newlabel); 1694 subj = SLOT(&cred->cr_label); 1695 obj = SLOT(socketlabel); 1696 1697 /* 1698 * If there is an MLS label update for the socket, it may be 1699 * an update of single. 1700 */ 1701 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); 1702 if (error) 1703 return (error); 1704 1705 /* 1706 * To relabel a socket, the old socket single must be in the subject 1707 * range. 1708 */ 1709 if (!mac_mls_single_in_range(obj, subj)) 1710 return (EPERM); 1711 1712 /* 1713 * If the MLS label is to be changed, authorize as appropriate. 1714 */ 1715 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { 1716 /* 1717 * To relabel a socket, the new socket single must be in 1718 * the subject range. 1719 */ 1720 if (!mac_mls_single_in_range(new, subj)) 1721 return (EPERM); 1722 1723 /* 1724 * To change the MLS label on the socket to contain EQUAL, 1725 * the subject must have appropriate privilege. 1726 */ 1727 if (mac_mls_contains_equal(new)) { 1728 error = mac_mls_subject_equal_ok(subj); 1729 if (error) 1730 return (error); 1731 } 1732 } 1733 1734 return (0); 1735 } 1736 1737 static int 1738 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket, 1739 struct label *socketlabel) 1740 { 1741 struct mac_mls *subj, *obj; 1742 1743 if (!mac_mls_enabled) 1744 return (0); 1745 1746 subj = SLOT(&cred->cr_label); 1747 obj = SLOT(socketlabel); 1748 1749 if (!mac_mls_dominate_single(subj, obj)) 1750 return (ENOENT); 1751 1752 return (0); 1753 } 1754 1755 static int 1756 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, 1757 struct label *dlabel) 1758 { 1759 struct mac_mls *subj, *obj; 1760 1761 if (!mac_mls_enabled) 1762 return (0); 1763 1764 subj = SLOT(&cred->cr_label); 1765 obj = SLOT(dlabel); 1766 1767 if (!mac_mls_dominate_single(subj, obj)) 1768 return (EACCES); 1769 1770 return (0); 1771 } 1772 1773 static int 1774 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, 1775 struct label *dlabel) 1776 { 1777 struct mac_mls *subj, *obj; 1778 1779 if (!mac_mls_enabled) 1780 return (0); 1781 1782 subj = SLOT(&cred->cr_label); 1783 obj = SLOT(dlabel); 1784 1785 if (!mac_mls_dominate_single(subj, obj)) 1786 return (EACCES); 1787 1788 return (0); 1789 } 1790 1791 static int 1792 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1793 struct label *dlabel, struct componentname *cnp, struct vattr *vap) 1794 { 1795 struct mac_mls *subj, *obj; 1796 1797 if (!mac_mls_enabled) 1798 return (0); 1799 1800 subj = SLOT(&cred->cr_label); 1801 obj = SLOT(dlabel); 1802 1803 if (!mac_mls_dominate_single(obj, subj)) 1804 return (EACCES); 1805 1806 return (0); 1807 } 1808 1809 static int 1810 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp, 1811 struct label *dlabel, struct vnode *vp, struct label *label, 1812 struct componentname *cnp) 1813 { 1814 struct mac_mls *subj, *obj; 1815 1816 if (!mac_mls_enabled) 1817 return (0); 1818 1819 subj = SLOT(&cred->cr_label); 1820 obj = SLOT(dlabel); 1821 1822 if (!mac_mls_dominate_single(obj, subj)) 1823 return (EACCES); 1824 1825 obj = SLOT(label); 1826 1827 if (!mac_mls_dominate_single(obj, subj)) 1828 return (EACCES); 1829 1830 return (0); 1831 } 1832 1833 static int 1834 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1835 struct label *label, acl_type_t type) 1836 { 1837 struct mac_mls *subj, *obj; 1838 1839 if (!mac_mls_enabled) 1840 return (0); 1841 1842 subj = SLOT(&cred->cr_label); 1843 obj = SLOT(label); 1844 1845 if (!mac_mls_dominate_single(obj, subj)) 1846 return (EACCES); 1847 1848 return (0); 1849 } 1850 1851 static int 1852 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1853 struct label *label) 1854 { 1855 struct mac_mls *subj, *obj; 1856 1857 if (!mac_mls_enabled) 1858 return (0); 1859 1860 subj = SLOT(&cred->cr_label); 1861 obj = SLOT(label); 1862 1863 if (!mac_mls_dominate_single(subj, obj)) 1864 return (EACCES); 1865 1866 return (0); 1867 } 1868 1869 static int 1870 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp, 1871 struct label *label, acl_type_t type) 1872 { 1873 struct mac_mls *subj, *obj; 1874 1875 if (!mac_mls_enabled) 1876 return (0); 1877 1878 subj = SLOT(&cred->cr_label); 1879 obj = SLOT(label); 1880 1881 if (!mac_mls_dominate_single(subj, obj)) 1882 return (EACCES); 1883 1884 return (0); 1885 } 1886 1887 static int 1888 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1889 struct label *label, int attrnamespace, const char *name, struct uio *uio) 1890 { 1891 struct mac_mls *subj, *obj; 1892 1893 if (!mac_mls_enabled) 1894 return (0); 1895 1896 subj = SLOT(&cred->cr_label); 1897 obj = SLOT(label); 1898 1899 if (!mac_mls_dominate_single(subj, obj)) 1900 return (EACCES); 1901 1902 return (0); 1903 } 1904 1905 static int 1906 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1907 struct label *dlabel, struct vnode *vp, struct label *label, 1908 struct componentname *cnp) 1909 { 1910 struct mac_mls *subj, *obj; 1911 1912 if (!mac_mls_enabled) 1913 return (0); 1914 1915 subj = SLOT(&cred->cr_label); 1916 obj = SLOT(dlabel); 1917 1918 if (!mac_mls_dominate_single(obj, subj)) 1919 return (EACCES); 1920 1921 obj = SLOT(dlabel); 1922 if (!mac_mls_dominate_single(obj, subj)) 1923 return (EACCES); 1924 1925 return (0); 1926 } 1927 1928 static int 1929 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1930 struct label *dlabel, struct componentname *cnp) 1931 { 1932 struct mac_mls *subj, *obj; 1933 1934 if (!mac_mls_enabled) 1935 return (0); 1936 1937 subj = SLOT(&cred->cr_label); 1938 obj = SLOT(dlabel); 1939 1940 if (!mac_mls_dominate_single(subj, obj)) 1941 return (EACCES); 1942 1943 return (0); 1944 } 1945 1946 static int 1947 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp, 1948 struct label *label, int prot) 1949 { 1950 struct mac_mls *subj, *obj; 1951 1952 /* 1953 * Rely on the use of open()-time protections to handle 1954 * non-revocation cases. 1955 */ 1956 if (!mac_mls_enabled || !revocation_enabled) 1957 return (0); 1958 1959 subj = SLOT(&cred->cr_label); 1960 obj = SLOT(label); 1961 1962 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 1963 if (!mac_mls_dominate_single(subj, obj)) 1964 return (EACCES); 1965 } 1966 if (prot & VM_PROT_WRITE) { 1967 if (!mac_mls_dominate_single(obj, subj)) 1968 return (EACCES); 1969 } 1970 1971 return (0); 1972 } 1973 1974 static int 1975 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp, 1976 struct label *vnodelabel, mode_t acc_mode) 1977 { 1978 struct mac_mls *subj, *obj; 1979 1980 if (!mac_mls_enabled) 1981 return (0); 1982 1983 subj = SLOT(&cred->cr_label); 1984 obj = SLOT(vnodelabel); 1985 1986 /* XXX privilege override for admin? */ 1987 if (acc_mode & (VREAD | VEXEC | VSTAT)) { 1988 if (!mac_mls_dominate_single(subj, obj)) 1989 return (EACCES); 1990 } 1991 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) { 1992 if (!mac_mls_dominate_single(obj, subj)) 1993 return (EACCES); 1994 } 1995 1996 return (0); 1997 } 1998 1999 static int 2000 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2001 struct vnode *vp, struct label *label) 2002 { 2003 struct mac_mls *subj, *obj; 2004 2005 if (!mac_mls_enabled || !revocation_enabled) 2006 return (0); 2007 2008 subj = SLOT(&active_cred->cr_label); 2009 obj = SLOT(label); 2010 2011 if (!mac_mls_dominate_single(subj, obj)) 2012 return (EACCES); 2013 2014 return (0); 2015 } 2016 2017 static int 2018 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2019 struct vnode *vp, struct label *label) 2020 { 2021 struct mac_mls *subj, *obj; 2022 2023 if (!mac_mls_enabled || !revocation_enabled) 2024 return (0); 2025 2026 subj = SLOT(&active_cred->cr_label); 2027 obj = SLOT(label); 2028 2029 if (!mac_mls_dominate_single(subj, obj)) 2030 return (EACCES); 2031 2032 return (0); 2033 } 2034 2035 static int 2036 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, 2037 struct label *dlabel) 2038 { 2039 struct mac_mls *subj, *obj; 2040 2041 if (!mac_mls_enabled) 2042 return (0); 2043 2044 subj = SLOT(&cred->cr_label); 2045 obj = SLOT(dlabel); 2046 2047 if (!mac_mls_dominate_single(subj, obj)) 2048 return (EACCES); 2049 2050 return (0); 2051 } 2052 2053 static int 2054 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp, 2055 struct label *vnodelabel) 2056 { 2057 struct mac_mls *subj, *obj; 2058 2059 if (!mac_mls_enabled) 2060 return (0); 2061 2062 subj = SLOT(&cred->cr_label); 2063 obj = SLOT(vnodelabel); 2064 2065 if (!mac_mls_dominate_single(subj, obj)) 2066 return (EACCES); 2067 2068 return (0); 2069 } 2070 2071 static int 2072 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 2073 struct label *vnodelabel, struct label *newlabel) 2074 { 2075 struct mac_mls *old, *new, *subj; 2076 int error; 2077 2078 old = SLOT(vnodelabel); 2079 new = SLOT(newlabel); 2080 subj = SLOT(&cred->cr_label); 2081 2082 /* 2083 * If there is an MLS label update for the vnode, it must be a 2084 * single label. 2085 */ 2086 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); 2087 if (error) 2088 return (error); 2089 2090 /* 2091 * To perform a relabel of the vnode (MLS label or not), MLS must 2092 * authorize the relabel. 2093 */ 2094 if (!mac_mls_single_in_range(old, subj)) 2095 return (EPERM); 2096 2097 /* 2098 * If the MLS label is to be changed, authorize as appropriate. 2099 */ 2100 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { 2101 /* 2102 * To change the MLS label on a vnode, the new vnode label 2103 * must be in the subject range. 2104 */ 2105 if (!mac_mls_single_in_range(new, subj)) 2106 return (EPERM); 2107 2108 /* 2109 * To change the MLS label on the vnode to be EQUAL, 2110 * the subject must have appropriate privilege. 2111 */ 2112 if (mac_mls_contains_equal(new)) { 2113 error = mac_mls_subject_equal_ok(subj); 2114 if (error) 2115 return (error); 2116 } 2117 } 2118 2119 return (0); 2120 } 2121 2122 2123 static int 2124 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 2125 struct label *dlabel, struct vnode *vp, struct label *label, 2126 struct componentname *cnp) 2127 { 2128 struct mac_mls *subj, *obj; 2129 2130 if (!mac_mls_enabled) 2131 return (0); 2132 2133 subj = SLOT(&cred->cr_label); 2134 obj = SLOT(dlabel); 2135 2136 if (!mac_mls_dominate_single(obj, subj)) 2137 return (EACCES); 2138 2139 obj = SLOT(label); 2140 2141 if (!mac_mls_dominate_single(obj, subj)) 2142 return (EACCES); 2143 2144 return (0); 2145 } 2146 2147 static int 2148 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 2149 struct label *dlabel, struct vnode *vp, struct label *label, int samedir, 2150 struct componentname *cnp) 2151 { 2152 struct mac_mls *subj, *obj; 2153 2154 if (!mac_mls_enabled) 2155 return (0); 2156 2157 subj = SLOT(&cred->cr_label); 2158 obj = SLOT(dlabel); 2159 2160 if (!mac_mls_dominate_single(obj, subj)) 2161 return (EACCES); 2162 2163 if (vp != NULL) { 2164 obj = SLOT(label); 2165 2166 if (!mac_mls_dominate_single(obj, subj)) 2167 return (EACCES); 2168 } 2169 2170 return (0); 2171 } 2172 2173 static int 2174 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp, 2175 struct label *label) 2176 { 2177 struct mac_mls *subj, *obj; 2178 2179 if (!mac_mls_enabled) 2180 return (0); 2181 2182 subj = SLOT(&cred->cr_label); 2183 obj = SLOT(label); 2184 2185 if (!mac_mls_dominate_single(obj, subj)) 2186 return (EACCES); 2187 2188 return (0); 2189 } 2190 2191 static int 2192 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp, 2193 struct label *label, acl_type_t type, struct acl *acl) 2194 { 2195 struct mac_mls *subj, *obj; 2196 2197 if (!mac_mls_enabled) 2198 return (0); 2199 2200 subj = SLOT(&cred->cr_label); 2201 obj = SLOT(label); 2202 2203 if (!mac_mls_dominate_single(obj, subj)) 2204 return (EACCES); 2205 2206 return (0); 2207 } 2208 2209 static int 2210 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 2211 struct label *vnodelabel, int attrnamespace, const char *name, 2212 struct uio *uio) 2213 { 2214 struct mac_mls *subj, *obj; 2215 2216 if (!mac_mls_enabled) 2217 return (0); 2218 2219 subj = SLOT(&cred->cr_label); 2220 obj = SLOT(vnodelabel); 2221 2222 if (!mac_mls_dominate_single(obj, subj)) 2223 return (EACCES); 2224 2225 /* XXX: protect the MAC EA in a special way? */ 2226 2227 return (0); 2228 } 2229 2230 static int 2231 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp, 2232 struct label *vnodelabel, u_long flags) 2233 { 2234 struct mac_mls *subj, *obj; 2235 2236 if (!mac_mls_enabled) 2237 return (0); 2238 2239 subj = SLOT(&cred->cr_label); 2240 obj = SLOT(vnodelabel); 2241 2242 if (!mac_mls_dominate_single(obj, subj)) 2243 return (EACCES); 2244 2245 return (0); 2246 } 2247 2248 static int 2249 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp, 2250 struct label *vnodelabel, mode_t mode) 2251 { 2252 struct mac_mls *subj, *obj; 2253 2254 if (!mac_mls_enabled) 2255 return (0); 2256 2257 subj = SLOT(&cred->cr_label); 2258 obj = SLOT(vnodelabel); 2259 2260 if (!mac_mls_dominate_single(obj, subj)) 2261 return (EACCES); 2262 2263 return (0); 2264 } 2265 2266 static int 2267 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp, 2268 struct label *vnodelabel, uid_t uid, gid_t gid) 2269 { 2270 struct mac_mls *subj, *obj; 2271 2272 if (!mac_mls_enabled) 2273 return (0); 2274 2275 subj = SLOT(&cred->cr_label); 2276 obj = SLOT(vnodelabel); 2277 2278 if (!mac_mls_dominate_single(obj, subj)) 2279 return (EACCES); 2280 2281 return (0); 2282 } 2283 2284 static int 2285 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2286 struct label *vnodelabel, struct timespec atime, struct timespec mtime) 2287 { 2288 struct mac_mls *subj, *obj; 2289 2290 if (!mac_mls_enabled) 2291 return (0); 2292 2293 subj = SLOT(&cred->cr_label); 2294 obj = SLOT(vnodelabel); 2295 2296 if (!mac_mls_dominate_single(obj, subj)) 2297 return (EACCES); 2298 2299 return (0); 2300 } 2301 2302 static int 2303 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2304 struct vnode *vp, struct label *vnodelabel) 2305 { 2306 struct mac_mls *subj, *obj; 2307 2308 if (!mac_mls_enabled) 2309 return (0); 2310 2311 subj = SLOT(&active_cred->cr_label); 2312 obj = SLOT(vnodelabel); 2313 2314 if (!mac_mls_dominate_single(subj, obj)) 2315 return (EACCES); 2316 2317 return (0); 2318 } 2319 2320 static int 2321 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2322 struct vnode *vp, struct label *label) 2323 { 2324 struct mac_mls *subj, *obj; 2325 2326 if (!mac_mls_enabled || !revocation_enabled) 2327 return (0); 2328 2329 subj = SLOT(&active_cred->cr_label); 2330 obj = SLOT(label); 2331 2332 if (!mac_mls_dominate_single(obj, subj)) 2333 return (EACCES); 2334 2335 return (0); 2336 } 2337 2338 static struct mac_policy_op_entry mac_mls_ops[] = 2339 { 2340 { MAC_DESTROY, 2341 (macop_t)mac_mls_destroy }, 2342 { MAC_INIT, 2343 (macop_t)mac_mls_init }, 2344 { MAC_INIT_BPFDESC_LABEL, 2345 (macop_t)mac_mls_init_label }, 2346 { MAC_INIT_CRED_LABEL, 2347 (macop_t)mac_mls_init_label }, 2348 { MAC_INIT_DEVFSDIRENT_LABEL, 2349 (macop_t)mac_mls_init_label }, 2350 { MAC_INIT_IFNET_LABEL, 2351 (macop_t)mac_mls_init_label }, 2352 { MAC_INIT_IPQ_LABEL, 2353 (macop_t)mac_mls_init_label }, 2354 { MAC_INIT_MBUF_LABEL, 2355 (macop_t)mac_mls_init_label_waitcheck }, 2356 { MAC_INIT_MOUNT_LABEL, 2357 (macop_t)mac_mls_init_label }, 2358 { MAC_INIT_MOUNT_FS_LABEL, 2359 (macop_t)mac_mls_init_label }, 2360 { MAC_INIT_PIPE_LABEL, 2361 (macop_t)mac_mls_init_label }, 2362 { MAC_INIT_SOCKET_LABEL, 2363 (macop_t)mac_mls_init_label_waitcheck }, 2364 { MAC_INIT_SOCKET_PEER_LABEL, 2365 (macop_t)mac_mls_init_label_waitcheck }, 2366 { MAC_INIT_VNODE_LABEL, 2367 (macop_t)mac_mls_init_label }, 2368 { MAC_DESTROY_BPFDESC_LABEL, 2369 (macop_t)mac_mls_destroy_label }, 2370 { MAC_DESTROY_CRED_LABEL, 2371 (macop_t)mac_mls_destroy_label }, 2372 { MAC_DESTROY_DEVFSDIRENT_LABEL, 2373 (macop_t)mac_mls_destroy_label }, 2374 { MAC_DESTROY_IFNET_LABEL, 2375 (macop_t)mac_mls_destroy_label }, 2376 { MAC_DESTROY_IPQ_LABEL, 2377 (macop_t)mac_mls_destroy_label }, 2378 { MAC_DESTROY_MBUF_LABEL, 2379 (macop_t)mac_mls_destroy_label }, 2380 { MAC_DESTROY_MOUNT_LABEL, 2381 (macop_t)mac_mls_destroy_label }, 2382 { MAC_DESTROY_MOUNT_FS_LABEL, 2383 (macop_t)mac_mls_destroy_label }, 2384 { MAC_DESTROY_PIPE_LABEL, 2385 (macop_t)mac_mls_destroy_label }, 2386 { MAC_DESTROY_SOCKET_LABEL, 2387 (macop_t)mac_mls_destroy_label }, 2388 { MAC_DESTROY_SOCKET_PEER_LABEL, 2389 (macop_t)mac_mls_destroy_label }, 2390 { MAC_DESTROY_VNODE_LABEL, 2391 (macop_t)mac_mls_destroy_label }, 2392 { MAC_COPY_PIPE_LABEL, 2393 (macop_t)mac_mls_copy_label }, 2394 { MAC_COPY_VNODE_LABEL, 2395 (macop_t)mac_mls_copy_label }, 2396 { MAC_EXTERNALIZE_CRED_LABEL, 2397 (macop_t)mac_mls_externalize_label }, 2398 { MAC_EXTERNALIZE_IFNET_LABEL, 2399 (macop_t)mac_mls_externalize_label }, 2400 { MAC_EXTERNALIZE_PIPE_LABEL, 2401 (macop_t)mac_mls_externalize_label }, 2402 { MAC_EXTERNALIZE_SOCKET_LABEL, 2403 (macop_t)mac_mls_externalize_label }, 2404 { MAC_EXTERNALIZE_SOCKET_PEER_LABEL, 2405 (macop_t)mac_mls_externalize_label }, 2406 { MAC_EXTERNALIZE_VNODE_LABEL, 2407 (macop_t)mac_mls_externalize_label }, 2408 { MAC_EXTERNALIZE_VNODE_OLDMAC, 2409 (macop_t)mac_mls_externalize_vnode_oldmac }, 2410 { MAC_INTERNALIZE_CRED_LABEL, 2411 (macop_t)mac_mls_internalize_label }, 2412 { MAC_INTERNALIZE_IFNET_LABEL, 2413 (macop_t)mac_mls_internalize_label }, 2414 { MAC_INTERNALIZE_PIPE_LABEL, 2415 (macop_t)mac_mls_internalize_label }, 2416 { MAC_INTERNALIZE_SOCKET_LABEL, 2417 (macop_t)mac_mls_internalize_label }, 2418 { MAC_INTERNALIZE_VNODE_LABEL, 2419 (macop_t)mac_mls_internalize_label }, 2420 { MAC_CREATE_DEVFS_DEVICE, 2421 (macop_t)mac_mls_create_devfs_device }, 2422 { MAC_CREATE_DEVFS_DIRECTORY, 2423 (macop_t)mac_mls_create_devfs_directory }, 2424 { MAC_CREATE_DEVFS_SYMLINK, 2425 (macop_t)mac_mls_create_devfs_symlink }, 2426 { MAC_CREATE_DEVFS_VNODE, 2427 (macop_t)mac_mls_create_devfs_vnode }, 2428 { MAC_CREATE_VNODE, 2429 (macop_t)mac_mls_create_vnode }, 2430 { MAC_CREATE_MOUNT, 2431 (macop_t)mac_mls_create_mount }, 2432 { MAC_CREATE_ROOT_MOUNT, 2433 (macop_t)mac_mls_create_root_mount }, 2434 { MAC_RELABEL_VNODE, 2435 (macop_t)mac_mls_relabel_vnode }, 2436 { MAC_UPDATE_DEVFSDIRENT, 2437 (macop_t)mac_mls_update_devfsdirent }, 2438 { MAC_UPDATE_PROCFSVNODE, 2439 (macop_t)mac_mls_update_procfsvnode }, 2440 { MAC_UPDATE_VNODE_FROM_EXTERNALIZED, 2441 (macop_t)mac_mls_update_vnode_from_externalized }, 2442 { MAC_UPDATE_VNODE_FROM_MOUNT, 2443 (macop_t)mac_mls_update_vnode_from_mount }, 2444 { MAC_CREATE_MBUF_FROM_SOCKET, 2445 (macop_t)mac_mls_create_mbuf_from_socket }, 2446 { MAC_CREATE_PIPE, 2447 (macop_t)mac_mls_create_pipe }, 2448 { MAC_CREATE_SOCKET, 2449 (macop_t)mac_mls_create_socket }, 2450 { MAC_CREATE_SOCKET_FROM_SOCKET, 2451 (macop_t)mac_mls_create_socket_from_socket }, 2452 { MAC_RELABEL_PIPE, 2453 (macop_t)mac_mls_relabel_pipe }, 2454 { MAC_RELABEL_SOCKET, 2455 (macop_t)mac_mls_relabel_socket }, 2456 { MAC_SET_SOCKET_PEER_FROM_MBUF, 2457 (macop_t)mac_mls_set_socket_peer_from_mbuf }, 2458 { MAC_SET_SOCKET_PEER_FROM_SOCKET, 2459 (macop_t)mac_mls_set_socket_peer_from_socket }, 2460 { MAC_CREATE_BPFDESC, 2461 (macop_t)mac_mls_create_bpfdesc }, 2462 { MAC_CREATE_DATAGRAM_FROM_IPQ, 2463 (macop_t)mac_mls_create_datagram_from_ipq }, 2464 { MAC_CREATE_FRAGMENT, 2465 (macop_t)mac_mls_create_fragment }, 2466 { MAC_CREATE_IFNET, 2467 (macop_t)mac_mls_create_ifnet }, 2468 { MAC_CREATE_IPQ, 2469 (macop_t)mac_mls_create_ipq }, 2470 { MAC_CREATE_MBUF_FROM_MBUF, 2471 (macop_t)mac_mls_create_mbuf_from_mbuf }, 2472 { MAC_CREATE_MBUF_LINKLAYER, 2473 (macop_t)mac_mls_create_mbuf_linklayer }, 2474 { MAC_CREATE_MBUF_FROM_BPFDESC, 2475 (macop_t)mac_mls_create_mbuf_from_bpfdesc }, 2476 { MAC_CREATE_MBUF_FROM_IFNET, 2477 (macop_t)mac_mls_create_mbuf_from_ifnet }, 2478 { MAC_CREATE_MBUF_MULTICAST_ENCAP, 2479 (macop_t)mac_mls_create_mbuf_multicast_encap }, 2480 { MAC_CREATE_MBUF_NETLAYER, 2481 (macop_t)mac_mls_create_mbuf_netlayer }, 2482 { MAC_FRAGMENT_MATCH, 2483 (macop_t)mac_mls_fragment_match }, 2484 { MAC_RELABEL_IFNET, 2485 (macop_t)mac_mls_relabel_ifnet }, 2486 { MAC_UPDATE_IPQ, 2487 (macop_t)mac_mls_update_ipq }, 2488 { MAC_CREATE_CRED, 2489 (macop_t)mac_mls_create_cred }, 2490 { MAC_EXECVE_TRANSITION, 2491 (macop_t)mac_mls_execve_transition }, 2492 { MAC_EXECVE_WILL_TRANSITION, 2493 (macop_t)mac_mls_execve_will_transition }, 2494 { MAC_CREATE_PROC0, 2495 (macop_t)mac_mls_create_proc0 }, 2496 { MAC_CREATE_PROC1, 2497 (macop_t)mac_mls_create_proc1 }, 2498 { MAC_RELABEL_CRED, 2499 (macop_t)mac_mls_relabel_cred }, 2500 { MAC_CHECK_BPFDESC_RECEIVE, 2501 (macop_t)mac_mls_check_bpfdesc_receive }, 2502 { MAC_CHECK_CRED_RELABEL, 2503 (macop_t)mac_mls_check_cred_relabel }, 2504 { MAC_CHECK_CRED_VISIBLE, 2505 (macop_t)mac_mls_check_cred_visible }, 2506 { MAC_CHECK_IFNET_RELABEL, 2507 (macop_t)mac_mls_check_ifnet_relabel }, 2508 { MAC_CHECK_IFNET_TRANSMIT, 2509 (macop_t)mac_mls_check_ifnet_transmit }, 2510 { MAC_CHECK_MOUNT_STAT, 2511 (macop_t)mac_mls_check_mount_stat }, 2512 { MAC_CHECK_PIPE_IOCTL, 2513 (macop_t)mac_mls_check_pipe_ioctl }, 2514 { MAC_CHECK_PIPE_POLL, 2515 (macop_t)mac_mls_check_pipe_poll }, 2516 { MAC_CHECK_PIPE_READ, 2517 (macop_t)mac_mls_check_pipe_read }, 2518 { MAC_CHECK_PIPE_RELABEL, 2519 (macop_t)mac_mls_check_pipe_relabel }, 2520 { MAC_CHECK_PIPE_STAT, 2521 (macop_t)mac_mls_check_pipe_stat }, 2522 { MAC_CHECK_PIPE_WRITE, 2523 (macop_t)mac_mls_check_pipe_write }, 2524 { MAC_CHECK_PROC_DEBUG, 2525 (macop_t)mac_mls_check_proc_debug }, 2526 { MAC_CHECK_PROC_SCHED, 2527 (macop_t)mac_mls_check_proc_sched }, 2528 { MAC_CHECK_PROC_SIGNAL, 2529 (macop_t)mac_mls_check_proc_signal }, 2530 { MAC_CHECK_SOCKET_DELIVER, 2531 (macop_t)mac_mls_check_socket_deliver }, 2532 { MAC_CHECK_SOCKET_RELABEL, 2533 (macop_t)mac_mls_check_socket_relabel }, 2534 { MAC_CHECK_SOCKET_VISIBLE, 2535 (macop_t)mac_mls_check_socket_visible }, 2536 { MAC_CHECK_VNODE_ACCESS, 2537 (macop_t)mac_mls_check_vnode_open }, 2538 { MAC_CHECK_VNODE_CHDIR, 2539 (macop_t)mac_mls_check_vnode_chdir }, 2540 { MAC_CHECK_VNODE_CHROOT, 2541 (macop_t)mac_mls_check_vnode_chroot }, 2542 { MAC_CHECK_VNODE_CREATE, 2543 (macop_t)mac_mls_check_vnode_create }, 2544 { MAC_CHECK_VNODE_DELETE, 2545 (macop_t)mac_mls_check_vnode_delete }, 2546 { MAC_CHECK_VNODE_DELETEACL, 2547 (macop_t)mac_mls_check_vnode_deleteacl }, 2548 { MAC_CHECK_VNODE_EXEC, 2549 (macop_t)mac_mls_check_vnode_exec }, 2550 { MAC_CHECK_VNODE_GETACL, 2551 (macop_t)mac_mls_check_vnode_getacl }, 2552 { MAC_CHECK_VNODE_GETEXTATTR, 2553 (macop_t)mac_mls_check_vnode_getextattr }, 2554 { MAC_CHECK_VNODE_LINK, 2555 (macop_t)mac_mls_check_vnode_link }, 2556 { MAC_CHECK_VNODE_LOOKUP, 2557 (macop_t)mac_mls_check_vnode_lookup }, 2558 { MAC_CHECK_VNODE_MMAP, 2559 (macop_t)mac_mls_check_vnode_mmap }, 2560 { MAC_CHECK_VNODE_MPROTECT, 2561 (macop_t)mac_mls_check_vnode_mmap }, 2562 { MAC_CHECK_VNODE_OPEN, 2563 (macop_t)mac_mls_check_vnode_open }, 2564 { MAC_CHECK_VNODE_POLL, 2565 (macop_t)mac_mls_check_vnode_poll }, 2566 { MAC_CHECK_VNODE_READ, 2567 (macop_t)mac_mls_check_vnode_read }, 2568 { MAC_CHECK_VNODE_READDIR, 2569 (macop_t)mac_mls_check_vnode_readdir }, 2570 { MAC_CHECK_VNODE_READLINK, 2571 (macop_t)mac_mls_check_vnode_readlink }, 2572 { MAC_CHECK_VNODE_RELABEL, 2573 (macop_t)mac_mls_check_vnode_relabel }, 2574 { MAC_CHECK_VNODE_RENAME_FROM, 2575 (macop_t)mac_mls_check_vnode_rename_from }, 2576 { MAC_CHECK_VNODE_RENAME_TO, 2577 (macop_t)mac_mls_check_vnode_rename_to }, 2578 { MAC_CHECK_VNODE_REVOKE, 2579 (macop_t)mac_mls_check_vnode_revoke }, 2580 { MAC_CHECK_VNODE_SETACL, 2581 (macop_t)mac_mls_check_vnode_setacl }, 2582 { MAC_CHECK_VNODE_SETEXTATTR, 2583 (macop_t)mac_mls_check_vnode_setextattr }, 2584 { MAC_CHECK_VNODE_SETFLAGS, 2585 (macop_t)mac_mls_check_vnode_setflags }, 2586 { MAC_CHECK_VNODE_SETMODE, 2587 (macop_t)mac_mls_check_vnode_setmode }, 2588 { MAC_CHECK_VNODE_SETOWNER, 2589 (macop_t)mac_mls_check_vnode_setowner }, 2590 { MAC_CHECK_VNODE_SETUTIMES, 2591 (macop_t)mac_mls_check_vnode_setutimes }, 2592 { MAC_CHECK_VNODE_STAT, 2593 (macop_t)mac_mls_check_vnode_stat }, 2594 { MAC_CHECK_VNODE_WRITE, 2595 (macop_t)mac_mls_check_vnode_write }, 2596 { MAC_OP_LAST, NULL } 2597 }; 2598 2599 MAC_POLICY_SET(mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS", 2600 MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot); 2601