Home | History | Annotate | Download | only in src
      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 	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 
    563 static 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 
    570 int 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 
    615 struct 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 
    622 static 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 
    708 static 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 
    744 static 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 
    760 static 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 
    835 int 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  */
    875 void 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 
    903 avtab_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