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