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 	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