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 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. */ 174cond_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 */ 191cond_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 */ 210int 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 269cond_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 */ 308static 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 */ 344int 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 443int 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 456int 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 466void 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 476void 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 489void 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 501void 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 515void 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 523int 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 534int 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 543int 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 if (p->p_bool_val_to_name[booldatum->s.value - 1] != NULL) 555 return -EINVAL; 556 557 p->p_bool_val_to_name[booldatum->s.value - 1] = key; 558 p->bool_val_to_struct[booldatum->s.value - 1] = booldatum; 559 560 return 0; 561} 562 563static int bool_isvalid(cond_bool_datum_t * b) 564{ 565 if (!(b->state == 0 || b->state == 1)) 566 return 0; 567 return 1; 568} 569 570int cond_read_bool(policydb_t * p, 571 hashtab_t h, 572 struct policy_file *fp) 573{ 574 char *key = 0; 575 cond_bool_datum_t *booldatum; 576 uint32_t buf[3], len; 577 int rc; 578 579 booldatum = malloc(sizeof(cond_bool_datum_t)); 580 if (!booldatum) 581 return -1; 582 memset(booldatum, 0, sizeof(cond_bool_datum_t)); 583 584 rc = next_entry(buf, fp, sizeof(uint32_t) * 3); 585 if (rc < 0) 586 goto err; 587 588 booldatum->s.value = le32_to_cpu(buf[0]); 589 booldatum->state = le32_to_cpu(buf[1]); 590 591 if (!bool_isvalid(booldatum)) 592 goto err; 593 594 len = le32_to_cpu(buf[2]); 595 if (str_read(&key, fp, len)) 596 goto err; 597 598 if (p->policy_type != POLICY_KERN && 599 p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { 600 rc = next_entry(buf, fp, sizeof(uint32_t)); 601 if (rc < 0) 602 goto err; 603 booldatum->flags = le32_to_cpu(buf[0]); 604 } 605 606 if (hashtab_insert(h, key, booldatum)) 607 goto err; 608 609 return 0; 610 err: 611 cond_destroy_bool(key, booldatum, 0); 612 return -1; 613} 614 615struct cond_insertf_data { 616 struct policydb *p; 617 cond_av_list_t *other; 618 cond_av_list_t *head; 619 cond_av_list_t *tail; 620}; 621 622static int cond_insertf(avtab_t * a 623 __attribute__ ((unused)), avtab_key_t * k, 624 avtab_datum_t * d, void *ptr) 625{ 626 struct cond_insertf_data *data = ptr; 627 struct policydb *p = data->p; 628 cond_av_list_t *other = data->other, *list, *cur; 629 avtab_ptr_t node_ptr; 630 uint8_t found; 631 632 /* 633 * For type rules we have to make certain there aren't any 634 * conflicting rules by searching the te_avtab and the 635 * cond_te_avtab. 636 */ 637 if (k->specified & AVTAB_TYPE) { 638 if (avtab_search(&p->te_avtab, k)) { 639 printf 640 ("security: type rule already exists outside of a conditional."); 641 goto err; 642 } 643 /* 644 * If we are reading the false list other will be a pointer to 645 * the true list. We can have duplicate entries if there is only 646 * 1 other entry and it is in our true list. 647 * 648 * If we are reading the true list (other == NULL) there shouldn't 649 * be any other entries. 650 */ 651 if (other) { 652 node_ptr = avtab_search_node(&p->te_cond_avtab, k); 653 if (node_ptr) { 654 if (avtab_search_node_next 655 (node_ptr, k->specified)) { 656 printf 657 ("security: too many conflicting type rules."); 658 goto err; 659 } 660 found = 0; 661 for (cur = other; cur != NULL; cur = cur->next) { 662 if (cur->node == node_ptr) { 663 found = 1; 664 break; 665 } 666 } 667 if (!found) { 668 printf 669 ("security: conflicting type rules.\n"); 670 goto err; 671 } 672 } 673 } else { 674 if (avtab_search(&p->te_cond_avtab, k)) { 675 printf 676 ("security: conflicting type rules when adding type rule for true.\n"); 677 goto err; 678 } 679 } 680 } 681 682 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); 683 if (!node_ptr) { 684 printf("security: could not insert rule."); 685 goto err; 686 } 687 node_ptr->parse_context = (void *)1; 688 689 list = malloc(sizeof(cond_av_list_t)); 690 if (!list) 691 goto err; 692 memset(list, 0, sizeof(cond_av_list_t)); 693 694 list->node = node_ptr; 695 if (!data->head) 696 data->head = list; 697 else 698 data->tail->next = list; 699 data->tail = list; 700 return 0; 701 702 err: 703 cond_av_list_destroy(data->head); 704 data->head = NULL; 705 return -1; 706} 707 708static int cond_read_av_list(policydb_t * p, void *fp, 709 cond_av_list_t ** ret_list, cond_av_list_t * other) 710{ 711 unsigned int i; 712 int rc; 713 uint32_t buf[1], len; 714 struct cond_insertf_data data; 715 716 *ret_list = NULL; 717 718 len = 0; 719 rc = next_entry(buf, fp, sizeof(uint32_t)); 720 if (rc < 0) 721 return -1; 722 723 len = le32_to_cpu(buf[0]); 724 if (len == 0) { 725 return 0; 726 } 727 728 data.p = p; 729 data.other = other; 730 data.head = NULL; 731 data.tail = NULL; 732 for (i = 0; i < len; i++) { 733 rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, 734 cond_insertf, &data); 735 if (rc) 736 return rc; 737 738 } 739 740 *ret_list = data.head; 741 return 0; 742} 743 744static int expr_isvalid(policydb_t * p, cond_expr_t * expr) 745{ 746 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { 747 printf 748 ("security: conditional expressions uses unknown operator.\n"); 749 return 0; 750 } 751 752 if (expr->bool > p->p_bools.nprim) { 753 printf 754 ("security: conditional expressions uses unknown bool.\n"); 755 return 0; 756 } 757 return 1; 758} 759 760static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) 761{ 762 uint32_t buf[2]; 763 int len, i, rc; 764 cond_expr_t *expr = NULL, *last = NULL; 765 766 rc = next_entry(buf, fp, sizeof(uint32_t)); 767 if (rc < 0) 768 goto err; 769 770 node->cur_state = le32_to_cpu(buf[0]); 771 772 len = 0; 773 rc = next_entry(buf, fp, sizeof(uint32_t)); 774 if (rc < 0) 775 goto err; 776 777 /* expr */ 778 len = le32_to_cpu(buf[0]); 779 780 for (i = 0; i < len; i++) { 781 rc = next_entry(buf, fp, sizeof(uint32_t) * 2); 782 if (rc < 0) 783 goto err; 784 785 expr = malloc(sizeof(cond_expr_t)); 786 if (!expr) { 787 goto err; 788 } 789 memset(expr, 0, sizeof(cond_expr_t)); 790 791 expr->expr_type = le32_to_cpu(buf[0]); 792 expr->bool = le32_to_cpu(buf[1]); 793 794 if (!expr_isvalid(p, expr)) { 795 free(expr); 796 goto err; 797 } 798 799 if (i == 0) { 800 node->expr = expr; 801 } else { 802 last->next = expr; 803 } 804 last = expr; 805 } 806 807 if (p->policy_type == POLICY_KERN) { 808 if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) 809 goto err; 810 if (cond_read_av_list(p, fp, &node->false_list, node->true_list) 811 != 0) 812 goto err; 813 } else { 814 if (avrule_read_list(p, &node->avtrue_list, fp)) 815 goto err; 816 if (avrule_read_list(p, &node->avfalse_list, fp)) 817 goto err; 818 } 819 820 if (p->policy_type != POLICY_KERN && 821 p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { 822 rc = next_entry(buf, fp, sizeof(uint32_t)); 823 if (rc < 0) 824 goto err; 825 node->flags = le32_to_cpu(buf[0]); 826 } 827 828 return 0; 829 err: 830 cond_node_destroy(node); 831 free(node); 832 return -1; 833} 834 835int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) 836{ 837 cond_node_t *node, *last = NULL; 838 uint32_t buf[1]; 839 int i, len, rc; 840 841 rc = next_entry(buf, fp, sizeof(uint32_t)); 842 if (rc < 0) 843 return -1; 844 845 len = le32_to_cpu(buf[0]); 846 847 rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel); 848 if (rc) 849 goto err; 850 851 for (i = 0; i < len; i++) { 852 node = malloc(sizeof(cond_node_t)); 853 if (!node) 854 goto err; 855 memset(node, 0, sizeof(cond_node_t)); 856 857 if (cond_read_node(p, node, fp) != 0) 858 goto err; 859 860 if (i == 0) { 861 *list = node; 862 } else { 863 last->next = node; 864 } 865 last = node; 866 } 867 return 0; 868 err: 869 return -1; 870} 871 872/* Determine whether additional permissions are granted by the conditional 873 * av table, and if so, add them to the result 874 */ 875void cond_compute_av(avtab_t * ctab, avtab_key_t * key, 876 struct sepol_av_decision *avd) 877{ 878 avtab_ptr_t node; 879 880 if (!ctab || !key || !avd) 881 return; 882 883 for (node = avtab_search_node(ctab, key); node != NULL; 884 node = avtab_search_node_next(node, key->specified)) { 885 if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) == 886 (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED))) 887 avd->allowed |= node->datum.data; 888 if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) == 889 (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) 890 /* Since a '0' in an auditdeny mask represents a 891 * permission we do NOT want to audit (dontaudit), we use 892 * the '&' operand to ensure that all '0's in the mask 893 * are retained (much unlike the allow and auditallow cases). 894 */ 895 avd->auditdeny &= node->datum.data; 896 if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) == 897 (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED))) 898 avd->auditallow |= node->datum.data; 899 } 900 return; 901} 902 903avtab_datum_t *cond_av_list_search(avtab_key_t * key, 904 cond_av_list_t * cond_list) 905{ 906 907 cond_av_list_t *cur_av; 908 909 for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) { 910 911 if (cur_av->node->key.source_type == key->source_type && 912 cur_av->node->key.target_type == key->target_type && 913 cur_av->node->key.target_class == key->target_class) 914 915 return &cur_av->node->datum; 916 917 } 918 return NULL; 919 920} 921