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 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
bool_isvalid(cond_bool_datum_t * b)560 static 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
cond_read_bool(policydb_t * p,hashtab_t h,struct policy_file * fp)567 int 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
618 struct 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
cond_insertf(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * ptr)625 static 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
cond_read_av_list(policydb_t * p,void * fp,cond_av_list_t ** ret_list,cond_av_list_t * other)711 static 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
expr_isvalid(policydb_t * p,cond_expr_t * expr)747 static 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
cond_read_node(policydb_t * p,cond_node_t * node,void * fp)763 static 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
cond_read_list(policydb_t * p,cond_list_t ** list,void * fp)838 int 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 */
cond_compute_av(avtab_t * ctab,avtab_key_t * key,struct sepol_av_decision * avd)878 void 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
cond_av_list_search(avtab_key_t * key,cond_av_list_t * cond_list)906 avtab_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