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