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