• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2   *          Frank Mayer <mayerf@tresys.com>
3   *          David Caplan <dac@tresys.com>
4   *
5   * Copyright (C) 2003 - 2005 Tresys Technology, LLC
6   *
7   *  This library is free software; you can redistribute it and/or
8   *  modify it under the terms of the GNU Lesser General Public
9   *  License as published by the Free Software Foundation; either
10   *  version 2.1 of the License, or (at your option) any later version.
11   *
12   *  This library is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   *  Lesser General Public License for more details.
16   *
17   *  You should have received a copy of the GNU Lesser General Public
18   *  License along with this library; if not, write to the Free Software
19   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20   */
21  
22  #include <stdlib.h>
23  
24  #include <sepol/policydb/flask_types.h>
25  #include <sepol/policydb/conditional.h>
26  
27  #include "private.h"
28  
29  /* move all type rules to top of t/f lists to help kernel on evaluation */
cond_optimize(cond_av_list_t ** l)30  static 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 */
cond_optimize_lists(cond_list_t * cl)51  void 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  
bool_present(unsigned int target,unsigned int bools[],unsigned int num_bools)61  static 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  
same_bools(cond_node_t * a,cond_node_t * b)77  static 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   */
cond_expr_equal(cond_node_t * a,cond_node_t * b)97  int 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   */
cond_node_create(policydb_t * p,cond_node_t * node)141  cond_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. */
cond_node_find(policydb_t * p,cond_node_t * needle,cond_node_t * haystack,int * was_created)174  cond_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 */
cond_node_search(policydb_t * p,cond_node_t * list,cond_node_t * cn)191  cond_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   */
cond_evaluate_expr(policydb_t * p,cond_expr_t * expr)210  int 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  
cond_copy_expr(cond_expr_t * expr)269  cond_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   */
evaluate_cond_node(policydb_t * p,cond_node_t * node)308  static 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   */
cond_normalize_expr(policydb_t * p,cond_node_t * cn)344  int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
345  {
346  	cond_expr_t *ne, *e;
347  	cond_av_list_t *tmp;
348  	unsigned int i, j, orig_value[COND_MAX_BOOLS];
349  	int k;
350  	uint32_t test = 0x0;
351  	avrule_t *tmp2;
352  
353  	cn->nbools = 0;
354  
355  	memset(cn->bool_ids, 0, sizeof(cn->bool_ids));
356  	cn->expr_pre_comp = 0x0;
357  
358  	/* take care of !expr case */
359  	ne = NULL;
360  	e = cn->expr;
361  
362  	/* 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  
evaluate_conds(policydb_t * p)443  int 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  
cond_policydb_init(policydb_t * p)456  int 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  
cond_av_list_destroy(cond_av_list_t * list)466  void 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  
cond_expr_destroy(cond_expr_t * expr)476  void 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  
cond_node_destroy(cond_node_t * node)489  void 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  
cond_list_destroy(cond_list_t * list)501  void 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  
cond_policydb_destroy(policydb_t * p)515  void 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  
cond_init_bool_indexes(policydb_t * p)523  int 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  
cond_destroy_bool(hashtab_key_t key,hashtab_datum_t datum,void * p)534  int 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  
cond_index_bool(hashtab_key_t key,hashtab_datum_t datum,void * datap)543  int 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  
bool_isvalid(cond_bool_datum_t * b)563  static 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  
cond_read_bool(policydb_t * p,hashtab_t h,struct policy_file * fp)570  int 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  
615  struct 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  
cond_insertf(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * ptr)622  static 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  
cond_read_av_list(policydb_t * p,void * fp,cond_av_list_t ** ret_list,cond_av_list_t * other)708  static 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  
expr_isvalid(policydb_t * p,cond_expr_t * expr)744  static 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  
cond_read_node(policydb_t * p,cond_node_t * node,void * fp)760  static 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  
cond_read_list(policydb_t * p,cond_list_t ** list,void * fp)835  int 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   */
cond_compute_av(avtab_t * ctab,avtab_key_t * key,struct sepol_av_decision * avd)875  void 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  
cond_av_list_search(avtab_key_t * key,cond_av_list_t * cond_list)903  avtab_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