conditional.c revision 255e72915d4cbddceb435e13d81601755714e9f3
1/* Authors: Karl MacMillan <kmacmillan@tresys.com> 2 * Frank Mayer <mayerf@tresys.com> 3 * David Caplan <dac@tresys.com> 4 * 5 * Copyright (C) 2003 - 2005 Tresys Technology, LLC 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include <stdlib.h> 23 24#include <sepol/policydb/flask_types.h> 25#include <sepol/policydb/conditional.h> 26 27#include "private.h" 28 29/* move all type rules to top of t/f lists to help kernel on evaluation */ 30static void cond_optimize(cond_av_list_t ** l) 31{ 32 cond_av_list_t *top, *p, *cur; 33 34 top = p = cur = *l; 35 36 while (cur) { 37 if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) { 38 p->next = cur->next; 39 cur->next = top; 40 top = cur; 41 cur = p->next; 42 } else { 43 p = cur; 44 cur = cur->next; 45 } 46 } 47 *l = top; 48} 49 50/* reorder t/f lists for kernel */ 51void cond_optimize_lists(cond_list_t * cl) 52{ 53 cond_list_t *n; 54 55 for (n = cl; n != NULL; n = n->next) { 56 cond_optimize(&n->true_list); 57 cond_optimize(&n->false_list); 58 } 59} 60 61static int bool_present(unsigned int target, unsigned int bools[], 62 unsigned int num_bools) 63{ 64 unsigned int i = 0; 65 int ret = 1; 66 67 if (num_bools > COND_MAX_BOOLS) { 68 return 0; 69 } 70 while (i < num_bools && target != bools[i]) 71 i++; 72 if (i == num_bools) 73 ret = 0; /* got to end w/o match */ 74 return ret; 75} 76 77static int same_bools(cond_node_t * a, cond_node_t * b) 78{ 79 unsigned int i, x; 80 81 x = a->nbools; 82 83 /* same number of bools? */ 84 if (x != b->nbools) 85 return 0; 86 87 /* make sure all the bools in a are also in b */ 88 for (i = 0; i < x; i++) 89 if (!bool_present(a->bool_ids[i], b->bool_ids, x)) 90 return 0; 91 return 1; 92} 93 94/* 95 * Determine if two conditional expressions are equal. 96 */ 97int cond_expr_equal(cond_node_t * a, cond_node_t * b) 98{ 99 cond_expr_t *cur_a, *cur_b; 100 101 if (a == NULL || b == NULL) 102 return 0; 103 104 if (a->nbools != b->nbools) 105 return 0; 106 107 /* if exprs have <= COND_MAX_BOOLS we can check the precompute values 108 * for the expressions. 109 */ 110 if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) { 111 if (!same_bools(a, b)) 112 return 0; 113 return (a->expr_pre_comp == b->expr_pre_comp); 114 } 115 116 /* for long expressions we check for exactly the same expression */ 117 cur_a = a->expr; 118 cur_b = b->expr; 119 while (1) { 120 if (cur_a == NULL && cur_b == NULL) 121 return 1; 122 else if (cur_a == NULL || cur_b == NULL) 123 return 0; 124 if (cur_a->expr_type != cur_b->expr_type) 125 return 0; 126 if (cur_a->expr_type == COND_BOOL) { 127 if (cur_a->bool != cur_b->bool) 128 return 0; 129 } 130 cur_a = cur_a->next; 131 cur_b = cur_b->next; 132 } 133 return 1; 134} 135 136/* Create a new conditional node, optionally copying 137 * the conditional expression from an existing node. 138 * If node is NULL then a new node will be created 139 * with no conditional expression. 140 */ 141cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node) 142{ 143 cond_node_t *new_node; 144 unsigned int i; 145 146 new_node = (cond_node_t *)malloc(sizeof(cond_node_t)); 147 if (!new_node) { 148 return NULL; 149 } 150 memset(new_node, 0, sizeof(cond_node_t)); 151 152 if (node) { 153 new_node->expr = cond_copy_expr(node->expr); 154 if (!new_node->expr) { 155 free(new_node); 156 return NULL; 157 } 158 new_node->cur_state = cond_evaluate_expr(p, new_node->expr); 159 new_node->nbools = node->nbools; 160 for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++) 161 new_node->bool_ids[i] = node->bool_ids[i]; 162 new_node->expr_pre_comp = node->expr_pre_comp; 163 } 164 165 return new_node; 166} 167 168/* Find a conditional (the needle) within a list of existing ones (the 169 * haystack) that has a matching expression. If found, return a 170 * pointer to the existing node, setting 'was_created' to 0. 171 * Otherwise create a new one and return it, setting 'was_created' to 172 * 1. */ 173cond_node_t *cond_node_find(policydb_t * p, 174 cond_node_t * needle, cond_node_t * haystack, 175 int *was_created) 176{ 177 while (haystack) { 178 if (cond_expr_equal(needle, haystack)) { 179 *was_created = 0; 180 return haystack; 181 } 182 haystack = haystack->next; 183 } 184 *was_created = 1; 185 186 return cond_node_create(p, needle); 187} 188 189/* return either a pre-existing matching node or create a new node */ 190cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list, 191 cond_node_t * cn) 192{ 193 int was_created; 194 cond_node_t *result = cond_node_find(p, cn, list, &was_created); 195 if (result != NULL && was_created) { 196 /* add conditional node to policy list */ 197 result->next = p->cond_list; 198 p->cond_list = result; 199 } 200 return result; 201} 202 203/* 204 * cond_evaluate_expr evaluates a conditional expr 205 * in reverse polish notation. It returns true (1), false (0), 206 * or undefined (-1). Undefined occurs when the expression 207 * exceeds the stack depth of COND_EXPR_MAXDEPTH. 208 */ 209int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr) 210{ 211 212 cond_expr_t *cur; 213 int s[COND_EXPR_MAXDEPTH]; 214 int sp = -1; 215 216 s[0] = -1; 217 218 for (cur = expr; cur != NULL; cur = cur->next) { 219 switch (cur->expr_type) { 220 case COND_BOOL: 221 if (sp == (COND_EXPR_MAXDEPTH - 1)) 222 return -1; 223 sp++; 224 s[sp] = p->bool_val_to_struct[cur->bool - 1]->state; 225 break; 226 case COND_NOT: 227 if (sp < 0) 228 return -1; 229 s[sp] = !s[sp]; 230 break; 231 case COND_OR: 232 if (sp < 1) 233 return -1; 234 sp--; 235 s[sp] |= s[sp + 1]; 236 break; 237 case COND_AND: 238 if (sp < 1) 239 return -1; 240 sp--; 241 s[sp] &= s[sp + 1]; 242 break; 243 case COND_XOR: 244 if (sp < 1) 245 return -1; 246 sp--; 247 s[sp] ^= s[sp + 1]; 248 break; 249 case COND_EQ: 250 if (sp < 1) 251 return -1; 252 sp--; 253 s[sp] = (s[sp] == s[sp + 1]); 254 break; 255 case COND_NEQ: 256 if (sp < 1) 257 return -1; 258 sp--; 259 s[sp] = (s[sp] != s[sp + 1]); 260 break; 261 default: 262 return -1; 263 } 264 } 265 return s[0]; 266} 267 268cond_expr_t *cond_copy_expr(cond_expr_t * expr) 269{ 270 cond_expr_t *cur, *head, *tail, *new_expr; 271 tail = head = NULL; 272 cur = expr; 273 while (cur) { 274 new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t)); 275 if (!new_expr) 276 goto free_head; 277 memset(new_expr, 0, sizeof(cond_expr_t)); 278 279 new_expr->expr_type = cur->expr_type; 280 new_expr->bool = cur->bool; 281 282 if (!head) 283 head = new_expr; 284 if (tail) 285 tail->next = new_expr; 286 tail = new_expr; 287 cur = cur->next; 288 } 289 return head; 290 291 free_head: 292 while (head) { 293 tail = head->next; 294 free(head); 295 head = tail; 296 } 297 return NULL; 298} 299 300/* 301 * evaluate_cond_node evaluates the conditional stored in 302 * a cond_node_t and if the result is different than the 303 * current state of the node it sets the rules in the true/false 304 * list appropriately. If the result of the expression is undefined 305 * all of the rules are disabled for safety. 306 */ 307static int evaluate_cond_node(policydb_t * p, cond_node_t * node) 308{ 309 int new_state; 310 cond_av_list_t *cur; 311 312 new_state = cond_evaluate_expr(p, node->expr); 313 if (new_state != node->cur_state) { 314 node->cur_state = new_state; 315 if (new_state == -1) 316 printf 317 ("expression result was undefined - disabling all rules.\n"); 318 /* turn the rules on or off */ 319 for (cur = node->true_list; cur != NULL; cur = cur->next) { 320 if (new_state <= 0) { 321 cur->node->key.specified &= ~AVTAB_ENABLED; 322 } else { 323 cur->node->key.specified |= AVTAB_ENABLED; 324 } 325 } 326 327 for (cur = node->false_list; cur != NULL; cur = cur->next) { 328 /* -1 or 1 */ 329 if (new_state) { 330 cur->node->key.specified &= ~AVTAB_ENABLED; 331 } else { 332 cur->node->key.specified |= AVTAB_ENABLED; 333 } 334 } 335 } 336 return 0; 337} 338 339/* precompute and simplify an expression if possible. If left with !expression, change 340 * to expression and switch t and f. precompute expression for expressions with limited 341 * number of bools. 342 */ 343int cond_normalize_expr(policydb_t * p, cond_node_t * cn) 344{ 345 cond_expr_t *ne, *e; 346 cond_av_list_t *tmp; 347 unsigned int i, j, orig_value[COND_MAX_BOOLS]; 348 int k; 349 uint32_t test = 0x0; 350 avrule_t *tmp2; 351 352 cn->nbools = 0; 353 354 memset(cn->bool_ids, 0, sizeof(cn->bool_ids)); 355 cn->expr_pre_comp = 0x0; 356 357 /* take care of !expr case */ 358 ne = NULL; 359 e = cn->expr; 360 361 /* becuase it's RPN look at last element */ 362 while (e->next != NULL) { 363 ne = e; 364 e = e->next; 365 } 366 if (e->expr_type == COND_NOT) { 367 if (ne) { 368 ne->next = NULL; 369 } else { /* ne should never be NULL */ 370 printf 371 ("Found expr with no bools and only a ! - this should never happen.\n"); 372 return -1; 373 } 374 /* swap the true and false lists */ 375 tmp = cn->true_list; 376 cn->true_list = cn->false_list; 377 cn->false_list = tmp; 378 tmp2 = cn->avtrue_list; 379 cn->avtrue_list = cn->avfalse_list; 380 cn->avfalse_list = tmp2; 381 382 /* free the "not" node in the list */ 383 free(e); 384 } 385 386 /* find all the bools in the expression */ 387 for (e = cn->expr; e != NULL; e = e->next) { 388 switch (e->expr_type) { 389 case COND_BOOL: 390 i = 0; 391 /* see if we've already seen this bool */ 392 if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) { 393 /* count em all but only record up to COND_MAX_BOOLS */ 394 if (cn->nbools < COND_MAX_BOOLS) 395 cn->bool_ids[cn->nbools++] = e->bool; 396 else 397 cn->nbools++; 398 } 399 break; 400 default: 401 break; 402 } 403 } 404 405 /* only precompute for exprs with <= COND_AX_BOOLS */ 406 if (cn->nbools <= COND_MAX_BOOLS) { 407 /* save the default values for the bools so we can play with them */ 408 for (i = 0; i < cn->nbools; i++) { 409 orig_value[i] = 410 p->bool_val_to_struct[cn->bool_ids[i] - 1]->state; 411 } 412 413 /* loop through all possible combinations of values for bools in expression */ 414 for (test = 0x0; test < (0x1U << cn->nbools); test++) { 415 /* temporarily set the value for all the bools in the 416 * expression using the corr. bit in test */ 417 for (j = 0; j < cn->nbools; j++) { 418 p->bool_val_to_struct[cn->bool_ids[j] - 419 1]->state = 420 (test & (0x1 << j)) ? 1 : 0; 421 } 422 k = cond_evaluate_expr(p, cn->expr); 423 if (k == -1) { 424 printf 425 ("While testing expression, expression result " 426 "was undefined - this should never happen.\n"); 427 return -1; 428 } 429 /* set the bit if expression evaluates true */ 430 if (k) 431 cn->expr_pre_comp |= 0x1 << test; 432 } 433 434 /* restore bool default values */ 435 for (i = 0; i < cn->nbools; i++) 436 p->bool_val_to_struct[cn->bool_ids[i] - 1]->state = 437 orig_value[i]; 438 } 439 return 0; 440} 441 442int evaluate_conds(policydb_t * p) 443{ 444 int ret; 445 cond_node_t *cur; 446 447 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 448 ret = evaluate_cond_node(p, cur); 449 if (ret) 450 return ret; 451 } 452 return 0; 453} 454 455int cond_policydb_init(policydb_t * p) 456{ 457 p->bool_val_to_struct = NULL; 458 p->cond_list = NULL; 459 if (avtab_init(&p->te_cond_avtab)) 460 return -1; 461 462 return 0; 463} 464 465void cond_av_list_destroy(cond_av_list_t * list) 466{ 467 cond_av_list_t *cur, *next; 468 for (cur = list; cur != NULL; cur = next) { 469 next = cur->next; 470 /* the avtab_ptr_t node is destroy by the avtab */ 471 free(cur); 472 } 473} 474 475void cond_expr_destroy(cond_expr_t * expr) 476{ 477 cond_expr_t *cur_expr, *next_expr; 478 479 if (!expr) 480 return; 481 482 for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) { 483 next_expr = cur_expr->next; 484 free(cur_expr); 485 } 486} 487 488void cond_node_destroy(cond_node_t * node) 489{ 490 if (!node) 491 return; 492 493 cond_expr_destroy(node->expr); 494 avrule_list_destroy(node->avtrue_list); 495 avrule_list_destroy(node->avfalse_list); 496 cond_av_list_destroy(node->true_list); 497 cond_av_list_destroy(node->false_list); 498} 499 500void cond_list_destroy(cond_list_t * list) 501{ 502 cond_node_t *next, *cur; 503 504 if (list == NULL) 505 return; 506 507 for (cur = list; cur != NULL; cur = next) { 508 next = cur->next; 509 cond_node_destroy(cur); 510 free(cur); 511 } 512} 513 514void cond_policydb_destroy(policydb_t * p) 515{ 516 if (p->bool_val_to_struct != NULL) 517 free(p->bool_val_to_struct); 518 avtab_destroy(&p->te_cond_avtab); 519 cond_list_destroy(p->cond_list); 520} 521 522int cond_init_bool_indexes(policydb_t * p) 523{ 524 if (p->bool_val_to_struct) 525 free(p->bool_val_to_struct); 526 p->bool_val_to_struct = (cond_bool_datum_t **) 527 malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *)); 528 if (!p->bool_val_to_struct) 529 return -1; 530 return 0; 531} 532 533int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p 534 __attribute__ ((unused))) 535{ 536 if (key) 537 free(key); 538 free(datum); 539 return 0; 540} 541 542int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap) 543{ 544 policydb_t *p; 545 cond_bool_datum_t *booldatum; 546 547 booldatum = datum; 548 p = datap; 549 550 if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim) 551 return -EINVAL; 552 553 p->p_bool_val_to_name[booldatum->s.value - 1] = key; 554 p->bool_val_to_struct[booldatum->s.value - 1] = booldatum; 555 556 return 0; 557} 558 559static int bool_isvalid(cond_bool_datum_t * b) 560{ 561 if (!(b->state == 0 || b->state == 1)) 562 return 0; 563 return 1; 564} 565 566int cond_read_bool(policydb_t * p 567 __attribute__ ((unused)), hashtab_t h, 568 struct policy_file *fp) 569{ 570 char *key = 0; 571 cond_bool_datum_t *booldatum; 572 uint32_t buf[3], len; 573 int rc; 574 575 booldatum = malloc(sizeof(cond_bool_datum_t)); 576 if (!booldatum) 577 return -1; 578 memset(booldatum, 0, sizeof(cond_bool_datum_t)); 579 580 rc = next_entry(buf, fp, sizeof(uint32_t) * 3); 581 if (rc < 0) 582 goto err; 583 584 booldatum->s.value = le32_to_cpu(buf[0]); 585 booldatum->state = le32_to_cpu(buf[1]); 586 587 if (!bool_isvalid(booldatum)) 588 goto err; 589 590 len = le32_to_cpu(buf[2]); 591 592 key = malloc(len + 1); 593 if (!key) 594 goto err; 595 rc = next_entry(key, fp, len); 596 if (rc < 0) 597 goto err; 598 key[len] = 0; 599 if (hashtab_insert(h, key, booldatum)) 600 goto err; 601 602 return 0; 603 err: 604 cond_destroy_bool(key, booldatum, 0); 605 return -1; 606} 607 608struct cond_insertf_data { 609 struct policydb *p; 610 cond_av_list_t *other; 611 cond_av_list_t *head; 612 cond_av_list_t *tail; 613}; 614 615static int cond_insertf(avtab_t * a 616 __attribute__ ((unused)), avtab_key_t * k, 617 avtab_datum_t * d, void *ptr) 618{ 619 struct cond_insertf_data *data = ptr; 620 struct policydb *p = data->p; 621 cond_av_list_t *other = data->other, *list, *cur; 622 avtab_ptr_t node_ptr; 623 uint8_t found; 624 625 /* 626 * For type rules we have to make certain there aren't any 627 * conflicting rules by searching the te_avtab and the 628 * cond_te_avtab. 629 */ 630 if (k->specified & AVTAB_TYPE) { 631 if (avtab_search(&p->te_avtab, k)) { 632 printf 633 ("security: type rule already exists outside of a conditional."); 634 goto err; 635 } 636 /* 637 * If we are reading the false list other will be a pointer to 638 * the true list. We can have duplicate entries if there is only 639 * 1 other entry and it is in our true list. 640 * 641 * If we are reading the true list (other == NULL) there shouldn't 642 * be any other entries. 643 */ 644 if (other) { 645 node_ptr = avtab_search_node(&p->te_cond_avtab, k); 646 if (node_ptr) { 647 if (avtab_search_node_next 648 (node_ptr, k->specified)) { 649 printf 650 ("security: too many conflicting type rules."); 651 goto err; 652 } 653 found = 0; 654 for (cur = other; cur != NULL; cur = cur->next) { 655 if (cur->node == node_ptr) { 656 found = 1; 657 break; 658 } 659 } 660 if (!found) { 661 printf 662 ("security: conflicting type rules.\n"); 663 goto err; 664 } 665 } 666 } else { 667 if (avtab_search(&p->te_cond_avtab, k)) { 668 printf 669 ("security: conflicting type rules when adding type rule for true.\n"); 670 goto err; 671 } 672 } 673 } 674 675 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); 676 if (!node_ptr) { 677 printf("security: could not insert rule."); 678 goto err; 679 } 680 node_ptr->parse_context = (void *)1; 681 682 list = malloc(sizeof(cond_av_list_t)); 683 if (!list) 684 goto err; 685 memset(list, 0, sizeof(cond_av_list_t)); 686 687 list->node = node_ptr; 688 if (!data->head) 689 data->head = list; 690 else 691 data->tail->next = list; 692 data->tail = list; 693 return 0; 694 695 err: 696 cond_av_list_destroy(data->head); 697 data->head = NULL; 698 return -1; 699} 700 701static int cond_read_av_list(policydb_t * p, void *fp, 702 cond_av_list_t ** ret_list, cond_av_list_t * other) 703{ 704 unsigned int i; 705 int rc; 706 uint32_t buf[1], len; 707 struct cond_insertf_data data; 708 709 *ret_list = NULL; 710 711 len = 0; 712 rc = next_entry(buf, fp, sizeof(uint32_t)); 713 if (rc < 0) 714 return -1; 715 716 len = le32_to_cpu(buf[0]); 717 if (len == 0) { 718 return 0; 719 } 720 721 data.p = p; 722 data.other = other; 723 data.head = NULL; 724 data.tail = NULL; 725 for (i = 0; i < len; i++) { 726 rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, 727 cond_insertf, &data); 728 if (rc) 729 return rc; 730 731 } 732 733 *ret_list = data.head; 734 return 0; 735} 736 737static int expr_isvalid(policydb_t * p, cond_expr_t * expr) 738{ 739 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { 740 printf 741 ("security: conditional expressions uses unknown operator.\n"); 742 return 0; 743 } 744 745 if (expr->bool > p->p_bools.nprim) { 746 printf 747 ("security: conditional expressions uses unknown bool.\n"); 748 return 0; 749 } 750 return 1; 751} 752 753static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) 754{ 755 uint32_t buf[2]; 756 int len, i, rc; 757 cond_expr_t *expr = NULL, *last = NULL; 758 759 rc = next_entry(buf, fp, sizeof(uint32_t)); 760 if (rc < 0) 761 goto err; 762 763 node->cur_state = le32_to_cpu(buf[0]); 764 765 len = 0; 766 rc = next_entry(buf, fp, sizeof(uint32_t)); 767 if (rc < 0) 768 goto err; 769 770 /* expr */ 771 len = le32_to_cpu(buf[0]); 772 773 for (i = 0; i < len; i++) { 774 rc = next_entry(buf, fp, sizeof(uint32_t) * 2); 775 if (rc < 0) 776 goto err; 777 778 expr = malloc(sizeof(cond_expr_t)); 779 if (!expr) { 780 goto err; 781 } 782 memset(expr, 0, sizeof(cond_expr_t)); 783 784 expr->expr_type = le32_to_cpu(buf[0]); 785 expr->bool = le32_to_cpu(buf[1]); 786 787 if (!expr_isvalid(p, expr)) { 788 free(expr); 789 goto err; 790 } 791 792 if (i == 0) { 793 node->expr = expr; 794 } else { 795 last->next = expr; 796 } 797 last = expr; 798 } 799 800 if (p->policy_type == POLICY_KERN) { 801 if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) 802 goto err; 803 if (cond_read_av_list(p, fp, &node->false_list, node->true_list) 804 != 0) 805 goto err; 806 } else { 807 if (avrule_read_list(p, &node->avtrue_list, fp)) 808 goto err; 809 if (avrule_read_list(p, &node->avfalse_list, fp)) 810 goto err; 811 } 812 813 return 0; 814 err: 815 cond_node_destroy(node); 816 free(node); 817 return -1; 818} 819 820int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) 821{ 822 cond_node_t *node, *last = NULL; 823 uint32_t buf[1]; 824 int i, len, rc; 825 826 rc = next_entry(buf, fp, sizeof(uint32_t)); 827 if (rc < 0) 828 return -1; 829 830 len = le32_to_cpu(buf[0]); 831 832 rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel); 833 if (rc) 834 goto err; 835 836 for (i = 0; i < len; i++) { 837 node = malloc(sizeof(cond_node_t)); 838 if (!node) 839 goto err; 840 memset(node, 0, sizeof(cond_node_t)); 841 842 if (cond_read_node(p, node, fp) != 0) 843 goto err; 844 845 if (i == 0) { 846 *list = node; 847 } else { 848 last->next = node; 849 } 850 last = node; 851 } 852 return 0; 853 err: 854 return -1; 855} 856 857/* Determine whether additional permissions are granted by the conditional 858 * av table, and if so, add them to the result 859 */ 860void cond_compute_av(avtab_t * ctab, avtab_key_t * key, 861 struct sepol_av_decision *avd) 862{ 863 avtab_ptr_t node; 864 865 if (!ctab || !key || !avd) 866 return; 867 868 for (node = avtab_search_node(ctab, key); node != NULL; 869 node = avtab_search_node_next(node, key->specified)) { 870 if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) == 871 (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED))) 872 avd->allowed |= node->datum.data; 873 if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) == 874 (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) 875 /* Since a '0' in an auditdeny mask represents a 876 * permission we do NOT want to audit (dontaudit), we use 877 * the '&' operand to ensure that all '0's in the mask 878 * are retained (much unlike the allow and auditallow cases). 879 */ 880 avd->auditdeny &= node->datum.data; 881 if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) == 882 (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED))) 883 avd->auditallow |= node->datum.data; 884 } 885 return; 886} 887 888avtab_datum_t *cond_av_list_search(avtab_key_t * key, 889 cond_av_list_t * cond_list) 890{ 891 892 cond_av_list_t *cur_av; 893 894 for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) { 895 896 if (cur_av->node->key.source_type == key->source_type && 897 cur_av->node->key.target_type == key->target_type && 898 cur_av->node->key.target_class == key->target_class) 899 900 return &cur_av->node->datum; 901 902 } 903 return NULL; 904 905} 906