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 */
cond_optimize(cond_av_list_t ** l)31 static 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 */
cond_optimize_lists(cond_list_t * cl)52 void 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
bool_present(unsigned int target,unsigned int bools[],unsigned int num_bools)62 static 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
same_bools(cond_node_t * a,cond_node_t * b)78 static 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 */
cond_expr_equal(cond_node_t * a,cond_node_t * b)98 int 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 */
cond_node_create(policydb_t * p,cond_node_t * node)142 cond_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. */
cond_node_find(policydb_t * p,cond_node_t * needle,cond_node_t * haystack,int * was_created)175 cond_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 */
cond_node_search(policydb_t * p,cond_node_t * list,cond_node_t * cn)192 cond_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 */
cond_evaluate_expr(policydb_t * p,cond_expr_t * expr)211 int 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
cond_copy_expr(cond_expr_t * expr)270 cond_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 */
evaluate_cond_node(policydb_t * p,cond_node_t * node)309 static 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 */
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 /* 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
evaluate_conds(policydb_t * p)440 int 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
cond_policydb_init(policydb_t * p)453 int 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
cond_av_list_destroy(cond_av_list_t * list)463 void 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
cond_expr_destroy(cond_expr_t * expr)473 void 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
cond_node_destroy(cond_node_t * node)486 void 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
cond_list_destroy(cond_list_t * list)498 void 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
cond_policydb_destroy(policydb_t * p)512 void 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
cond_init_bool_indexes(policydb_t * p)520 int 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
cond_destroy_bool(hashtab_key_t key,hashtab_datum_t datum,void * p)531 int 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
cond_index_bool(hashtab_key_t key,hashtab_datum_t datum,void * datap)540 int 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
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 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
612 struct 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
cond_insertf(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * ptr)619 static 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
cond_read_av_list(policydb_t * p,void * fp,cond_av_list_t ** ret_list,cond_av_list_t * other)696 static 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
expr_isvalid(policydb_t * p,cond_expr_t * expr)733 static 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
cond_read_node(policydb_t * p,cond_node_t * node,void * fp)747 static 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
cond_read_list(policydb_t * p,cond_list_t ** list,void * fp)821 int 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 */
cond_compute_av(avtab_t * ctab,avtab_key_t * key,struct sepol_av_decision * avd)861 void 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
cond_av_list_search(avtab_key_t * key,cond_av_list_t * cond_list)889 avtab_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