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