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