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