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