conditional.c revision 255e72915d4cbddceb435e13d81601755714e9f3
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 */
30static 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 */
51void 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
61static 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
77static 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 */
97int 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 */
141cond_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	}
164
165	return new_node;
166}
167
168/* Find a conditional (the needle) within a list of existing ones (the
169 * haystack) that has a matching expression.  If found, return a
170 * pointer to the existing node, setting 'was_created' to 0.
171 * Otherwise create a new one and return it, setting 'was_created' to
172 * 1. */
173cond_node_t *cond_node_find(policydb_t * p,
174			    cond_node_t * needle, cond_node_t * haystack,
175			    int *was_created)
176{
177	while (haystack) {
178		if (cond_expr_equal(needle, haystack)) {
179			*was_created = 0;
180			return haystack;
181		}
182		haystack = haystack->next;
183	}
184	*was_created = 1;
185
186	return cond_node_create(p, needle);
187}
188
189/* return either a pre-existing matching node or create a new node */
190cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list,
191			      cond_node_t * cn)
192{
193	int was_created;
194	cond_node_t *result = cond_node_find(p, cn, list, &was_created);
195	if (result != NULL && was_created) {
196		/* add conditional node to policy list */
197		result->next = p->cond_list;
198		p->cond_list = result;
199	}
200	return result;
201}
202
203/*
204 * cond_evaluate_expr evaluates a conditional expr
205 * in reverse polish notation. It returns true (1), false (0),
206 * or undefined (-1). Undefined occurs when the expression
207 * exceeds the stack depth of COND_EXPR_MAXDEPTH.
208 */
209int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr)
210{
211
212	cond_expr_t *cur;
213	int s[COND_EXPR_MAXDEPTH];
214	int sp = -1;
215
216	s[0] = -1;
217
218	for (cur = expr; cur != NULL; cur = cur->next) {
219		switch (cur->expr_type) {
220		case COND_BOOL:
221			if (sp == (COND_EXPR_MAXDEPTH - 1))
222				return -1;
223			sp++;
224			s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
225			break;
226		case COND_NOT:
227			if (sp < 0)
228				return -1;
229			s[sp] = !s[sp];
230			break;
231		case COND_OR:
232			if (sp < 1)
233				return -1;
234			sp--;
235			s[sp] |= s[sp + 1];
236			break;
237		case COND_AND:
238			if (sp < 1)
239				return -1;
240			sp--;
241			s[sp] &= s[sp + 1];
242			break;
243		case COND_XOR:
244			if (sp < 1)
245				return -1;
246			sp--;
247			s[sp] ^= s[sp + 1];
248			break;
249		case COND_EQ:
250			if (sp < 1)
251				return -1;
252			sp--;
253			s[sp] = (s[sp] == s[sp + 1]);
254			break;
255		case COND_NEQ:
256			if (sp < 1)
257				return -1;
258			sp--;
259			s[sp] = (s[sp] != s[sp + 1]);
260			break;
261		default:
262			return -1;
263		}
264	}
265	return s[0];
266}
267
268cond_expr_t *cond_copy_expr(cond_expr_t * expr)
269{
270	cond_expr_t *cur, *head, *tail, *new_expr;
271	tail = head = NULL;
272	cur = expr;
273	while (cur) {
274		new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t));
275		if (!new_expr)
276			goto free_head;
277		memset(new_expr, 0, sizeof(cond_expr_t));
278
279		new_expr->expr_type = cur->expr_type;
280		new_expr->bool = cur->bool;
281
282		if (!head)
283			head = new_expr;
284		if (tail)
285			tail->next = new_expr;
286		tail = new_expr;
287		cur = cur->next;
288	}
289	return head;
290
291      free_head:
292	while (head) {
293		tail = head->next;
294		free(head);
295		head = tail;
296	}
297	return NULL;
298}
299
300/*
301 * evaluate_cond_node evaluates the conditional stored in
302 * a cond_node_t and if the result is different than the
303 * current state of the node it sets the rules in the true/false
304 * list appropriately. If the result of the expression is undefined
305 * all of the rules are disabled for safety.
306 */
307static int evaluate_cond_node(policydb_t * p, cond_node_t * node)
308{
309	int new_state;
310	cond_av_list_t *cur;
311
312	new_state = cond_evaluate_expr(p, node->expr);
313	if (new_state != node->cur_state) {
314		node->cur_state = new_state;
315		if (new_state == -1)
316			printf
317			    ("expression result was undefined - disabling all rules.\n");
318		/* turn the rules on or off */
319		for (cur = node->true_list; cur != NULL; cur = cur->next) {
320			if (new_state <= 0) {
321				cur->node->key.specified &= ~AVTAB_ENABLED;
322			} else {
323				cur->node->key.specified |= AVTAB_ENABLED;
324			}
325		}
326
327		for (cur = node->false_list; cur != NULL; cur = cur->next) {
328			/* -1 or 1 */
329			if (new_state) {
330				cur->node->key.specified &= ~AVTAB_ENABLED;
331			} else {
332				cur->node->key.specified |= AVTAB_ENABLED;
333			}
334		}
335	}
336	return 0;
337}
338
339/* precompute and simplify an expression if possible.  If left with !expression, change
340 * to expression and switch t and f. precompute expression for expressions with limited
341 * number of bools.
342 */
343int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
344{
345	cond_expr_t *ne, *e;
346	cond_av_list_t *tmp;
347	unsigned int i, j, orig_value[COND_MAX_BOOLS];
348	int k;
349	uint32_t test = 0x0;
350	avrule_t *tmp2;
351
352	cn->nbools = 0;
353
354	memset(cn->bool_ids, 0, sizeof(cn->bool_ids));
355	cn->expr_pre_comp = 0x0;
356
357	/* take care of !expr case */
358	ne = NULL;
359	e = cn->expr;
360
361	/* becuase it's RPN look at last element */
362	while (e->next != NULL) {
363		ne = e;
364		e = e->next;
365	}
366	if (e->expr_type == COND_NOT) {
367		if (ne) {
368			ne->next = NULL;
369		} else {	/* ne should never be NULL */
370			printf
371			    ("Found expr with no bools and only a ! - this should never happen.\n");
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			i = 0;
391			/* see if we've already seen this bool */
392			if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
393				/* count em all but only record up to COND_MAX_BOOLS */
394				if (cn->nbools < COND_MAX_BOOLS)
395					cn->bool_ids[cn->nbools++] = e->bool;
396				else
397					cn->nbools++;
398			}
399			break;
400		default:
401			break;
402		}
403	}
404
405	/* only precompute for exprs with <= COND_AX_BOOLS */
406	if (cn->nbools <= COND_MAX_BOOLS) {
407		/* save the default values for the bools so we can play with them */
408		for (i = 0; i < cn->nbools; i++) {
409			orig_value[i] =
410			    p->bool_val_to_struct[cn->bool_ids[i] - 1]->state;
411		}
412
413		/* loop through all possible combinations of values for bools in expression */
414		for (test = 0x0; test < (0x1U << cn->nbools); test++) {
415			/* temporarily set the value for all the bools in the
416			 * expression using the corr.  bit in test */
417			for (j = 0; j < cn->nbools; j++) {
418				p->bool_val_to_struct[cn->bool_ids[j] -
419						      1]->state =
420				    (test & (0x1 << j)) ? 1 : 0;
421			}
422			k = cond_evaluate_expr(p, cn->expr);
423			if (k == -1) {
424				printf
425				    ("While testing expression, expression result "
426				     "was undefined - this should never happen.\n");
427				return -1;
428			}
429			/* set the bit if expression evaluates true */
430			if (k)
431				cn->expr_pre_comp |= 0x1 << test;
432		}
433
434		/* restore bool default values */
435		for (i = 0; i < cn->nbools; i++)
436			p->bool_val_to_struct[cn->bool_ids[i] - 1]->state =
437			    orig_value[i];
438	}
439	return 0;
440}
441
442int evaluate_conds(policydb_t * p)
443{
444	int ret;
445	cond_node_t *cur;
446
447	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
448		ret = evaluate_cond_node(p, cur);
449		if (ret)
450			return ret;
451	}
452	return 0;
453}
454
455int cond_policydb_init(policydb_t * p)
456{
457	p->bool_val_to_struct = NULL;
458	p->cond_list = NULL;
459	if (avtab_init(&p->te_cond_avtab))
460		return -1;
461
462	return 0;
463}
464
465void cond_av_list_destroy(cond_av_list_t * list)
466{
467	cond_av_list_t *cur, *next;
468	for (cur = list; cur != NULL; cur = next) {
469		next = cur->next;
470		/* the avtab_ptr_t node is destroy by the avtab */
471		free(cur);
472	}
473}
474
475void cond_expr_destroy(cond_expr_t * expr)
476{
477	cond_expr_t *cur_expr, *next_expr;
478
479	if (!expr)
480		return;
481
482	for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) {
483		next_expr = cur_expr->next;
484		free(cur_expr);
485	}
486}
487
488void cond_node_destroy(cond_node_t * node)
489{
490	if (!node)
491		return;
492
493	cond_expr_destroy(node->expr);
494	avrule_list_destroy(node->avtrue_list);
495	avrule_list_destroy(node->avfalse_list);
496	cond_av_list_destroy(node->true_list);
497	cond_av_list_destroy(node->false_list);
498}
499
500void cond_list_destroy(cond_list_t * list)
501{
502	cond_node_t *next, *cur;
503
504	if (list == NULL)
505		return;
506
507	for (cur = list; cur != NULL; cur = next) {
508		next = cur->next;
509		cond_node_destroy(cur);
510		free(cur);
511	}
512}
513
514void cond_policydb_destroy(policydb_t * p)
515{
516	if (p->bool_val_to_struct != NULL)
517		free(p->bool_val_to_struct);
518	avtab_destroy(&p->te_cond_avtab);
519	cond_list_destroy(p->cond_list);
520}
521
522int cond_init_bool_indexes(policydb_t * p)
523{
524	if (p->bool_val_to_struct)
525		free(p->bool_val_to_struct);
526	p->bool_val_to_struct = (cond_bool_datum_t **)
527	    malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *));
528	if (!p->bool_val_to_struct)
529		return -1;
530	return 0;
531}
532
533int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p
534		      __attribute__ ((unused)))
535{
536	if (key)
537		free(key);
538	free(datum);
539	return 0;
540}
541
542int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
543{
544	policydb_t *p;
545	cond_bool_datum_t *booldatum;
546
547	booldatum = datum;
548	p = datap;
549
550	if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim)
551		return -EINVAL;
552
553	p->p_bool_val_to_name[booldatum->s.value - 1] = key;
554	p->bool_val_to_struct[booldatum->s.value - 1] = booldatum;
555
556	return 0;
557}
558
559static int bool_isvalid(cond_bool_datum_t * b)
560{
561	if (!(b->state == 0 || b->state == 1))
562		return 0;
563	return 1;
564}
565
566int cond_read_bool(policydb_t * p
567		   __attribute__ ((unused)), hashtab_t h,
568		   struct policy_file *fp)
569{
570	char *key = 0;
571	cond_bool_datum_t *booldatum;
572	uint32_t buf[3], len;
573	int rc;
574
575	booldatum = malloc(sizeof(cond_bool_datum_t));
576	if (!booldatum)
577		return -1;
578	memset(booldatum, 0, sizeof(cond_bool_datum_t));
579
580	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
581	if (rc < 0)
582		goto err;
583
584	booldatum->s.value = le32_to_cpu(buf[0]);
585	booldatum->state = le32_to_cpu(buf[1]);
586
587	if (!bool_isvalid(booldatum))
588		goto err;
589
590	len = le32_to_cpu(buf[2]);
591
592	key = malloc(len + 1);
593	if (!key)
594		goto err;
595	rc = next_entry(key, fp, len);
596	if (rc < 0)
597		goto err;
598	key[len] = 0;
599	if (hashtab_insert(h, key, booldatum))
600		goto err;
601
602	return 0;
603      err:
604	cond_destroy_bool(key, booldatum, 0);
605	return -1;
606}
607
608struct cond_insertf_data {
609	struct policydb *p;
610	cond_av_list_t *other;
611	cond_av_list_t *head;
612	cond_av_list_t *tail;
613};
614
615static int cond_insertf(avtab_t * a
616			__attribute__ ((unused)), avtab_key_t * k,
617			avtab_datum_t * d, void *ptr)
618{
619	struct cond_insertf_data *data = ptr;
620	struct policydb *p = data->p;
621	cond_av_list_t *other = data->other, *list, *cur;
622	avtab_ptr_t node_ptr;
623	uint8_t found;
624
625	/*
626	 * For type rules we have to make certain there aren't any
627	 * conflicting rules by searching the te_avtab and the
628	 * cond_te_avtab.
629	 */
630	if (k->specified & AVTAB_TYPE) {
631		if (avtab_search(&p->te_avtab, k)) {
632			printf
633			    ("security: type rule already exists outside of a conditional.");
634			goto err;
635		}
636		/*
637		 * If we are reading the false list other will be a pointer to
638		 * the true list. We can have duplicate entries if there is only
639		 * 1 other entry and it is in our true list.
640		 *
641		 * If we are reading the true list (other == NULL) there shouldn't
642		 * be any other entries.
643		 */
644		if (other) {
645			node_ptr = avtab_search_node(&p->te_cond_avtab, k);
646			if (node_ptr) {
647				if (avtab_search_node_next
648				    (node_ptr, k->specified)) {
649					printf
650					    ("security: too many conflicting type rules.");
651					goto err;
652				}
653				found = 0;
654				for (cur = other; cur != NULL; cur = cur->next) {
655					if (cur->node == node_ptr) {
656						found = 1;
657						break;
658					}
659				}
660				if (!found) {
661					printf
662					    ("security: conflicting type rules.\n");
663					goto err;
664				}
665			}
666		} else {
667			if (avtab_search(&p->te_cond_avtab, k)) {
668				printf
669				    ("security: conflicting type rules when adding type rule for true.\n");
670				goto err;
671			}
672		}
673	}
674
675	node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
676	if (!node_ptr) {
677		printf("security: could not insert rule.");
678		goto err;
679	}
680	node_ptr->parse_context = (void *)1;
681
682	list = malloc(sizeof(cond_av_list_t));
683	if (!list)
684		goto err;
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      err:
696	cond_av_list_destroy(data->head);
697	data->head = NULL;
698	return -1;
699}
700
701static int cond_read_av_list(policydb_t * p, void *fp,
702			     cond_av_list_t ** ret_list, cond_av_list_t * other)
703{
704	unsigned int i;
705	int rc;
706	uint32_t buf[1], len;
707	struct cond_insertf_data data;
708
709	*ret_list = NULL;
710
711	len = 0;
712	rc = next_entry(buf, fp, sizeof(uint32_t));
713	if (rc < 0)
714		return -1;
715
716	len = le32_to_cpu(buf[0]);
717	if (len == 0) {
718		return 0;
719	}
720
721	data.p = p;
722	data.other = other;
723	data.head = NULL;
724	data.tail = NULL;
725	for (i = 0; i < len; i++) {
726		rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab,
727				     cond_insertf, &data);
728		if (rc)
729			return rc;
730
731	}
732
733	*ret_list = data.head;
734	return 0;
735}
736
737static int expr_isvalid(policydb_t * p, cond_expr_t * expr)
738{
739	if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
740		printf
741		    ("security: conditional expressions uses unknown operator.\n");
742		return 0;
743	}
744
745	if (expr->bool > p->p_bools.nprim) {
746		printf
747		    ("security: conditional expressions uses unknown bool.\n");
748		return 0;
749	}
750	return 1;
751}
752
753static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
754{
755	uint32_t buf[2];
756	int len, i, rc;
757	cond_expr_t *expr = NULL, *last = NULL;
758
759	rc = next_entry(buf, fp, sizeof(uint32_t));
760	if (rc < 0)
761		goto err;
762
763	node->cur_state = le32_to_cpu(buf[0]);
764
765	len = 0;
766	rc = next_entry(buf, fp, sizeof(uint32_t));
767	if (rc < 0)
768		goto err;
769
770	/* expr */
771	len = le32_to_cpu(buf[0]);
772
773	for (i = 0; i < len; i++) {
774		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
775		if (rc < 0)
776			goto err;
777
778		expr = malloc(sizeof(cond_expr_t));
779		if (!expr) {
780			goto err;
781		}
782		memset(expr, 0, sizeof(cond_expr_t));
783
784		expr->expr_type = le32_to_cpu(buf[0]);
785		expr->bool = le32_to_cpu(buf[1]);
786
787		if (!expr_isvalid(p, expr)) {
788			free(expr);
789			goto err;
790		}
791
792		if (i == 0) {
793			node->expr = expr;
794		} else {
795			last->next = expr;
796		}
797		last = expr;
798	}
799
800	if (p->policy_type == POLICY_KERN) {
801		if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
802			goto err;
803		if (cond_read_av_list(p, fp, &node->false_list, node->true_list)
804		    != 0)
805			goto err;
806	} else {
807		if (avrule_read_list(p, &node->avtrue_list, fp))
808			goto err;
809		if (avrule_read_list(p, &node->avfalse_list, fp))
810			goto err;
811	}
812
813	return 0;
814      err:
815	cond_node_destroy(node);
816	free(node);
817	return -1;
818}
819
820int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp)
821{
822	cond_node_t *node, *last = NULL;
823	uint32_t buf[1];
824	int i, len, rc;
825
826	rc = next_entry(buf, fp, sizeof(uint32_t));
827	if (rc < 0)
828		return -1;
829
830	len = le32_to_cpu(buf[0]);
831
832	rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel);
833	if (rc)
834		goto err;
835
836	for (i = 0; i < len; i++) {
837		node = malloc(sizeof(cond_node_t));
838		if (!node)
839			goto err;
840		memset(node, 0, sizeof(cond_node_t));
841
842		if (cond_read_node(p, node, fp) != 0)
843			goto err;
844
845		if (i == 0) {
846			*list = node;
847		} else {
848			last->next = node;
849		}
850		last = node;
851	}
852	return 0;
853      err:
854	return -1;
855}
856
857/* Determine whether additional permissions are granted by the conditional
858 * av table, and if so, add them to the result
859 */
860void cond_compute_av(avtab_t * ctab, avtab_key_t * key,
861		     struct sepol_av_decision *avd)
862{
863	avtab_ptr_t node;
864
865	if (!ctab || !key || !avd)
866		return;
867
868	for (node = avtab_search_node(ctab, key); node != NULL;
869	     node = avtab_search_node_next(node, key->specified)) {
870		if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) ==
871		    (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
872			avd->allowed |= node->datum.data;
873		if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) ==
874		    (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED)))
875			/* Since a '0' in an auditdeny mask represents a
876			 * permission we do NOT want to audit (dontaudit), we use
877			 * the '&' operand to ensure that all '0's in the mask
878			 * are retained (much unlike the allow and auditallow cases).
879			 */
880			avd->auditdeny &= node->datum.data;
881		if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
882		    (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
883			avd->auditallow |= node->datum.data;
884	}
885	return;
886}
887
888avtab_datum_t *cond_av_list_search(avtab_key_t * key,
889				   cond_av_list_t * cond_list)
890{
891
892	cond_av_list_t *cur_av;
893
894	for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) {
895
896		if (cur_av->node->key.source_type == key->source_type &&
897		    cur_av->node->key.target_type == key->target_type &&
898		    cur_av->node->key.target_class == key->target_class)
899
900			return &cur_av->node->datum;
901
902	}
903	return NULL;
904
905}
906