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