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 /* Initial sizes malloc'd for sepol_compute_av_reason_buffer() support */ 47 #define REASON_BUF_SIZE 2048 48 #define EXPR_BUF_SIZE 1024 49 #define STACK_LEN 32 50 51 #include <stdlib.h> 52 #include <sys/types.h> 53 #include <sys/socket.h> 54 #include <netinet/in.h> 55 #include <arpa/inet.h> 56 57 #include <sepol/policydb/policydb.h> 58 #include <sepol/policydb/sidtab.h> 59 #include <sepol/policydb/services.h> 60 #include <sepol/policydb/conditional.h> 61 #include <sepol/policydb/flask.h> 62 #include <sepol/policydb/util.h> 63 64 #include "debug.h" 65 #include "private.h" 66 #include "context.h" 67 #include "av_permissions.h" 68 #include "dso.h" 69 #include "mls.h" 70 71 #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) 72 #define BUG_ON(x) do { if (x) ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) 73 74 static int selinux_enforcing = 1; 75 76 static sidtab_t mysidtab, *sidtab = &mysidtab; 77 static policydb_t mypolicydb, *policydb = &mypolicydb; 78 79 /* Used by sepol_compute_av_reason_buffer() to keep track of entries */ 80 static int reason_buf_used; 81 static int reason_buf_len; 82 83 /* Stack services for RPN to infix conversion. */ 84 static char **stack; 85 static int stack_len; 86 static int next_stack_entry; 87 88 static void push(char *expr_ptr) 89 { 90 if (next_stack_entry >= stack_len) { 91 char **new_stack = stack; 92 int new_stack_len; 93 94 if (stack_len == 0) 95 new_stack_len = STACK_LEN; 96 else 97 new_stack_len = stack_len * 2; 98 99 new_stack = realloc(stack, new_stack_len * sizeof(*stack)); 100 if (!new_stack) { 101 ERR(NULL, "unable to allocate stack space"); 102 return; 103 } 104 stack_len = new_stack_len; 105 stack = new_stack; 106 } 107 stack[next_stack_entry] = expr_ptr; 108 next_stack_entry++; 109 } 110 111 static char *pop(void) 112 { 113 next_stack_entry--; 114 if (next_stack_entry < 0) { 115 next_stack_entry = 0; 116 ERR(NULL, "pop called with no stack entries"); 117 return NULL; 118 } 119 return stack[next_stack_entry]; 120 } 121 /* End Stack services */ 122 123 int hidden sepol_set_sidtab(sidtab_t * s) 124 { 125 sidtab = s; 126 return 0; 127 } 128 129 int hidden sepol_set_policydb(policydb_t * p) 130 { 131 policydb = p; 132 return 0; 133 } 134 135 int sepol_set_policydb_from_file(FILE * fp) 136 { 137 struct policy_file pf; 138 139 policy_file_init(&pf); 140 pf.fp = fp; 141 pf.type = PF_USE_STDIO; 142 if (mypolicydb.policy_type) 143 policydb_destroy(&mypolicydb); 144 if (policydb_init(&mypolicydb)) { 145 ERR(NULL, "Out of memory!"); 146 return -1; 147 } 148 if (policydb_read(&mypolicydb, &pf, 0)) { 149 policydb_destroy(&mypolicydb); 150 ERR(NULL, "can't read binary policy: %s", strerror(errno)); 151 return -1; 152 } 153 policydb = &mypolicydb; 154 return sepol_sidtab_init(sidtab); 155 } 156 157 /* 158 * The largest sequence number that has been used when 159 * providing an access decision to the access vector cache. 160 * The sequence number only changes when a policy change 161 * occurs. 162 */ 163 static uint32_t latest_granting = 0; 164 165 /* 166 * cat_expr_buf adds a string to an expression buffer and handles 167 * realloc's if buffer is too small. The array of expression text 168 * buffer pointers and its counter are globally defined here as 169 * constraint_expr_eval_reason() sets them up and cat_expr_buf 170 * updates the e_buf pointer. 171 */ 172 static int expr_counter; 173 static char **expr_list; 174 static int expr_buf_used; 175 static int expr_buf_len; 176 177 static void cat_expr_buf(char *e_buf, char *string) 178 { 179 int len, new_buf_len; 180 char *p, *new_buf = e_buf; 181 182 while (1) { 183 p = e_buf + expr_buf_used; 184 len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string); 185 if (len < 0 || len >= expr_buf_len - expr_buf_used) { 186 new_buf_len = expr_buf_len + EXPR_BUF_SIZE; 187 new_buf = realloc(e_buf, new_buf_len); 188 if (!new_buf) { 189 ERR(NULL, "failed to realloc expr buffer"); 190 return; 191 } 192 /* Update new ptr in expr list and locally + new len */ 193 expr_list[expr_counter] = new_buf; 194 e_buf = new_buf; 195 expr_buf_len = new_buf_len; 196 } else { 197 expr_buf_used += len; 198 return; 199 } 200 } 201 } 202 203 /* 204 * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES, 205 * then for 'types' only, read the types_names->types list as it will 206 * contain a list of types and attributes that were defined in the 207 * policy source. 208 * For user and role plus types (for policy vers < 209 * POLICYDB_VERSION_CONSTRAINT_NAMES) just read the e->names list. 210 */ 211 static void get_name_list(constraint_expr_t *e, int type, 212 char *src, char *op, int failed) 213 { 214 ebitmap_t *types; 215 int rc = 0; 216 unsigned int i; 217 char tmp_buf[128]; 218 int counter = 0; 219 220 if (policydb->policy_type == POLICY_KERN && 221 policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && 222 type == CEXPR_TYPE) 223 types = &e->type_names->types; 224 else 225 types = &e->names; 226 227 /* Find out how many entries */ 228 for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { 229 rc = ebitmap_get_bit(types, i); 230 if (rc == 0) 231 continue; 232 else 233 counter++; 234 } 235 snprintf(tmp_buf, sizeof(tmp_buf), "(%s%s", src, op); 236 cat_expr_buf(expr_list[expr_counter], tmp_buf); 237 238 if (counter == 0) 239 cat_expr_buf(expr_list[expr_counter], "<empty_set> "); 240 if (counter > 1) 241 cat_expr_buf(expr_list[expr_counter], " {"); 242 if (counter >= 1) { 243 for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { 244 rc = ebitmap_get_bit(types, i); 245 if (rc == 0) 246 continue; 247 248 /* Collect entries */ 249 switch (type) { 250 case CEXPR_USER: 251 snprintf(tmp_buf, sizeof(tmp_buf), " %s", 252 policydb->p_user_val_to_name[i]); 253 break; 254 case CEXPR_ROLE: 255 snprintf(tmp_buf, sizeof(tmp_buf), " %s", 256 policydb->p_role_val_to_name[i]); 257 break; 258 case CEXPR_TYPE: 259 snprintf(tmp_buf, sizeof(tmp_buf), " %s", 260 policydb->p_type_val_to_name[i]); 261 break; 262 } 263 cat_expr_buf(expr_list[expr_counter], tmp_buf); 264 } 265 } 266 if (counter > 1) 267 cat_expr_buf(expr_list[expr_counter], " }"); 268 if (failed) 269 cat_expr_buf(expr_list[expr_counter], " -Fail-) "); 270 else 271 cat_expr_buf(expr_list[expr_counter], ") "); 272 273 return; 274 } 275 276 static void msgcat(char *src, char *tgt, char *op, int failed) 277 { 278 char tmp_buf[128]; 279 if (failed) 280 snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ", 281 src, op, tgt); 282 else 283 snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s) ", 284 src, op, tgt); 285 cat_expr_buf(expr_list[expr_counter], tmp_buf); 286 } 287 288 /* Returns a buffer with class, statement type and permissions */ 289 static char *get_class_info(sepol_security_class_t tclass, 290 constraint_node_t *constraint, 291 context_struct_t *xcontext) 292 { 293 constraint_expr_t *e; 294 int mls, state_num; 295 296 /* Find if MLS statement or not */ 297 mls = 0; 298 for (e = constraint->expr; e; e = e->next) { 299 if (e->attr >= CEXPR_L1L2) { 300 mls = 1; 301 break; 302 } 303 } 304 305 /* Determine statement type */ 306 char *statements[] = { 307 "constrain ", /* 0 */ 308 "mlsconstrain ", /* 1 */ 309 "validatetrans ", /* 2 */ 310 "mlsvalidatetrans ", /* 3 */ 311 0 }; 312 313 if (xcontext == NULL) 314 state_num = mls + 0; 315 else 316 state_num = mls + 2; 317 318 int class_buf_len = 0; 319 int new_class_buf_len; 320 int len, buf_used; 321 char *class_buf = NULL, *p; 322 char *new_class_buf = NULL; 323 324 while (1) { 325 new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; 326 new_class_buf = realloc(class_buf, new_class_buf_len); 327 if (!new_class_buf) 328 return NULL; 329 class_buf_len = new_class_buf_len; 330 class_buf = new_class_buf; 331 buf_used = 0; 332 p = class_buf; 333 334 /* Add statement type */ 335 len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]); 336 if (len < 0 || len >= class_buf_len - buf_used) 337 continue; 338 339 /* Add class entry */ 340 p += len; 341 buf_used += len; 342 len = snprintf(p, class_buf_len - buf_used, "%s ", 343 policydb->p_class_val_to_name[tclass - 1]); 344 if (len < 0 || len >= class_buf_len - buf_used) 345 continue; 346 347 /* Add permission entries */ 348 p += len; 349 buf_used += len; 350 len = snprintf(p, class_buf_len - buf_used, "{%s } (", 351 sepol_av_to_string(policydb, tclass, constraint->permissions)); 352 if (len < 0 || len >= class_buf_len - buf_used) 353 continue; 354 break; 355 } 356 return class_buf; 357 } 358 359 /* 360 * Modified version of constraint_expr_eval that will process each 361 * constraint as before but adds the information to text buffers that 362 * will hold various components. The expression will be in RPN format, 363 * therefore there is a stack based RPN to infix converter to produce 364 * the final readable constraint. 365 * 366 * Return the boolean value of a constraint expression 367 * when it is applied to the specified source and target 368 * security contexts. 369 * 370 * xcontext is a special beast... It is used by the validatetrans rules 371 * only. For these rules, scontext is the context before the transition, 372 * tcontext is the context after the transition, and xcontext is the 373 * context of the process performing the transition. All other callers 374 * of constraint_expr_eval_reason should pass in NULL for xcontext. 375 * 376 * This function will also build a buffer as the constraint is processed 377 * for analysis. If this option is not required, then: 378 * 'tclass' should be '0' and r_buf MUST be NULL. 379 */ 380 static int constraint_expr_eval_reason(context_struct_t *scontext, 381 context_struct_t *tcontext, 382 context_struct_t *xcontext, 383 sepol_security_class_t tclass, 384 constraint_node_t *constraint, 385 char **r_buf, 386 unsigned int flags) 387 { 388 uint32_t val1, val2; 389 context_struct_t *c; 390 role_datum_t *r1, *r2; 391 mls_level_t *l1, *l2; 392 constraint_expr_t *e; 393 int s[CEXPR_MAXDEPTH]; 394 int sp = -1; 395 char tmp_buf[128]; 396 397 /* 398 * Define the s_t_x_num values that make up r1, t2 etc. in text strings 399 * Set 1 = source, 2 = target, 3 = xcontext for validatetrans 400 */ 401 #define SOURCE 1 402 #define TARGET 2 403 #define XTARGET 3 404 405 int s_t_x_num = SOURCE; 406 407 /* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */ 408 int u_r_t = 0; 409 410 char *src = NULL; 411 char *tgt = NULL; 412 int rc = 0, x; 413 char *class_buf = NULL; 414 415 class_buf = get_class_info(tclass, constraint, xcontext); 416 if (!class_buf) { 417 ERR(NULL, "failed to allocate class buffer"); 418 return -ENOMEM; 419 } 420 421 /* Original function but with buffer support */ 422 int expr_list_len = 0; 423 expr_counter = 0; 424 expr_list = NULL; 425 for (e = constraint->expr; e; e = e->next) { 426 /* Allocate a stack to hold expression buffer entries */ 427 if (expr_counter >= expr_list_len) { 428 char **new_expr_list = expr_list; 429 int new_expr_list_len; 430 431 if (expr_list_len == 0) 432 new_expr_list_len = STACK_LEN; 433 else 434 new_expr_list_len = expr_list_len * 2; 435 436 new_expr_list = realloc(expr_list, 437 new_expr_list_len * sizeof(*expr_list)); 438 if (!new_expr_list) { 439 ERR(NULL, "failed to allocate expr buffer stack"); 440 rc = -ENOMEM; 441 goto out; 442 } 443 expr_list_len = new_expr_list_len; 444 expr_list = new_expr_list; 445 } 446 447 /* 448 * malloc a buffer to store each expression text component. If 449 * buffer is too small cat_expr_buf() will realloc extra space. 450 */ 451 expr_buf_len = EXPR_BUF_SIZE; 452 expr_list[expr_counter] = malloc(expr_buf_len); 453 if (!expr_list[expr_counter]) { 454 ERR(NULL, "failed to allocate expr buffer"); 455 rc = -ENOMEM; 456 goto out; 457 } 458 expr_buf_used = 0; 459 460 /* Now process each expression of the constraint */ 461 switch (e->expr_type) { 462 case CEXPR_NOT: 463 BUG_ON(sp < 0); 464 s[sp] = !s[sp]; 465 cat_expr_buf(expr_list[expr_counter], "not"); 466 break; 467 case CEXPR_AND: 468 BUG_ON(sp < 1); 469 sp--; 470 s[sp] &= s[sp + 1]; 471 cat_expr_buf(expr_list[expr_counter], "and"); 472 break; 473 case CEXPR_OR: 474 BUG_ON(sp < 1); 475 sp--; 476 s[sp] |= s[sp + 1]; 477 cat_expr_buf(expr_list[expr_counter], "or"); 478 break; 479 case CEXPR_ATTR: 480 if (sp == (CEXPR_MAXDEPTH - 1)) 481 goto out; 482 483 switch (e->attr) { 484 case CEXPR_USER: 485 val1 = scontext->user; 486 val2 = tcontext->user; 487 free(src); src = strdup("u1"); 488 free(tgt); tgt = strdup("u2"); 489 break; 490 case CEXPR_TYPE: 491 val1 = scontext->type; 492 val2 = tcontext->type; 493 free(src); src = strdup("t1"); 494 free(tgt); tgt = strdup("t2"); 495 break; 496 case CEXPR_ROLE: 497 val1 = scontext->role; 498 val2 = tcontext->role; 499 r1 = policydb->role_val_to_struct[val1 - 1]; 500 r2 = policydb->role_val_to_struct[val2 - 1]; 501 free(src); src = strdup("r1"); 502 free(tgt); tgt = strdup("r2"); 503 504 switch (e->op) { 505 case CEXPR_DOM: 506 s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1); 507 msgcat(src, tgt, "dom", s[sp] == 0); 508 expr_counter++; 509 continue; 510 case CEXPR_DOMBY: 511 s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1); 512 msgcat(src, tgt, "domby", s[sp] == 0); 513 expr_counter++; 514 continue; 515 case CEXPR_INCOMP: 516 s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1) 517 && !ebitmap_get_bit(&r2->dominates, val1 - 1)); 518 msgcat(src, tgt, "incomp", s[sp] == 0); 519 expr_counter++; 520 continue; 521 default: 522 break; 523 } 524 break; 525 case CEXPR_L1L2: 526 l1 = &(scontext->range.level[0]); 527 l2 = &(tcontext->range.level[0]); 528 free(src); src = strdup("l1"); 529 free(tgt); tgt = strdup("l2"); 530 goto mls_ops; 531 case CEXPR_L1H2: 532 l1 = &(scontext->range.level[0]); 533 l2 = &(tcontext->range.level[1]); 534 free(src); src = strdup("l1"); 535 free(tgt); tgt = strdup("h2"); 536 goto mls_ops; 537 case CEXPR_H1L2: 538 l1 = &(scontext->range.level[1]); 539 l2 = &(tcontext->range.level[0]); 540 free(src); src = strdup("h1"); 541 free(tgt); tgt = strdup("l2"); 542 goto mls_ops; 543 case CEXPR_H1H2: 544 l1 = &(scontext->range.level[1]); 545 l2 = &(tcontext->range.level[1]); 546 free(src); src = strdup("h1"); 547 free(tgt); tgt = strdup("h2"); 548 goto mls_ops; 549 case CEXPR_L1H1: 550 l1 = &(scontext->range.level[0]); 551 l2 = &(scontext->range.level[1]); 552 free(src); src = strdup("l1"); 553 free(tgt); tgt = strdup("h1"); 554 goto mls_ops; 555 case CEXPR_L2H2: 556 l1 = &(tcontext->range.level[0]); 557 l2 = &(tcontext->range.level[1]); 558 free(src); src = strdup("l2"); 559 free(tgt); tgt = strdup("h2"); 560 mls_ops: 561 switch (e->op) { 562 case CEXPR_EQ: 563 s[++sp] = mls_level_eq(l1, l2); 564 msgcat(src, tgt, "eq", s[sp] == 0); 565 expr_counter++; 566 continue; 567 case CEXPR_NEQ: 568 s[++sp] = !mls_level_eq(l1, l2); 569 msgcat(src, tgt, "!=", s[sp] == 0); 570 expr_counter++; 571 continue; 572 case CEXPR_DOM: 573 s[++sp] = mls_level_dom(l1, l2); 574 msgcat(src, tgt, "dom", s[sp] == 0); 575 expr_counter++; 576 continue; 577 case CEXPR_DOMBY: 578 s[++sp] = mls_level_dom(l2, l1); 579 msgcat(src, tgt, "domby", s[sp] == 0); 580 expr_counter++; 581 continue; 582 case CEXPR_INCOMP: 583 s[++sp] = mls_level_incomp(l2, l1); 584 msgcat(src, tgt, "incomp", s[sp] == 0); 585 expr_counter++; 586 continue; 587 default: 588 BUG(); 589 goto out; 590 } 591 break; 592 default: 593 BUG(); 594 goto out; 595 } 596 597 switch (e->op) { 598 case CEXPR_EQ: 599 s[++sp] = (val1 == val2); 600 msgcat(src, tgt, "==", s[sp] == 0); 601 break; 602 case CEXPR_NEQ: 603 s[++sp] = (val1 != val2); 604 msgcat(src, tgt, "!=", s[sp] == 0); 605 break; 606 default: 607 BUG(); 608 goto out; 609 } 610 break; 611 case CEXPR_NAMES: 612 if (sp == (CEXPR_MAXDEPTH - 1)) 613 goto out; 614 s_t_x_num = SOURCE; 615 c = scontext; 616 if (e->attr & CEXPR_TARGET) { 617 s_t_x_num = TARGET; 618 c = tcontext; 619 } else if (e->attr & CEXPR_XTARGET) { 620 s_t_x_num = XTARGET; 621 c = xcontext; 622 } 623 if (!c) { 624 BUG(); 625 goto out; 626 } 627 if (e->attr & CEXPR_USER) { 628 u_r_t = CEXPR_USER; 629 val1 = c->user; 630 snprintf(tmp_buf, sizeof(tmp_buf), "u%d ", s_t_x_num); 631 free(src); src = strdup(tmp_buf); 632 } else if (e->attr & CEXPR_ROLE) { 633 u_r_t = CEXPR_ROLE; 634 val1 = c->role; 635 snprintf(tmp_buf, sizeof(tmp_buf), "r%d ", s_t_x_num); 636 free(src); src = strdup(tmp_buf); 637 } else if (e->attr & CEXPR_TYPE) { 638 u_r_t = CEXPR_TYPE; 639 val1 = c->type; 640 snprintf(tmp_buf, sizeof(tmp_buf), "t%d ", s_t_x_num); 641 free(src); src = strdup(tmp_buf); 642 } else { 643 BUG(); 644 goto out; 645 } 646 647 switch (e->op) { 648 case CEXPR_EQ: 649 s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); 650 get_name_list(e, u_r_t, src, "==", s[sp] == 0); 651 break; 652 653 case CEXPR_NEQ: 654 s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); 655 get_name_list(e, u_r_t, src, "!=", s[sp] == 0); 656 break; 657 default: 658 BUG(); 659 goto out; 660 } 661 break; 662 default: 663 BUG(); 664 goto out; 665 } 666 expr_counter++; 667 } 668 669 /* 670 * At this point each expression of the constraint is in 671 * expr_list[n+1] and in RPN format. Now convert to 'infix' 672 */ 673 674 /* 675 * Save expr count but zero expr_counter to detect if 676 * 'BUG(); goto out;' was called as we need to release any used 677 * expr_list malloc's. Normally they are released by the RPN to 678 * infix code. 679 */ 680 int expr_count = expr_counter; 681 expr_counter = 0; 682 683 /* 684 * The array of expression answer buffer pointers and counter. 685 * Generate the same number of answer buffer entries as expression 686 * buffers (as there will never be more). 687 */ 688 char **answer_list; 689 int answer_counter = 0; 690 691 answer_list = malloc(expr_count * sizeof(*answer_list)); 692 if (!answer_list) { 693 ERR(NULL, "failed to allocate answer stack"); 694 rc = -ENOMEM; 695 goto out; 696 } 697 698 /* The pop operands */ 699 char *a; 700 char *b; 701 int a_len, b_len; 702 703 /* Convert constraint from RPN to infix notation. */ 704 for (x = 0; x != expr_count; x++) { 705 if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x], 706 "or", 2) == 0) { 707 b = pop(); 708 b_len = strlen(b); 709 a = pop(); 710 a_len = strlen(a); 711 712 /* get a buffer to hold the answer */ 713 answer_list[answer_counter] = malloc(a_len + b_len + 8); 714 if (!answer_list[answer_counter]) { 715 ERR(NULL, "failed to allocate answer buffer"); 716 rc = -ENOMEM; 717 goto out; 718 } 719 memset(answer_list[answer_counter], '\0', a_len + b_len + 8); 720 721 sprintf(answer_list[answer_counter], "%s %s %s", a, 722 expr_list[x], b); 723 push(answer_list[answer_counter++]); 724 free(a); 725 free(b); 726 } else if (strncmp(expr_list[x], "not", 3) == 0) { 727 b = pop(); 728 b_len = strlen(b); 729 730 answer_list[answer_counter] = malloc(b_len + 8); 731 if (!answer_list[answer_counter]) { 732 ERR(NULL, "failed to allocate answer buffer"); 733 rc = -ENOMEM; 734 goto out; 735 } 736 memset(answer_list[answer_counter], '\0', b_len + 8); 737 738 if (strncmp(b, "not", 3) == 0) 739 sprintf(answer_list[answer_counter], "%s (%s)", 740 expr_list[x], b); 741 else 742 sprintf(answer_list[answer_counter], "%s%s", 743 expr_list[x], b); 744 push(answer_list[answer_counter++]); 745 free(b); 746 } else { 747 push(expr_list[x]); 748 } 749 } 750 /* Get the final answer from tos and build constraint text */ 751 a = pop(); 752 753 /* Constraint calculation: rc = 0 is denied, rc = 1 is granted */ 754 sprintf(tmp_buf, "Constraint %s\n", s[0] ? "GRANTED" : "DENIED"); 755 756 int len, new_buf_len; 757 char *p, **new_buf = r_buf; 758 /* 759 * These contain the constraint components that are added to the 760 * callers reason buffer. 761 */ 762 char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; 763 764 /* 765 * This will add the constraints to the callers reason buffer (who is 766 * responsible for freeing the memory). It will handle any realloc's 767 * should the buffer be too short. 768 * The reason_buf_used and reason_buf_len counters are defined 769 * globally as multiple constraints can be in the buffer. 770 */ 771 772 if (r_buf && ((s[0] == 0) || ((s[0] == 1 && 773 (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { 774 for (x = 0; buffers[x] != NULL; x++) { 775 while (1) { 776 p = *r_buf + reason_buf_used; 777 len = snprintf(p, reason_buf_len - reason_buf_used, 778 "%s", buffers[x]); 779 if (len < 0 || len >= reason_buf_len - reason_buf_used) { 780 new_buf_len = reason_buf_len + REASON_BUF_SIZE; 781 *new_buf = realloc(*r_buf, new_buf_len); 782 if (!new_buf) { 783 ERR(NULL, "failed to realloc reason buffer"); 784 goto out1; 785 } 786 **r_buf = **new_buf; 787 reason_buf_len = new_buf_len; 788 continue; 789 } else { 790 reason_buf_used += len; 791 break; 792 } 793 } 794 } 795 } 796 797 out1: 798 rc = s[0]; 799 free(a); 800 801 out: 802 free(class_buf); 803 free(src); 804 free(tgt); 805 806 if (expr_counter) { 807 for (x = 0; expr_list[x] != NULL; x++) 808 free(expr_list[x]); 809 } 810 return rc; 811 } 812 813 /* 814 * Compute access vectors based on a context structure pair for 815 * the permissions in a particular class. 816 */ 817 static int context_struct_compute_av(context_struct_t * scontext, 818 context_struct_t * tcontext, 819 sepol_security_class_t tclass, 820 sepol_access_vector_t requested, 821 struct sepol_av_decision *avd, 822 unsigned int *reason, 823 char **r_buf, 824 unsigned int flags) 825 { 826 constraint_node_t *constraint; 827 struct role_allow *ra; 828 avtab_key_t avkey; 829 class_datum_t *tclass_datum; 830 avtab_ptr_t node; 831 ebitmap_t *sattr, *tattr; 832 ebitmap_node_t *snode, *tnode; 833 unsigned int i, j; 834 835 if (!tclass || tclass > policydb->p_classes.nprim) { 836 ERR(NULL, "unrecognized class %d", tclass); 837 return -EINVAL; 838 } 839 tclass_datum = policydb->class_val_to_struct[tclass - 1]; 840 841 /* 842 * Initialize the access vectors to the default values. 843 */ 844 avd->allowed = 0; 845 avd->decided = 0xffffffff; 846 avd->auditallow = 0; 847 avd->auditdeny = 0xffffffff; 848 avd->seqno = latest_granting; 849 *reason = 0; 850 851 /* 852 * If a specific type enforcement rule was defined for 853 * this permission check, then use it. 854 */ 855 avkey.target_class = tclass; 856 avkey.specified = AVTAB_AV; 857 sattr = &policydb->type_attr_map[scontext->type - 1]; 858 tattr = &policydb->type_attr_map[tcontext->type - 1]; 859 ebitmap_for_each_bit(sattr, snode, i) { 860 if (!ebitmap_node_get_bit(snode, i)) 861 continue; 862 ebitmap_for_each_bit(tattr, tnode, j) { 863 if (!ebitmap_node_get_bit(tnode, j)) 864 continue; 865 avkey.source_type = i + 1; 866 avkey.target_type = j + 1; 867 for (node = 868 avtab_search_node(&policydb->te_avtab, &avkey); 869 node != NULL; 870 node = 871 avtab_search_node_next(node, avkey.specified)) { 872 if (node->key.specified == AVTAB_ALLOWED) 873 avd->allowed |= node->datum.data; 874 else if (node->key.specified == 875 AVTAB_AUDITALLOW) 876 avd->auditallow |= node->datum.data; 877 else if (node->key.specified == AVTAB_AUDITDENY) 878 avd->auditdeny &= node->datum.data; 879 } 880 881 /* Check conditional av table for additional permissions */ 882 cond_compute_av(&policydb->te_cond_avtab, &avkey, avd); 883 884 } 885 } 886 887 if (requested & ~avd->allowed) { 888 *reason |= SEPOL_COMPUTEAV_TE; 889 requested &= avd->allowed; 890 } 891 892 /* 893 * Remove any permissions prohibited by a constraint (this includes 894 * the MLS policy). 895 */ 896 constraint = tclass_datum->constraints; 897 while (constraint) { 898 if ((constraint->permissions & (avd->allowed)) && 899 !constraint_expr_eval_reason(scontext, tcontext, NULL, 900 tclass, constraint, r_buf, flags)) { 901 avd->allowed = 902 (avd->allowed) & ~(constraint->permissions); 903 } 904 constraint = constraint->next; 905 } 906 907 if (requested & ~avd->allowed) { 908 *reason |= SEPOL_COMPUTEAV_CONS; 909 requested &= avd->allowed; 910 } 911 912 /* 913 * If checking process transition permission and the 914 * role is changing, then check the (current_role, new_role) 915 * pair. 916 */ 917 if (tclass == SECCLASS_PROCESS && 918 (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && 919 scontext->role != tcontext->role) { 920 for (ra = policydb->role_allow; ra; ra = ra->next) { 921 if (scontext->role == ra->role && 922 tcontext->role == ra->new_role) 923 break; 924 } 925 if (!ra) 926 avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | 927 PROCESS__DYNTRANSITION); 928 } 929 930 if (requested & ~avd->allowed) { 931 *reason |= SEPOL_COMPUTEAV_RBAC; 932 requested &= avd->allowed; 933 } 934 935 return 0; 936 } 937 938 int hidden sepol_validate_transition(sepol_security_id_t oldsid, 939 sepol_security_id_t newsid, 940 sepol_security_id_t tasksid, 941 sepol_security_class_t tclass) 942 { 943 context_struct_t *ocontext; 944 context_struct_t *ncontext; 945 context_struct_t *tcontext; 946 class_datum_t *tclass_datum; 947 constraint_node_t *constraint; 948 949 if (!tclass || tclass > policydb->p_classes.nprim) { 950 ERR(NULL, "unrecognized class %d", tclass); 951 return -EINVAL; 952 } 953 tclass_datum = policydb->class_val_to_struct[tclass - 1]; 954 955 ocontext = sepol_sidtab_search(sidtab, oldsid); 956 if (!ocontext) { 957 ERR(NULL, "unrecognized SID %d", oldsid); 958 return -EINVAL; 959 } 960 961 ncontext = sepol_sidtab_search(sidtab, newsid); 962 if (!ncontext) { 963 ERR(NULL, "unrecognized SID %d", newsid); 964 return -EINVAL; 965 } 966 967 tcontext = sepol_sidtab_search(sidtab, tasksid); 968 if (!tcontext) { 969 ERR(NULL, "unrecognized SID %d", tasksid); 970 return -EINVAL; 971 } 972 973 constraint = tclass_datum->validatetrans; 974 while (constraint) { 975 if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext, 976 0, constraint, NULL, 0)) { 977 return -EPERM; 978 } 979 constraint = constraint->next; 980 } 981 982 return 0; 983 } 984 985 int hidden sepol_compute_av_reason(sepol_security_id_t ssid, 986 sepol_security_id_t tsid, 987 sepol_security_class_t tclass, 988 sepol_access_vector_t requested, 989 struct sepol_av_decision *avd, 990 unsigned int *reason) 991 { 992 context_struct_t *scontext = 0, *tcontext = 0; 993 int rc = 0; 994 995 scontext = sepol_sidtab_search(sidtab, ssid); 996 if (!scontext) { 997 ERR(NULL, "unrecognized SID %d", ssid); 998 rc = -EINVAL; 999 goto out; 1000 } 1001 tcontext = sepol_sidtab_search(sidtab, tsid); 1002 if (!tcontext) { 1003 ERR(NULL, "unrecognized SID %d", tsid); 1004 rc = -EINVAL; 1005 goto out; 1006 } 1007 1008 rc = context_struct_compute_av(scontext, tcontext, tclass, 1009 requested, avd, reason, NULL, 0); 1010 out: 1011 return rc; 1012 } 1013 1014 /* 1015 * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to 1016 * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd 1017 * in the constraint_expr_eval_reason() function. 1018 */ 1019 int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid, 1020 sepol_security_id_t tsid, 1021 sepol_security_class_t tclass, 1022 sepol_access_vector_t requested, 1023 struct sepol_av_decision *avd, 1024 unsigned int *reason, 1025 char **reason_buf, 1026 unsigned int flags) 1027 { 1028 context_struct_t *scontext = 0, *tcontext = 0; 1029 int rc = 0; 1030 1031 scontext = sepol_sidtab_search(sidtab, ssid); 1032 if (!scontext) { 1033 ERR(NULL, "unrecognized SID %d", ssid); 1034 rc = -EINVAL; 1035 goto out; 1036 } 1037 tcontext = sepol_sidtab_search(sidtab, tsid); 1038 if (!tcontext) { 1039 ERR(NULL, "unrecognized SID %d", tsid); 1040 rc = -EINVAL; 1041 goto out; 1042 } 1043 1044 /* 1045 * Set the buffer to NULL as constraints may not be processed. 1046 * If a buffer is required, then the routines in 1047 * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE 1048 * chunks (as it gets called for each constraint processed). 1049 * We just make sure these start from zero. 1050 */ 1051 *reason_buf = NULL; 1052 reason_buf_used = 0; 1053 reason_buf_len = 0; 1054 1055 rc = context_struct_compute_av(scontext, tcontext, tclass, 1056 requested, avd, reason, reason_buf, flags); 1057 out: 1058 return rc; 1059 } 1060 1061 int hidden sepol_compute_av(sepol_security_id_t ssid, 1062 sepol_security_id_t tsid, 1063 sepol_security_class_t tclass, 1064 sepol_access_vector_t requested, 1065 struct sepol_av_decision *avd) 1066 { 1067 unsigned int reason = 0; 1068 return sepol_compute_av_reason(ssid, tsid, tclass, requested, avd, 1069 &reason); 1070 } 1071 1072 /* 1073 * Return a class ID associated with the class string specified by 1074 * class_name. 1075 */ 1076 int hidden sepol_string_to_security_class(const char *class_name, 1077 sepol_security_class_t *tclass) 1078 { 1079 char *class = NULL; 1080 sepol_security_class_t id; 1081 1082 for (id = 1;; id++) { 1083 class = policydb->p_class_val_to_name[id - 1]; 1084 if (class == NULL) { 1085 ERR(NULL, "could not convert %s to class id", class_name); 1086 return STATUS_ERR; 1087 } 1088 if ((strcmp(class, class_name)) == 0) { 1089 *tclass = id; 1090 return STATUS_SUCCESS; 1091 } 1092 } 1093 } 1094 1095 /* 1096 * Return access vector bit associated with the class ID and permission 1097 * string. 1098 */ 1099 int hidden sepol_string_to_av_perm(sepol_security_class_t tclass, 1100 const char *perm_name, 1101 sepol_access_vector_t *av) 1102 { 1103 class_datum_t *tclass_datum; 1104 perm_datum_t *perm_datum; 1105 1106 if (!tclass || tclass > policydb->p_classes.nprim) { 1107 ERR(NULL, "unrecognized class %d", tclass); 1108 return -EINVAL; 1109 } 1110 tclass_datum = policydb->class_val_to_struct[tclass - 1]; 1111 1112 /* Check for unique perms then the common ones (if any) */ 1113 perm_datum = (perm_datum_t *) 1114 hashtab_search(tclass_datum->permissions.table, 1115 (hashtab_key_t)perm_name); 1116 if (perm_datum != NULL) { 1117 *av = 0x1 << (perm_datum->s.value - 1); 1118 return STATUS_SUCCESS; 1119 } 1120 1121 if (tclass_datum->comdatum == NULL) 1122 goto out; 1123 1124 perm_datum = (perm_datum_t *) 1125 hashtab_search(tclass_datum->comdatum->permissions.table, 1126 (hashtab_key_t)perm_name); 1127 1128 if (perm_datum != NULL) { 1129 *av = 0x1 << (perm_datum->s.value - 1); 1130 return STATUS_SUCCESS; 1131 } 1132 out: 1133 ERR(NULL, "could not convert %s to av bit", perm_name); 1134 return STATUS_ERR; 1135 } 1136 1137 /* 1138 * Write the security context string representation of 1139 * the context associated with `sid' into a dynamically 1140 * allocated string of the correct size. Set `*scontext' 1141 * to point to this string and set `*scontext_len' to 1142 * the length of the string. 1143 */ 1144 int hidden sepol_sid_to_context(sepol_security_id_t sid, 1145 sepol_security_context_t * scontext, 1146 size_t * scontext_len) 1147 { 1148 context_struct_t *context; 1149 int rc = 0; 1150 1151 context = sepol_sidtab_search(sidtab, sid); 1152 if (!context) { 1153 ERR(NULL, "unrecognized SID %d", sid); 1154 rc = -EINVAL; 1155 goto out; 1156 } 1157 rc = context_to_string(NULL, policydb, context, scontext, scontext_len); 1158 out: 1159 return rc; 1160 1161 } 1162 1163 /* 1164 * Return a SID associated with the security context that 1165 * has the string representation specified by `scontext'. 1166 */ 1167 int hidden sepol_context_to_sid(const sepol_security_context_t scontext, 1168 size_t scontext_len, sepol_security_id_t * sid) 1169 { 1170 1171 context_struct_t *context = NULL; 1172 1173 /* First, create the context */ 1174 if (context_from_string(NULL, policydb, &context, 1175 scontext, scontext_len) < 0) 1176 goto err; 1177 1178 /* Obtain the new sid */ 1179 if (sid && (sepol_sidtab_context_to_sid(sidtab, context, sid) < 0)) 1180 goto err; 1181 1182 context_destroy(context); 1183 free(context); 1184 return STATUS_SUCCESS; 1185 1186 err: 1187 if (context) { 1188 context_destroy(context); 1189 free(context); 1190 } 1191 ERR(NULL, "could not convert %s to sid", scontext); 1192 return STATUS_ERR; 1193 } 1194 1195 static inline int compute_sid_handle_invalid_context(context_struct_t * 1196 scontext, 1197 context_struct_t * 1198 tcontext, 1199 sepol_security_class_t 1200 tclass, 1201 context_struct_t * 1202 newcontext) 1203 { 1204 if (selinux_enforcing) { 1205 return -EACCES; 1206 } else { 1207 sepol_security_context_t s, t, n; 1208 size_t slen, tlen, nlen; 1209 1210 context_to_string(NULL, policydb, scontext, &s, &slen); 1211 context_to_string(NULL, policydb, tcontext, &t, &tlen); 1212 context_to_string(NULL, policydb, newcontext, &n, &nlen); 1213 ERR(NULL, "invalid context %s for " 1214 "scontext=%s tcontext=%s tclass=%s", 1215 n, s, t, policydb->p_class_val_to_name[tclass - 1]); 1216 free(s); 1217 free(t); 1218 free(n); 1219 return 0; 1220 } 1221 } 1222 1223 static int sepol_compute_sid(sepol_security_id_t ssid, 1224 sepol_security_id_t tsid, 1225 sepol_security_class_t tclass, 1226 uint32_t specified, sepol_security_id_t * out_sid) 1227 { 1228 context_struct_t *scontext = 0, *tcontext = 0, newcontext; 1229 struct role_trans *roletr = 0; 1230 avtab_key_t avkey; 1231 avtab_datum_t *avdatum; 1232 avtab_ptr_t node; 1233 int rc = 0; 1234 1235 scontext = sepol_sidtab_search(sidtab, ssid); 1236 if (!scontext) { 1237 ERR(NULL, "unrecognized SID %d", ssid); 1238 rc = -EINVAL; 1239 goto out; 1240 } 1241 tcontext = sepol_sidtab_search(sidtab, tsid); 1242 if (!tcontext) { 1243 ERR(NULL, "unrecognized SID %d", tsid); 1244 rc = -EINVAL; 1245 goto out; 1246 } 1247 1248 context_init(&newcontext); 1249 1250 /* Set the user identity. */ 1251 switch (specified) { 1252 case AVTAB_TRANSITION: 1253 case AVTAB_CHANGE: 1254 /* Use the process user identity. */ 1255 newcontext.user = scontext->user; 1256 break; 1257 case AVTAB_MEMBER: 1258 /* Use the related object owner. */ 1259 newcontext.user = tcontext->user; 1260 break; 1261 } 1262 1263 /* Set the role and type to default values. */ 1264 switch (tclass) { 1265 case SECCLASS_PROCESS: 1266 /* Use the current role and type of process. */ 1267 newcontext.role = scontext->role; 1268 newcontext.type = scontext->type; 1269 break; 1270 default: 1271 /* Use the well-defined object role. */ 1272 newcontext.role = OBJECT_R_VAL; 1273 /* Use the type of the related object. */ 1274 newcontext.type = tcontext->type; 1275 } 1276 1277 /* Look for a type transition/member/change rule. */ 1278 avkey.source_type = scontext->type; 1279 avkey.target_type = tcontext->type; 1280 avkey.target_class = tclass; 1281 avkey.specified = specified; 1282 avdatum = avtab_search(&policydb->te_avtab, &avkey); 1283 1284 /* If no permanent rule, also check for enabled conditional rules */ 1285 if (!avdatum) { 1286 node = avtab_search_node(&policydb->te_cond_avtab, &avkey); 1287 for (; node != NULL; 1288 node = avtab_search_node_next(node, specified)) { 1289 if (node->key.specified & AVTAB_ENABLED) { 1290 avdatum = &node->datum; 1291 break; 1292 } 1293 } 1294 } 1295 1296 if (avdatum) { 1297 /* Use the type from the type transition/member/change rule. */ 1298 newcontext.type = avdatum->data; 1299 } 1300 1301 /* Check for class-specific changes. */ 1302 switch (tclass) { 1303 case SECCLASS_PROCESS: 1304 if (specified & AVTAB_TRANSITION) { 1305 /* Look for a role transition rule. */ 1306 for (roletr = policydb->role_tr; roletr; 1307 roletr = roletr->next) { 1308 if (roletr->role == scontext->role && 1309 roletr->type == tcontext->type) { 1310 /* Use the role transition rule. */ 1311 newcontext.role = roletr->new_role; 1312 break; 1313 } 1314 } 1315 } 1316 break; 1317 default: 1318 break; 1319 } 1320 1321 /* Set the MLS attributes. 1322 This is done last because it may allocate memory. */ 1323 rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified, 1324 &newcontext); 1325 if (rc) 1326 goto out; 1327 1328 /* Check the validity of the context. */ 1329 if (!policydb_context_isvalid(policydb, &newcontext)) { 1330 rc = compute_sid_handle_invalid_context(scontext, 1331 tcontext, 1332 tclass, &newcontext); 1333 if (rc) 1334 goto out; 1335 } 1336 /* Obtain the sid for the context. */ 1337 rc = sepol_sidtab_context_to_sid(sidtab, &newcontext, out_sid); 1338 out: 1339 context_destroy(&newcontext); 1340 return rc; 1341 } 1342 1343 /* 1344 * Compute a SID to use for labeling a new object in the 1345 * class `tclass' based on a SID pair. 1346 */ 1347 int hidden sepol_transition_sid(sepol_security_id_t ssid, 1348 sepol_security_id_t tsid, 1349 sepol_security_class_t tclass, 1350 sepol_security_id_t * out_sid) 1351 { 1352 return sepol_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); 1353 } 1354 1355 /* 1356 * Compute a SID to use when selecting a member of a 1357 * polyinstantiated object of class `tclass' based on 1358 * a SID pair. 1359 */ 1360 int hidden sepol_member_sid(sepol_security_id_t ssid, 1361 sepol_security_id_t tsid, 1362 sepol_security_class_t tclass, 1363 sepol_security_id_t * out_sid) 1364 { 1365 return sepol_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); 1366 } 1367 1368 /* 1369 * Compute a SID to use for relabeling an object in the 1370 * class `tclass' based on a SID pair. 1371 */ 1372 int hidden sepol_change_sid(sepol_security_id_t ssid, 1373 sepol_security_id_t tsid, 1374 sepol_security_class_t tclass, 1375 sepol_security_id_t * out_sid) 1376 { 1377 return sepol_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); 1378 } 1379 1380 /* 1381 * Verify that each permission that is defined under the 1382 * existing policy is still defined with the same value 1383 * in the new policy. 1384 */ 1385 static int validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) 1386 { 1387 hashtab_t h; 1388 perm_datum_t *perdatum, *perdatum2; 1389 1390 h = (hashtab_t) p; 1391 perdatum = (perm_datum_t *) datum; 1392 1393 perdatum2 = (perm_datum_t *) hashtab_search(h, key); 1394 if (!perdatum2) { 1395 ERR(NULL, "permission %s disappeared", key); 1396 return -1; 1397 } 1398 if (perdatum->s.value != perdatum2->s.value) { 1399 ERR(NULL, "the value of permissions %s changed", key); 1400 return -1; 1401 } 1402 return 0; 1403 } 1404 1405 /* 1406 * Verify that each class that is defined under the 1407 * existing policy is still defined with the same 1408 * attributes in the new policy. 1409 */ 1410 static int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p) 1411 { 1412 policydb_t *newp; 1413 class_datum_t *cladatum, *cladatum2; 1414 1415 newp = (policydb_t *) p; 1416 cladatum = (class_datum_t *) datum; 1417 1418 cladatum2 = 1419 (class_datum_t *) hashtab_search(newp->p_classes.table, key); 1420 if (!cladatum2) { 1421 ERR(NULL, "class %s disappeared", key); 1422 return -1; 1423 } 1424 if (cladatum->s.value != cladatum2->s.value) { 1425 ERR(NULL, "the value of class %s changed", key); 1426 return -1; 1427 } 1428 if ((cladatum->comdatum && !cladatum2->comdatum) || 1429 (!cladatum->comdatum && cladatum2->comdatum)) { 1430 ERR(NULL, "the inherits clause for the access " 1431 "vector definition for class %s changed", key); 1432 return -1; 1433 } 1434 if (cladatum->comdatum) { 1435 if (hashtab_map 1436 (cladatum->comdatum->permissions.table, validate_perm, 1437 cladatum2->comdatum->permissions.table)) { 1438 ERR(NULL, 1439 " in the access vector definition " 1440 "for class %s\n", key); 1441 return -1; 1442 } 1443 } 1444 if (hashtab_map(cladatum->permissions.table, validate_perm, 1445 cladatum2->permissions.table)) { 1446 ERR(NULL, " in access vector definition for class %s", key); 1447 return -1; 1448 } 1449 return 0; 1450 } 1451 1452 /* Clone the SID into the new SID table. */ 1453 static int clone_sid(sepol_security_id_t sid, 1454 context_struct_t * context, void *arg) 1455 { 1456 sidtab_t *s = arg; 1457 1458 return sepol_sidtab_insert(s, sid, context); 1459 } 1460 1461 static inline int convert_context_handle_invalid_context(context_struct_t * 1462 context) 1463 { 1464 if (selinux_enforcing) { 1465 return -EINVAL; 1466 } else { 1467 sepol_security_context_t s; 1468 size_t len; 1469 1470 context_to_string(NULL, policydb, context, &s, &len); 1471 ERR(NULL, "context %s is invalid", s); 1472 free(s); 1473 return 0; 1474 } 1475 } 1476 1477 typedef struct { 1478 policydb_t *oldp; 1479 policydb_t *newp; 1480 } convert_context_args_t; 1481 1482 /* 1483 * Convert the values in the security context 1484 * structure `c' from the values specified 1485 * in the policy `p->oldp' to the values specified 1486 * in the policy `p->newp'. Verify that the 1487 * context is valid under the new policy. 1488 */ 1489 static int convert_context(sepol_security_id_t key __attribute__ ((unused)), 1490 context_struct_t * c, void *p) 1491 { 1492 convert_context_args_t *args; 1493 context_struct_t oldc; 1494 role_datum_t *role; 1495 type_datum_t *typdatum; 1496 user_datum_t *usrdatum; 1497 sepol_security_context_t s; 1498 size_t len; 1499 int rc = -EINVAL; 1500 1501 args = (convert_context_args_t *) p; 1502 1503 if (context_cpy(&oldc, c)) 1504 return -ENOMEM; 1505 1506 /* Convert the user. */ 1507 usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table, 1508 args->oldp-> 1509 p_user_val_to_name[c->user - 1510 1]); 1511 1512 if (!usrdatum) { 1513 goto bad; 1514 } 1515 c->user = usrdatum->s.value; 1516 1517 /* Convert the role. */ 1518 role = (role_datum_t *) hashtab_search(args->newp->p_roles.table, 1519 args->oldp-> 1520 p_role_val_to_name[c->role - 1]); 1521 if (!role) { 1522 goto bad; 1523 } 1524 c->role = role->s.value; 1525 1526 /* Convert the type. */ 1527 typdatum = (type_datum_t *) 1528 hashtab_search(args->newp->p_types.table, 1529 args->oldp->p_type_val_to_name[c->type - 1]); 1530 if (!typdatum) { 1531 goto bad; 1532 } 1533 c->type = typdatum->s.value; 1534 1535 rc = mls_convert_context(args->oldp, args->newp, c); 1536 if (rc) 1537 goto bad; 1538 1539 /* Check the validity of the new context. */ 1540 if (!policydb_context_isvalid(args->newp, c)) { 1541 rc = convert_context_handle_invalid_context(&oldc); 1542 if (rc) 1543 goto bad; 1544 } 1545 1546 context_destroy(&oldc); 1547 return 0; 1548 1549 bad: 1550 context_to_string(NULL, policydb, &oldc, &s, &len); 1551 context_destroy(&oldc); 1552 ERR(NULL, "invalidating context %s", s); 1553 free(s); 1554 return rc; 1555 } 1556 1557 /* Reading from a policy "file". */ 1558 int hidden next_entry(void *buf, struct policy_file *fp, size_t bytes) 1559 { 1560 size_t nread; 1561 1562 switch (fp->type) { 1563 case PF_USE_STDIO: 1564 nread = fread(buf, bytes, 1, fp->fp); 1565 1566 if (nread != 1) 1567 return -1; 1568 break; 1569 case PF_USE_MEMORY: 1570 if (bytes > fp->len) 1571 return -1; 1572 memcpy(buf, fp->data, bytes); 1573 fp->data += bytes; 1574 fp->len -= bytes; 1575 break; 1576 default: 1577 return -1; 1578 } 1579 return 0; 1580 } 1581 1582 size_t hidden put_entry(const void *ptr, size_t size, size_t n, 1583 struct policy_file *fp) 1584 { 1585 size_t bytes = size * n; 1586 1587 switch (fp->type) { 1588 case PF_USE_STDIO: 1589 return fwrite(ptr, size, n, fp->fp); 1590 case PF_USE_MEMORY: 1591 if (bytes > fp->len) { 1592 errno = ENOSPC; 1593 return 0; 1594 } 1595 1596 memcpy(fp->data, ptr, bytes); 1597 fp->data += bytes; 1598 fp->len -= bytes; 1599 return n; 1600 case PF_LEN: 1601 fp->len += bytes; 1602 return n; 1603 default: 1604 return 0; 1605 } 1606 return 0; 1607 } 1608 1609 /* 1610 * Read a new set of configuration data from 1611 * a policy database binary representation file. 1612 * 1613 * Verify that each class that is defined under the 1614 * existing policy is still defined with the same 1615 * attributes in the new policy. 1616 * 1617 * Convert the context structures in the SID table to the 1618 * new representation and verify that all entries 1619 * in the SID table are valid under the new policy. 1620 * 1621 * Change the active policy database to use the new 1622 * configuration data. 1623 * 1624 * Reset the access vector cache. 1625 */ 1626 int hidden sepol_load_policy(void *data, size_t len) 1627 { 1628 policydb_t oldpolicydb, newpolicydb; 1629 sidtab_t oldsidtab, newsidtab; 1630 convert_context_args_t args; 1631 int rc = 0; 1632 struct policy_file file, *fp; 1633 1634 policy_file_init(&file); 1635 file.type = PF_USE_MEMORY; 1636 file.data = data; 1637 file.len = len; 1638 fp = &file; 1639 1640 if (policydb_init(&newpolicydb)) 1641 return -ENOMEM; 1642 1643 if (policydb_read(&newpolicydb, fp, 1)) { 1644 policydb_destroy(&mypolicydb); 1645 return -EINVAL; 1646 } 1647 1648 sepol_sidtab_init(&newsidtab); 1649 1650 /* Verify that the existing classes did not change. */ 1651 if (hashtab_map 1652 (policydb->p_classes.table, validate_class, &newpolicydb)) { 1653 ERR(NULL, "the definition of an existing class changed"); 1654 rc = -EINVAL; 1655 goto err; 1656 } 1657 1658 /* Clone the SID table. */ 1659 sepol_sidtab_shutdown(sidtab); 1660 if (sepol_sidtab_map(sidtab, clone_sid, &newsidtab)) { 1661 rc = -ENOMEM; 1662 goto err; 1663 } 1664 1665 /* Convert the internal representations of contexts 1666 in the new SID table and remove invalid SIDs. */ 1667 args.oldp = policydb; 1668 args.newp = &newpolicydb; 1669 sepol_sidtab_map_remove_on_error(&newsidtab, convert_context, &args); 1670 1671 /* Save the old policydb and SID table to free later. */ 1672 memcpy(&oldpolicydb, policydb, sizeof *policydb); 1673 sepol_sidtab_set(&oldsidtab, sidtab); 1674 1675 /* Install the new policydb and SID table. */ 1676 memcpy(policydb, &newpolicydb, sizeof *policydb); 1677 sepol_sidtab_set(sidtab, &newsidtab); 1678 1679 /* Free the old policydb and SID table. */ 1680 policydb_destroy(&oldpolicydb); 1681 sepol_sidtab_destroy(&oldsidtab); 1682 1683 return 0; 1684 1685 err: 1686 sepol_sidtab_destroy(&newsidtab); 1687 policydb_destroy(&newpolicydb); 1688 return rc; 1689 1690 } 1691 1692 /* 1693 * Return the SIDs to use for an unlabeled file system 1694 * that is being mounted from the device with the 1695 * the kdevname `name'. The `fs_sid' SID is returned for 1696 * the file system and the `file_sid' SID is returned 1697 * for all files within that file system. 1698 */ 1699 int hidden sepol_fs_sid(char *name, 1700 sepol_security_id_t * fs_sid, 1701 sepol_security_id_t * file_sid) 1702 { 1703 int rc = 0; 1704 ocontext_t *c; 1705 1706 c = policydb->ocontexts[OCON_FS]; 1707 while (c) { 1708 if (strcmp(c->u.name, name) == 0) 1709 break; 1710 c = c->next; 1711 } 1712 1713 if (c) { 1714 if (!c->sid[0] || !c->sid[1]) { 1715 rc = sepol_sidtab_context_to_sid(sidtab, 1716 &c->context[0], 1717 &c->sid[0]); 1718 if (rc) 1719 goto out; 1720 rc = sepol_sidtab_context_to_sid(sidtab, 1721 &c->context[1], 1722 &c->sid[1]); 1723 if (rc) 1724 goto out; 1725 } 1726 *fs_sid = c->sid[0]; 1727 *file_sid = c->sid[1]; 1728 } else { 1729 *fs_sid = SECINITSID_FS; 1730 *file_sid = SECINITSID_FILE; 1731 } 1732 1733 out: 1734 return rc; 1735 } 1736 1737 /* 1738 * Return the SID of the port specified by 1739 * `domain', `type', `protocol', and `port'. 1740 */ 1741 int hidden sepol_port_sid(uint16_t domain __attribute__ ((unused)), 1742 uint16_t type __attribute__ ((unused)), 1743 uint8_t protocol, 1744 uint16_t port, sepol_security_id_t * out_sid) 1745 { 1746 ocontext_t *c; 1747 int rc = 0; 1748 1749 c = policydb->ocontexts[OCON_PORT]; 1750 while (c) { 1751 if (c->u.port.protocol == protocol && 1752 c->u.port.low_port <= port && c->u.port.high_port >= port) 1753 break; 1754 c = c->next; 1755 } 1756 1757 if (c) { 1758 if (!c->sid[0]) { 1759 rc = sepol_sidtab_context_to_sid(sidtab, 1760 &c->context[0], 1761 &c->sid[0]); 1762 if (rc) 1763 goto out; 1764 } 1765 *out_sid = c->sid[0]; 1766 } else { 1767 *out_sid = SECINITSID_PORT; 1768 } 1769 1770 out: 1771 return rc; 1772 } 1773 1774 /* 1775 * Return the SIDs to use for a network interface 1776 * with the name `name'. The `if_sid' SID is returned for 1777 * the interface and the `msg_sid' SID is returned as 1778 * the default SID for messages received on the 1779 * interface. 1780 */ 1781 int hidden sepol_netif_sid(char *name, 1782 sepol_security_id_t * if_sid, 1783 sepol_security_id_t * msg_sid) 1784 { 1785 int rc = 0; 1786 ocontext_t *c; 1787 1788 c = policydb->ocontexts[OCON_NETIF]; 1789 while (c) { 1790 if (strcmp(name, c->u.name) == 0) 1791 break; 1792 c = c->next; 1793 } 1794 1795 if (c) { 1796 if (!c->sid[0] || !c->sid[1]) { 1797 rc = sepol_sidtab_context_to_sid(sidtab, 1798 &c->context[0], 1799 &c->sid[0]); 1800 if (rc) 1801 goto out; 1802 rc = sepol_sidtab_context_to_sid(sidtab, 1803 &c->context[1], 1804 &c->sid[1]); 1805 if (rc) 1806 goto out; 1807 } 1808 *if_sid = c->sid[0]; 1809 *msg_sid = c->sid[1]; 1810 } else { 1811 *if_sid = SECINITSID_NETIF; 1812 *msg_sid = SECINITSID_NETMSG; 1813 } 1814 1815 out: 1816 return rc; 1817 } 1818 1819 static int match_ipv6_addrmask(uint32_t * input, uint32_t * addr, 1820 uint32_t * mask) 1821 { 1822 int i, fail = 0; 1823 1824 for (i = 0; i < 4; i++) 1825 if (addr[i] != (input[i] & mask[i])) { 1826 fail = 1; 1827 break; 1828 } 1829 1830 return !fail; 1831 } 1832 1833 /* 1834 * Return the SID of the node specified by the address 1835 * `addrp' where `addrlen' is the length of the address 1836 * in bytes and `domain' is the communications domain or 1837 * address family in which the address should be interpreted. 1838 */ 1839 int hidden sepol_node_sid(uint16_t domain, 1840 void *addrp, 1841 size_t addrlen, sepol_security_id_t * out_sid) 1842 { 1843 int rc = 0; 1844 ocontext_t *c; 1845 1846 switch (domain) { 1847 case AF_INET:{ 1848 uint32_t addr; 1849 1850 if (addrlen != sizeof(uint32_t)) { 1851 rc = -EINVAL; 1852 goto out; 1853 } 1854 1855 addr = *((uint32_t *) addrp); 1856 1857 c = policydb->ocontexts[OCON_NODE]; 1858 while (c) { 1859 if (c->u.node.addr == (addr & c->u.node.mask)) 1860 break; 1861 c = c->next; 1862 } 1863 break; 1864 } 1865 1866 case AF_INET6: 1867 if (addrlen != sizeof(uint64_t) * 2) { 1868 rc = -EINVAL; 1869 goto out; 1870 } 1871 1872 c = policydb->ocontexts[OCON_NODE6]; 1873 while (c) { 1874 if (match_ipv6_addrmask(addrp, c->u.node6.addr, 1875 c->u.node6.mask)) 1876 break; 1877 c = c->next; 1878 } 1879 break; 1880 1881 default: 1882 *out_sid = SECINITSID_NODE; 1883 goto out; 1884 } 1885 1886 if (c) { 1887 if (!c->sid[0]) { 1888 rc = sepol_sidtab_context_to_sid(sidtab, 1889 &c->context[0], 1890 &c->sid[0]); 1891 if (rc) 1892 goto out; 1893 } 1894 *out_sid = c->sid[0]; 1895 } else { 1896 *out_sid = SECINITSID_NODE; 1897 } 1898 1899 out: 1900 return rc; 1901 } 1902 1903 /* 1904 * Generate the set of SIDs for legal security contexts 1905 * for a given user that can be reached by `fromsid'. 1906 * Set `*sids' to point to a dynamically allocated 1907 * array containing the set of SIDs. Set `*nel' to the 1908 * number of elements in the array. 1909 */ 1910 #define SIDS_NEL 25 1911 1912 int hidden sepol_get_user_sids(sepol_security_id_t fromsid, 1913 char *username, 1914 sepol_security_id_t ** sids, uint32_t * nel) 1915 { 1916 context_struct_t *fromcon, usercon; 1917 sepol_security_id_t *mysids, *mysids2, sid; 1918 uint32_t mynel = 0, maxnel = SIDS_NEL; 1919 user_datum_t *user; 1920 role_datum_t *role; 1921 struct sepol_av_decision avd; 1922 int rc = 0; 1923 unsigned int i, j, reason; 1924 ebitmap_node_t *rnode, *tnode; 1925 1926 fromcon = sepol_sidtab_search(sidtab, fromsid); 1927 if (!fromcon) { 1928 rc = -EINVAL; 1929 goto out; 1930 } 1931 1932 user = (user_datum_t *) hashtab_search(policydb->p_users.table, 1933 username); 1934 if (!user) { 1935 rc = -EINVAL; 1936 goto out; 1937 } 1938 usercon.user = user->s.value; 1939 1940 mysids = malloc(maxnel * sizeof(sepol_security_id_t)); 1941 if (!mysids) { 1942 rc = -ENOMEM; 1943 goto out; 1944 } 1945 memset(mysids, 0, maxnel * sizeof(sepol_security_id_t)); 1946 1947 ebitmap_for_each_bit(&user->roles.roles, rnode, i) { 1948 if (!ebitmap_node_get_bit(rnode, i)) 1949 continue; 1950 role = policydb->role_val_to_struct[i]; 1951 usercon.role = i + 1; 1952 ebitmap_for_each_bit(&role->types.types, tnode, j) { 1953 if (!ebitmap_node_get_bit(tnode, j)) 1954 continue; 1955 usercon.type = j + 1; 1956 if (usercon.type == fromcon->type) 1957 continue; 1958 1959 if (mls_setup_user_range 1960 (fromcon, user, &usercon, policydb->mls)) 1961 continue; 1962 1963 rc = context_struct_compute_av(fromcon, &usercon, 1964 SECCLASS_PROCESS, 1965 PROCESS__TRANSITION, 1966 &avd, &reason, NULL, 0); 1967 if (rc || !(avd.allowed & PROCESS__TRANSITION)) 1968 continue; 1969 rc = sepol_sidtab_context_to_sid(sidtab, &usercon, 1970 &sid); 1971 if (rc) { 1972 free(mysids); 1973 goto out; 1974 } 1975 if (mynel < maxnel) { 1976 mysids[mynel++] = sid; 1977 } else { 1978 maxnel += SIDS_NEL; 1979 mysids2 = 1980 malloc(maxnel * 1981 sizeof(sepol_security_id_t)); 1982 1983 if (!mysids2) { 1984 rc = -ENOMEM; 1985 free(mysids); 1986 goto out; 1987 } 1988 memset(mysids2, 0, 1989 maxnel * sizeof(sepol_security_id_t)); 1990 memcpy(mysids2, mysids, 1991 mynel * sizeof(sepol_security_id_t)); 1992 free(mysids); 1993 mysids = mysids2; 1994 mysids[mynel++] = sid; 1995 } 1996 } 1997 } 1998 1999 *sids = mysids; 2000 *nel = mynel; 2001 2002 out: 2003 return rc; 2004 } 2005 2006 /* 2007 * Return the SID to use for a file in a filesystem 2008 * that cannot support a persistent label mapping or use another 2009 * fixed labeling behavior like transition SIDs or task SIDs. 2010 */ 2011 int hidden sepol_genfs_sid(const char *fstype, 2012 char *path, 2013 sepol_security_class_t sclass, 2014 sepol_security_id_t * sid) 2015 { 2016 size_t len; 2017 genfs_t *genfs; 2018 ocontext_t *c; 2019 int rc = 0, cmp = 0; 2020 2021 for (genfs = policydb->genfs; genfs; genfs = genfs->next) { 2022 cmp = strcmp(fstype, genfs->fstype); 2023 if (cmp <= 0) 2024 break; 2025 } 2026 2027 if (!genfs || cmp) { 2028 *sid = SECINITSID_UNLABELED; 2029 rc = -ENOENT; 2030 goto out; 2031 } 2032 2033 for (c = genfs->head; c; c = c->next) { 2034 len = strlen(c->u.name); 2035 if ((!c->v.sclass || sclass == c->v.sclass) && 2036 (strncmp(c->u.name, path, len) == 0)) 2037 break; 2038 } 2039 2040 if (!c) { 2041 *sid = SECINITSID_UNLABELED; 2042 rc = -ENOENT; 2043 goto out; 2044 } 2045 2046 if (!c->sid[0]) { 2047 rc = sepol_sidtab_context_to_sid(sidtab, 2048 &c->context[0], &c->sid[0]); 2049 if (rc) 2050 goto out; 2051 } 2052 2053 *sid = c->sid[0]; 2054 out: 2055 return rc; 2056 } 2057 2058 int hidden sepol_fs_use(const char *fstype, 2059 unsigned int *behavior, sepol_security_id_t * sid) 2060 { 2061 int rc = 0; 2062 ocontext_t *c; 2063 2064 c = policydb->ocontexts[OCON_FSUSE]; 2065 while (c) { 2066 if (strcmp(fstype, c->u.name) == 0) 2067 break; 2068 c = c->next; 2069 } 2070 2071 if (c) { 2072 *behavior = c->v.behavior; 2073 if (!c->sid[0]) { 2074 rc = sepol_sidtab_context_to_sid(sidtab, 2075 &c->context[0], 2076 &c->sid[0]); 2077 if (rc) 2078 goto out; 2079 } 2080 *sid = c->sid[0]; 2081 } else { 2082 rc = sepol_genfs_sid(fstype, "/", SECCLASS_DIR, sid); 2083 if (rc) { 2084 *behavior = SECURITY_FS_USE_NONE; 2085 rc = 0; 2086 } else { 2087 *behavior = SECURITY_FS_USE_GENFS; 2088 } 2089 } 2090 2091 out: 2092 return rc; 2093 } 2094 2095 /* FLASK */ 2096