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