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