• 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 #include "debug.h"
29 
30 /* move all type rules to top of t/f lists to help kernel on evaluation */
cond_optimize(cond_av_list_t ** l)31 static 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 */
cond_optimize_lists(cond_list_t * cl)52 void 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 
bool_present(unsigned int target,unsigned int bools[],unsigned int num_bools)62 static 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 
same_bools(cond_node_t * a,cond_node_t * b)78 static 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  */
cond_expr_equal(cond_node_t * a,cond_node_t * b)98 int 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  */
cond_node_create(policydb_t * p,cond_node_t * node)142 cond_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. */
cond_node_find(policydb_t * p,cond_node_t * needle,cond_node_t * haystack,int * was_created)175 cond_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 */
cond_node_search(policydb_t * p,cond_node_t * list,cond_node_t * cn)192 cond_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  */
cond_evaluate_expr(policydb_t * p,cond_expr_t * expr)211 int 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 
cond_copy_expr(cond_expr_t * expr)270 cond_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  */
evaluate_cond_node(policydb_t * p,cond_node_t * node)309 static 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  */
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 	/* 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 
evaluate_conds(policydb_t * p)440 int 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 
cond_policydb_init(policydb_t * p)453 int 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 
cond_av_list_destroy(cond_av_list_t * list)463 void 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 
cond_expr_destroy(cond_expr_t * expr)473 void 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 
cond_node_destroy(cond_node_t * node)486 void 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 
cond_list_destroy(cond_list_t * list)498 void 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 
cond_policydb_destroy(policydb_t * p)512 void 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 
cond_init_bool_indexes(policydb_t * p)520 int 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 
cond_destroy_bool(hashtab_key_t key,hashtab_datum_t datum,void * p)531 int 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 
cond_index_bool(hashtab_key_t key,hashtab_datum_t datum,void * datap)540 int 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 
bool_isvalid(cond_bool_datum_t * b)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 
cond_read_bool(policydb_t * p,hashtab_t h,struct policy_file * fp)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 	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 
612 struct 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 
cond_insertf(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * ptr)619 static 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 
cond_read_av_list(policydb_t * p,void * fp,cond_av_list_t ** ret_list,cond_av_list_t * other)696 static 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 
expr_isvalid(policydb_t * p,cond_expr_t * expr)733 static 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 
cond_read_node(policydb_t * p,cond_node_t * node,void * fp)747 static 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 
cond_read_list(policydb_t * p,cond_list_t ** list,void * fp)821 int 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  */
cond_compute_av(avtab_t * ctab,avtab_key_t * key,struct sepol_av_decision * avd)861 void 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 
cond_av_list_search(avtab_key_t * key,cond_av_list_t * cond_list)889 avtab_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