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