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		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. */
174cond_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 */
191cond_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 */
210int 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
269cond_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 */
308static 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 */
344int 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
443int 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
456int 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
466void 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
476void 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
489void 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
501void 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
515void 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
523int 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
534int 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
543int 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
560static 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
567int 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
618struct 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
625static 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
711static 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
747static 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
763static 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
838int 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 */
878void 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
906avtab_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