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