1 2 /* 3 * Author : Stephen Smalley, <sds (at) epoch.ncsc.mil> 4 */ 5 /* 6 * Updated: Trusted Computer Solutions, Inc. <dgoeddel (at) trustedcs.com> 7 * 8 * Support for enhanced MLS infrastructure. 9 * 10 * Updated: Frank Mayer <mayerf (at) tresys.com> 11 * and Karl MacMillan <kmacmillan (at) tresys.com> 12 * 13 * Added conditional policy language extensions 14 * 15 * Updated: Red Hat, Inc. James Morris <jmorris (at) redhat.com> 16 * 17 * Fine-grained netlink support 18 * IPv6 support 19 * Code cleanup 20 * 21 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 23 * Copyright (C) 2003 - 2004 Red Hat, Inc. 24 * 25 * This library is free software; you can redistribute it and/or 26 * modify it under the terms of the GNU Lesser General Public 27 * License as published by the Free Software Foundation; either 28 * version 2.1 of the License, or (at your option) any later version. 29 * 30 * This library is distributed in the hope that it will be useful, 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33 * Lesser General Public License for more details. 34 * 35 * You should have received a copy of the GNU Lesser General Public 36 * License along with this library; if not, write to the Free Software 37 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 38 */ 39 40 /* FLASK */ 41 42 /* 43 * Implementation of the security services. 44 */ 45 46 #include <stdlib.h> 47 #include <sys/types.h> 48 #include <sys/socket.h> 49 #include <netinet/in.h> 50 #include <arpa/inet.h> 51 52 #include <sepol/policydb/policydb.h> 53 #include <sepol/policydb/sidtab.h> 54 #include <sepol/policydb/services.h> 55 #include <sepol/policydb/conditional.h> 56 #include <sepol/policydb/flask.h> 57 58 #include "debug.h" 59 #include "private.h" 60 #include "context.h" 61 #include "av_permissions.h" 62 #include "dso.h" 63 #include "mls.h" 64 65 #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) 66 #define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) 67 68 static int selinux_enforcing = 1; 69 70 static sidtab_t mysidtab, *sidtab = &mysidtab; 71 static policydb_t mypolicydb, *policydb = &mypolicydb; 72 73 int hidden sepol_set_sidtab(sidtab_t * s) 74 { 75 sidtab = s; 76 return 0; 77 } 78 79 int hidden sepol_set_policydb(policydb_t * p) 80 { 81 policydb = p; 82 return 0; 83 } 84 85 int sepol_set_policydb_from_file(FILE * fp) 86 { 87 struct policy_file pf; 88 89 policy_file_init(&pf); 90 pf.fp = fp; 91 pf.type = PF_USE_STDIO; 92 if (mypolicydb.policy_type) 93 policydb_destroy(&mypolicydb); 94 if (policydb_init(&mypolicydb)) { 95 ERR(NULL, "Out of memory!"); 96 return -1; 97 } 98 if (policydb_read(&mypolicydb, &pf, 0)) { 99 policydb_destroy(&mypolicydb); 100 ERR(NULL, "can't read binary policy: %s", strerror(errno)); 101 return -1; 102 } 103 policydb = &mypolicydb; 104 return sepol_sidtab_init(sidtab); 105 } 106 107 /* 108 * The largest sequence number that has been used when 109 * providing an access decision to the access vector cache. 110 * The sequence number only changes when a policy change 111 * occurs. 112 */ 113 static uint32_t latest_granting = 0; 114 115 /* 116 * Return the boolean value of a constraint expression 117 * when it is applied to the specified source and target 118 * security contexts. 119 * 120 * xcontext is a special beast... It is used by the validatetrans rules 121 * only. For these rules, scontext is the context before the transition, 122 * tcontext is the context after the transition, and xcontext is the context 123 * of the process performing the transition. All other callers of 124 * constraint_expr_eval should pass in NULL for xcontext. 125 */ 126 static int constraint_expr_eval(context_struct_t * scontext, 127 context_struct_t * tcontext, 128 context_struct_t * xcontext, 129 constraint_expr_t * cexpr) 130 { 131 uint32_t val1, val2; 132 context_struct_t *c; 133 role_datum_t *r1, *r2; 134 mls_level_t *l1, *l2; 135 constraint_expr_t *e; 136 int s[CEXPR_MAXDEPTH]; 137 int sp = -1; 138 139 for (e = cexpr; e; e = e->next) { 140 switch (e->expr_type) { 141 case CEXPR_NOT: 142 BUG_ON(sp < 0); 143 s[sp] = !s[sp]; 144 break; 145 case CEXPR_AND: 146 BUG_ON(sp < 1); 147 sp--; 148 s[sp] &= s[sp + 1]; 149 break; 150 case CEXPR_OR: 151 BUG_ON(sp < 1); 152 sp--; 153 s[sp] |= s[sp + 1]; 154 break; 155 case CEXPR_ATTR: 156 if (sp == (CEXPR_MAXDEPTH - 1)) 157 return 0; 158 switch (e->attr) { 159 case CEXPR_USER: 160 val1 = scontext->user; 161 val2 = tcontext->user; 162 break; 163 case CEXPR_TYPE: 164 val1 = scontext->type; 165 val2 = tcontext->type; 166 break; 167 case CEXPR_ROLE: 168 val1 = scontext->role; 169 val2 = tcontext->role; 170 r1 = policydb->role_val_to_struct[val1 - 1]; 171 r2 = policydb->role_val_to_struct[val2 - 1]; 172 switch (e->op) { 173 case CEXPR_DOM: 174 s[++sp] = 175 ebitmap_get_bit(&r1->dominates, 176 val2 - 1); 177 continue; 178 case CEXPR_DOMBY: 179 s[++sp] = 180 ebitmap_get_bit(&r2->dominates, 181 val1 - 1); 182 continue; 183 case CEXPR_INCOMP: 184 s[++sp] = 185 (!ebitmap_get_bit 186 (&r1->dominates, val2 - 1) 187 && !ebitmap_get_bit(&r2->dominates, 188 val1 - 1)); 189 continue; 190 default: 191 break; 192 } 193 break; 194 case CEXPR_L1L2: 195 l1 = &(scontext->range.level[0]); 196 l2 = &(tcontext->range.level[0]); 197 goto mls_ops; 198 case CEXPR_L1H2: 199 l1 = &(scontext->range.level[0]); 200 l2 = &(tcontext->range.level[1]); 201 goto mls_ops; 202 case CEXPR_H1L2: 203 l1 = &(scontext->range.level[1]); 204 l2 = &(tcontext->range.level[0]); 205 goto mls_ops; 206 case CEXPR_H1H2: 207 l1 = &(scontext->range.level[1]); 208 l2 = &(tcontext->range.level[1]); 209 goto mls_ops; 210 case CEXPR_L1H1: 211 l1 = &(scontext->range.level[0]); 212 l2 = &(scontext->range.level[1]); 213 goto mls_ops; 214 case CEXPR_L2H2: 215 l1 = &(tcontext->range.level[0]); 216 l2 = &(tcontext->range.level[1]); 217 goto mls_ops; 218 mls_ops: 219 switch (e->op) { 220 case CEXPR_EQ: 221 s[++sp] = mls_level_eq(l1, l2); 222 continue; 223 case CEXPR_NEQ: 224 s[++sp] = !mls_level_eq(l1, l2); 225 continue; 226 case CEXPR_DOM: 227 s[++sp] = mls_level_dom(l1, l2); 228 continue; 229 case CEXPR_DOMBY: 230 s[++sp] = mls_level_dom(l2, l1); 231 continue; 232 case CEXPR_INCOMP: 233 s[++sp] = mls_level_incomp(l2, l1); 234 continue; 235 default: 236 BUG(); 237 return 0; 238 } 239 break; 240 default: 241 BUG(); 242 return 0; 243 } 244 245 switch (e->op) { 246 case CEXPR_EQ: 247 s[++sp] = (val1 == val2); 248 break; 249 case CEXPR_NEQ: 250 s[++sp] = (val1 != val2); 251 break; 252 default: 253 BUG(); 254 return 0; 255 } 256 break; 257 case CEXPR_NAMES: 258 if (sp == (CEXPR_MAXDEPTH - 1)) 259 return 0; 260 c = scontext; 261 if (e->attr & CEXPR_TARGET) 262 c = tcontext; 263 else if (e->attr & CEXPR_XTARGET) { 264 c = xcontext; 265 if (!c) { 266 BUG(); 267 return 0; 268 } 269 } 270 if (e->attr & CEXPR_USER) 271 val1 = c->user; 272 else if (e->attr & CEXPR_ROLE) 273 val1 = c->role; 274 else if (e->attr & CEXPR_TYPE) 275 val1 = c->type; 276 else { 277 BUG(); 278 return 0; 279 } 280 281 switch (e->op) { 282 case CEXPR_EQ: 283 s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); 284 break; 285 case CEXPR_NEQ: 286 s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); 287 break; 288 default: 289 BUG(); 290 return 0; 291 } 292 break; 293 default: 294 BUG(); 295 return 0; 296 } 297 } 298 299 BUG_ON(sp != 0); 300 return s[0]; 301 } 302 303 /* 304 * Compute access vectors based on a context structure pair for 305 * the permissions in a particular class. 306 */ 307 static int context_struct_compute_av(context_struct_t * scontext, 308 context_struct_t * tcontext, 309 sepol_security_class_t tclass, 310 sepol_access_vector_t requested, 311 struct sepol_av_decision *avd, 312 unsigned int *reason) 313 { 314 constraint_node_t *constraint; 315 struct role_allow *ra; 316 avtab_key_t avkey; 317 class_datum_t *tclass_datum; 318 avtab_ptr_t node; 319 ebitmap_t *sattr, *tattr; 320 ebitmap_node_t *snode, *tnode; 321 unsigned int i, j; 322 323 if (!tclass || tclass > policydb->p_classes.nprim) { 324 ERR(NULL, "unrecognized class %d", tclass); 325 return -EINVAL; 326 } 327 tclass_datum = policydb->class_val_to_struct[tclass - 1]; 328 329 /* 330 * Initialize the access vectors to the default values. 331 */ 332 avd->allowed = 0; 333 avd->decided = 0xffffffff; 334 avd->auditallow = 0; 335 avd->auditdeny = 0xffffffff; 336 avd->seqno = latest_granting; 337 *reason = 0; 338 339 /* 340 * If a specific type enforcement rule was defined for 341 * this permission check, then use it. 342 */ 343 avkey.target_class = tclass; 344 avkey.specified = AVTAB_AV; 345 sattr = &policydb->type_attr_map[scontext->type - 1]; 346 tattr = &policydb->type_attr_map[tcontext->type - 1]; 347 ebitmap_for_each_bit(sattr, snode, i) { 348 if (!ebitmap_node_get_bit(snode, i)) 349 continue; 350 ebitmap_for_each_bit(tattr, tnode, j) { 351 if (!ebitmap_node_get_bit(tnode, j)) 352 continue; 353 avkey.source_type = i + 1; 354 avkey.target_type = j + 1; 355 for (node = 356 avtab_search_node(&policydb->te_avtab, &avkey); 357 node != NULL; 358 node = 359 avtab_search_node_next(node, avkey.specified)) { 360 if (node->key.specified == AVTAB_ALLOWED) 361 avd->allowed |= node->datum.data; 362 else if (node->key.specified == 363 AVTAB_AUDITALLOW) 364 avd->auditallow |= node->datum.data; 365 else if (node->key.specified == AVTAB_AUDITDENY) 366 avd->auditdeny &= node->datum.data; 367 } 368 369 /* Check conditional av table for additional permissions */ 370 cond_compute_av(&policydb->te_cond_avtab, &avkey, avd); 371 372 } 373 } 374 375 if (requested & ~avd->allowed) { 376 *reason |= SEPOL_COMPUTEAV_TE; 377 requested &= avd->allowed; 378 } 379 380 /* 381 * Remove any permissions prohibited by a constraint (this includes 382 * the MLS policy). 383 */ 384 constraint = tclass_datum->constraints; 385 while (constraint) { 386 if ((constraint->permissions & (avd->allowed)) && 387 !constraint_expr_eval(scontext, tcontext, NULL, 388 constraint->expr)) { 389 avd->allowed = 390 (avd->allowed) & ~(constraint->permissions); 391 } 392 constraint = constraint->next; 393 } 394 395 if (requested & ~avd->allowed) { 396 *reason |= SEPOL_COMPUTEAV_CONS; 397 requested &= avd->allowed; 398 } 399 400 /* 401 * If checking process transition permission and the 402 * role is changing, then check the (current_role, new_role) 403 * pair. 404 */ 405 if (tclass == SECCLASS_PROCESS && 406 (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && 407 scontext->role != tcontext->role) { 408 for (ra = policydb->role_allow; ra; ra = ra->next) { 409 if (scontext->role == ra->role && 410 tcontext->role == ra->new_role) 411 break; 412 } 413 if (!ra) 414 avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | 415 PROCESS__DYNTRANSITION); 416 } 417 418 if (requested & ~avd->allowed) { 419 *reason |= SEPOL_COMPUTEAV_RBAC; 420 requested &= avd->allowed; 421 } 422 423 return 0; 424 } 425 426 int hidden sepol_validate_transition(sepol_security_id_t oldsid, 427 sepol_security_id_t newsid, 428 sepol_security_id_t tasksid, 429 sepol_security_class_t tclass) 430 { 431 context_struct_t *ocontext; 432 context_struct_t *ncontext; 433 context_struct_t *tcontext; 434 class_datum_t *tclass_datum; 435 constraint_node_t *constraint; 436 437 if (!tclass || tclass > policydb->p_classes.nprim) { 438 ERR(NULL, "unrecognized class %d", tclass); 439 return -EINVAL; 440 } 441 tclass_datum = policydb->class_val_to_struct[tclass - 1]; 442 443 ocontext = sepol_sidtab_search(sidtab, oldsid); 444 if (!ocontext) { 445 ERR(NULL, "unrecognized SID %d", oldsid); 446 return -EINVAL; 447 } 448 449 ncontext = sepol_sidtab_search(sidtab, newsid); 450 if (!ncontext) { 451 ERR(NULL, "unrecognized SID %d", newsid); 452 return -EINVAL; 453 } 454 455 tcontext = sepol_sidtab_search(sidtab, tasksid); 456 if (!tcontext) { 457 ERR(NULL, "unrecognized SID %d", tasksid); 458 return -EINVAL; 459 } 460 461 constraint = tclass_datum->validatetrans; 462 while (constraint) { 463 if (!constraint_expr_eval(ocontext, ncontext, tcontext, 464 constraint->expr)) { 465 return -EPERM; 466 } 467 constraint = constraint->next; 468 } 469 470 return 0; 471 } 472 473 int hidden sepol_compute_av_reason(sepol_security_id_t ssid, 474 sepol_security_id_t tsid, 475 sepol_security_class_t tclass, 476 sepol_access_vector_t requested, 477 struct sepol_av_decision *avd, 478 unsigned int *reason) 479 { 480 context_struct_t *scontext = 0, *tcontext = 0; 481 int rc = 0; 482 483 scontext = sepol_sidtab_search(sidtab, ssid); 484 if (!scontext) { 485 ERR(NULL, "unrecognized SID %d", ssid); 486 rc = -EINVAL; 487 goto out; 488 } 489 tcontext = sepol_sidtab_search(sidtab, tsid); 490 if (!tcontext) { 491 ERR(NULL, "unrecognized SID %d", tsid); 492 rc = -EINVAL; 493 goto out; 494 } 495 496 rc = context_struct_compute_av(scontext, tcontext, tclass, 497 requested, avd, reason); 498 out: 499 return rc; 500 } 501 502 int hidden sepol_compute_av(sepol_security_id_t ssid, 503 sepol_security_id_t tsid, 504 sepol_security_class_t tclass, 505 sepol_access_vector_t requested, 506 struct sepol_av_decision *avd) 507 { 508 unsigned int reason = 0; 509 return sepol_compute_av_reason(ssid, tsid, tclass, requested, avd, 510 &reason); 511 } 512 513 /* 514 * Write the security context string representation of 515 * the context associated with `sid' into a dynamically 516 * allocated string of the correct size. Set `*scontext' 517 * to point to this string and set `*scontext_len' to 518 * the length of the string. 519 */ 520 int hidden sepol_sid_to_context(sepol_security_id_t sid, 521 sepol_security_context_t * scontext, 522 size_t * scontext_len) 523 { 524 context_struct_t *context; 525 int rc = 0; 526 527 context = sepol_sidtab_search(sidtab, sid); 528 if (!context) { 529 ERR(NULL, "unrecognized SID %d", sid); 530 rc = -EINVAL; 531 goto out; 532 } 533 rc = context_to_string(NULL, policydb, context, scontext, scontext_len); 534 out: 535 return rc; 536 537 } 538 539 /* 540 * Return a SID associated with the security context that 541 * has the string representation specified by `scontext'. 542 */ 543 int hidden sepol_context_to_sid(const sepol_security_context_t scontext, 544 size_t scontext_len, sepol_security_id_t * sid) 545 { 546 547 context_struct_t *context = NULL; 548 549 /* First, create the context */ 550 if (context_from_string(NULL, policydb, &context, 551 scontext, scontext_len) < 0) 552 goto err; 553 554 /* Obtain the new sid */ 555 if (sid && (sepol_sidtab_context_to_sid(sidtab, context, sid) < 0)) 556 goto err; 557 558 context_destroy(context); 559 free(context); 560 return STATUS_SUCCESS; 561 562 err: 563 if (context) { 564 context_destroy(context); 565 free(context); 566 } 567 ERR(NULL, "could not convert %s to sid", scontext); 568 return STATUS_ERR; 569 } 570 571 static inline int compute_sid_handle_invalid_context(context_struct_t * 572 scontext, 573 context_struct_t * 574 tcontext, 575 sepol_security_class_t 576 tclass, 577 context_struct_t * 578 newcontext) 579 { 580 if (selinux_enforcing) { 581 return -EACCES; 582 } else { 583 sepol_security_context_t s, t, n; 584 size_t slen, tlen, nlen; 585 586 context_to_string(NULL, policydb, scontext, &s, &slen); 587 context_to_string(NULL, policydb, tcontext, &t, &tlen); 588 context_to_string(NULL, policydb, newcontext, &n, &nlen); 589 ERR(NULL, "invalid context %s for " 590 "scontext=%s tcontext=%s tclass=%s", 591 n, s, t, policydb->p_class_val_to_name[tclass - 1]); 592 free(s); 593 free(t); 594 free(n); 595 return 0; 596 } 597 } 598 599 static int sepol_compute_sid(sepol_security_id_t ssid, 600 sepol_security_id_t tsid, 601 sepol_security_class_t tclass, 602 uint32_t specified, sepol_security_id_t * out_sid) 603 { 604 context_struct_t *scontext = 0, *tcontext = 0, newcontext; 605 struct role_trans *roletr = 0; 606 avtab_key_t avkey; 607 avtab_datum_t *avdatum; 608 avtab_ptr_t node; 609 int rc = 0; 610 611 scontext = sepol_sidtab_search(sidtab, ssid); 612 if (!scontext) { 613 ERR(NULL, "unrecognized SID %d", ssid); 614 rc = -EINVAL; 615 goto out; 616 } 617 tcontext = sepol_sidtab_search(sidtab, tsid); 618 if (!tcontext) { 619 ERR(NULL, "unrecognized SID %d", tsid); 620 rc = -EINVAL; 621 goto out; 622 } 623 624 context_init(&newcontext); 625 626 /* Set the user identity. */ 627 switch (specified) { 628 case AVTAB_TRANSITION: 629 case AVTAB_CHANGE: 630 /* Use the process user identity. */ 631 newcontext.user = scontext->user; 632 break; 633 case AVTAB_MEMBER: 634 /* Use the related object owner. */ 635 newcontext.user = tcontext->user; 636 break; 637 } 638 639 /* Set the role and type to default values. */ 640 switch (tclass) { 641 case SECCLASS_PROCESS: 642 /* Use the current role and type of process. */ 643 newcontext.role = scontext->role; 644 newcontext.type = scontext->type; 645 break; 646 default: 647 /* Use the well-defined object role. */ 648 newcontext.role = OBJECT_R_VAL; 649 /* Use the type of the related object. */ 650 newcontext.type = tcontext->type; 651 } 652 653 /* Look for a type transition/member/change rule. */ 654 avkey.source_type = scontext->type; 655 avkey.target_type = tcontext->type; 656 avkey.target_class = tclass; 657 avkey.specified = specified; 658 avdatum = avtab_search(&policydb->te_avtab, &avkey); 659 660 /* If no permanent rule, also check for enabled conditional rules */ 661 if (!avdatum) { 662 node = avtab_search_node(&policydb->te_cond_avtab, &avkey); 663 for (; node != NULL; 664 node = avtab_search_node_next(node, specified)) { 665 if (node->key.specified & AVTAB_ENABLED) { 666 avdatum = &node->datum; 667 break; 668 } 669 } 670 } 671 672 if (avdatum) { 673 /* Use the type from the type transition/member/change rule. */ 674 newcontext.type = avdatum->data; 675 } 676 677 /* Check for class-specific changes. */ 678 switch (tclass) { 679 case SECCLASS_PROCESS: 680 if (specified & AVTAB_TRANSITION) { 681 /* Look for a role transition rule. */ 682 for (roletr = policydb->role_tr; roletr; 683 roletr = roletr->next) { 684 if (roletr->role == scontext->role && 685 roletr->type == tcontext->type) { 686 /* Use the role transition rule. */ 687 newcontext.role = roletr->new_role; 688 break; 689 } 690 } 691 } 692 break; 693 default: 694 break; 695 } 696 697 /* Set the MLS attributes. 698 This is done last because it may allocate memory. */ 699 rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified, 700 &newcontext); 701 if (rc) 702 goto out; 703 704 /* Check the validity of the context. */ 705 if (!policydb_context_isvalid(policydb, &newcontext)) { 706 rc = compute_sid_handle_invalid_context(scontext, 707 tcontext, 708 tclass, &newcontext); 709 if (rc) 710 goto out; 711 } 712 /* Obtain the sid for the context. */ 713 rc = sepol_sidtab_context_to_sid(sidtab, &newcontext, out_sid); 714 out: 715 context_destroy(&newcontext); 716 return rc; 717 } 718 719 /* 720 * Compute a SID to use for labeling a new object in the 721 * class `tclass' based on a SID pair. 722 */ 723 int hidden sepol_transition_sid(sepol_security_id_t ssid, 724 sepol_security_id_t tsid, 725 sepol_security_class_t tclass, 726 sepol_security_id_t * out_sid) 727 { 728 return sepol_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); 729 } 730 731 /* 732 * Compute a SID to use when selecting a member of a 733 * polyinstantiated object of class `tclass' based on 734 * a SID pair. 735 */ 736 int hidden sepol_member_sid(sepol_security_id_t ssid, 737 sepol_security_id_t tsid, 738 sepol_security_class_t tclass, 739 sepol_security_id_t * out_sid) 740 { 741 return sepol_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); 742 } 743 744 /* 745 * Compute a SID to use for relabeling an object in the 746 * class `tclass' based on a SID pair. 747 */ 748 int hidden sepol_change_sid(sepol_security_id_t ssid, 749 sepol_security_id_t tsid, 750 sepol_security_class_t tclass, 751 sepol_security_id_t * out_sid) 752 { 753 return sepol_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); 754 } 755 756 /* 757 * Verify that each permission that is defined under the 758 * existing policy is still defined with the same value 759 * in the new policy. 760 */ 761 static int validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) 762 { 763 hashtab_t h; 764 perm_datum_t *perdatum, *perdatum2; 765 766 h = (hashtab_t) p; 767 perdatum = (perm_datum_t *) datum; 768 769 perdatum2 = (perm_datum_t *) hashtab_search(h, key); 770 if (!perdatum2) { 771 ERR(NULL, "permission %s disappeared", key); 772 return -1; 773 } 774 if (perdatum->s.value != perdatum2->s.value) { 775 ERR(NULL, "the value of permissions %s changed", key); 776 return -1; 777 } 778 return 0; 779 } 780 781 /* 782 * Verify that each class that is defined under the 783 * existing policy is still defined with the same 784 * attributes in the new policy. 785 */ 786 static int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p) 787 { 788 policydb_t *newp; 789 class_datum_t *cladatum, *cladatum2; 790 791 newp = (policydb_t *) p; 792 cladatum = (class_datum_t *) datum; 793 794 cladatum2 = 795 (class_datum_t *) hashtab_search(newp->p_classes.table, key); 796 if (!cladatum2) { 797 ERR(NULL, "class %s disappeared", key); 798 return -1; 799 } 800 if (cladatum->s.value != cladatum2->s.value) { 801 ERR(NULL, "the value of class %s changed", key); 802 return -1; 803 } 804 if ((cladatum->comdatum && !cladatum2->comdatum) || 805 (!cladatum->comdatum && cladatum2->comdatum)) { 806 ERR(NULL, "the inherits clause for the access " 807 "vector definition for class %s changed", key); 808 return -1; 809 } 810 if (cladatum->comdatum) { 811 if (hashtab_map 812 (cladatum->comdatum->permissions.table, validate_perm, 813 cladatum2->comdatum->permissions.table)) { 814 ERR(NULL, 815 " in the access vector definition " 816 "for class %s\n", key); 817 return -1; 818 } 819 } 820 if (hashtab_map(cladatum->permissions.table, validate_perm, 821 cladatum2->permissions.table)) { 822 ERR(NULL, " in access vector definition for class %s", key); 823 return -1; 824 } 825 return 0; 826 } 827 828 /* Clone the SID into the new SID table. */ 829 static int clone_sid(sepol_security_id_t sid, 830 context_struct_t * context, void *arg) 831 { 832 sidtab_t *s = arg; 833 834 return sepol_sidtab_insert(s, sid, context); 835 } 836 837 static inline int convert_context_handle_invalid_context(context_struct_t * 838 context) 839 { 840 if (selinux_enforcing) { 841 return -EINVAL; 842 } else { 843 sepol_security_context_t s; 844 size_t len; 845 846 context_to_string(NULL, policydb, context, &s, &len); 847 ERR(NULL, "context %s is invalid", s); 848 free(s); 849 return 0; 850 } 851 } 852 853 typedef struct { 854 policydb_t *oldp; 855 policydb_t *newp; 856 } convert_context_args_t; 857 858 /* 859 * Convert the values in the security context 860 * structure `c' from the values specified 861 * in the policy `p->oldp' to the values specified 862 * in the policy `p->newp'. Verify that the 863 * context is valid under the new policy. 864 */ 865 static int convert_context(sepol_security_id_t key __attribute__ ((unused)), 866 context_struct_t * c, void *p) 867 { 868 convert_context_args_t *args; 869 context_struct_t oldc; 870 role_datum_t *role; 871 type_datum_t *typdatum; 872 user_datum_t *usrdatum; 873 sepol_security_context_t s; 874 size_t len; 875 int rc = -EINVAL; 876 877 args = (convert_context_args_t *) p; 878 879 if (context_cpy(&oldc, c)) 880 return -ENOMEM; 881 882 /* Convert the user. */ 883 usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table, 884 args->oldp-> 885 p_user_val_to_name[c->user - 886 1]); 887 888 if (!usrdatum) { 889 goto bad; 890 } 891 c->user = usrdatum->s.value; 892 893 /* Convert the role. */ 894 role = (role_datum_t *) hashtab_search(args->newp->p_roles.table, 895 args->oldp-> 896 p_role_val_to_name[c->role - 1]); 897 if (!role) { 898 goto bad; 899 } 900 c->role = role->s.value; 901 902 /* Convert the type. */ 903 typdatum = (type_datum_t *) 904 hashtab_search(args->newp->p_types.table, 905 args->oldp->p_type_val_to_name[c->type - 1]); 906 if (!typdatum) { 907 goto bad; 908 } 909 c->type = typdatum->s.value; 910 911 rc = mls_convert_context(args->oldp, args->newp, c); 912 if (rc) 913 goto bad; 914 915 /* Check the validity of the new context. */ 916 if (!policydb_context_isvalid(args->newp, c)) { 917 rc = convert_context_handle_invalid_context(&oldc); 918 if (rc) 919 goto bad; 920 } 921 922 context_destroy(&oldc); 923 return 0; 924 925 bad: 926 context_to_string(NULL, policydb, &oldc, &s, &len); 927 context_destroy(&oldc); 928 ERR(NULL, "invalidating context %s", s); 929 free(s); 930 return rc; 931 } 932 933 /* Reading from a policy "file". */ 934 int hidden next_entry(void *buf, struct policy_file *fp, size_t bytes) 935 { 936 size_t nread; 937 938 switch (fp->type) { 939 case PF_USE_STDIO: 940 nread = fread(buf, bytes, 1, fp->fp); 941 942 if (nread != 1) 943 return -1; 944 break; 945 case PF_USE_MEMORY: 946 if (bytes > fp->len) 947 return -1; 948 memcpy(buf, fp->data, bytes); 949 fp->data += bytes; 950 fp->len -= bytes; 951 break; 952 default: 953 return -1; 954 } 955 return 0; 956 } 957 958 size_t hidden put_entry(const void *ptr, size_t size, size_t n, 959 struct policy_file *fp) 960 { 961 size_t bytes = size * n; 962 963 switch (fp->type) { 964 case PF_USE_STDIO: 965 return fwrite(ptr, size, n, fp->fp); 966 case PF_USE_MEMORY: 967 if (bytes > fp->len) { 968 errno = ENOSPC; 969 return 0; 970 } 971 972 memcpy(fp->data, ptr, bytes); 973 fp->data += bytes; 974 fp->len -= bytes; 975 return n; 976 case PF_LEN: 977 fp->len += bytes; 978 return n; 979 default: 980 return 0; 981 } 982 return 0; 983 } 984 985 /* 986 * Read a new set of configuration data from 987 * a policy database binary representation file. 988 * 989 * Verify that each class that is defined under the 990 * existing policy is still defined with the same 991 * attributes in the new policy. 992 * 993 * Convert the context structures in the SID table to the 994 * new representation and verify that all entries 995 * in the SID table are valid under the new policy. 996 * 997 * Change the active policy database to use the new 998 * configuration data. 999 * 1000 * Reset the access vector cache. 1001 */ 1002 int hidden sepol_load_policy(void *data, size_t len) 1003 { 1004 policydb_t oldpolicydb, newpolicydb; 1005 sidtab_t oldsidtab, newsidtab; 1006 convert_context_args_t args; 1007 int rc = 0; 1008 struct policy_file file, *fp; 1009 1010 policy_file_init(&file); 1011 file.type = PF_USE_MEMORY; 1012 file.data = data; 1013 file.len = len; 1014 fp = &file; 1015 1016 if (policydb_init(&newpolicydb)) 1017 return -ENOMEM; 1018 1019 if (policydb_read(&newpolicydb, fp, 1)) { 1020 policydb_destroy(&newpolicydb); 1021 return -EINVAL; 1022 } 1023 1024 sepol_sidtab_init(&newsidtab); 1025 1026 /* Verify that the existing classes did not change. */ 1027 if (hashtab_map 1028 (policydb->p_classes.table, validate_class, &newpolicydb)) { 1029 ERR(NULL, "the definition of an existing class changed"); 1030 rc = -EINVAL; 1031 goto err; 1032 } 1033 1034 /* Clone the SID table. */ 1035 sepol_sidtab_shutdown(sidtab); 1036 if (sepol_sidtab_map(sidtab, clone_sid, &newsidtab)) { 1037 rc = -ENOMEM; 1038 goto err; 1039 } 1040 1041 /* Convert the internal representations of contexts 1042 in the new SID table and remove invalid SIDs. */ 1043 args.oldp = policydb; 1044 args.newp = &newpolicydb; 1045 sepol_sidtab_map_remove_on_error(&newsidtab, convert_context, &args); 1046 1047 /* Save the old policydb and SID table to free later. */ 1048 memcpy(&oldpolicydb, policydb, sizeof *policydb); 1049 sepol_sidtab_set(&oldsidtab, sidtab); 1050 1051 /* Install the new policydb and SID table. */ 1052 memcpy(policydb, &newpolicydb, sizeof *policydb); 1053 sepol_sidtab_set(sidtab, &newsidtab); 1054 1055 /* Free the old policydb and SID table. */ 1056 policydb_destroy(&oldpolicydb); 1057 sepol_sidtab_destroy(&oldsidtab); 1058 1059 return 0; 1060 1061 err: 1062 sepol_sidtab_destroy(&newsidtab); 1063 policydb_destroy(&newpolicydb); 1064 return rc; 1065 1066 } 1067 1068 /* 1069 * Return the SIDs to use for an unlabeled file system 1070 * that is being mounted from the device with the 1071 * the kdevname `name'. The `fs_sid' SID is returned for 1072 * the file system and the `file_sid' SID is returned 1073 * for all files within that file system. 1074 */ 1075 int hidden sepol_fs_sid(char *name, 1076 sepol_security_id_t * fs_sid, 1077 sepol_security_id_t * file_sid) 1078 { 1079 int rc = 0; 1080 ocontext_t *c; 1081 1082 c = policydb->ocontexts[OCON_FS]; 1083 while (c) { 1084 if (strcmp(c->u.name, name) == 0) 1085 break; 1086 c = c->next; 1087 } 1088 1089 if (c) { 1090 if (!c->sid[0] || !c->sid[1]) { 1091 rc = sepol_sidtab_context_to_sid(sidtab, 1092 &c->context[0], 1093 &c->sid[0]); 1094 if (rc) 1095 goto out; 1096 rc = sepol_sidtab_context_to_sid(sidtab, 1097 &c->context[1], 1098 &c->sid[1]); 1099 if (rc) 1100 goto out; 1101 } 1102 *fs_sid = c->sid[0]; 1103 *file_sid = c->sid[1]; 1104 } else { 1105 *fs_sid = SECINITSID_FS; 1106 *file_sid = SECINITSID_FILE; 1107 } 1108 1109 out: 1110 return rc; 1111 } 1112 1113 /* 1114 * Return the SID of the port specified by 1115 * `domain', `type', `protocol', and `port'. 1116 */ 1117 int hidden sepol_port_sid(uint16_t domain __attribute__ ((unused)), 1118 uint16_t type __attribute__ ((unused)), 1119 uint8_t protocol, 1120 uint16_t port, sepol_security_id_t * out_sid) 1121 { 1122 ocontext_t *c; 1123 int rc = 0; 1124 1125 c = policydb->ocontexts[OCON_PORT]; 1126 while (c) { 1127 if (c->u.port.protocol == protocol && 1128 c->u.port.low_port <= port && c->u.port.high_port >= port) 1129 break; 1130 c = c->next; 1131 } 1132 1133 if (c) { 1134 if (!c->sid[0]) { 1135 rc = sepol_sidtab_context_to_sid(sidtab, 1136 &c->context[0], 1137 &c->sid[0]); 1138 if (rc) 1139 goto out; 1140 } 1141 *out_sid = c->sid[0]; 1142 } else { 1143 *out_sid = SECINITSID_PORT; 1144 } 1145 1146 out: 1147 return rc; 1148 } 1149 1150 /* 1151 * Return the SIDs to use for a network interface 1152 * with the name `name'. The `if_sid' SID is returned for 1153 * the interface and the `msg_sid' SID is returned as 1154 * the default SID for messages received on the 1155 * interface. 1156 */ 1157 int hidden sepol_netif_sid(char *name, 1158 sepol_security_id_t * if_sid, 1159 sepol_security_id_t * msg_sid) 1160 { 1161 int rc = 0; 1162 ocontext_t *c; 1163 1164 c = policydb->ocontexts[OCON_NETIF]; 1165 while (c) { 1166 if (strcmp(name, c->u.name) == 0) 1167 break; 1168 c = c->next; 1169 } 1170 1171 if (c) { 1172 if (!c->sid[0] || !c->sid[1]) { 1173 rc = sepol_sidtab_context_to_sid(sidtab, 1174 &c->context[0], 1175 &c->sid[0]); 1176 if (rc) 1177 goto out; 1178 rc = sepol_sidtab_context_to_sid(sidtab, 1179 &c->context[1], 1180 &c->sid[1]); 1181 if (rc) 1182 goto out; 1183 } 1184 *if_sid = c->sid[0]; 1185 *msg_sid = c->sid[1]; 1186 } else { 1187 *if_sid = SECINITSID_NETIF; 1188 *msg_sid = SECINITSID_NETMSG; 1189 } 1190 1191 out: 1192 return rc; 1193 } 1194 1195 static int match_ipv6_addrmask(uint32_t * input, uint32_t * addr, 1196 uint32_t * mask) 1197 { 1198 int i, fail = 0; 1199 1200 for (i = 0; i < 4; i++) 1201 if (addr[i] != (input[i] & mask[i])) { 1202 fail = 1; 1203 break; 1204 } 1205 1206 return !fail; 1207 } 1208 1209 /* 1210 * Return the SID of the node specified by the address 1211 * `addrp' where `addrlen' is the length of the address 1212 * in bytes and `domain' is the communications domain or 1213 * address family in which the address should be interpreted. 1214 */ 1215 int hidden sepol_node_sid(uint16_t domain, 1216 void *addrp, 1217 size_t addrlen, sepol_security_id_t * out_sid) 1218 { 1219 int rc = 0; 1220 ocontext_t *c; 1221 1222 switch (domain) { 1223 case AF_INET:{ 1224 uint32_t addr; 1225 1226 if (addrlen != sizeof(uint32_t)) { 1227 rc = -EINVAL; 1228 goto out; 1229 } 1230 1231 addr = *((uint32_t *) addrp); 1232 1233 c = policydb->ocontexts[OCON_NODE]; 1234 while (c) { 1235 if (c->u.node.addr == (addr & c->u.node.mask)) 1236 break; 1237 c = c->next; 1238 } 1239 break; 1240 } 1241 1242 case AF_INET6: 1243 if (addrlen != sizeof(uint64_t) * 2) { 1244 rc = -EINVAL; 1245 goto out; 1246 } 1247 1248 c = policydb->ocontexts[OCON_NODE6]; 1249 while (c) { 1250 if (match_ipv6_addrmask(addrp, c->u.node6.addr, 1251 c->u.node6.mask)) 1252 break; 1253 c = c->next; 1254 } 1255 break; 1256 1257 default: 1258 *out_sid = SECINITSID_NODE; 1259 goto out; 1260 } 1261 1262 if (c) { 1263 if (!c->sid[0]) { 1264 rc = sepol_sidtab_context_to_sid(sidtab, 1265 &c->context[0], 1266 &c->sid[0]); 1267 if (rc) 1268 goto out; 1269 } 1270 *out_sid = c->sid[0]; 1271 } else { 1272 *out_sid = SECINITSID_NODE; 1273 } 1274 1275 out: 1276 return rc; 1277 } 1278 1279 /* 1280 * Generate the set of SIDs for legal security contexts 1281 * for a given user that can be reached by `fromsid'. 1282 * Set `*sids' to point to a dynamically allocated 1283 * array containing the set of SIDs. Set `*nel' to the 1284 * number of elements in the array. 1285 */ 1286 #define SIDS_NEL 25 1287 1288 int hidden sepol_get_user_sids(sepol_security_id_t fromsid, 1289 char *username, 1290 sepol_security_id_t ** sids, uint32_t * nel) 1291 { 1292 context_struct_t *fromcon, usercon; 1293 sepol_security_id_t *mysids, *mysids2, sid; 1294 uint32_t mynel = 0, maxnel = SIDS_NEL; 1295 user_datum_t *user; 1296 role_datum_t *role; 1297 struct sepol_av_decision avd; 1298 int rc = 0; 1299 unsigned int i, j, reason; 1300 ebitmap_node_t *rnode, *tnode; 1301 1302 fromcon = sepol_sidtab_search(sidtab, fromsid); 1303 if (!fromcon) { 1304 rc = -EINVAL; 1305 goto out; 1306 } 1307 1308 user = (user_datum_t *) hashtab_search(policydb->p_users.table, 1309 username); 1310 if (!user) { 1311 rc = -EINVAL; 1312 goto out; 1313 } 1314 usercon.user = user->s.value; 1315 1316 mysids = malloc(maxnel * sizeof(sepol_security_id_t)); 1317 if (!mysids) { 1318 rc = -ENOMEM; 1319 goto out; 1320 } 1321 memset(mysids, 0, maxnel * sizeof(sepol_security_id_t)); 1322 1323 ebitmap_for_each_bit(&user->roles.roles, rnode, i) { 1324 if (!ebitmap_node_get_bit(rnode, i)) 1325 continue; 1326 role = policydb->role_val_to_struct[i]; 1327 usercon.role = i + 1; 1328 ebitmap_for_each_bit(&role->types.types, tnode, j) { 1329 if (!ebitmap_node_get_bit(tnode, j)) 1330 continue; 1331 usercon.type = j + 1; 1332 if (usercon.type == fromcon->type) 1333 continue; 1334 1335 if (mls_setup_user_range 1336 (fromcon, user, &usercon, policydb->mls)) 1337 continue; 1338 1339 rc = context_struct_compute_av(fromcon, &usercon, 1340 SECCLASS_PROCESS, 1341 PROCESS__TRANSITION, 1342 &avd, &reason); 1343 if (rc || !(avd.allowed & PROCESS__TRANSITION)) 1344 continue; 1345 rc = sepol_sidtab_context_to_sid(sidtab, &usercon, 1346 &sid); 1347 if (rc) { 1348 free(mysids); 1349 goto out; 1350 } 1351 if (mynel < maxnel) { 1352 mysids[mynel++] = sid; 1353 } else { 1354 maxnel += SIDS_NEL; 1355 mysids2 = 1356 malloc(maxnel * 1357 sizeof(sepol_security_id_t)); 1358 1359 if (!mysids2) { 1360 rc = -ENOMEM; 1361 free(mysids); 1362 goto out; 1363 } 1364 memset(mysids2, 0, 1365 maxnel * sizeof(sepol_security_id_t)); 1366 memcpy(mysids2, mysids, 1367 mynel * sizeof(sepol_security_id_t)); 1368 free(mysids); 1369 mysids = mysids2; 1370 mysids[mynel++] = sid; 1371 } 1372 } 1373 } 1374 1375 *sids = mysids; 1376 *nel = mynel; 1377 1378 out: 1379 return rc; 1380 } 1381 1382 /* 1383 * Return the SID to use for a file in a filesystem 1384 * that cannot support a persistent label mapping or use another 1385 * fixed labeling behavior like transition SIDs or task SIDs. 1386 */ 1387 int hidden sepol_genfs_sid(const char *fstype, 1388 char *path, 1389 sepol_security_class_t sclass, 1390 sepol_security_id_t * sid) 1391 { 1392 size_t len; 1393 genfs_t *genfs; 1394 ocontext_t *c; 1395 int rc = 0, cmp = 0; 1396 1397 for (genfs = policydb->genfs; genfs; genfs = genfs->next) { 1398 cmp = strcmp(fstype, genfs->fstype); 1399 if (cmp <= 0) 1400 break; 1401 } 1402 1403 if (!genfs || cmp) { 1404 *sid = SECINITSID_UNLABELED; 1405 rc = -ENOENT; 1406 goto out; 1407 } 1408 1409 for (c = genfs->head; c; c = c->next) { 1410 len = strlen(c->u.name); 1411 if ((!c->v.sclass || sclass == c->v.sclass) && 1412 (strncmp(c->u.name, path, len) == 0)) 1413 break; 1414 } 1415 1416 if (!c) { 1417 *sid = SECINITSID_UNLABELED; 1418 rc = -ENOENT; 1419 goto out; 1420 } 1421 1422 if (!c->sid[0]) { 1423 rc = sepol_sidtab_context_to_sid(sidtab, 1424 &c->context[0], &c->sid[0]); 1425 if (rc) 1426 goto out; 1427 } 1428 1429 *sid = c->sid[0]; 1430 out: 1431 return rc; 1432 } 1433 1434 int hidden sepol_fs_use(const char *fstype, 1435 unsigned int *behavior, sepol_security_id_t * sid) 1436 { 1437 int rc = 0; 1438 ocontext_t *c; 1439 1440 c = policydb->ocontexts[OCON_FSUSE]; 1441 while (c) { 1442 if (strcmp(fstype, c->u.name) == 0) 1443 break; 1444 c = c->next; 1445 } 1446 1447 if (c) { 1448 *behavior = c->v.behavior; 1449 if (!c->sid[0]) { 1450 rc = sepol_sidtab_context_to_sid(sidtab, 1451 &c->context[0], 1452 &c->sid[0]); 1453 if (rc) 1454 goto out; 1455 } 1456 *sid = c->sid[0]; 1457 } else { 1458 rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid); 1459 if (rc) { 1460 *behavior = SECURITY_FS_USE_NONE; 1461 rc = 0; 1462 } else { 1463 *behavior = SECURITY_FS_USE_GENFS; 1464 } 1465 } 1466 1467 out: 1468 return rc; 1469 } 1470 1471 /* FLASK */ 1472