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