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