1 /*- 2 * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson 3 * Copyright (c) 2001-2005 McAfee, Inc. 4 * Copyright (c) 2006 SPARTA, Inc. 5 * All rights reserved. 6 * 7 * This software was developed by Robert Watson for the TrustedBSD Project. 8 * 9 * This software was developed for the FreeBSD Project in part by McAfee 10 * Research, the Security Research Division of McAfee, Inc. under 11 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 12 * CHATS research program. 13 * 14 * This software was enhanced by SPARTA ISSO under SPAWAR contract 15 * N66001-04-C-6019 ("SEFOS"). 16 * 17 * This software was developed at the University of Cambridge Computer 18 * Laboratory with support from a grant from Google, Inc. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 */ 41 42 /* 43 * Developed by the TrustedBSD Project. 44 * 45 * MLS fixed label mandatory confidentiality policy. 46 */ 47 48 #include <sys/types.h> 49 #include <sys/param.h> 50 #include <sys/acl.h> 51 #include <sys/conf.h> 52 #include <sys/extattr.h> 53 #include <sys/kernel.h> 54 #include <sys/ksem.h> 55 #include <sys/mman.h> 56 #include <sys/malloc.h> 57 #include <sys/mount.h> 58 #include <sys/proc.h> 59 #include <sys/sbuf.h> 60 #include <sys/systm.h> 61 #include <sys/sysproto.h> 62 #include <sys/sysent.h> 63 #include <sys/systm.h> 64 #include <sys/vnode.h> 65 #include <sys/file.h> 66 #include <sys/socket.h> 67 #include <sys/socketvar.h> 68 #include <sys/pipe.h> 69 #include <sys/sx.h> 70 #include <sys/sysctl.h> 71 #include <sys/msg.h> 72 #include <sys/sem.h> 73 #include <sys/shm.h> 74 75 #include <fs/devfs/devfs.h> 76 77 #include <net/bpfdesc.h> 78 #include <net/if.h> 79 #include <net/if_types.h> 80 #include <net/if_var.h> 81 82 #include <netinet/in.h> 83 #include <netinet/in_pcb.h> 84 #include <netinet/ip_var.h> 85 86 #include <vm/uma.h> 87 #include <vm/vm.h> 88 89 #include <security/mac/mac_policy.h> 90 #include <security/mac_mls/mac_mls.h> 91 92 SYSCTL_DECL(_security_mac); 93 94 static SYSCTL_NODE(_security_mac, OID_AUTO, mls, 95 CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 96 "TrustedBSD mac_mls policy controls"); 97 98 static int mls_label_size = sizeof(struct mac_mls); 99 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD, 100 &mls_label_size, 0, "Size of struct mac_mls"); 101 102 static int mls_enabled = 1; 103 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RWTUN, &mls_enabled, 0, 104 "Enforce MAC/MLS policy"); 105 106 static int destroyed_not_inited; 107 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 108 &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 109 110 static int ptys_equal = 0; 111 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RWTUN, 112 &ptys_equal, 0, "Label pty devices as mls/equal on create"); 113 114 static int revocation_enabled = 0; 115 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN, 116 &revocation_enabled, 0, "Revoke access to objects on relabel"); 117 118 static int max_compartments = MAC_MLS_MAX_COMPARTMENTS; 119 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD, 120 &max_compartments, 0, "Maximum compartments the policy supports"); 121 122 static int mls_slot; 123 #define SLOT(l) ((struct mac_mls *)mac_label_get((l), mls_slot)) 124 #define SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val)) 125 126 static uma_zone_t zone_mls; 127 128 static __inline int 129 mls_bit_set_empty(u_char *set) { 130 int i; 131 132 for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++) 133 if (set[i] != 0) 134 return (0); 135 return (1); 136 } 137 138 static struct mac_mls * 139 mls_alloc(int flag) 140 { 141 142 return (uma_zalloc(zone_mls, flag | M_ZERO)); 143 } 144 145 static void 146 mls_free(struct mac_mls *mm) 147 { 148 149 if (mm != NULL) 150 uma_zfree(zone_mls, mm); 151 else 152 atomic_add_int(&destroyed_not_inited, 1); 153 } 154 155 static int 156 mls_atmostflags(struct mac_mls *mm, int flags) 157 { 158 159 if ((mm->mm_flags & flags) != mm->mm_flags) 160 return (EINVAL); 161 return (0); 162 } 163 164 static int 165 mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b) 166 { 167 int bit; 168 169 switch (a->mme_type) { 170 case MAC_MLS_TYPE_EQUAL: 171 case MAC_MLS_TYPE_HIGH: 172 return (1); 173 174 case MAC_MLS_TYPE_LOW: 175 switch (b->mme_type) { 176 case MAC_MLS_TYPE_LEVEL: 177 case MAC_MLS_TYPE_HIGH: 178 return (0); 179 180 case MAC_MLS_TYPE_EQUAL: 181 case MAC_MLS_TYPE_LOW: 182 return (1); 183 184 default: 185 panic("mls_dominate_element: b->mme_type invalid"); 186 } 187 188 case MAC_MLS_TYPE_LEVEL: 189 switch (b->mme_type) { 190 case MAC_MLS_TYPE_EQUAL: 191 case MAC_MLS_TYPE_LOW: 192 return (1); 193 194 case MAC_MLS_TYPE_HIGH: 195 return (0); 196 197 case MAC_MLS_TYPE_LEVEL: 198 for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) 199 if (!MAC_MLS_BIT_TEST(bit, 200 a->mme_compartments) && 201 MAC_MLS_BIT_TEST(bit, b->mme_compartments)) 202 return (0); 203 return (a->mme_level >= b->mme_level); 204 205 default: 206 panic("mls_dominate_element: b->mme_type invalid"); 207 } 208 209 default: 210 panic("mls_dominate_element: a->mme_type invalid"); 211 } 212 213 return (0); 214 } 215 216 static int 217 mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb) 218 { 219 220 return (mls_dominate_element(&rangeb->mm_rangehigh, 221 &rangea->mm_rangehigh) && 222 mls_dominate_element(&rangea->mm_rangelow, 223 &rangeb->mm_rangelow)); 224 } 225 226 static int 227 mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range) 228 { 229 230 KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, 231 ("mls_effective_in_range: a not effective")); 232 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0, 233 ("mls_effective_in_range: b not range")); 234 235 return (mls_dominate_element(&range->mm_rangehigh, 236 &effective->mm_effective) && 237 mls_dominate_element(&effective->mm_effective, 238 &range->mm_rangelow)); 239 240 return (1); 241 } 242 243 static int 244 mls_dominate_effective(struct mac_mls *a, struct mac_mls *b) 245 { 246 KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, 247 ("mls_dominate_effective: a not effective")); 248 KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, 249 ("mls_dominate_effective: b not effective")); 250 251 return (mls_dominate_element(&a->mm_effective, &b->mm_effective)); 252 } 253 254 static int 255 mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b) 256 { 257 258 if (a->mme_type == MAC_MLS_TYPE_EQUAL || 259 b->mme_type == MAC_MLS_TYPE_EQUAL) 260 return (1); 261 262 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level); 263 } 264 265 static int 266 mls_equal_effective(struct mac_mls *a, struct mac_mls *b) 267 { 268 269 KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, 270 ("mls_equal_effective: a not effective")); 271 KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, 272 ("mls_equal_effective: b not effective")); 273 274 return (mls_equal_element(&a->mm_effective, &b->mm_effective)); 275 } 276 277 static int 278 mls_contains_equal(struct mac_mls *mm) 279 { 280 281 if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) 282 if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL) 283 return (1); 284 285 if (mm->mm_flags & MAC_MLS_FLAG_RANGE) { 286 if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL) 287 return (1); 288 if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) 289 return (1); 290 } 291 292 return (0); 293 } 294 295 static int 296 mls_subject_privileged(struct mac_mls *mm) 297 { 298 299 KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH, 300 ("mls_subject_privileged: subject doesn't have both labels")); 301 302 /* If the effective is EQUAL, it's ok. */ 303 if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL) 304 return (0); 305 306 /* If either range endpoint is EQUAL, it's ok. */ 307 if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL || 308 mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL) 309 return (0); 310 311 /* If the range is low-high, it's ok. */ 312 if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW && 313 mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH) 314 return (0); 315 316 /* It's not ok. */ 317 return (EPERM); 318 } 319 320 static int 321 mls_valid(struct mac_mls *mm) 322 { 323 324 if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { 325 switch (mm->mm_effective.mme_type) { 326 case MAC_MLS_TYPE_LEVEL: 327 break; 328 329 case MAC_MLS_TYPE_EQUAL: 330 case MAC_MLS_TYPE_HIGH: 331 case MAC_MLS_TYPE_LOW: 332 if (mm->mm_effective.mme_level != 0 || 333 !MAC_MLS_BIT_SET_EMPTY( 334 mm->mm_effective.mme_compartments)) 335 return (EINVAL); 336 break; 337 338 default: 339 return (EINVAL); 340 } 341 } else { 342 if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF) 343 return (EINVAL); 344 } 345 346 if (mm->mm_flags & MAC_MLS_FLAG_RANGE) { 347 switch (mm->mm_rangelow.mme_type) { 348 case MAC_MLS_TYPE_LEVEL: 349 break; 350 351 case MAC_MLS_TYPE_EQUAL: 352 case MAC_MLS_TYPE_HIGH: 353 case MAC_MLS_TYPE_LOW: 354 if (mm->mm_rangelow.mme_level != 0 || 355 !MAC_MLS_BIT_SET_EMPTY( 356 mm->mm_rangelow.mme_compartments)) 357 return (EINVAL); 358 break; 359 360 default: 361 return (EINVAL); 362 } 363 364 switch (mm->mm_rangehigh.mme_type) { 365 case MAC_MLS_TYPE_LEVEL: 366 break; 367 368 case MAC_MLS_TYPE_EQUAL: 369 case MAC_MLS_TYPE_HIGH: 370 case MAC_MLS_TYPE_LOW: 371 if (mm->mm_rangehigh.mme_level != 0 || 372 !MAC_MLS_BIT_SET_EMPTY( 373 mm->mm_rangehigh.mme_compartments)) 374 return (EINVAL); 375 break; 376 377 default: 378 return (EINVAL); 379 } 380 if (!mls_dominate_element(&mm->mm_rangehigh, 381 &mm->mm_rangelow)) 382 return (EINVAL); 383 } else { 384 if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF || 385 mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF) 386 return (EINVAL); 387 } 388 389 return (0); 390 } 391 392 static void 393 mls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow, 394 u_char *compartmentslow, u_short typehigh, u_short levelhigh, 395 u_char *compartmentshigh) 396 { 397 398 mm->mm_rangelow.mme_type = typelow; 399 mm->mm_rangelow.mme_level = levellow; 400 if (compartmentslow != NULL) 401 memcpy(mm->mm_rangelow.mme_compartments, compartmentslow, 402 sizeof(mm->mm_rangelow.mme_compartments)); 403 mm->mm_rangehigh.mme_type = typehigh; 404 mm->mm_rangehigh.mme_level = levelhigh; 405 if (compartmentshigh != NULL) 406 memcpy(mm->mm_rangehigh.mme_compartments, compartmentshigh, 407 sizeof(mm->mm_rangehigh.mme_compartments)); 408 mm->mm_flags |= MAC_MLS_FLAG_RANGE; 409 } 410 411 static void 412 mls_set_effective(struct mac_mls *mm, u_short type, u_short level, 413 u_char *compartments) 414 { 415 416 mm->mm_effective.mme_type = type; 417 mm->mm_effective.mme_level = level; 418 if (compartments != NULL) 419 memcpy(mm->mm_effective.mme_compartments, compartments, 420 sizeof(mm->mm_effective.mme_compartments)); 421 mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE; 422 } 423 424 static void 425 mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto) 426 { 427 428 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0, 429 ("mls_copy_range: labelfrom not range")); 430 431 labelto->mm_rangelow = labelfrom->mm_rangelow; 432 labelto->mm_rangehigh = labelfrom->mm_rangehigh; 433 labelto->mm_flags |= MAC_MLS_FLAG_RANGE; 434 } 435 436 static void 437 mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto) 438 { 439 440 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0, 441 ("mls_copy_effective: labelfrom not effective")); 442 443 labelto->mm_effective = labelfrom->mm_effective; 444 labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE; 445 } 446 447 static void 448 mls_copy(struct mac_mls *source, struct mac_mls *dest) 449 { 450 451 if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) 452 mls_copy_effective(source, dest); 453 if (source->mm_flags & MAC_MLS_FLAG_RANGE) 454 mls_copy_range(source, dest); 455 } 456 457 /* 458 * Policy module operations. 459 */ 460 static void 461 mls_init(struct mac_policy_conf *conf) 462 { 463 464 zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL, 465 NULL, NULL, NULL, UMA_ALIGN_PTR, 0); 466 } 467 468 /* 469 * Label operations. 470 */ 471 static void 472 mls_init_label(struct label *label) 473 { 474 475 SLOT_SET(label, mls_alloc(M_WAITOK)); 476 } 477 478 static int 479 mls_init_label_waitcheck(struct label *label, int flag) 480 { 481 482 SLOT_SET(label, mls_alloc(flag)); 483 if (SLOT(label) == NULL) 484 return (ENOMEM); 485 486 return (0); 487 } 488 489 static void 490 mls_destroy_label(struct label *label) 491 { 492 493 mls_free(SLOT(label)); 494 SLOT_SET(label, NULL); 495 } 496 497 /* 498 * mls_element_to_string() accepts an sbuf and MLS element. It converts the 499 * MLS element to a string and stores the result in the sbuf; if there isn't 500 * space in the sbuf, -1 is returned. 501 */ 502 static int 503 mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element) 504 { 505 int i, first; 506 507 switch (element->mme_type) { 508 case MAC_MLS_TYPE_HIGH: 509 return (sbuf_printf(sb, "high")); 510 511 case MAC_MLS_TYPE_LOW: 512 return (sbuf_printf(sb, "low")); 513 514 case MAC_MLS_TYPE_EQUAL: 515 return (sbuf_printf(sb, "equal")); 516 517 case MAC_MLS_TYPE_LEVEL: 518 if (sbuf_printf(sb, "%d", element->mme_level) == -1) 519 return (-1); 520 521 first = 1; 522 for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) { 523 if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) { 524 if (first) { 525 if (sbuf_putc(sb, ':') == -1) 526 return (-1); 527 if (sbuf_printf(sb, "%d", i) == -1) 528 return (-1); 529 first = 0; 530 } else { 531 if (sbuf_printf(sb, "+%d", i) == -1) 532 return (-1); 533 } 534 } 535 } 536 return (0); 537 538 default: 539 panic("mls_element_to_string: invalid type (%d)", 540 element->mme_type); 541 } 542 } 543 544 /* 545 * mls_to_string() converts an MLS label to a string, and places the results 546 * in the passed sbuf. It returns 0 on success, or EINVAL if there isn't 547 * room in the sbuf. Note: the sbuf will be modified even in a failure case, 548 * so the caller may need to revert the sbuf by restoring the offset if 549 * that's undesired. 550 */ 551 static int 552 mls_to_string(struct sbuf *sb, struct mac_mls *mm) 553 { 554 555 if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { 556 if (mls_element_to_string(sb, &mm->mm_effective) == -1) 557 return (EINVAL); 558 } 559 560 if (mm->mm_flags & MAC_MLS_FLAG_RANGE) { 561 if (sbuf_putc(sb, '(') == -1) 562 return (EINVAL); 563 564 if (mls_element_to_string(sb, &mm->mm_rangelow) == -1) 565 return (EINVAL); 566 567 if (sbuf_putc(sb, '-') == -1) 568 return (EINVAL); 569 570 if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1) 571 return (EINVAL); 572 573 if (sbuf_putc(sb, ')') == -1) 574 return (EINVAL); 575 } 576 577 return (0); 578 } 579 580 static int 581 mls_externalize_label(struct label *label, char *element_name, 582 struct sbuf *sb, int *claimed) 583 { 584 struct mac_mls *mm; 585 586 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0) 587 return (0); 588 589 (*claimed)++; 590 591 mm = SLOT(label); 592 593 return (mls_to_string(sb, mm)); 594 } 595 596 static int 597 mls_parse_element(struct mac_mls_element *element, char *string) 598 { 599 char *compartment, *end, *level; 600 int value; 601 602 if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { 603 element->mme_type = MAC_MLS_TYPE_HIGH; 604 element->mme_level = MAC_MLS_TYPE_UNDEF; 605 } else if (strcmp(string, "low") == 0 || 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 are 628 * included, we assume that the label has no compartments. 629 */ 630 if (string == NULL) 631 return (0); 632 if (*string == '\0') 633 return (0); 634 635 while ((compartment = strsep(&string, "+")) != NULL) { 636 value = strtol(compartment, &end, 10); 637 if (compartment == end || *end != '\0') 638 return (EINVAL); 639 if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS) 640 return (EINVAL); 641 MAC_MLS_BIT_SET(value, element->mme_compartments); 642 } 643 } 644 645 return (0); 646 } 647 648 /* 649 * Note: destructively consumes the string, make a local copy before calling 650 * if that's a problem. 651 */ 652 static int 653 mls_parse(struct mac_mls *mm, char *string) 654 { 655 char *rangehigh, *rangelow, *effective; 656 int error; 657 658 effective = strsep(&string, "("); 659 if (*effective == '\0') 660 effective = NULL; 661 662 if (string != NULL) { 663 rangelow = strsep(&string, "-"); 664 if (string == NULL) 665 return (EINVAL); 666 rangehigh = strsep(&string, ")"); 667 if (string == NULL) 668 return (EINVAL); 669 if (*string != '\0') 670 return (EINVAL); 671 } else { 672 rangelow = NULL; 673 rangehigh = NULL; 674 } 675 676 KASSERT((rangelow != NULL && rangehigh != NULL) || 677 (rangelow == NULL && rangehigh == NULL), 678 ("mls_parse: range mismatch")); 679 680 bzero(mm, sizeof(*mm)); 681 if (effective != NULL) { 682 error = mls_parse_element(&mm->mm_effective, effective); 683 if (error) 684 return (error); 685 mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE; 686 } 687 688 if (rangelow != NULL) { 689 error = mls_parse_element(&mm->mm_rangelow, rangelow); 690 if (error) 691 return (error); 692 error = mls_parse_element(&mm->mm_rangehigh, rangehigh); 693 if (error) 694 return (error); 695 mm->mm_flags |= MAC_MLS_FLAG_RANGE; 696 } 697 698 error = mls_valid(mm); 699 if (error) 700 return (error); 701 702 return (0); 703 } 704 705 static int 706 mls_internalize_label(struct label *label, char *element_name, 707 char *element_data, int *claimed) 708 { 709 struct mac_mls *mm, mm_temp; 710 int error; 711 712 if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0) 713 return (0); 714 715 (*claimed)++; 716 717 error = mls_parse(&mm_temp, element_data); 718 if (error) 719 return (error); 720 721 mm = SLOT(label); 722 *mm = mm_temp; 723 724 return (0); 725 } 726 727 static void 728 mls_copy_label(struct label *src, struct label *dest) 729 { 730 731 *SLOT(dest) = *SLOT(src); 732 } 733 734 /* 735 * Object-specific entry point implementations are sorted alphabetically by 736 * object type name and then by operation. 737 */ 738 static int 739 mls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel, 740 struct ifnet *ifp, struct label *ifplabel) 741 { 742 struct mac_mls *a, *b; 743 744 if (!mls_enabled) 745 return (0); 746 747 a = SLOT(dlabel); 748 b = SLOT(ifplabel); 749 750 if (mls_equal_effective(a, b)) 751 return (0); 752 return (EACCES); 753 } 754 755 static void 756 mls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel) 757 { 758 struct mac_mls *source, *dest; 759 760 source = SLOT(cred->cr_label); 761 dest = SLOT(dlabel); 762 763 mls_copy_effective(source, dest); 764 } 765 766 static void 767 mls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel, 768 struct mbuf *m, struct label *mlabel) 769 { 770 struct mac_mls *source, *dest; 771 772 source = SLOT(dlabel); 773 dest = SLOT(mlabel); 774 775 mls_copy_effective(source, dest); 776 } 777 778 static void 779 mls_cred_associate_nfsd(struct ucred *cred) 780 { 781 struct mac_mls *label; 782 783 label = SLOT(cred->cr_label); 784 mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL); 785 mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0, 786 NULL); 787 } 788 789 static int 790 mls_cred_check_relabel(struct ucred *cred, struct label *newlabel) 791 { 792 struct mac_mls *subj, *new; 793 int error; 794 795 subj = SLOT(cred->cr_label); 796 new = SLOT(newlabel); 797 798 /* 799 * If there is an MLS label update for the credential, it may be an 800 * update of effective, range, or both. 801 */ 802 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); 803 if (error) 804 return (error); 805 806 /* 807 * If the MLS label is to be changed, authorize as appropriate. 808 */ 809 if (new->mm_flags & MAC_MLS_FLAGS_BOTH) { 810 /* 811 * If the change request modifies both the MLS label 812 * effective and range, check that the new effective will be 813 * in the new range. 814 */ 815 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) == 816 MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new)) 817 return (EINVAL); 818 819 /* 820 * To change the MLS effective label on a credential, the new 821 * effective label must be in the current range. 822 */ 823 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE && 824 !mls_effective_in_range(new, subj)) 825 return (EPERM); 826 827 /* 828 * To change the MLS range label on a credential, the new 829 * range must be in the current range. 830 */ 831 if (new->mm_flags & MAC_MLS_FLAG_RANGE && 832 !mls_range_in_range(new, subj)) 833 return (EPERM); 834 835 /* 836 * To have EQUAL in any component of the new credential MLS 837 * label, the subject must already have EQUAL in their label. 838 */ 839 if (mls_contains_equal(new)) { 840 error = mls_subject_privileged(subj); 841 if (error) 842 return (error); 843 } 844 } 845 846 return (0); 847 } 848 849 static int 850 mls_cred_check_visible(struct ucred *cr1, struct ucred *cr2) 851 { 852 struct mac_mls *subj, *obj; 853 854 if (!mls_enabled) 855 return (0); 856 857 subj = SLOT(cr1->cr_label); 858 obj = SLOT(cr2->cr_label); 859 860 /* XXX: range */ 861 if (!mls_dominate_effective(subj, obj)) 862 return (ESRCH); 863 864 return (0); 865 } 866 867 static void 868 mls_cred_create_init(struct ucred *cred) 869 { 870 struct mac_mls *dest; 871 872 dest = SLOT(cred->cr_label); 873 874 mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL); 875 mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0, 876 NULL); 877 } 878 879 static void 880 mls_cred_create_swapper(struct ucred *cred) 881 { 882 struct mac_mls *dest; 883 884 dest = SLOT(cred->cr_label); 885 886 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 887 mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0, 888 NULL); 889 } 890 891 static void 892 mls_cred_relabel(struct ucred *cred, struct label *newlabel) 893 { 894 struct mac_mls *source, *dest; 895 896 source = SLOT(newlabel); 897 dest = SLOT(cred->cr_label); 898 899 mls_copy(source, dest); 900 } 901 902 static void 903 mls_devfs_create_device(struct ucred *cred, struct mount *mp, 904 struct cdev *dev, struct devfs_dirent *de, struct label *delabel) 905 { 906 struct mac_mls *mm; 907 const char *dn; 908 int mls_type; 909 910 mm = SLOT(delabel); 911 dn = devtoname(dev); 912 if (strcmp(dn, "null") == 0 || 913 strcmp(dn, "zero") == 0 || 914 strcmp(dn, "random") == 0 || 915 strncmp(dn, "fd/", strlen("fd/")) == 0) 916 mls_type = MAC_MLS_TYPE_EQUAL; 917 else if (strcmp(dn, "kmem") == 0 || 918 strcmp(dn, "mem") == 0) 919 mls_type = MAC_MLS_TYPE_HIGH; 920 else if (ptys_equal && 921 (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || 922 strncmp(dn, "pts/", strlen("pts/")) == 0 || 923 strncmp(dn, "ptyp", strlen("ptyp")) == 0)) 924 mls_type = MAC_MLS_TYPE_EQUAL; 925 else 926 mls_type = MAC_MLS_TYPE_LOW; 927 mls_set_effective(mm, mls_type, 0, NULL); 928 } 929 930 static void 931 mls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 932 struct devfs_dirent *de, struct label *delabel) 933 { 934 struct mac_mls *mm; 935 936 mm = SLOT(delabel); 937 mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL); 938 } 939 940 static void 941 mls_devfs_create_symlink(struct ucred *cred, struct mount *mp, 942 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 943 struct label *delabel) 944 { 945 struct mac_mls *source, *dest; 946 947 source = SLOT(cred->cr_label); 948 dest = SLOT(delabel); 949 950 mls_copy_effective(source, dest); 951 } 952 953 static void 954 mls_devfs_update(struct mount *mp, struct devfs_dirent *de, 955 struct label *delabel, struct vnode *vp, struct label *vplabel) 956 { 957 struct mac_mls *source, *dest; 958 959 source = SLOT(vplabel); 960 dest = SLOT(delabel); 961 962 mls_copy_effective(source, dest); 963 } 964 965 static void 966 mls_devfs_vnode_associate(struct mount *mp, struct label *mplabel, 967 struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 968 struct label *vplabel) 969 { 970 struct mac_mls *source, *dest; 971 972 source = SLOT(delabel); 973 dest = SLOT(vplabel); 974 975 mls_copy_effective(source, dest); 976 } 977 978 static int 979 mls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp, 980 struct label *ifplabel, struct label *newlabel) 981 { 982 struct mac_mls *subj, *new; 983 int error; 984 985 subj = SLOT(cred->cr_label); 986 new = SLOT(newlabel); 987 988 /* 989 * If there is an MLS label update for the interface, it may be an 990 * update of effective, range, or both. 991 */ 992 error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH); 993 if (error) 994 return (error); 995 996 /* 997 * Relabeling network interfaces requires MLS privilege. 998 */ 999 return (mls_subject_privileged(subj)); 1000 } 1001 1002 static int 1003 mls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel, 1004 struct mbuf *m, struct label *mlabel) 1005 { 1006 struct mac_mls *p, *i; 1007 1008 if (!mls_enabled) 1009 return (0); 1010 1011 p = SLOT(mlabel); 1012 i = SLOT(ifplabel); 1013 1014 return (mls_effective_in_range(p, i) ? 0 : EACCES); 1015 } 1016 1017 static void 1018 mls_ifnet_create(struct ifnet *ifp, struct label *ifplabel) 1019 { 1020 struct mac_mls *dest; 1021 int type; 1022 1023 dest = SLOT(ifplabel); 1024 1025 if (if_gettype(ifp) == IFT_LOOP) 1026 type = MAC_MLS_TYPE_EQUAL; 1027 else 1028 type = MAC_MLS_TYPE_LOW; 1029 1030 mls_set_effective(dest, type, 0, NULL); 1031 mls_set_range(dest, type, 0, NULL, type, 0, NULL); 1032 } 1033 1034 static void 1035 mls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel, 1036 struct mbuf *m, struct label *mlabel) 1037 { 1038 struct mac_mls *source, *dest; 1039 1040 source = SLOT(ifplabel); 1041 dest = SLOT(mlabel); 1042 1043 mls_copy_effective(source, dest); 1044 } 1045 1046 static void 1047 mls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp, 1048 struct label *ifplabel, struct label *newlabel) 1049 { 1050 struct mac_mls *source, *dest; 1051 1052 source = SLOT(newlabel); 1053 dest = SLOT(ifplabel); 1054 1055 mls_copy(source, dest); 1056 } 1057 1058 static int 1059 mls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel, 1060 struct mbuf *m, struct label *mlabel) 1061 { 1062 struct mac_mls *p, *i; 1063 1064 if (!mls_enabled) 1065 return (0); 1066 1067 p = SLOT(mlabel); 1068 i = SLOT(inplabel); 1069 1070 return (mls_equal_effective(p, i) ? 0 : EACCES); 1071 } 1072 1073 static int 1074 mls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp, 1075 struct label *inplabel) 1076 { 1077 struct mac_mls *subj, *obj; 1078 1079 if (!mls_enabled) 1080 return (0); 1081 1082 subj = SLOT(cred->cr_label); 1083 obj = SLOT(inplabel); 1084 1085 if (!mls_dominate_effective(subj, obj)) 1086 return (ENOENT); 1087 1088 return (0); 1089 } 1090 1091 static void 1092 mls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp, 1093 struct label *inplabel) 1094 { 1095 struct mac_mls *source, *dest; 1096 1097 source = SLOT(solabel); 1098 dest = SLOT(inplabel); 1099 1100 mls_copy_effective(source, dest); 1101 } 1102 1103 static void 1104 mls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel, 1105 struct mbuf *m, struct label *mlabel) 1106 { 1107 struct mac_mls *source, *dest; 1108 1109 source = SLOT(inplabel); 1110 dest = SLOT(mlabel); 1111 1112 mls_copy_effective(source, dest); 1113 } 1114 1115 static void 1116 mls_inpcb_sosetlabel(struct socket *so, struct label *solabel, 1117 struct inpcb *inp, struct label *inplabel) 1118 { 1119 struct mac_mls *source, *dest; 1120 1121 SOCK_LOCK_ASSERT(so); 1122 1123 source = SLOT(solabel); 1124 dest = SLOT(inplabel); 1125 1126 mls_copy(source, dest); 1127 } 1128 1129 static void 1130 mls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1131 struct label *q6label) 1132 { 1133 struct mac_mls *source, *dest; 1134 1135 source = SLOT(mlabel); 1136 dest = SLOT(q6label); 1137 1138 mls_copy_effective(source, dest); 1139 } 1140 1141 static int 1142 mls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1143 struct label *q6label) 1144 { 1145 struct mac_mls *a, *b; 1146 1147 a = SLOT(q6label); 1148 b = SLOT(mlabel); 1149 1150 return (mls_equal_effective(a, b)); 1151 } 1152 1153 static void 1154 mls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m, 1155 struct label *mlabel) 1156 { 1157 struct mac_mls *source, *dest; 1158 1159 source = SLOT(q6label); 1160 dest = SLOT(mlabel); 1161 1162 /* Just use the head, since we require them all to match. */ 1163 mls_copy_effective(source, dest); 1164 } 1165 1166 static void 1167 mls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1168 struct label *q6label) 1169 { 1170 1171 /* NOOP: we only accept matching labels, so no need to update */ 1172 } 1173 1174 static void 1175 mls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q, 1176 struct label *qlabel) 1177 { 1178 struct mac_mls *source, *dest; 1179 1180 source = SLOT(mlabel); 1181 dest = SLOT(qlabel); 1182 1183 mls_copy_effective(source, dest); 1184 } 1185 1186 static int 1187 mls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q, 1188 struct label *qlabel) 1189 { 1190 struct mac_mls *a, *b; 1191 1192 a = SLOT(qlabel); 1193 b = SLOT(mlabel); 1194 1195 return (mls_equal_effective(a, b)); 1196 } 1197 1198 static void 1199 mls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m, 1200 struct label *mlabel) 1201 { 1202 struct mac_mls *source, *dest; 1203 1204 source = SLOT(qlabel); 1205 dest = SLOT(mlabel); 1206 1207 /* Just use the head, since we require them all to match. */ 1208 mls_copy_effective(source, dest); 1209 } 1210 1211 static void 1212 mls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q, 1213 struct label *qlabel) 1214 { 1215 1216 /* NOOP: we only accept matching labels, so no need to update */ 1217 } 1218 1219 static int 1220 mls_mount_check_stat(struct ucred *cred, struct mount *mp, 1221 struct label *mntlabel) 1222 { 1223 struct mac_mls *subj, *obj; 1224 1225 if (!mls_enabled) 1226 return (0); 1227 1228 subj = SLOT(cred->cr_label); 1229 obj = SLOT(mntlabel); 1230 1231 if (!mls_dominate_effective(subj, obj)) 1232 return (EACCES); 1233 1234 return (0); 1235 } 1236 1237 static void 1238 mls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel) 1239 { 1240 struct mac_mls *source, *dest; 1241 1242 source = SLOT(cred->cr_label); 1243 dest = SLOT(mplabel); 1244 1245 mls_copy_effective(source, dest); 1246 } 1247 1248 static void 1249 mls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, 1250 struct mbuf *m, struct label *mlabel) 1251 { 1252 struct mac_mls *dest; 1253 1254 dest = SLOT(mlabel); 1255 1256 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 1257 } 1258 1259 static void 1260 mls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1261 struct mbuf *msend, struct label *msendlabel) 1262 { 1263 struct mac_mls *source, *dest; 1264 1265 source = SLOT(mrecvlabel); 1266 dest = SLOT(msendlabel); 1267 1268 mls_copy_effective(source, dest); 1269 } 1270 1271 static void 1272 mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel) 1273 { 1274 struct mac_mls *dest; 1275 1276 dest = SLOT(mlabel); 1277 1278 /* XXX: where is the label for the firewall really coming from? */ 1279 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 1280 } 1281 1282 static void 1283 mls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag, 1284 struct label *fraglabel) 1285 { 1286 struct mac_mls *source, *dest; 1287 1288 source = SLOT(mlabel); 1289 dest = SLOT(fraglabel); 1290 1291 mls_copy_effective(source, dest); 1292 } 1293 1294 static void 1295 mls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1296 struct mbuf *msend, struct label *msendlabel) 1297 { 1298 struct mac_mls *source, *dest; 1299 1300 source = SLOT(mrecvlabel); 1301 dest = SLOT(msendlabel); 1302 1303 mls_copy_effective(source, dest); 1304 } 1305 1306 static void 1307 mls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel, 1308 struct mbuf *m, struct label *mlabel) 1309 { 1310 struct mac_mls *dest; 1311 1312 dest = SLOT(mlabel); 1313 1314 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 1315 } 1316 1317 static void 1318 mls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel, 1319 struct mbuf *m, struct label *mlabel) 1320 { 1321 struct mac_mls *dest; 1322 1323 dest = SLOT(mlabel); 1324 1325 mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); 1326 } 1327 1328 static int 1329 mls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp, 1330 struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data) 1331 { 1332 1333 if (!mls_enabled) 1334 return (0); 1335 1336 /* XXX: This will be implemented soon... */ 1337 1338 return (0); 1339 } 1340 1341 static int 1342 mls_pipe_check_poll(struct ucred *cred, struct pipepair *pp, 1343 struct label *pplabel) 1344 { 1345 struct mac_mls *subj, *obj; 1346 1347 if (!mls_enabled) 1348 return (0); 1349 1350 subj = SLOT(cred->cr_label); 1351 obj = SLOT(pplabel); 1352 1353 if (!mls_dominate_effective(subj, obj)) 1354 return (EACCES); 1355 1356 return (0); 1357 } 1358 1359 static int 1360 mls_pipe_check_read(struct ucred *cred, struct pipepair *pp, 1361 struct label *pplabel) 1362 { 1363 struct mac_mls *subj, *obj; 1364 1365 if (!mls_enabled) 1366 return (0); 1367 1368 subj = SLOT(cred->cr_label); 1369 obj = SLOT(pplabel); 1370 1371 if (!mls_dominate_effective(subj, obj)) 1372 return (EACCES); 1373 1374 return (0); 1375 } 1376 1377 static int 1378 mls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp, 1379 struct label *pplabel, struct label *newlabel) 1380 { 1381 struct mac_mls *subj, *obj, *new; 1382 int error; 1383 1384 new = SLOT(newlabel); 1385 subj = SLOT(cred->cr_label); 1386 obj = SLOT(pplabel); 1387 1388 /* 1389 * If there is an MLS label update for a pipe, it must be a effective 1390 * update. 1391 */ 1392 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE); 1393 if (error) 1394 return (error); 1395 1396 /* 1397 * To perform a relabel of a pipe (MLS label or not), MLS must 1398 * authorize the relabel. 1399 */ 1400 if (!mls_effective_in_range(obj, subj)) 1401 return (EPERM); 1402 1403 /* 1404 * If the MLS label is to be changed, authorize as appropriate. 1405 */ 1406 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { 1407 /* 1408 * To change the MLS label on a pipe, the new pipe label must 1409 * be in the subject range. 1410 */ 1411 if (!mls_effective_in_range(new, subj)) 1412 return (EPERM); 1413 1414 /* 1415 * To change the MLS label on a pipe to be EQUAL, the subject 1416 * must have appropriate privilege. 1417 */ 1418 if (mls_contains_equal(new)) { 1419 error = mls_subject_privileged(subj); 1420 if (error) 1421 return (error); 1422 } 1423 } 1424 1425 return (0); 1426 } 1427 1428 static int 1429 mls_pipe_check_stat(struct ucred *cred, struct pipepair *pp, 1430 struct label *pplabel) 1431 { 1432 struct mac_mls *subj, *obj; 1433 1434 if (!mls_enabled) 1435 return (0); 1436 1437 subj = SLOT(cred->cr_label); 1438 obj = SLOT(pplabel); 1439 1440 if (!mls_dominate_effective(subj, obj)) 1441 return (EACCES); 1442 1443 return (0); 1444 } 1445 1446 static int 1447 mls_pipe_check_write(struct ucred *cred, struct pipepair *pp, 1448 struct label *pplabel) 1449 { 1450 struct mac_mls *subj, *obj; 1451 1452 if (!mls_enabled) 1453 return (0); 1454 1455 subj = SLOT(cred->cr_label); 1456 obj = SLOT(pplabel); 1457 1458 if (!mls_dominate_effective(obj, subj)) 1459 return (EACCES); 1460 1461 return (0); 1462 } 1463 1464 static void 1465 mls_pipe_create(struct ucred *cred, struct pipepair *pp, 1466 struct label *pplabel) 1467 { 1468 struct mac_mls *source, *dest; 1469 1470 source = SLOT(cred->cr_label); 1471 dest = SLOT(pplabel); 1472 1473 mls_copy_effective(source, dest); 1474 } 1475 1476 static void 1477 mls_pipe_relabel(struct ucred *cred, struct pipepair *pp, 1478 struct label *pplabel, struct label *newlabel) 1479 { 1480 struct mac_mls *source, *dest; 1481 1482 source = SLOT(newlabel); 1483 dest = SLOT(pplabel); 1484 1485 mls_copy(source, dest); 1486 } 1487 1488 static int 1489 mls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks, 1490 struct label *kslabel) 1491 { 1492 struct mac_mls *subj, *obj; 1493 1494 if (!mls_enabled) 1495 return (0); 1496 1497 subj = SLOT(cred->cr_label); 1498 obj = SLOT(kslabel); 1499 1500 if (!mls_dominate_effective(obj, subj)) 1501 return (EACCES); 1502 1503 return (0); 1504 } 1505 1506 static int 1507 mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred, 1508 struct ksem *ks, struct label *kslabel) 1509 { 1510 struct mac_mls *subj, *obj; 1511 1512 if (!mls_enabled) 1513 return (0); 1514 1515 subj = SLOT(active_cred->cr_label); 1516 obj = SLOT(kslabel); 1517 1518 if (!mls_dominate_effective(subj, obj)) 1519 return (EACCES); 1520 1521 return (0); 1522 } 1523 1524 static int 1525 mls_posixsem_check_setmode(struct ucred *cred, struct ksem *ks, 1526 struct label *shmlabel, mode_t mode) 1527 { 1528 struct mac_mls *subj, *obj; 1529 1530 if (!mls_enabled) 1531 return (0); 1532 1533 subj = SLOT(cred->cr_label); 1534 obj = SLOT(shmlabel); 1535 1536 if (!mls_dominate_effective(obj, subj)) 1537 return (EACCES); 1538 1539 return (0); 1540 } 1541 1542 static int 1543 mls_posixsem_check_setowner(struct ucred *cred, struct ksem *ks, 1544 struct label *shmlabel, uid_t uid, gid_t gid) 1545 { 1546 struct mac_mls *subj, *obj; 1547 1548 if (!mls_enabled) 1549 return (0); 1550 1551 subj = SLOT(cred->cr_label); 1552 obj = SLOT(shmlabel); 1553 1554 if (!mls_dominate_effective(obj, subj)) 1555 return (EACCES); 1556 1557 return (0); 1558 } 1559 1560 static int 1561 mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred, 1562 struct ksem *ks, struct label *kslabel) 1563 { 1564 struct mac_mls *subj, *obj; 1565 1566 if (!mls_enabled) 1567 return (0); 1568 1569 subj = SLOT(active_cred->cr_label); 1570 obj = SLOT(kslabel); 1571 1572 if (!mls_dominate_effective(obj, subj)) 1573 return (EACCES); 1574 1575 return (0); 1576 } 1577 1578 static void 1579 mls_posixsem_create(struct ucred *cred, struct ksem *ks, 1580 struct label *kslabel) 1581 { 1582 struct mac_mls *source, *dest; 1583 1584 source = SLOT(cred->cr_label); 1585 dest = SLOT(kslabel); 1586 1587 mls_copy_effective(source, dest); 1588 } 1589 1590 static int 1591 mls_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd, 1592 struct label *shmlabel, int prot, int flags) 1593 { 1594 struct mac_mls *subj, *obj; 1595 1596 if (!mls_enabled) 1597 return (0); 1598 1599 subj = SLOT(cred->cr_label); 1600 obj = SLOT(shmlabel); 1601 1602 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 1603 if (!mls_dominate_effective(subj, obj)) 1604 return (EACCES); 1605 } 1606 if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 1607 if (!mls_dominate_effective(obj, subj)) 1608 return (EACCES); 1609 } 1610 1611 return (0); 1612 } 1613 1614 static int 1615 mls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd, 1616 struct label *shmlabel, accmode_t accmode) 1617 { 1618 struct mac_mls *subj, *obj; 1619 1620 if (!mls_enabled) 1621 return (0); 1622 1623 subj = SLOT(cred->cr_label); 1624 obj = SLOT(shmlabel); 1625 1626 if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) { 1627 if (!mls_dominate_effective(subj, obj)) 1628 return (EACCES); 1629 } 1630 if (accmode & VMODIFY_PERMS) { 1631 if (!mls_dominate_effective(obj, subj)) 1632 return (EACCES); 1633 } 1634 1635 return (0); 1636 } 1637 1638 static int 1639 mls_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred, 1640 struct shmfd *shm, struct label *shmlabel) 1641 { 1642 struct mac_mls *subj, *obj; 1643 1644 if (!mls_enabled || !revocation_enabled) 1645 return (0); 1646 1647 subj = SLOT(active_cred->cr_label); 1648 obj = SLOT(shmlabel); 1649 1650 if (!mls_dominate_effective(subj, obj)) 1651 return (EACCES); 1652 1653 return (0); 1654 } 1655 1656 static int 1657 mls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd, 1658 struct label *shmlabel, mode_t mode) 1659 { 1660 struct mac_mls *subj, *obj; 1661 1662 if (!mls_enabled) 1663 return (0); 1664 1665 subj = SLOT(cred->cr_label); 1666 obj = SLOT(shmlabel); 1667 1668 if (!mls_dominate_effective(obj, subj)) 1669 return (EACCES); 1670 1671 return (0); 1672 } 1673 1674 static int 1675 mls_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd, 1676 struct label *shmlabel, uid_t uid, gid_t gid) 1677 { 1678 struct mac_mls *subj, *obj; 1679 1680 if (!mls_enabled) 1681 return (0); 1682 1683 subj = SLOT(cred->cr_label); 1684 obj = SLOT(shmlabel); 1685 1686 if (!mls_dominate_effective(obj, subj)) 1687 return (EACCES); 1688 1689 return (0); 1690 } 1691 1692 static int 1693 mls_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred, 1694 struct shmfd *shmfd, struct label *shmlabel) 1695 { 1696 struct mac_mls *subj, *obj; 1697 1698 if (!mls_enabled) 1699 return (0); 1700 1701 subj = SLOT(active_cred->cr_label); 1702 obj = SLOT(shmlabel); 1703 1704 if (!mls_dominate_effective(subj, obj)) 1705 return (EACCES); 1706 1707 return (0); 1708 } 1709 1710 static int 1711 mls_posixshm_check_truncate(struct ucred *active_cred, 1712 struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel) 1713 { 1714 struct mac_mls *subj, *obj; 1715 1716 if (!mls_enabled) 1717 return (0); 1718 1719 subj = SLOT(active_cred->cr_label); 1720 obj = SLOT(shmlabel); 1721 1722 if (!mls_dominate_effective(obj, subj)) 1723 return (EACCES); 1724 1725 return (0); 1726 } 1727 1728 static int 1729 mls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd, 1730 struct label *shmlabel) 1731 { 1732 struct mac_mls *subj, *obj; 1733 1734 if (!mls_enabled) 1735 return (0); 1736 1737 subj = SLOT(cred->cr_label); 1738 obj = SLOT(shmlabel); 1739 1740 if (!mls_dominate_effective(obj, subj)) 1741 return (EACCES); 1742 1743 return (0); 1744 } 1745 1746 static int 1747 mls_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred, 1748 struct shmfd *shm, struct label *shmlabel) 1749 { 1750 struct mac_mls *subj, *obj; 1751 1752 if (!mls_enabled || !revocation_enabled) 1753 return (0); 1754 1755 subj = SLOT(active_cred->cr_label); 1756 obj = SLOT(shmlabel); 1757 1758 if (!mls_dominate_effective(subj, obj)) 1759 return (EACCES); 1760 1761 return (0); 1762 } 1763 1764 static void 1765 mls_posixshm_create(struct ucred *cred, struct shmfd *shmfd, 1766 struct label *shmlabel) 1767 { 1768 struct mac_mls *source, *dest; 1769 1770 source = SLOT(cred->cr_label); 1771 dest = SLOT(shmlabel); 1772 1773 mls_copy_effective(source, dest); 1774 } 1775 1776 static int 1777 mls_proc_check_debug(struct ucred *cred, struct proc *p) 1778 { 1779 struct mac_mls *subj, *obj; 1780 1781 if (!mls_enabled) 1782 return (0); 1783 1784 subj = SLOT(cred->cr_label); 1785 obj = SLOT(p->p_ucred->cr_label); 1786 1787 /* XXX: range checks */ 1788 if (!mls_dominate_effective(subj, obj)) 1789 return (ESRCH); 1790 if (!mls_dominate_effective(obj, subj)) 1791 return (EACCES); 1792 1793 return (0); 1794 } 1795 1796 static int 1797 mls_proc_check_sched(struct ucred *cred, struct proc *p) 1798 { 1799 struct mac_mls *subj, *obj; 1800 1801 if (!mls_enabled) 1802 return (0); 1803 1804 subj = SLOT(cred->cr_label); 1805 obj = SLOT(p->p_ucred->cr_label); 1806 1807 /* XXX: range checks */ 1808 if (!mls_dominate_effective(subj, obj)) 1809 return (ESRCH); 1810 if (!mls_dominate_effective(obj, subj)) 1811 return (EACCES); 1812 1813 return (0); 1814 } 1815 1816 static int 1817 mls_proc_check_signal(struct ucred *cred, struct proc *p, int signum) 1818 { 1819 struct mac_mls *subj, *obj; 1820 1821 if (!mls_enabled) 1822 return (0); 1823 1824 subj = SLOT(cred->cr_label); 1825 obj = SLOT(p->p_ucred->cr_label); 1826 1827 /* XXX: range checks */ 1828 if (!mls_dominate_effective(subj, obj)) 1829 return (ESRCH); 1830 if (!mls_dominate_effective(obj, subj)) 1831 return (EACCES); 1832 1833 return (0); 1834 } 1835 1836 static int 1837 mls_socket_check_deliver(struct socket *so, struct label *solabel, 1838 struct mbuf *m, struct label *mlabel) 1839 { 1840 struct mac_mls *p, *s; 1841 int error; 1842 1843 if (!mls_enabled) 1844 return (0); 1845 1846 p = SLOT(mlabel); 1847 s = SLOT(solabel); 1848 1849 SOCK_LOCK(so); 1850 error = mls_equal_effective(p, s) ? 0 : EACCES; 1851 SOCK_UNLOCK(so); 1852 1853 return (error); 1854 } 1855 1856 static int 1857 mls_socket_check_relabel(struct ucred *cred, struct socket *so, 1858 struct label *solabel, struct label *newlabel) 1859 { 1860 struct mac_mls *subj, *obj, *new; 1861 int error; 1862 1863 SOCK_LOCK_ASSERT(so); 1864 1865 new = SLOT(newlabel); 1866 subj = SLOT(cred->cr_label); 1867 obj = SLOT(solabel); 1868 1869 /* 1870 * If there is an MLS label update for the socket, it may be an 1871 * update of effective. 1872 */ 1873 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE); 1874 if (error) 1875 return (error); 1876 1877 /* 1878 * To relabel a socket, the old socket effective must be in the 1879 * subject range. 1880 */ 1881 if (!mls_effective_in_range(obj, subj)) 1882 return (EPERM); 1883 1884 /* 1885 * If the MLS label is to be changed, authorize as appropriate. 1886 */ 1887 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { 1888 /* 1889 * To relabel a socket, the new socket effective must be in 1890 * the subject range. 1891 */ 1892 if (!mls_effective_in_range(new, subj)) 1893 return (EPERM); 1894 1895 /* 1896 * To change the MLS label on the socket to contain EQUAL, 1897 * the subject must have appropriate privilege. 1898 */ 1899 if (mls_contains_equal(new)) { 1900 error = mls_subject_privileged(subj); 1901 if (error) 1902 return (error); 1903 } 1904 } 1905 1906 return (0); 1907 } 1908 1909 static int 1910 mls_socket_check_visible(struct ucred *cred, struct socket *so, 1911 struct label *solabel) 1912 { 1913 struct mac_mls *subj, *obj; 1914 1915 if (!mls_enabled) 1916 return (0); 1917 1918 subj = SLOT(cred->cr_label); 1919 obj = SLOT(solabel); 1920 1921 SOCK_LOCK(so); 1922 if (!mls_dominate_effective(subj, obj)) { 1923 SOCK_UNLOCK(so); 1924 return (ENOENT); 1925 } 1926 SOCK_UNLOCK(so); 1927 1928 return (0); 1929 } 1930 1931 static void 1932 mls_socket_create(struct ucred *cred, struct socket *so, 1933 struct label *solabel) 1934 { 1935 struct mac_mls *source, *dest; 1936 1937 source = SLOT(cred->cr_label); 1938 dest = SLOT(solabel); 1939 1940 mls_copy_effective(source, dest); 1941 } 1942 1943 static void 1944 mls_socket_create_mbuf(struct socket *so, struct label *solabel, 1945 struct mbuf *m, struct label *mlabel) 1946 { 1947 struct mac_mls *source, *dest; 1948 1949 source = SLOT(solabel); 1950 dest = SLOT(mlabel); 1951 1952 SOCK_LOCK(so); 1953 mls_copy_effective(source, dest); 1954 SOCK_UNLOCK(so); 1955 } 1956 1957 static void 1958 mls_socket_newconn(struct socket *oldso, struct label *oldsolabel, 1959 struct socket *newso, struct label *newsolabel) 1960 { 1961 struct mac_mls source, *dest; 1962 1963 SOCK_LOCK(oldso); 1964 source = *SLOT(oldsolabel); 1965 SOCK_UNLOCK(oldso); 1966 1967 dest = SLOT(newsolabel); 1968 1969 SOCK_LOCK(newso); 1970 mls_copy_effective(&source, dest); 1971 SOCK_UNLOCK(newso); 1972 } 1973 1974 static void 1975 mls_socket_relabel(struct ucred *cred, struct socket *so, 1976 struct label *solabel, struct label *newlabel) 1977 { 1978 struct mac_mls *source, *dest; 1979 1980 SOCK_LOCK_ASSERT(so); 1981 1982 source = SLOT(newlabel); 1983 dest = SLOT(solabel); 1984 1985 mls_copy(source, dest); 1986 } 1987 1988 static void 1989 mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, 1990 struct socket *so, struct label *sopeerlabel) 1991 { 1992 struct mac_mls *source, *dest; 1993 1994 source = SLOT(mlabel); 1995 dest = SLOT(sopeerlabel); 1996 1997 SOCK_LOCK(so); 1998 mls_copy_effective(source, dest); 1999 SOCK_UNLOCK(so); 2000 } 2001 2002 static void 2003 mls_socketpeer_set_from_socket(struct socket *oldso, 2004 struct label *oldsolabel, struct socket *newso, 2005 struct label *newsopeerlabel) 2006 { 2007 struct mac_mls source, *dest; 2008 2009 SOCK_LOCK(oldso); 2010 source = *SLOT(oldsolabel); 2011 SOCK_UNLOCK(oldso); 2012 2013 dest = SLOT(newsopeerlabel); 2014 2015 SOCK_LOCK(newso); 2016 mls_copy_effective(&source, dest); 2017 SOCK_UNLOCK(newso); 2018 } 2019 2020 static void 2021 mls_syncache_create(struct label *label, struct inpcb *inp) 2022 { 2023 struct mac_mls *source, *dest; 2024 2025 source = SLOT(inp->inp_label); 2026 dest = SLOT(label); 2027 2028 mls_copy_effective(source, dest); 2029 } 2030 2031 static void 2032 mls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m, 2033 struct label *mlabel) 2034 { 2035 struct mac_mls *source, *dest; 2036 2037 source = SLOT(sc_label); 2038 dest = SLOT(mlabel); 2039 2040 mls_copy_effective(source, dest); 2041 } 2042 2043 static int 2044 mls_system_check_acct(struct ucred *cred, struct vnode *vp, 2045 struct label *vplabel) 2046 { 2047 struct mac_mls *subj, *obj; 2048 2049 if (!mls_enabled) 2050 return (0); 2051 2052 if (vplabel == NULL) 2053 return (0); 2054 2055 subj = SLOT(cred->cr_label); 2056 obj = SLOT(vplabel); 2057 2058 if (!mls_dominate_effective(obj, subj) || 2059 !mls_dominate_effective(subj, obj)) 2060 return (EACCES); 2061 2062 return (0); 2063 } 2064 2065 static int 2066 mls_system_check_auditctl(struct ucred *cred, struct vnode *vp, 2067 struct label *vplabel) 2068 { 2069 struct mac_mls *subj, *obj; 2070 2071 if (!mls_enabled) 2072 return (0); 2073 2074 subj = SLOT(cred->cr_label); 2075 obj = SLOT(vplabel); 2076 2077 if (!mls_dominate_effective(obj, subj) || 2078 !mls_dominate_effective(subj, obj)) 2079 return (EACCES); 2080 2081 return (0); 2082 } 2083 2084 static int 2085 mls_system_check_swapon(struct ucred *cred, struct vnode *vp, 2086 struct label *vplabel) 2087 { 2088 struct mac_mls *subj, *obj; 2089 2090 if (!mls_enabled) 2091 return (0); 2092 2093 subj = SLOT(cred->cr_label); 2094 obj = SLOT(vplabel); 2095 2096 if (!mls_dominate_effective(obj, subj) || 2097 !mls_dominate_effective(subj, obj)) 2098 return (EACCES); 2099 2100 return (0); 2101 } 2102 2103 static void 2104 mls_sysvmsg_cleanup(struct label *msglabel) 2105 { 2106 2107 bzero(SLOT(msglabel), sizeof(struct mac_mls)); 2108 } 2109 2110 static void 2111 mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr, 2112 struct label *msqlabel, struct msg *msgptr, struct label *msglabel) 2113 { 2114 struct mac_mls *source, *dest; 2115 2116 /* Ignore the msgq label. */ 2117 source = SLOT(cred->cr_label); 2118 dest = SLOT(msglabel); 2119 2120 mls_copy_effective(source, dest); 2121 } 2122 2123 static int 2124 mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr, 2125 struct label *msglabel) 2126 { 2127 struct mac_mls *subj, *obj; 2128 2129 if (!mls_enabled) 2130 return (0); 2131 2132 subj = SLOT(cred->cr_label); 2133 obj = SLOT(msglabel); 2134 2135 if (!mls_dominate_effective(subj, obj)) 2136 return (EACCES); 2137 2138 return (0); 2139 } 2140 2141 static int 2142 mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr, 2143 struct label *msglabel) 2144 { 2145 struct mac_mls *subj, *obj; 2146 2147 if (!mls_enabled) 2148 return (0); 2149 2150 subj = SLOT(cred->cr_label); 2151 obj = SLOT(msglabel); 2152 2153 if (!mls_dominate_effective(obj, subj)) 2154 return (EACCES); 2155 2156 return (0); 2157 } 2158 2159 static int 2160 mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr, 2161 struct label *msqklabel) 2162 { 2163 struct mac_mls *subj, *obj; 2164 2165 if (!mls_enabled) 2166 return (0); 2167 2168 subj = SLOT(cred->cr_label); 2169 obj = SLOT(msqklabel); 2170 2171 if (!mls_dominate_effective(subj, obj)) 2172 return (EACCES); 2173 2174 return (0); 2175 } 2176 2177 static int 2178 mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr, 2179 struct label *msqklabel) 2180 { 2181 struct mac_mls *subj, *obj; 2182 2183 if (!mls_enabled) 2184 return (0); 2185 2186 subj = SLOT(cred->cr_label); 2187 obj = SLOT(msqklabel); 2188 2189 if (!mls_dominate_effective(obj, subj)) 2190 return (EACCES); 2191 2192 return (0); 2193 } 2194 2195 static int 2196 mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr, 2197 struct label *msqklabel) 2198 { 2199 struct mac_mls *subj, *obj; 2200 2201 if (!mls_enabled) 2202 return (0); 2203 2204 subj = SLOT(cred->cr_label); 2205 obj = SLOT(msqklabel); 2206 2207 if (!mls_dominate_effective(subj, obj)) 2208 return (EACCES); 2209 2210 return (0); 2211 } 2212 2213 static int 2214 mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, 2215 struct label *msqklabel, int cmd) 2216 { 2217 struct mac_mls *subj, *obj; 2218 2219 if (!mls_enabled) 2220 return (0); 2221 2222 subj = SLOT(cred->cr_label); 2223 obj = SLOT(msqklabel); 2224 2225 switch(cmd) { 2226 case IPC_RMID: 2227 case IPC_SET: 2228 if (!mls_dominate_effective(obj, subj)) 2229 return (EACCES); 2230 break; 2231 2232 case IPC_STAT: 2233 if (!mls_dominate_effective(subj, obj)) 2234 return (EACCES); 2235 break; 2236 2237 default: 2238 return (EACCES); 2239 } 2240 2241 return (0); 2242 } 2243 2244 static void 2245 mls_sysvmsq_cleanup(struct label *msqlabel) 2246 { 2247 2248 bzero(SLOT(msqlabel), sizeof(struct mac_mls)); 2249 } 2250 2251 static void 2252 mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr, 2253 struct label *msqlabel) 2254 { 2255 struct mac_mls *source, *dest; 2256 2257 source = SLOT(cred->cr_label); 2258 dest = SLOT(msqlabel); 2259 2260 mls_copy_effective(source, dest); 2261 } 2262 2263 static int 2264 mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr, 2265 struct label *semaklabel, int cmd) 2266 { 2267 struct mac_mls *subj, *obj; 2268 2269 if (!mls_enabled) 2270 return (0); 2271 2272 subj = SLOT(cred->cr_label); 2273 obj = SLOT(semaklabel); 2274 2275 switch(cmd) { 2276 case IPC_RMID: 2277 case IPC_SET: 2278 case SETVAL: 2279 case SETALL: 2280 if (!mls_dominate_effective(obj, subj)) 2281 return (EACCES); 2282 break; 2283 2284 case IPC_STAT: 2285 case GETVAL: 2286 case GETPID: 2287 case GETNCNT: 2288 case GETZCNT: 2289 case GETALL: 2290 if (!mls_dominate_effective(subj, obj)) 2291 return (EACCES); 2292 break; 2293 2294 default: 2295 return (EACCES); 2296 } 2297 2298 return (0); 2299 } 2300 2301 static int 2302 mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr, 2303 struct label *semaklabel) 2304 { 2305 struct mac_mls *subj, *obj; 2306 2307 if (!mls_enabled) 2308 return (0); 2309 2310 subj = SLOT(cred->cr_label); 2311 obj = SLOT(semaklabel); 2312 2313 if (!mls_dominate_effective(subj, obj)) 2314 return (EACCES); 2315 2316 return (0); 2317 } 2318 2319 static int 2320 mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr, 2321 struct label *semaklabel, size_t accesstype) 2322 { 2323 struct mac_mls *subj, *obj; 2324 2325 if (!mls_enabled) 2326 return (0); 2327 2328 subj = SLOT(cred->cr_label); 2329 obj = SLOT(semaklabel); 2330 2331 if( accesstype & SEM_R ) 2332 if (!mls_dominate_effective(subj, obj)) 2333 return (EACCES); 2334 2335 if( accesstype & SEM_A ) 2336 if (!mls_dominate_effective(obj, subj)) 2337 return (EACCES); 2338 2339 return (0); 2340 } 2341 2342 static void 2343 mls_sysvsem_cleanup(struct label *semalabel) 2344 { 2345 2346 bzero(SLOT(semalabel), sizeof(struct mac_mls)); 2347 } 2348 2349 static void 2350 mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr, 2351 struct label *semalabel) 2352 { 2353 struct mac_mls *source, *dest; 2354 2355 source = SLOT(cred->cr_label); 2356 dest = SLOT(semalabel); 2357 2358 mls_copy_effective(source, dest); 2359 } 2360 2361 static int 2362 mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, 2363 struct label *shmseglabel, int shmflg) 2364 { 2365 struct mac_mls *subj, *obj; 2366 2367 if (!mls_enabled) 2368 return (0); 2369 2370 subj = SLOT(cred->cr_label); 2371 obj = SLOT(shmseglabel); 2372 2373 if (!mls_dominate_effective(subj, obj)) 2374 return (EACCES); 2375 if ((shmflg & SHM_RDONLY) == 0) { 2376 if (!mls_dominate_effective(obj, subj)) 2377 return (EACCES); 2378 } 2379 2380 return (0); 2381 } 2382 2383 static int 2384 mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, 2385 struct label *shmseglabel, int cmd) 2386 { 2387 struct mac_mls *subj, *obj; 2388 2389 if (!mls_enabled) 2390 return (0); 2391 2392 subj = SLOT(cred->cr_label); 2393 obj = SLOT(shmseglabel); 2394 2395 switch(cmd) { 2396 case IPC_RMID: 2397 case IPC_SET: 2398 if (!mls_dominate_effective(obj, subj)) 2399 return (EACCES); 2400 break; 2401 2402 case IPC_STAT: 2403 case SHM_STAT: 2404 if (!mls_dominate_effective(subj, obj)) 2405 return (EACCES); 2406 break; 2407 2408 default: 2409 return (EACCES); 2410 } 2411 2412 return (0); 2413 } 2414 2415 static int 2416 mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, 2417 struct label *shmseglabel, int shmflg) 2418 { 2419 struct mac_mls *subj, *obj; 2420 2421 if (!mls_enabled) 2422 return (0); 2423 2424 subj = SLOT(cred->cr_label); 2425 obj = SLOT(shmseglabel); 2426 2427 if (!mls_dominate_effective(obj, subj)) 2428 return (EACCES); 2429 2430 return (0); 2431 } 2432 2433 static void 2434 mls_sysvshm_cleanup(struct label *shmlabel) 2435 { 2436 2437 bzero(SLOT(shmlabel), sizeof(struct mac_mls)); 2438 } 2439 2440 static void 2441 mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr, 2442 struct label *shmlabel) 2443 { 2444 struct mac_mls *source, *dest; 2445 2446 source = SLOT(cred->cr_label); 2447 dest = SLOT(shmlabel); 2448 2449 mls_copy_effective(source, dest); 2450 } 2451 2452 static int 2453 mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel, 2454 struct vnode *vp, struct label *vplabel) 2455 { 2456 struct mac_mls mm_temp, *source, *dest; 2457 int buflen, error; 2458 2459 source = SLOT(mplabel); 2460 dest = SLOT(vplabel); 2461 2462 buflen = sizeof(mm_temp); 2463 bzero(&mm_temp, buflen); 2464 2465 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, 2466 MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread); 2467 if (error == ENOATTR || error == EOPNOTSUPP) { 2468 /* Fall back to the mntlabel. */ 2469 mls_copy_effective(source, dest); 2470 return (0); 2471 } else if (error) 2472 return (error); 2473 2474 if (buflen != sizeof(mm_temp)) { 2475 printf("mls_vnode_associate_extattr: bad size %d\n", buflen); 2476 return (EPERM); 2477 } 2478 if (mls_valid(&mm_temp) != 0) { 2479 printf("mls_vnode_associate_extattr: invalid\n"); 2480 return (EPERM); 2481 } 2482 if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) != 2483 MAC_MLS_FLAG_EFFECTIVE) { 2484 printf("mls_associated_vnode_extattr: not effective\n"); 2485 return (EPERM); 2486 } 2487 2488 mls_copy_effective(&mm_temp, dest); 2489 return (0); 2490 } 2491 2492 static void 2493 mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel, 2494 struct vnode *vp, struct label *vplabel) 2495 { 2496 struct mac_mls *source, *dest; 2497 2498 source = SLOT(mplabel); 2499 dest = SLOT(vplabel); 2500 2501 mls_copy_effective(source, dest); 2502 } 2503 2504 static int 2505 mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp, 2506 struct label *dvplabel) 2507 { 2508 struct mac_mls *subj, *obj; 2509 2510 if (!mls_enabled) 2511 return (0); 2512 2513 subj = SLOT(cred->cr_label); 2514 obj = SLOT(dvplabel); 2515 2516 if (!mls_dominate_effective(subj, obj)) 2517 return (EACCES); 2518 2519 return (0); 2520 } 2521 2522 static int 2523 mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp, 2524 struct label *dvplabel) 2525 { 2526 struct mac_mls *subj, *obj; 2527 2528 if (!mls_enabled) 2529 return (0); 2530 2531 subj = SLOT(cred->cr_label); 2532 obj = SLOT(dvplabel); 2533 2534 if (!mls_dominate_effective(subj, obj)) 2535 return (EACCES); 2536 2537 return (0); 2538 } 2539 2540 static int 2541 mls_vnode_check_create(struct ucred *cred, struct vnode *dvp, 2542 struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 2543 { 2544 struct mac_mls *subj, *obj; 2545 2546 if (!mls_enabled) 2547 return (0); 2548 2549 subj = SLOT(cred->cr_label); 2550 obj = SLOT(dvplabel); 2551 2552 if (!mls_dominate_effective(obj, subj)) 2553 return (EACCES); 2554 2555 return (0); 2556 } 2557 2558 static int 2559 mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 2560 struct label *vplabel, acl_type_t type) 2561 { 2562 struct mac_mls *subj, *obj; 2563 2564 if (!mls_enabled) 2565 return (0); 2566 2567 subj = SLOT(cred->cr_label); 2568 obj = SLOT(vplabel); 2569 2570 if (!mls_dominate_effective(obj, subj)) 2571 return (EACCES); 2572 2573 return (0); 2574 } 2575 2576 static int 2577 mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp, 2578 struct label *vplabel, int attrnamespace, const char *name) 2579 { 2580 struct mac_mls *subj, *obj; 2581 2582 if (!mls_enabled) 2583 return (0); 2584 2585 subj = SLOT(cred->cr_label); 2586 obj = SLOT(vplabel); 2587 2588 if (!mls_dominate_effective(obj, subj)) 2589 return (EACCES); 2590 2591 return (0); 2592 } 2593 2594 static int 2595 mls_vnode_check_exec(struct ucred *cred, struct vnode *vp, 2596 struct label *vplabel, struct image_params *imgp, 2597 struct label *execlabel) 2598 { 2599 struct mac_mls *subj, *obj, *exec; 2600 int error; 2601 2602 if (execlabel != NULL) { 2603 /* 2604 * We currently don't permit labels to be changed at 2605 * exec-time as part of MLS, so disallow non-NULL MLS label 2606 * elements in the execlabel. 2607 */ 2608 exec = SLOT(execlabel); 2609 error = mls_atmostflags(exec, 0); 2610 if (error) 2611 return (error); 2612 } 2613 2614 if (!mls_enabled) 2615 return (0); 2616 2617 subj = SLOT(cred->cr_label); 2618 obj = SLOT(vplabel); 2619 2620 if (!mls_dominate_effective(subj, obj)) 2621 return (EACCES); 2622 2623 return (0); 2624 } 2625 2626 static int 2627 mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp, 2628 struct label *vplabel, acl_type_t type) 2629 { 2630 struct mac_mls *subj, *obj; 2631 2632 if (!mls_enabled) 2633 return (0); 2634 2635 subj = SLOT(cred->cr_label); 2636 obj = SLOT(vplabel); 2637 2638 if (!mls_dominate_effective(subj, obj)) 2639 return (EACCES); 2640 2641 return (0); 2642 } 2643 2644 static int 2645 mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp, 2646 struct label *vplabel, int attrnamespace, const char *name) 2647 { 2648 struct mac_mls *subj, *obj; 2649 2650 if (!mls_enabled) 2651 return (0); 2652 2653 subj = SLOT(cred->cr_label); 2654 obj = SLOT(vplabel); 2655 2656 if (!mls_dominate_effective(subj, obj)) 2657 return (EACCES); 2658 2659 return (0); 2660 } 2661 2662 static int 2663 mls_vnode_check_link(struct ucred *cred, struct vnode *dvp, 2664 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2665 struct componentname *cnp) 2666 { 2667 struct mac_mls *subj, *obj; 2668 2669 if (!mls_enabled) 2670 return (0); 2671 2672 subj = SLOT(cred->cr_label); 2673 obj = SLOT(dvplabel); 2674 2675 if (!mls_dominate_effective(obj, subj)) 2676 return (EACCES); 2677 2678 obj = SLOT(vplabel); 2679 if (!mls_dominate_effective(obj, subj)) 2680 return (EACCES); 2681 2682 return (0); 2683 } 2684 2685 static int 2686 mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp, 2687 struct label *vplabel, int attrnamespace) 2688 { 2689 2690 struct mac_mls *subj, *obj; 2691 2692 if (!mls_enabled) 2693 return (0); 2694 2695 subj = SLOT(cred->cr_label); 2696 obj = SLOT(vplabel); 2697 2698 if (!mls_dominate_effective(subj, obj)) 2699 return (EACCES); 2700 2701 return (0); 2702 } 2703 2704 static int 2705 mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp, 2706 struct label *dvplabel, struct componentname *cnp) 2707 { 2708 struct mac_mls *subj, *obj; 2709 2710 if (!mls_enabled) 2711 return (0); 2712 2713 subj = SLOT(cred->cr_label); 2714 obj = SLOT(dvplabel); 2715 2716 if (!mls_dominate_effective(subj, obj)) 2717 return (EACCES); 2718 2719 return (0); 2720 } 2721 2722 static int 2723 mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp, 2724 struct label *vplabel, int prot, int flags) 2725 { 2726 struct mac_mls *subj, *obj; 2727 2728 /* 2729 * Rely on the use of open()-time protections to handle 2730 * non-revocation cases. 2731 */ 2732 if (!mls_enabled || !revocation_enabled) 2733 return (0); 2734 2735 subj = SLOT(cred->cr_label); 2736 obj = SLOT(vplabel); 2737 2738 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 2739 if (!mls_dominate_effective(subj, obj)) 2740 return (EACCES); 2741 } 2742 if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 2743 if (!mls_dominate_effective(obj, subj)) 2744 return (EACCES); 2745 } 2746 2747 return (0); 2748 } 2749 2750 static int 2751 mls_vnode_check_open(struct ucred *cred, struct vnode *vp, 2752 struct label *vplabel, accmode_t accmode) 2753 { 2754 struct mac_mls *subj, *obj; 2755 2756 if (!mls_enabled) 2757 return (0); 2758 2759 subj = SLOT(cred->cr_label); 2760 obj = SLOT(vplabel); 2761 2762 /* XXX privilege override for admin? */ 2763 if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) { 2764 if (!mls_dominate_effective(subj, obj)) 2765 return (EACCES); 2766 } 2767 if (accmode & VMODIFY_PERMS) { 2768 if (!mls_dominate_effective(obj, subj)) 2769 return (EACCES); 2770 } 2771 2772 return (0); 2773 } 2774 2775 static int 2776 mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred, 2777 struct vnode *vp, struct label *vplabel) 2778 { 2779 struct mac_mls *subj, *obj; 2780 2781 if (!mls_enabled || !revocation_enabled) 2782 return (0); 2783 2784 subj = SLOT(active_cred->cr_label); 2785 obj = SLOT(vplabel); 2786 2787 if (!mls_dominate_effective(subj, obj)) 2788 return (EACCES); 2789 2790 return (0); 2791 } 2792 2793 static int 2794 mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, 2795 struct vnode *vp, struct label *vplabel) 2796 { 2797 struct mac_mls *subj, *obj; 2798 2799 if (!mls_enabled || !revocation_enabled) 2800 return (0); 2801 2802 subj = SLOT(active_cred->cr_label); 2803 obj = SLOT(vplabel); 2804 2805 if (!mls_dominate_effective(subj, obj)) 2806 return (EACCES); 2807 2808 return (0); 2809 } 2810 2811 static int 2812 mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp, 2813 struct label *dvplabel) 2814 { 2815 struct mac_mls *subj, *obj; 2816 2817 if (!mls_enabled) 2818 return (0); 2819 2820 subj = SLOT(cred->cr_label); 2821 obj = SLOT(dvplabel); 2822 2823 if (!mls_dominate_effective(subj, obj)) 2824 return (EACCES); 2825 2826 return (0); 2827 } 2828 2829 static int 2830 mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp, 2831 struct label *vplabel) 2832 { 2833 struct mac_mls *subj, *obj; 2834 2835 if (!mls_enabled) 2836 return (0); 2837 2838 subj = SLOT(cred->cr_label); 2839 obj = SLOT(vplabel); 2840 2841 if (!mls_dominate_effective(subj, obj)) 2842 return (EACCES); 2843 2844 return (0); 2845 } 2846 2847 static int 2848 mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 2849 struct label *vplabel, struct label *newlabel) 2850 { 2851 struct mac_mls *old, *new, *subj; 2852 int error; 2853 2854 old = SLOT(vplabel); 2855 new = SLOT(newlabel); 2856 subj = SLOT(cred->cr_label); 2857 2858 /* 2859 * If there is an MLS label update for the vnode, it must be a 2860 * effective label. 2861 */ 2862 error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE); 2863 if (error) 2864 return (error); 2865 2866 /* 2867 * To perform a relabel of the vnode (MLS label or not), MLS must 2868 * authorize the relabel. 2869 */ 2870 if (!mls_effective_in_range(old, subj)) 2871 return (EPERM); 2872 2873 /* 2874 * If the MLS label is to be changed, authorize as appropriate. 2875 */ 2876 if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) { 2877 /* 2878 * To change the MLS label on a vnode, the new vnode label 2879 * must be in the subject range. 2880 */ 2881 if (!mls_effective_in_range(new, subj)) 2882 return (EPERM); 2883 2884 /* 2885 * To change the MLS label on the vnode to be EQUAL, the 2886 * subject must have appropriate privilege. 2887 */ 2888 if (mls_contains_equal(new)) { 2889 error = mls_subject_privileged(subj); 2890 if (error) 2891 return (error); 2892 } 2893 } 2894 2895 return (0); 2896 } 2897 2898 static int 2899 mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 2900 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2901 struct componentname *cnp) 2902 { 2903 struct mac_mls *subj, *obj; 2904 2905 if (!mls_enabled) 2906 return (0); 2907 2908 subj = SLOT(cred->cr_label); 2909 obj = SLOT(dvplabel); 2910 2911 if (!mls_dominate_effective(obj, subj)) 2912 return (EACCES); 2913 2914 obj = SLOT(vplabel); 2915 2916 if (!mls_dominate_effective(obj, subj)) 2917 return (EACCES); 2918 2919 return (0); 2920 } 2921 2922 static int 2923 mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 2924 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2925 int samedir, struct componentname *cnp) 2926 { 2927 struct mac_mls *subj, *obj; 2928 2929 if (!mls_enabled) 2930 return (0); 2931 2932 subj = SLOT(cred->cr_label); 2933 obj = SLOT(dvplabel); 2934 2935 if (!mls_dominate_effective(obj, subj)) 2936 return (EACCES); 2937 2938 if (vp != NULL) { 2939 obj = SLOT(vplabel); 2940 2941 if (!mls_dominate_effective(obj, subj)) 2942 return (EACCES); 2943 } 2944 2945 return (0); 2946 } 2947 2948 static int 2949 mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 2950 struct label *vplabel) 2951 { 2952 struct mac_mls *subj, *obj; 2953 2954 if (!mls_enabled) 2955 return (0); 2956 2957 subj = SLOT(cred->cr_label); 2958 obj = SLOT(vplabel); 2959 2960 if (!mls_dominate_effective(obj, subj)) 2961 return (EACCES); 2962 2963 return (0); 2964 } 2965 2966 static int 2967 mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp, 2968 struct label *vplabel, acl_type_t type, struct acl *acl) 2969 { 2970 struct mac_mls *subj, *obj; 2971 2972 if (!mls_enabled) 2973 return (0); 2974 2975 subj = SLOT(cred->cr_label); 2976 obj = SLOT(vplabel); 2977 2978 if (!mls_dominate_effective(obj, subj)) 2979 return (EACCES); 2980 2981 return (0); 2982 } 2983 2984 static int 2985 mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 2986 struct label *vplabel, int attrnamespace, const char *name) 2987 { 2988 struct mac_mls *subj, *obj; 2989 2990 if (!mls_enabled) 2991 return (0); 2992 2993 subj = SLOT(cred->cr_label); 2994 obj = SLOT(vplabel); 2995 2996 if (!mls_dominate_effective(obj, subj)) 2997 return (EACCES); 2998 2999 /* XXX: protect the MAC EA in a special way? */ 3000 3001 return (0); 3002 } 3003 3004 static int 3005 mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 3006 struct label *vplabel, u_long flags) 3007 { 3008 struct mac_mls *subj, *obj; 3009 3010 if (!mls_enabled) 3011 return (0); 3012 3013 subj = SLOT(cred->cr_label); 3014 obj = SLOT(vplabel); 3015 3016 if (!mls_dominate_effective(obj, subj)) 3017 return (EACCES); 3018 3019 return (0); 3020 } 3021 3022 static int 3023 mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 3024 struct label *vplabel, mode_t mode) 3025 { 3026 struct mac_mls *subj, *obj; 3027 3028 if (!mls_enabled) 3029 return (0); 3030 3031 subj = SLOT(cred->cr_label); 3032 obj = SLOT(vplabel); 3033 3034 if (!mls_dominate_effective(obj, subj)) 3035 return (EACCES); 3036 3037 return (0); 3038 } 3039 3040 static int 3041 mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 3042 struct label *vplabel, uid_t uid, gid_t gid) 3043 { 3044 struct mac_mls *subj, *obj; 3045 3046 if (!mls_enabled) 3047 return (0); 3048 3049 subj = SLOT(cred->cr_label); 3050 obj = SLOT(vplabel); 3051 3052 if (!mls_dominate_effective(obj, subj)) 3053 return (EACCES); 3054 3055 return (0); 3056 } 3057 3058 static int 3059 mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 3060 struct label *vplabel, struct timespec atime, struct timespec mtime) 3061 { 3062 struct mac_mls *subj, *obj; 3063 3064 if (!mls_enabled) 3065 return (0); 3066 3067 subj = SLOT(cred->cr_label); 3068 obj = SLOT(vplabel); 3069 3070 if (!mls_dominate_effective(obj, subj)) 3071 return (EACCES); 3072 3073 return (0); 3074 } 3075 3076 static int 3077 mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred, 3078 struct vnode *vp, struct label *vplabel) 3079 { 3080 struct mac_mls *subj, *obj; 3081 3082 if (!mls_enabled) 3083 return (0); 3084 3085 subj = SLOT(active_cred->cr_label); 3086 obj = SLOT(vplabel); 3087 3088 if (!mls_dominate_effective(subj, obj)) 3089 return (EACCES); 3090 3091 return (0); 3092 } 3093 3094 static int 3095 mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 3096 struct label *dvplabel, struct vnode *vp, struct label *vplabel, 3097 struct componentname *cnp) 3098 { 3099 struct mac_mls *subj, *obj; 3100 3101 if (!mls_enabled) 3102 return (0); 3103 3104 subj = SLOT(cred->cr_label); 3105 obj = SLOT(dvplabel); 3106 3107 if (!mls_dominate_effective(obj, subj)) 3108 return (EACCES); 3109 3110 obj = SLOT(vplabel); 3111 3112 if (!mls_dominate_effective(obj, subj)) 3113 return (EACCES); 3114 3115 return (0); 3116 } 3117 3118 static int 3119 mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred, 3120 struct vnode *vp, struct label *vplabel) 3121 { 3122 struct mac_mls *subj, *obj; 3123 3124 if (!mls_enabled || !revocation_enabled) 3125 return (0); 3126 3127 subj = SLOT(active_cred->cr_label); 3128 obj = SLOT(vplabel); 3129 3130 if (!mls_dominate_effective(obj, subj)) 3131 return (EACCES); 3132 3133 return (0); 3134 } 3135 3136 static int 3137 mls_vnode_create_extattr(struct ucred *cred, struct mount *mp, 3138 struct label *mplabel, struct vnode *dvp, struct label *dvplabel, 3139 struct vnode *vp, struct label *vplabel, struct componentname *cnp) 3140 { 3141 struct mac_mls *source, *dest, mm_temp; 3142 size_t buflen; 3143 int error; 3144 3145 buflen = sizeof(mm_temp); 3146 bzero(&mm_temp, buflen); 3147 3148 source = SLOT(cred->cr_label); 3149 dest = SLOT(vplabel); 3150 mls_copy_effective(source, &mm_temp); 3151 3152 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, 3153 MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread); 3154 if (error == 0) 3155 mls_copy_effective(source, dest); 3156 return (error); 3157 } 3158 3159 static void 3160 mls_vnode_relabel(struct ucred *cred, struct vnode *vp, 3161 struct label *vplabel, struct label *label) 3162 { 3163 struct mac_mls *source, *dest; 3164 3165 source = SLOT(label); 3166 dest = SLOT(vplabel); 3167 3168 mls_copy(source, dest); 3169 } 3170 3171 static int 3172 mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 3173 struct label *vplabel, struct label *intlabel) 3174 { 3175 struct mac_mls *source, mm_temp; 3176 size_t buflen; 3177 int error; 3178 3179 buflen = sizeof(mm_temp); 3180 bzero(&mm_temp, buflen); 3181 3182 source = SLOT(intlabel); 3183 if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0) 3184 return (0); 3185 3186 mls_copy_effective(source, &mm_temp); 3187 3188 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, 3189 MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread); 3190 return (error); 3191 } 3192 3193 static struct mac_policy_ops mls_ops = 3194 { 3195 .mpo_init = mls_init, 3196 3197 .mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive, 3198 .mpo_bpfdesc_create = mls_bpfdesc_create, 3199 .mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf, 3200 .mpo_bpfdesc_destroy_label = mls_destroy_label, 3201 .mpo_bpfdesc_init_label = mls_init_label, 3202 3203 .mpo_cred_associate_nfsd = mls_cred_associate_nfsd, 3204 .mpo_cred_check_relabel = mls_cred_check_relabel, 3205 .mpo_cred_check_visible = mls_cred_check_visible, 3206 .mpo_cred_copy_label = mls_copy_label, 3207 .mpo_cred_create_init = mls_cred_create_init, 3208 .mpo_cred_create_swapper = mls_cred_create_swapper, 3209 .mpo_cred_destroy_label = mls_destroy_label, 3210 .mpo_cred_externalize_label = mls_externalize_label, 3211 .mpo_cred_init_label = mls_init_label, 3212 .mpo_cred_internalize_label = mls_internalize_label, 3213 .mpo_cred_relabel = mls_cred_relabel, 3214 3215 .mpo_devfs_create_device = mls_devfs_create_device, 3216 .mpo_devfs_create_directory = mls_devfs_create_directory, 3217 .mpo_devfs_create_symlink = mls_devfs_create_symlink, 3218 .mpo_devfs_destroy_label = mls_destroy_label, 3219 .mpo_devfs_init_label = mls_init_label, 3220 .mpo_devfs_update = mls_devfs_update, 3221 .mpo_devfs_vnode_associate = mls_devfs_vnode_associate, 3222 3223 .mpo_ifnet_check_relabel = mls_ifnet_check_relabel, 3224 .mpo_ifnet_check_transmit = mls_ifnet_check_transmit, 3225 .mpo_ifnet_copy_label = mls_copy_label, 3226 .mpo_ifnet_create = mls_ifnet_create, 3227 .mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf, 3228 .mpo_ifnet_destroy_label = mls_destroy_label, 3229 .mpo_ifnet_externalize_label = mls_externalize_label, 3230 .mpo_ifnet_init_label = mls_init_label, 3231 .mpo_ifnet_internalize_label = mls_internalize_label, 3232 .mpo_ifnet_relabel = mls_ifnet_relabel, 3233 3234 .mpo_inpcb_check_deliver = mls_inpcb_check_deliver, 3235 .mpo_inpcb_check_visible = mls_inpcb_check_visible, 3236 .mpo_inpcb_create = mls_inpcb_create, 3237 .mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf, 3238 .mpo_inpcb_destroy_label = mls_destroy_label, 3239 .mpo_inpcb_init_label = mls_init_label_waitcheck, 3240 .mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel, 3241 3242 .mpo_ip6q_create = mls_ip6q_create, 3243 .mpo_ip6q_destroy_label = mls_destroy_label, 3244 .mpo_ip6q_init_label = mls_init_label_waitcheck, 3245 .mpo_ip6q_match = mls_ip6q_match, 3246 .mpo_ip6q_reassemble = mls_ip6q_reassemble, 3247 .mpo_ip6q_update = mls_ip6q_update, 3248 3249 .mpo_ipq_create = mls_ipq_create, 3250 .mpo_ipq_destroy_label = mls_destroy_label, 3251 .mpo_ipq_init_label = mls_init_label_waitcheck, 3252 .mpo_ipq_match = mls_ipq_match, 3253 .mpo_ipq_reassemble = mls_ipq_reassemble, 3254 .mpo_ipq_update = mls_ipq_update, 3255 3256 .mpo_mbuf_copy_label = mls_copy_label, 3257 .mpo_mbuf_destroy_label = mls_destroy_label, 3258 .mpo_mbuf_init_label = mls_init_label_waitcheck, 3259 3260 .mpo_mount_check_stat = mls_mount_check_stat, 3261 .mpo_mount_create = mls_mount_create, 3262 .mpo_mount_destroy_label = mls_destroy_label, 3263 .mpo_mount_init_label = mls_init_label, 3264 3265 .mpo_netinet_arp_send = mls_netinet_arp_send, 3266 .mpo_netinet_firewall_reply = mls_netinet_firewall_reply, 3267 .mpo_netinet_firewall_send = mls_netinet_firewall_send, 3268 .mpo_netinet_fragment = mls_netinet_fragment, 3269 .mpo_netinet_icmp_reply = mls_netinet_icmp_reply, 3270 .mpo_netinet_igmp_send = mls_netinet_igmp_send, 3271 3272 .mpo_netinet6_nd6_send = mls_netinet6_nd6_send, 3273 3274 .mpo_pipe_check_ioctl = mls_pipe_check_ioctl, 3275 .mpo_pipe_check_poll = mls_pipe_check_poll, 3276 .mpo_pipe_check_read = mls_pipe_check_read, 3277 .mpo_pipe_check_relabel = mls_pipe_check_relabel, 3278 .mpo_pipe_check_stat = mls_pipe_check_stat, 3279 .mpo_pipe_check_write = mls_pipe_check_write, 3280 .mpo_pipe_copy_label = mls_copy_label, 3281 .mpo_pipe_create = mls_pipe_create, 3282 .mpo_pipe_destroy_label = mls_destroy_label, 3283 .mpo_pipe_externalize_label = mls_externalize_label, 3284 .mpo_pipe_init_label = mls_init_label, 3285 .mpo_pipe_internalize_label = mls_internalize_label, 3286 .mpo_pipe_relabel = mls_pipe_relabel, 3287 3288 .mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly, 3289 .mpo_posixsem_check_open = mls_posixsem_check_openunlink, 3290 .mpo_posixsem_check_post = mls_posixsem_check_write, 3291 .mpo_posixsem_check_setmode = mls_posixsem_check_setmode, 3292 .mpo_posixsem_check_setowner = mls_posixsem_check_setowner, 3293 .mpo_posixsem_check_stat = mls_posixsem_check_rdonly, 3294 .mpo_posixsem_check_unlink = mls_posixsem_check_openunlink, 3295 .mpo_posixsem_check_wait = mls_posixsem_check_write, 3296 .mpo_posixsem_create = mls_posixsem_create, 3297 .mpo_posixsem_destroy_label = mls_destroy_label, 3298 .mpo_posixsem_init_label = mls_init_label, 3299 3300 .mpo_posixshm_check_mmap = mls_posixshm_check_mmap, 3301 .mpo_posixshm_check_open = mls_posixshm_check_open, 3302 .mpo_posixshm_check_read = mls_posixshm_check_read, 3303 .mpo_posixshm_check_setmode = mls_posixshm_check_setmode, 3304 .mpo_posixshm_check_setowner = mls_posixshm_check_setowner, 3305 .mpo_posixshm_check_stat = mls_posixshm_check_stat, 3306 .mpo_posixshm_check_truncate = mls_posixshm_check_truncate, 3307 .mpo_posixshm_check_unlink = mls_posixshm_check_unlink, 3308 .mpo_posixshm_check_write = mls_posixshm_check_write, 3309 .mpo_posixshm_create = mls_posixshm_create, 3310 .mpo_posixshm_destroy_label = mls_destroy_label, 3311 .mpo_posixshm_init_label = mls_init_label, 3312 3313 .mpo_proc_check_debug = mls_proc_check_debug, 3314 .mpo_proc_check_sched = mls_proc_check_sched, 3315 .mpo_proc_check_signal = mls_proc_check_signal, 3316 3317 .mpo_socket_check_deliver = mls_socket_check_deliver, 3318 .mpo_socket_check_relabel = mls_socket_check_relabel, 3319 .mpo_socket_check_visible = mls_socket_check_visible, 3320 .mpo_socket_copy_label = mls_copy_label, 3321 .mpo_socket_create = mls_socket_create, 3322 .mpo_socket_create_mbuf = mls_socket_create_mbuf, 3323 .mpo_socket_destroy_label = mls_destroy_label, 3324 .mpo_socket_externalize_label = mls_externalize_label, 3325 .mpo_socket_init_label = mls_init_label_waitcheck, 3326 .mpo_socket_internalize_label = mls_internalize_label, 3327 .mpo_socket_newconn = mls_socket_newconn, 3328 .mpo_socket_relabel = mls_socket_relabel, 3329 3330 .mpo_socketpeer_destroy_label = mls_destroy_label, 3331 .mpo_socketpeer_externalize_label = mls_externalize_label, 3332 .mpo_socketpeer_init_label = mls_init_label_waitcheck, 3333 .mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf, 3334 .mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket, 3335 3336 .mpo_syncache_create = mls_syncache_create, 3337 .mpo_syncache_create_mbuf = mls_syncache_create_mbuf, 3338 .mpo_syncache_destroy_label = mls_destroy_label, 3339 .mpo_syncache_init_label = mls_init_label_waitcheck, 3340 3341 .mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup, 3342 .mpo_sysvmsg_create = mls_sysvmsg_create, 3343 .mpo_sysvmsg_destroy_label = mls_destroy_label, 3344 .mpo_sysvmsg_init_label = mls_init_label, 3345 3346 .mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv, 3347 .mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid, 3348 .mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget, 3349 .mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd, 3350 .mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv, 3351 .mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl, 3352 .mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup, 3353 .mpo_sysvmsq_destroy_label = mls_destroy_label, 3354 .mpo_sysvmsq_init_label = mls_init_label, 3355 .mpo_sysvmsq_create = mls_sysvmsq_create, 3356 3357 .mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl, 3358 .mpo_sysvsem_check_semget = mls_sysvsem_check_semget, 3359 .mpo_sysvsem_check_semop = mls_sysvsem_check_semop, 3360 .mpo_sysvsem_cleanup = mls_sysvsem_cleanup, 3361 .mpo_sysvsem_create = mls_sysvsem_create, 3362 .mpo_sysvsem_destroy_label = mls_destroy_label, 3363 .mpo_sysvsem_init_label = mls_init_label, 3364 3365 .mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat, 3366 .mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl, 3367 .mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget, 3368 .mpo_sysvshm_cleanup = mls_sysvshm_cleanup, 3369 .mpo_sysvshm_create = mls_sysvshm_create, 3370 .mpo_sysvshm_destroy_label = mls_destroy_label, 3371 .mpo_sysvshm_init_label = mls_init_label, 3372 3373 .mpo_system_check_acct = mls_system_check_acct, 3374 .mpo_system_check_auditctl = mls_system_check_auditctl, 3375 .mpo_system_check_swapon = mls_system_check_swapon, 3376 3377 .mpo_vnode_associate_extattr = mls_vnode_associate_extattr, 3378 .mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel, 3379 .mpo_vnode_check_access = mls_vnode_check_open, 3380 .mpo_vnode_check_chdir = mls_vnode_check_chdir, 3381 .mpo_vnode_check_chroot = mls_vnode_check_chroot, 3382 .mpo_vnode_check_create = mls_vnode_check_create, 3383 .mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl, 3384 .mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr, 3385 .mpo_vnode_check_exec = mls_vnode_check_exec, 3386 .mpo_vnode_check_getacl = mls_vnode_check_getacl, 3387 .mpo_vnode_check_getextattr = mls_vnode_check_getextattr, 3388 .mpo_vnode_check_link = mls_vnode_check_link, 3389 .mpo_vnode_check_listextattr = mls_vnode_check_listextattr, 3390 .mpo_vnode_check_lookup = mls_vnode_check_lookup, 3391 .mpo_vnode_check_mmap = mls_vnode_check_mmap, 3392 .mpo_vnode_check_open = mls_vnode_check_open, 3393 .mpo_vnode_check_poll = mls_vnode_check_poll, 3394 .mpo_vnode_check_read = mls_vnode_check_read, 3395 .mpo_vnode_check_readdir = mls_vnode_check_readdir, 3396 .mpo_vnode_check_readlink = mls_vnode_check_readlink, 3397 .mpo_vnode_check_relabel = mls_vnode_check_relabel, 3398 .mpo_vnode_check_rename_from = mls_vnode_check_rename_from, 3399 .mpo_vnode_check_rename_to = mls_vnode_check_rename_to, 3400 .mpo_vnode_check_revoke = mls_vnode_check_revoke, 3401 .mpo_vnode_check_setacl = mls_vnode_check_setacl, 3402 .mpo_vnode_check_setextattr = mls_vnode_check_setextattr, 3403 .mpo_vnode_check_setflags = mls_vnode_check_setflags, 3404 .mpo_vnode_check_setmode = mls_vnode_check_setmode, 3405 .mpo_vnode_check_setowner = mls_vnode_check_setowner, 3406 .mpo_vnode_check_setutimes = mls_vnode_check_setutimes, 3407 .mpo_vnode_check_stat = mls_vnode_check_stat, 3408 .mpo_vnode_check_unlink = mls_vnode_check_unlink, 3409 .mpo_vnode_check_write = mls_vnode_check_write, 3410 .mpo_vnode_copy_label = mls_copy_label, 3411 .mpo_vnode_create_extattr = mls_vnode_create_extattr, 3412 .mpo_vnode_destroy_label = mls_destroy_label, 3413 .mpo_vnode_externalize_label = mls_externalize_label, 3414 .mpo_vnode_init_label = mls_init_label, 3415 .mpo_vnode_internalize_label = mls_internalize_label, 3416 .mpo_vnode_relabel = mls_vnode_relabel, 3417 .mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr, 3418 }; 3419 3420 MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS", 3421 MPC_LOADTIME_FLAG_NOTLATE, &mls_slot); 3422