• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
cond_optimize(cond_av_list_t ** l)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 */
cond_optimize_lists(cond_list_t * cl)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 
bool_present(unsigned int target,unsigned int bools[],unsigned int num_bools)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 
same_bools(cond_node_t * a,cond_node_t * b)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  */
cond_expr_equal(cond_node_t * a,cond_node_t * b)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  */
cond_node_create(policydb_t * p,cond_node_t * node)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. */
cond_node_find(policydb_t * p,cond_node_t * needle,cond_node_t * haystack,int * was_created)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 */
cond_node_search(policydb_t * p,cond_node_t * list,cond_node_t * cn)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  */
cond_evaluate_expr(policydb_t * p,cond_expr_t * expr)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 
cond_copy_expr(cond_expr_t * expr)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  */
evaluate_cond_node(policydb_t * p,cond_node_t * node)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  */
cond_normalize_expr(policydb_t * p,cond_node_t * cn)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 
evaluate_conds(policydb_t * p)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 
cond_policydb_init(policydb_t * p)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 
cond_av_list_destroy(cond_av_list_t * list)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 
cond_expr_destroy(cond_expr_t * expr)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 
cond_node_destroy(cond_node_t * node)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 
cond_list_destroy(cond_list_t * list)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 
cond_policydb_destroy(policydb_t * p)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 
cond_init_bool_indexes(policydb_t * p)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 
cond_destroy_bool(hashtab_key_t key,hashtab_datum_t datum,void * p)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 
cond_index_bool(hashtab_key_t key,hashtab_datum_t datum,void * datap)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 
bool_isvalid(cond_bool_datum_t * b)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 
cond_read_bool(policydb_t * p,hashtab_t h,struct policy_file * fp)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 
cond_insertf(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * ptr)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 
cond_read_av_list(policydb_t * p,void * fp,cond_av_list_t ** ret_list,cond_av_list_t * other)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 
expr_isvalid(policydb_t * p,cond_expr_t * expr)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 
cond_read_node(policydb_t * p,cond_node_t * node,void * fp)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 
cond_read_list(policydb_t * p,cond_list_t ** list,void * fp)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  */
cond_compute_av(avtab_t * ctab,avtab_key_t * key,struct sepol_av_decision * avd)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 
cond_av_list_search(avtab_key_t * key,cond_av_list_t * cond_list)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