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