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	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
563static 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
570int 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
615struct 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
622static 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
708static 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
744static 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
760static 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
835int 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 */
875void 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
903avtab_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