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 */
31static 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 */
52void 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
62static 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
78static 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 */
98int 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 */
142cond_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. */
175cond_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 */
192cond_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 */
211int 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
270cond_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 */
309static 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 */
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	/* 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
440int 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
453int 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
463void 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
473void 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
486void 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
498void 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
512void 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
520int 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
531int 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
540int 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
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	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
612struct 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
619static 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
696static 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
733static 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
747static 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
821int 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 */
861void 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
889avtab_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