1 /*- 2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc. 4 * All rights reserved. 5 * 6 * This software was developed by Robert Watson for the TrustedBSD Project. 7 * 8 * This software was developed for the FreeBSD Project in part by Network 9 * Associates Laboratories, the Security Research Division of Network 10 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 11 * as part of the DARPA CHATS research program. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $FreeBSD$ 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 79 SYSCTL_DECL(_security_mac); 80 81 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0, 82 "TrustedBSD mac_mls policy controls"); 83 84 static int mac_mls_label_size = sizeof(struct mac_mls); 85 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD, 86 &mac_mls_label_size, 0, "Size of struct mac_mls"); 87 88 static int mac_mls_enabled = 1; 89 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, 90 &mac_mls_enabled, 0, "Enforce MAC/MLS policy"); 91 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled); 92 93 static int destroyed_not_inited; 94 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 95 &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 96 97 static int ptys_equal = 0; 98 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW, 99 &ptys_equal, 0, "Label pty devices as mls/equal on create"); 100 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal); 101 102 static int revocation_enabled = 0; 103 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW, 104 &revocation_enabled, 0, "Revoke access to objects on relabel"); 105 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled); 106 107 static int max_compartments = MAC_MLS_MAX_COMPARTMENTS; 108 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD, 109 &max_compartments, 0, "Maximum compartments the policy supports"); 110 111 static int mac_mls_slot; 112 #define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr) 113 114 MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels"); 115 116 static __inline int 117 mls_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 126 static struct mac_mls * 127 mls_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 136 static void 137 mls_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 146 static int 147 mls_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 155 static int 156 mac_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 208 static int 209 mac_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 218 static int 219 mac_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 235 static int 236 mac_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 246 static int 247 mac_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 257 static int 258 mac_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 269 static int 270 mac_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 287 static int 288 mac_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 312 static int 313 mac_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 384 static void 385 mac_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 405 static void 406 mac_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 418 static void 419 mac_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 430 static void 431 mac_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 441 static void 442 mac_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 */ 454 static void 455 mac_mls_destroy(struct mac_policy_conf *conf) 456 { 457 458 } 459 460 static void 461 mac_mls_init(struct mac_policy_conf *conf) 462 { 463 464 } 465 466 /* 467 * Label operations. 468 */ 469 static void 470 mac_mls_init_label(struct label *label) 471 { 472 473 SLOT(label) = mls_alloc(M_WAITOK); 474 } 475 476 static int 477 mac_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 487 static void 488 mac_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 */ 500 static size_t 501 mac_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 533 static size_t 534 mac_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 591 static int 592 mac_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 613 static int 614 mac_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 */ 672 static int 673 mac_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 735 static int 736 mac_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 757 static void 758 mac_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 */ 768 static void 769 mac_mls_create_devfs_device(struct mount *mp, dev_t dev, 770 struct devfs_dirent *devfs_dirent, struct label *label) 771 { 772 struct mac_mls *mac_mls; 773 int mls_type; 774 775 mac_mls = SLOT(label); 776 if (strcmp(dev->si_name, "null") == 0 || 777 strcmp(dev->si_name, "zero") == 0 || 778 strcmp(dev->si_name, "random") == 0 || 779 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0) 780 mls_type = MAC_MLS_TYPE_EQUAL; 781 else if (strcmp(dev->si_name, "kmem") == 0 || 782 strcmp(dev->si_name, "mem") == 0) 783 mls_type = MAC_MLS_TYPE_HIGH; 784 else if (ptys_equal && 785 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || 786 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) 787 mls_type = MAC_MLS_TYPE_EQUAL; 788 else 789 mls_type = MAC_MLS_TYPE_LOW; 790 mac_mls_set_single(mac_mls, mls_type, 0, NULL); 791 } 792 793 static void 794 mac_mls_create_devfs_directory(struct mount *mp, char *dirname, 795 int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label) 796 { 797 struct mac_mls *mac_mls; 798 799 mac_mls = SLOT(label); 800 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); 801 } 802 803 static void 804 mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp, 805 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 806 struct label *delabel) 807 { 808 struct mac_mls *source, *dest; 809 810 source = SLOT(&cred->cr_label); 811 dest = SLOT(delabel); 812 813 mac_mls_copy_single(source, dest); 814 } 815 816 static void 817 mac_mls_create_mount(struct ucred *cred, struct mount *mp, 818 struct label *mntlabel, struct label *fslabel) 819 { 820 struct mac_mls *source, *dest; 821 822 source = SLOT(&cred->cr_label); 823 dest = SLOT(mntlabel); 824 mac_mls_copy_single(source, dest); 825 dest = SLOT(fslabel); 826 mac_mls_copy_single(source, dest); 827 } 828 829 static void 830 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp, 831 struct label *mntlabel, struct label *fslabel) 832 { 833 struct mac_mls *mac_mls; 834 835 /* Always mount root as high integrity. */ 836 mac_mls = SLOT(fslabel); 837 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); 838 mac_mls = SLOT(mntlabel); 839 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL); 840 } 841 842 static void 843 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp, 844 struct label *vnodelabel, struct label *label) 845 { 846 struct mac_mls *source, *dest; 847 848 source = SLOT(label); 849 dest = SLOT(vnodelabel); 850 851 mac_mls_copy(source, dest); 852 } 853 854 static void 855 mac_mls_update_devfsdirent(struct mount *mp, 856 struct devfs_dirent *devfs_dirent, struct label *direntlabel, 857 struct vnode *vp, struct label *vnodelabel) 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 867 static void 868 mac_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 880 static int 881 mac_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 920 static void 921 mac_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 932 static int 933 mac_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 955 static int 956 mac_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 */ 980 static void 981 mac_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 992 static void 993 mac_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 1004 static void 1005 mac_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 1016 static void 1017 mac_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 1029 static void 1030 mac_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 1041 static void 1042 mac_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 1053 static void 1054 mac_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 */ 1068 static void 1069 mac_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 1081 static void 1082 mac_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 1093 static void 1094 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel) 1095 { 1096 struct mac_mls *dest; 1097 int type; 1098 1099 dest = SLOT(ifnetlabel); 1100 1101 if (ifnet->if_type == IFT_LOOP) 1102 type = MAC_MLS_TYPE_EQUAL; 1103 else 1104 type = MAC_MLS_TYPE_LOW; 1105 1106 mac_mls_set_single(dest, type, 0, NULL); 1107 mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL); 1108 } 1109 1110 static void 1111 mac_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 1122 static void 1123 mac_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 1135 static void 1136 mac_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 1147 static void 1148 mac_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 1168 static void 1169 mac_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 1179 static void 1180 mac_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 1191 static void 1192 mac_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 1203 static void 1204 mac_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 1216 static void 1217 mac_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 1228 static int 1229 mac_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 1240 static void 1241 mac_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 1252 static void 1253 mac_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 */ 1263 static void 1264 mac_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 1275 static void 1276 mac_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 1287 static void 1288 mac_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 1299 static void 1300 mac_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 */ 1313 static int 1314 mac_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 1330 static int 1331 mac_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 * If the change request modifies both the MLS label single 1353 * and range, check that the new single will be in the 1354 * new range. 1355 */ 1356 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) == 1357 MAC_MLS_FLAGS_BOTH && 1358 !mac_mls_single_in_range(new, new)) 1359 return (EINVAL); 1360 1361 /* 1362 * To change the MLS single label on a credential, the 1363 * new single label must be in the current range. 1364 */ 1365 if (new->mm_flags & MAC_MLS_FLAG_SINGLE && 1366 !mac_mls_single_in_range(new, subj)) 1367 return (EPERM); 1368 1369 /* 1370 * To change the MLS range label on a credential, the 1371 * new range must be in the current range. 1372 */ 1373 if (new->mm_flags & MAC_MLS_FLAG_RANGE && 1374 !mac_mls_range_in_range(new, subj)) 1375 return (EPERM); 1376 1377 /* 1378 * To have EQUAL in any component of the new credential 1379 * MLS label, the subject must already have EQUAL in 1380 * their label. 1381 */ 1382 if (mac_mls_contains_equal(new)) { 1383 error = mac_mls_subject_equal_ok(subj); 1384 if (error) 1385 return (error); 1386 } 1387 } 1388 1389 return (0); 1390 } 1391 1392 static int 1393 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2) 1394 { 1395 struct mac_mls *subj, *obj; 1396 1397 if (!mac_mls_enabled) 1398 return (0); 1399 1400 subj = SLOT(&u1->cr_label); 1401 obj = SLOT(&u2->cr_label); 1402 1403 /* XXX: range */ 1404 if (!mac_mls_dominate_single(subj, obj)) 1405 return (ESRCH); 1406 1407 return (0); 1408 } 1409 1410 static int 1411 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, 1412 struct label *ifnetlabel, struct label *newlabel) 1413 { 1414 struct mac_mls *subj, *new; 1415 int error; 1416 1417 subj = SLOT(&cred->cr_label); 1418 new = SLOT(newlabel); 1419 1420 /* 1421 * If there is an MLS label update for the interface, it may 1422 * be an update of single, range, or both. 1423 */ 1424 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); 1425 if (error) 1426 return (error); 1427 1428 /* 1429 * If the MLS label is to be changed, authorize as appropriate. 1430 */ 1431 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { 1432 /* 1433 * Rely on traditional superuser status for the MLS 1434 * interface relabel requirements. XXX: This will go 1435 * away. 1436 */ 1437 error = suser_cred(cred, 0); 1438 if (error) 1439 return (EPERM); 1440 1441 /* 1442 * XXXMAC: Additional consistency tests regarding the single 1443 * and the range of the new label might be performed here. 1444 */ 1445 } 1446 1447 return (0); 1448 } 1449 1450 static int 1451 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel, 1452 struct mbuf *m, struct label *mbuflabel) 1453 { 1454 struct mac_mls *p, *i; 1455 1456 if (!mac_mls_enabled) 1457 return (0); 1458 1459 p = SLOT(mbuflabel); 1460 i = SLOT(ifnetlabel); 1461 1462 return (mac_mls_single_in_range(p, i) ? 0 : EACCES); 1463 } 1464 1465 static int 1466 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp, 1467 struct label *mntlabel) 1468 { 1469 struct mac_mls *subj, *obj; 1470 1471 if (!mac_mls_enabled) 1472 return (0); 1473 1474 subj = SLOT(&cred->cr_label); 1475 obj = SLOT(mntlabel); 1476 1477 if (!mac_mls_dominate_single(subj, obj)) 1478 return (EACCES); 1479 1480 return (0); 1481 } 1482 1483 static int 1484 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, 1485 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data) 1486 { 1487 1488 if(!mac_mls_enabled) 1489 return (0); 1490 1491 /* XXX: This will be implemented soon... */ 1492 1493 return (0); 1494 } 1495 1496 static int 1497 mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe, 1498 struct label *pipelabel) 1499 { 1500 struct mac_mls *subj, *obj; 1501 1502 if (!mac_mls_enabled) 1503 return (0); 1504 1505 subj = SLOT(&cred->cr_label); 1506 obj = SLOT((pipelabel)); 1507 1508 if (!mac_mls_dominate_single(subj, obj)) 1509 return (EACCES); 1510 1511 return (0); 1512 } 1513 1514 static int 1515 mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe, 1516 struct label *pipelabel) 1517 { 1518 struct mac_mls *subj, *obj; 1519 1520 if (!mac_mls_enabled) 1521 return (0); 1522 1523 subj = SLOT(&cred->cr_label); 1524 obj = SLOT((pipelabel)); 1525 1526 if (!mac_mls_dominate_single(subj, obj)) 1527 return (EACCES); 1528 1529 return (0); 1530 } 1531 1532 static int 1533 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 1534 struct label *pipelabel, struct label *newlabel) 1535 { 1536 struct mac_mls *subj, *obj, *new; 1537 int error; 1538 1539 new = SLOT(newlabel); 1540 subj = SLOT(&cred->cr_label); 1541 obj = SLOT(pipelabel); 1542 1543 /* 1544 * If there is an MLS label update for a pipe, it must be a 1545 * single update. 1546 */ 1547 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); 1548 if (error) 1549 return (error); 1550 1551 /* 1552 * To perform a relabel of a pipe (MLS label or not), MLS must 1553 * authorize the relabel. 1554 */ 1555 if (!mac_mls_single_in_range(obj, subj)) 1556 return (EPERM); 1557 1558 /* 1559 * If the MLS label is to be changed, authorize as appropriate. 1560 */ 1561 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { 1562 /* 1563 * To change the MLS label on a pipe, the new pipe label 1564 * must be in the subject range. 1565 */ 1566 if (!mac_mls_single_in_range(new, subj)) 1567 return (EPERM); 1568 1569 /* 1570 * To change the MLS label on a pipe to be EQUAL, the 1571 * subject must have appropriate privilege. 1572 */ 1573 if (mac_mls_contains_equal(new)) { 1574 error = mac_mls_subject_equal_ok(subj); 1575 if (error) 1576 return (error); 1577 } 1578 } 1579 1580 return (0); 1581 } 1582 1583 static int 1584 mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe, 1585 struct label *pipelabel) 1586 { 1587 struct mac_mls *subj, *obj; 1588 1589 if (!mac_mls_enabled) 1590 return (0); 1591 1592 subj = SLOT(&cred->cr_label); 1593 obj = SLOT((pipelabel)); 1594 1595 if (!mac_mls_dominate_single(subj, obj)) 1596 return (EACCES); 1597 1598 return (0); 1599 } 1600 1601 static int 1602 mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe, 1603 struct label *pipelabel) 1604 { 1605 struct mac_mls *subj, *obj; 1606 1607 if (!mac_mls_enabled) 1608 return (0); 1609 1610 subj = SLOT(&cred->cr_label); 1611 obj = SLOT((pipelabel)); 1612 1613 if (!mac_mls_dominate_single(obj, subj)) 1614 return (EACCES); 1615 1616 return (0); 1617 } 1618 1619 static int 1620 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc) 1621 { 1622 struct mac_mls *subj, *obj; 1623 1624 if (!mac_mls_enabled) 1625 return (0); 1626 1627 subj = SLOT(&cred->cr_label); 1628 obj = SLOT(&proc->p_ucred->cr_label); 1629 1630 /* XXX: range checks */ 1631 if (!mac_mls_dominate_single(subj, obj)) 1632 return (ESRCH); 1633 if (!mac_mls_dominate_single(obj, subj)) 1634 return (EACCES); 1635 1636 return (0); 1637 } 1638 1639 static int 1640 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc) 1641 { 1642 struct mac_mls *subj, *obj; 1643 1644 if (!mac_mls_enabled) 1645 return (0); 1646 1647 subj = SLOT(&cred->cr_label); 1648 obj = SLOT(&proc->p_ucred->cr_label); 1649 1650 /* XXX: range checks */ 1651 if (!mac_mls_dominate_single(subj, obj)) 1652 return (ESRCH); 1653 if (!mac_mls_dominate_single(obj, subj)) 1654 return (EACCES); 1655 1656 return (0); 1657 } 1658 1659 static int 1660 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum) 1661 { 1662 struct mac_mls *subj, *obj; 1663 1664 if (!mac_mls_enabled) 1665 return (0); 1666 1667 subj = SLOT(&cred->cr_label); 1668 obj = SLOT(&proc->p_ucred->cr_label); 1669 1670 /* XXX: range checks */ 1671 if (!mac_mls_dominate_single(subj, obj)) 1672 return (ESRCH); 1673 if (!mac_mls_dominate_single(obj, subj)) 1674 return (EACCES); 1675 1676 return (0); 1677 } 1678 1679 static int 1680 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel, 1681 struct mbuf *m, struct label *mbuflabel) 1682 { 1683 struct mac_mls *p, *s; 1684 1685 if (!mac_mls_enabled) 1686 return (0); 1687 1688 p = SLOT(mbuflabel); 1689 s = SLOT(socketlabel); 1690 1691 return (mac_mls_equal_single(p, s) ? 0 : EACCES); 1692 } 1693 1694 static int 1695 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket, 1696 struct label *socketlabel, struct label *newlabel) 1697 { 1698 struct mac_mls *subj, *obj, *new; 1699 int error; 1700 1701 new = SLOT(newlabel); 1702 subj = SLOT(&cred->cr_label); 1703 obj = SLOT(socketlabel); 1704 1705 /* 1706 * If there is an MLS label update for the socket, it may be 1707 * an update of single. 1708 */ 1709 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); 1710 if (error) 1711 return (error); 1712 1713 /* 1714 * To relabel a socket, the old socket single must be in the subject 1715 * range. 1716 */ 1717 if (!mac_mls_single_in_range(obj, subj)) 1718 return (EPERM); 1719 1720 /* 1721 * If the MLS label is to be changed, authorize as appropriate. 1722 */ 1723 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { 1724 /* 1725 * To relabel a socket, the new socket single must be in 1726 * the subject range. 1727 */ 1728 if (!mac_mls_single_in_range(new, subj)) 1729 return (EPERM); 1730 1731 /* 1732 * To change the MLS label on the socket to contain EQUAL, 1733 * the subject must have appropriate privilege. 1734 */ 1735 if (mac_mls_contains_equal(new)) { 1736 error = mac_mls_subject_equal_ok(subj); 1737 if (error) 1738 return (error); 1739 } 1740 } 1741 1742 return (0); 1743 } 1744 1745 static int 1746 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket, 1747 struct label *socketlabel) 1748 { 1749 struct mac_mls *subj, *obj; 1750 1751 if (!mac_mls_enabled) 1752 return (0); 1753 1754 subj = SLOT(&cred->cr_label); 1755 obj = SLOT(socketlabel); 1756 1757 if (!mac_mls_dominate_single(subj, obj)) 1758 return (ENOENT); 1759 1760 return (0); 1761 } 1762 1763 static int 1764 mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp, 1765 struct label *label) 1766 { 1767 struct mac_mls *subj, *obj; 1768 1769 if (!mac_mls_enabled) 1770 return (0); 1771 1772 subj = SLOT(&cred->cr_label); 1773 obj = SLOT(label); 1774 1775 if (!mac_mls_dominate_single(obj, subj) || 1776 !mac_mls_dominate_single(subj, obj)) 1777 return (EACCES); 1778 1779 return (0); 1780 } 1781 1782 static int 1783 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, 1784 struct label *dlabel) 1785 { 1786 struct mac_mls *subj, *obj; 1787 1788 if (!mac_mls_enabled) 1789 return (0); 1790 1791 subj = SLOT(&cred->cr_label); 1792 obj = SLOT(dlabel); 1793 1794 if (!mac_mls_dominate_single(subj, obj)) 1795 return (EACCES); 1796 1797 return (0); 1798 } 1799 1800 static int 1801 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, 1802 struct label *dlabel) 1803 { 1804 struct mac_mls *subj, *obj; 1805 1806 if (!mac_mls_enabled) 1807 return (0); 1808 1809 subj = SLOT(&cred->cr_label); 1810 obj = SLOT(dlabel); 1811 1812 if (!mac_mls_dominate_single(subj, obj)) 1813 return (EACCES); 1814 1815 return (0); 1816 } 1817 1818 static int 1819 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp, 1820 struct label *dlabel, struct componentname *cnp, struct vattr *vap) 1821 { 1822 struct mac_mls *subj, *obj; 1823 1824 if (!mac_mls_enabled) 1825 return (0); 1826 1827 subj = SLOT(&cred->cr_label); 1828 obj = SLOT(dlabel); 1829 1830 if (!mac_mls_dominate_single(obj, subj)) 1831 return (EACCES); 1832 1833 return (0); 1834 } 1835 1836 static int 1837 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp, 1838 struct label *dlabel, struct vnode *vp, struct label *label, 1839 struct componentname *cnp) 1840 { 1841 struct mac_mls *subj, *obj; 1842 1843 if (!mac_mls_enabled) 1844 return (0); 1845 1846 subj = SLOT(&cred->cr_label); 1847 obj = SLOT(dlabel); 1848 1849 if (!mac_mls_dominate_single(obj, subj)) 1850 return (EACCES); 1851 1852 obj = SLOT(label); 1853 1854 if (!mac_mls_dominate_single(obj, subj)) 1855 return (EACCES); 1856 1857 return (0); 1858 } 1859 1860 static int 1861 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, 1862 struct label *label, acl_type_t type) 1863 { 1864 struct mac_mls *subj, *obj; 1865 1866 if (!mac_mls_enabled) 1867 return (0); 1868 1869 subj = SLOT(&cred->cr_label); 1870 obj = SLOT(label); 1871 1872 if (!mac_mls_dominate_single(obj, subj)) 1873 return (EACCES); 1874 1875 return (0); 1876 } 1877 1878 static int 1879 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp, 1880 struct label *label, struct image_params *imgp, 1881 struct label *execlabel) 1882 { 1883 struct mac_mls *subj, *obj, *exec; 1884 int error; 1885 1886 if (execlabel != NULL) { 1887 /* 1888 * We currently don't permit labels to be changed at 1889 * exec-time as part of MLS, so disallow non-NULL 1890 * MLS label elements in the execlabel. 1891 */ 1892 exec = SLOT(execlabel); 1893 error = mls_atmostflags(exec, 0); 1894 if (error) 1895 return (error); 1896 } 1897 1898 if (!mac_mls_enabled) 1899 return (0); 1900 1901 subj = SLOT(&cred->cr_label); 1902 obj = SLOT(label); 1903 1904 if (!mac_mls_dominate_single(subj, obj)) 1905 return (EACCES); 1906 1907 return (0); 1908 } 1909 1910 static int 1911 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp, 1912 struct label *label, acl_type_t type) 1913 { 1914 struct mac_mls *subj, *obj; 1915 1916 if (!mac_mls_enabled) 1917 return (0); 1918 1919 subj = SLOT(&cred->cr_label); 1920 obj = SLOT(label); 1921 1922 if (!mac_mls_dominate_single(subj, obj)) 1923 return (EACCES); 1924 1925 return (0); 1926 } 1927 1928 static int 1929 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, 1930 struct label *label, int attrnamespace, const char *name, struct uio *uio) 1931 { 1932 struct mac_mls *subj, *obj; 1933 1934 if (!mac_mls_enabled) 1935 return (0); 1936 1937 subj = SLOT(&cred->cr_label); 1938 obj = SLOT(label); 1939 1940 if (!mac_mls_dominate_single(subj, obj)) 1941 return (EACCES); 1942 1943 return (0); 1944 } 1945 1946 static int 1947 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp, 1948 struct label *dlabel, struct vnode *vp, struct label *label, 1949 struct componentname *cnp) 1950 { 1951 struct mac_mls *subj, *obj; 1952 1953 if (!mac_mls_enabled) 1954 return (0); 1955 1956 subj = SLOT(&cred->cr_label); 1957 obj = SLOT(dlabel); 1958 1959 if (!mac_mls_dominate_single(obj, subj)) 1960 return (EACCES); 1961 1962 obj = SLOT(dlabel); 1963 if (!mac_mls_dominate_single(obj, subj)) 1964 return (EACCES); 1965 1966 return (0); 1967 } 1968 1969 static int 1970 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, 1971 struct label *dlabel, struct componentname *cnp) 1972 { 1973 struct mac_mls *subj, *obj; 1974 1975 if (!mac_mls_enabled) 1976 return (0); 1977 1978 subj = SLOT(&cred->cr_label); 1979 obj = SLOT(dlabel); 1980 1981 if (!mac_mls_dominate_single(subj, obj)) 1982 return (EACCES); 1983 1984 return (0); 1985 } 1986 1987 static int 1988 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp, 1989 struct label *label, int prot) 1990 { 1991 struct mac_mls *subj, *obj; 1992 1993 /* 1994 * Rely on the use of open()-time protections to handle 1995 * non-revocation cases. 1996 */ 1997 if (!mac_mls_enabled || !revocation_enabled) 1998 return (0); 1999 2000 subj = SLOT(&cred->cr_label); 2001 obj = SLOT(label); 2002 2003 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 2004 if (!mac_mls_dominate_single(subj, obj)) 2005 return (EACCES); 2006 } 2007 if (prot & VM_PROT_WRITE) { 2008 if (!mac_mls_dominate_single(obj, subj)) 2009 return (EACCES); 2010 } 2011 2012 return (0); 2013 } 2014 2015 static int 2016 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp, 2017 struct label *vnodelabel, int acc_mode) 2018 { 2019 struct mac_mls *subj, *obj; 2020 2021 if (!mac_mls_enabled) 2022 return (0); 2023 2024 subj = SLOT(&cred->cr_label); 2025 obj = SLOT(vnodelabel); 2026 2027 /* XXX privilege override for admin? */ 2028 if (acc_mode & (VREAD | VEXEC | VSTAT)) { 2029 if (!mac_mls_dominate_single(subj, obj)) 2030 return (EACCES); 2031 } 2032 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) { 2033 if (!mac_mls_dominate_single(obj, subj)) 2034 return (EACCES); 2035 } 2036 2037 return (0); 2038 } 2039 2040 static int 2041 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, 2042 struct vnode *vp, struct label *label) 2043 { 2044 struct mac_mls *subj, *obj; 2045 2046 if (!mac_mls_enabled || !revocation_enabled) 2047 return (0); 2048 2049 subj = SLOT(&active_cred->cr_label); 2050 obj = SLOT(label); 2051 2052 if (!mac_mls_dominate_single(subj, obj)) 2053 return (EACCES); 2054 2055 return (0); 2056 } 2057 2058 static int 2059 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, 2060 struct vnode *vp, struct label *label) 2061 { 2062 struct mac_mls *subj, *obj; 2063 2064 if (!mac_mls_enabled || !revocation_enabled) 2065 return (0); 2066 2067 subj = SLOT(&active_cred->cr_label); 2068 obj = SLOT(label); 2069 2070 if (!mac_mls_dominate_single(subj, obj)) 2071 return (EACCES); 2072 2073 return (0); 2074 } 2075 2076 static int 2077 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, 2078 struct label *dlabel) 2079 { 2080 struct mac_mls *subj, *obj; 2081 2082 if (!mac_mls_enabled) 2083 return (0); 2084 2085 subj = SLOT(&cred->cr_label); 2086 obj = SLOT(dlabel); 2087 2088 if (!mac_mls_dominate_single(subj, obj)) 2089 return (EACCES); 2090 2091 return (0); 2092 } 2093 2094 static int 2095 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp, 2096 struct label *vnodelabel) 2097 { 2098 struct mac_mls *subj, *obj; 2099 2100 if (!mac_mls_enabled) 2101 return (0); 2102 2103 subj = SLOT(&cred->cr_label); 2104 obj = SLOT(vnodelabel); 2105 2106 if (!mac_mls_dominate_single(subj, obj)) 2107 return (EACCES); 2108 2109 return (0); 2110 } 2111 2112 static int 2113 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp, 2114 struct label *vnodelabel, struct label *newlabel) 2115 { 2116 struct mac_mls *old, *new, *subj; 2117 int error; 2118 2119 old = SLOT(vnodelabel); 2120 new = SLOT(newlabel); 2121 subj = SLOT(&cred->cr_label); 2122 2123 /* 2124 * If there is an MLS label update for the vnode, it must be a 2125 * single label. 2126 */ 2127 error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE); 2128 if (error) 2129 return (error); 2130 2131 /* 2132 * To perform a relabel of the vnode (MLS label or not), MLS must 2133 * authorize the relabel. 2134 */ 2135 if (!mac_mls_single_in_range(old, subj)) 2136 return (EPERM); 2137 2138 /* 2139 * If the MLS label is to be changed, authorize as appropriate. 2140 */ 2141 if (new->mm_flags & MAC_MLS_FLAG_SINGLE) { 2142 /* 2143 * To change the MLS label on a vnode, the new vnode label 2144 * must be in the subject range. 2145 */ 2146 if (!mac_mls_single_in_range(new, subj)) 2147 return (EPERM); 2148 2149 /* 2150 * To change the MLS label on the vnode to be EQUAL, 2151 * the subject must have appropriate privilege. 2152 */ 2153 if (mac_mls_contains_equal(new)) { 2154 error = mac_mls_subject_equal_ok(subj); 2155 if (error) 2156 return (error); 2157 } 2158 } 2159 2160 return (0); 2161 } 2162 2163 2164 static int 2165 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, 2166 struct label *dlabel, struct vnode *vp, struct label *label, 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 obj = SLOT(label); 2181 2182 if (!mac_mls_dominate_single(obj, subj)) 2183 return (EACCES); 2184 2185 return (0); 2186 } 2187 2188 static int 2189 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, 2190 struct label *dlabel, struct vnode *vp, struct label *label, int samedir, 2191 struct componentname *cnp) 2192 { 2193 struct mac_mls *subj, *obj; 2194 2195 if (!mac_mls_enabled) 2196 return (0); 2197 2198 subj = SLOT(&cred->cr_label); 2199 obj = SLOT(dlabel); 2200 2201 if (!mac_mls_dominate_single(obj, subj)) 2202 return (EACCES); 2203 2204 if (vp != NULL) { 2205 obj = SLOT(label); 2206 2207 if (!mac_mls_dominate_single(obj, subj)) 2208 return (EACCES); 2209 } 2210 2211 return (0); 2212 } 2213 2214 static int 2215 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp, 2216 struct label *label) 2217 { 2218 struct mac_mls *subj, *obj; 2219 2220 if (!mac_mls_enabled) 2221 return (0); 2222 2223 subj = SLOT(&cred->cr_label); 2224 obj = SLOT(label); 2225 2226 if (!mac_mls_dominate_single(obj, subj)) 2227 return (EACCES); 2228 2229 return (0); 2230 } 2231 2232 static int 2233 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp, 2234 struct label *label, acl_type_t type, struct acl *acl) 2235 { 2236 struct mac_mls *subj, *obj; 2237 2238 if (!mac_mls_enabled) 2239 return (0); 2240 2241 subj = SLOT(&cred->cr_label); 2242 obj = SLOT(label); 2243 2244 if (!mac_mls_dominate_single(obj, subj)) 2245 return (EACCES); 2246 2247 return (0); 2248 } 2249 2250 static int 2251 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, 2252 struct label *vnodelabel, int attrnamespace, const char *name, 2253 struct uio *uio) 2254 { 2255 struct mac_mls *subj, *obj; 2256 2257 if (!mac_mls_enabled) 2258 return (0); 2259 2260 subj = SLOT(&cred->cr_label); 2261 obj = SLOT(vnodelabel); 2262 2263 if (!mac_mls_dominate_single(obj, subj)) 2264 return (EACCES); 2265 2266 /* XXX: protect the MAC EA in a special way? */ 2267 2268 return (0); 2269 } 2270 2271 static int 2272 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp, 2273 struct label *vnodelabel, u_long flags) 2274 { 2275 struct mac_mls *subj, *obj; 2276 2277 if (!mac_mls_enabled) 2278 return (0); 2279 2280 subj = SLOT(&cred->cr_label); 2281 obj = SLOT(vnodelabel); 2282 2283 if (!mac_mls_dominate_single(obj, subj)) 2284 return (EACCES); 2285 2286 return (0); 2287 } 2288 2289 static int 2290 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp, 2291 struct label *vnodelabel, mode_t mode) 2292 { 2293 struct mac_mls *subj, *obj; 2294 2295 if (!mac_mls_enabled) 2296 return (0); 2297 2298 subj = SLOT(&cred->cr_label); 2299 obj = SLOT(vnodelabel); 2300 2301 if (!mac_mls_dominate_single(obj, subj)) 2302 return (EACCES); 2303 2304 return (0); 2305 } 2306 2307 static int 2308 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp, 2309 struct label *vnodelabel, uid_t uid, gid_t gid) 2310 { 2311 struct mac_mls *subj, *obj; 2312 2313 if (!mac_mls_enabled) 2314 return (0); 2315 2316 subj = SLOT(&cred->cr_label); 2317 obj = SLOT(vnodelabel); 2318 2319 if (!mac_mls_dominate_single(obj, subj)) 2320 return (EACCES); 2321 2322 return (0); 2323 } 2324 2325 static int 2326 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, 2327 struct label *vnodelabel, struct timespec atime, struct timespec mtime) 2328 { 2329 struct mac_mls *subj, *obj; 2330 2331 if (!mac_mls_enabled) 2332 return (0); 2333 2334 subj = SLOT(&cred->cr_label); 2335 obj = SLOT(vnodelabel); 2336 2337 if (!mac_mls_dominate_single(obj, subj)) 2338 return (EACCES); 2339 2340 return (0); 2341 } 2342 2343 static int 2344 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, 2345 struct vnode *vp, struct label *vnodelabel) 2346 { 2347 struct mac_mls *subj, *obj; 2348 2349 if (!mac_mls_enabled) 2350 return (0); 2351 2352 subj = SLOT(&active_cred->cr_label); 2353 obj = SLOT(vnodelabel); 2354 2355 if (!mac_mls_dominate_single(subj, obj)) 2356 return (EACCES); 2357 2358 return (0); 2359 } 2360 2361 static int 2362 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, 2363 struct vnode *vp, struct label *label) 2364 { 2365 struct mac_mls *subj, *obj; 2366 2367 if (!mac_mls_enabled || !revocation_enabled) 2368 return (0); 2369 2370 subj = SLOT(&active_cred->cr_label); 2371 obj = SLOT(label); 2372 2373 if (!mac_mls_dominate_single(obj, subj)) 2374 return (EACCES); 2375 2376 return (0); 2377 } 2378 2379 static struct mac_policy_ops mac_mls_ops = 2380 { 2381 .mpo_destroy = mac_mls_destroy, 2382 .mpo_init = mac_mls_init, 2383 .mpo_init_bpfdesc_label = mac_mls_init_label, 2384 .mpo_init_cred_label = mac_mls_init_label, 2385 .mpo_init_devfsdirent_label = mac_mls_init_label, 2386 .mpo_init_ifnet_label = mac_mls_init_label, 2387 .mpo_init_ipq_label = mac_mls_init_label_waitcheck, 2388 .mpo_init_mbuf_label = mac_mls_init_label_waitcheck, 2389 .mpo_init_mount_label = mac_mls_init_label, 2390 .mpo_init_mount_fs_label = mac_mls_init_label, 2391 .mpo_init_pipe_label = mac_mls_init_label, 2392 .mpo_init_socket_label = mac_mls_init_label_waitcheck, 2393 .mpo_init_socket_peer_label = mac_mls_init_label_waitcheck, 2394 .mpo_init_vnode_label = mac_mls_init_label, 2395 .mpo_destroy_bpfdesc_label = mac_mls_destroy_label, 2396 .mpo_destroy_cred_label = mac_mls_destroy_label, 2397 .mpo_destroy_devfsdirent_label = mac_mls_destroy_label, 2398 .mpo_destroy_ifnet_label = mac_mls_destroy_label, 2399 .mpo_destroy_ipq_label = mac_mls_destroy_label, 2400 .mpo_destroy_mbuf_label = mac_mls_destroy_label, 2401 .mpo_destroy_mount_label = mac_mls_destroy_label, 2402 .mpo_destroy_mount_fs_label = mac_mls_destroy_label, 2403 .mpo_destroy_pipe_label = mac_mls_destroy_label, 2404 .mpo_destroy_socket_label = mac_mls_destroy_label, 2405 .mpo_destroy_socket_peer_label = mac_mls_destroy_label, 2406 .mpo_destroy_vnode_label = mac_mls_destroy_label, 2407 .mpo_copy_pipe_label = mac_mls_copy_label, 2408 .mpo_copy_vnode_label = mac_mls_copy_label, 2409 .mpo_externalize_cred_label = mac_mls_externalize_label, 2410 .mpo_externalize_ifnet_label = mac_mls_externalize_label, 2411 .mpo_externalize_pipe_label = mac_mls_externalize_label, 2412 .mpo_externalize_socket_label = mac_mls_externalize_label, 2413 .mpo_externalize_socket_peer_label = mac_mls_externalize_label, 2414 .mpo_externalize_vnode_label = mac_mls_externalize_label, 2415 .mpo_internalize_cred_label = mac_mls_internalize_label, 2416 .mpo_internalize_ifnet_label = mac_mls_internalize_label, 2417 .mpo_internalize_pipe_label = mac_mls_internalize_label, 2418 .mpo_internalize_socket_label = mac_mls_internalize_label, 2419 .mpo_internalize_vnode_label = mac_mls_internalize_label, 2420 .mpo_create_devfs_device = mac_mls_create_devfs_device, 2421 .mpo_create_devfs_directory = mac_mls_create_devfs_directory, 2422 .mpo_create_devfs_symlink = mac_mls_create_devfs_symlink, 2423 .mpo_create_mount = mac_mls_create_mount, 2424 .mpo_create_root_mount = mac_mls_create_root_mount, 2425 .mpo_relabel_vnode = mac_mls_relabel_vnode, 2426 .mpo_update_devfsdirent = mac_mls_update_devfsdirent, 2427 .mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs, 2428 .mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr, 2429 .mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel, 2430 .mpo_create_vnode_extattr = mac_mls_create_vnode_extattr, 2431 .mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr, 2432 .mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket, 2433 .mpo_create_pipe = mac_mls_create_pipe, 2434 .mpo_create_socket = mac_mls_create_socket, 2435 .mpo_create_socket_from_socket = mac_mls_create_socket_from_socket, 2436 .mpo_relabel_pipe = mac_mls_relabel_pipe, 2437 .mpo_relabel_socket = mac_mls_relabel_socket, 2438 .mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf, 2439 .mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket, 2440 .mpo_create_bpfdesc = mac_mls_create_bpfdesc, 2441 .mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq, 2442 .mpo_create_fragment = mac_mls_create_fragment, 2443 .mpo_create_ifnet = mac_mls_create_ifnet, 2444 .mpo_create_ipq = mac_mls_create_ipq, 2445 .mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf, 2446 .mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer, 2447 .mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc, 2448 .mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet, 2449 .mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap, 2450 .mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer, 2451 .mpo_fragment_match = mac_mls_fragment_match, 2452 .mpo_relabel_ifnet = mac_mls_relabel_ifnet, 2453 .mpo_update_ipq = mac_mls_update_ipq, 2454 .mpo_create_cred = mac_mls_create_cred, 2455 .mpo_create_proc0 = mac_mls_create_proc0, 2456 .mpo_create_proc1 = mac_mls_create_proc1, 2457 .mpo_relabel_cred = mac_mls_relabel_cred, 2458 .mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive, 2459 .mpo_check_cred_relabel = mac_mls_check_cred_relabel, 2460 .mpo_check_cred_visible = mac_mls_check_cred_visible, 2461 .mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel, 2462 .mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit, 2463 .mpo_check_mount_stat = mac_mls_check_mount_stat, 2464 .mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl, 2465 .mpo_check_pipe_poll = mac_mls_check_pipe_poll, 2466 .mpo_check_pipe_read = mac_mls_check_pipe_read, 2467 .mpo_check_pipe_relabel = mac_mls_check_pipe_relabel, 2468 .mpo_check_pipe_stat = mac_mls_check_pipe_stat, 2469 .mpo_check_pipe_write = mac_mls_check_pipe_write, 2470 .mpo_check_proc_debug = mac_mls_check_proc_debug, 2471 .mpo_check_proc_sched = mac_mls_check_proc_sched, 2472 .mpo_check_proc_signal = mac_mls_check_proc_signal, 2473 .mpo_check_socket_deliver = mac_mls_check_socket_deliver, 2474 .mpo_check_socket_relabel = mac_mls_check_socket_relabel, 2475 .mpo_check_socket_visible = mac_mls_check_socket_visible, 2476 .mpo_check_system_swapon = mac_mls_check_system_swapon, 2477 .mpo_check_vnode_access = mac_mls_check_vnode_open, 2478 .mpo_check_vnode_chdir = mac_mls_check_vnode_chdir, 2479 .mpo_check_vnode_chroot = mac_mls_check_vnode_chroot, 2480 .mpo_check_vnode_create = mac_mls_check_vnode_create, 2481 .mpo_check_vnode_delete = mac_mls_check_vnode_delete, 2482 .mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl, 2483 .mpo_check_vnode_exec = mac_mls_check_vnode_exec, 2484 .mpo_check_vnode_getacl = mac_mls_check_vnode_getacl, 2485 .mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr, 2486 .mpo_check_vnode_link = mac_mls_check_vnode_link, 2487 .mpo_check_vnode_lookup = mac_mls_check_vnode_lookup, 2488 .mpo_check_vnode_mmap = mac_mls_check_vnode_mmap, 2489 .mpo_check_vnode_mprotect = mac_mls_check_vnode_mmap, 2490 .mpo_check_vnode_open = mac_mls_check_vnode_open, 2491 .mpo_check_vnode_poll = mac_mls_check_vnode_poll, 2492 .mpo_check_vnode_read = mac_mls_check_vnode_read, 2493 .mpo_check_vnode_readdir = mac_mls_check_vnode_readdir, 2494 .mpo_check_vnode_readlink = mac_mls_check_vnode_readlink, 2495 .mpo_check_vnode_relabel = mac_mls_check_vnode_relabel, 2496 .mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from, 2497 .mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to, 2498 .mpo_check_vnode_revoke = mac_mls_check_vnode_revoke, 2499 .mpo_check_vnode_setacl = mac_mls_check_vnode_setacl, 2500 .mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr, 2501 .mpo_check_vnode_setflags = mac_mls_check_vnode_setflags, 2502 .mpo_check_vnode_setmode = mac_mls_check_vnode_setmode, 2503 .mpo_check_vnode_setowner = mac_mls_check_vnode_setowner, 2504 .mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes, 2505 .mpo_check_vnode_stat = mac_mls_check_vnode_stat, 2506 .mpo_check_vnode_write = mac_mls_check_vnode_write, 2507 }; 2508 2509 MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS", 2510 MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot); 2511