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