1
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2
* Frank Mayer <mayerf@tresys.com>
3
* David Caplan <dac@tresys.com>
5
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, version 2.
11
#include "include/security.h"
12
#include "conditional.h"
15
/* move all type rules to top of t/f lists to help kernel on evaluation */
16
static void cond_optimize(cond_av_list_t **l) {
17
cond_av_list_t *top, *p,*cur;
22
if ((cur->node->datum.specified & AVTAB_TYPE) && (top != cur)) {
35
/* reorder t/f lists for kernel */
36
void cond_optimize_lists(cond_list_t* cl) {
39
for (n = cl; n != NULL; n = n->next) {
40
cond_optimize(&n->true_list);
41
cond_optimize(&n->false_list);
46
static int bool_present(int target, int bools[], int num_bools) {
50
if (num_bools > COND_MAX_BOOLS) {
53
while( i < num_bools && target != bools[i]) i++;
54
if (i == num_bools) ret = 0; /* got to end w/o match */
58
static int same_bools(cond_node_t *a, cond_node_t *b) {
63
/* same number of bools? */
64
if (x != b->nbools) return 0;
66
/* make sure all the bools in a are also in b */
67
for(i = 0; i < x; i++) if (!bool_present(a->bool_ids[i], b->bool_ids, x)) return 0;
72
* Determine if two conditional expressions are equal.
74
static int cond_expr_equal(cond_node_t *a, cond_node_t *b)
76
cond_expr_t *cur_a, *cur_b;
78
if (a == NULL || b == NULL)
81
if(a->nbools != b->nbools) return 0;
83
/* if exprs have <= COND_MAX_BOOLS we can check the precompute values
84
* for the expressions.
86
if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS)
88
if(!same_bools(a,b)) return 0;
89
return (a->expr_pre_comp == b->expr_pre_comp);
92
/* for long expressions we check for exactly the same expression */
96
if (cur_a == NULL && cur_b == NULL)
98
else if (cur_a == NULL || cur_b == NULL)
100
if (cur_a->expr_type != cur_b->expr_type)
102
if (cur_a->expr_type == COND_BOOL) {
103
if (cur_a->bool != cur_b->bool)
112
/* return either a pre-existing matching node or create a new node */
113
cond_node_t *cond_node_search(policydb_t *p, cond_node_t *cn)
115
cond_node_t *list,*new;
121
if (cond_expr_equal(cn,list)) break;
124
if (list) return list;
126
new = (cond_node_t *)malloc(sizeof (cond_node_t));
130
new->expr = cn->expr;
131
new->cur_state = cond_evaluate_expr(p, new->expr);
132
new->nbools = cn->nbools;
133
for (i = 0; i < cn->nbools; i++)
134
new->bool_ids[i] = cn->bool_ids[i];
135
new->expr_pre_comp = cn->expr_pre_comp;
136
new->true_list = NULL;
137
new->false_list = NULL;
138
/* add conditional node to policy list */
139
new->next = p->cond_list;
146
* cond_evaluate_expr evaluates a conditional expr
147
* in reverse polish notation. It returns true (1), false (0),
148
* or undefined (-1). Undefined occurs when the expression
149
* exceeds the stack depth of COND_EXPR_MAXDEPTH.
151
int cond_evaluate_expr(policydb_t *p, cond_expr_t *expr)
155
int s[COND_EXPR_MAXDEPTH];
158
for (cur = expr; cur != NULL; cur = cur->next) {
159
switch (cur->expr_type) {
161
if (sp == (COND_EXPR_MAXDEPTH - 1))
164
s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
193
s[sp] = (s[sp] == s[sp + 1]);
199
s[sp] = (s[sp] != s[sp + 1]);
209
* evaluate_cond_node evaluates the conditional stored in
210
* a cond_node_t and if the result is different than the
211
* current state of the node it sets the rules in the true/false
212
* list appropriately. If the result of the expression is undefined
213
* all of the rules are disabled for safety.
215
static int evaluate_cond_node(policydb_t *p, cond_node_t *node)
220
new_state = cond_evaluate_expr(p, node->expr);
221
if (new_state != node->cur_state) {
222
node->cur_state = new_state;
224
printk("expression result was undefined - disabling all rules.\n");
225
/* turn the rules on or off */
226
for (cur = node->true_list; cur != NULL; cur = cur->next) {
227
if (new_state <= 0) {
228
cur->node->datum.specified &= ~AVTAB_ENABLED;
230
cur->node->datum.specified |= AVTAB_ENABLED;
234
for (cur = node->false_list; cur != NULL; cur = cur->next) {
237
cur->node->datum.specified &= ~AVTAB_ENABLED;
239
cur->node->datum.specified |= AVTAB_ENABLED;
246
/* precompute and simplify an expression if possible. If left with !expression, change
247
* to expression and switch t and f. precompute expression for expressions with limited
250
int normalize_expr(policydb_t *p, cond_node_t *cn)
254
int i, j, k, orig_value[COND_MAX_BOOLS];
260
memset(cn->bool_ids, 0,sizeof(cn->bool_ids) );
261
cn->expr_pre_comp = 0x0;
263
/* take care of !expr case */
267
/* becuase it's RPN look at last element */
268
while(e->next != NULL) {
271
if (e->expr_type == COND_NOT) {
274
} else { /* ne should never be NULL */
275
printk("Found expr with no bools and only a ! - this should never happen.\n");
278
/* swap the true and false lists */
280
cn->true_list = cn->false_list;
281
cn->false_list = tmp;
282
/* free the "not" node in the list */
286
/* find all the bools in the expression */
287
for(e = cn->expr; e != NULL; e = e->next) {
288
switch(e->expr_type) {
291
/* see if we've already seen this bool */
292
if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
293
/* count em all but only record up to COND_MAX_BOOLS */
294
if (cn->nbools < COND_MAX_BOOLS)
295
cn->bool_ids[cn->nbools++] = e->bool;
305
/* only precompute for exprs with <= COND_AX_BOOLS */
306
if (cn->nbools <= COND_MAX_BOOLS) {
307
/* save the default values for the bools so we can play with them */
308
for(i = 0; i < cn->nbools; i++) {
309
orig_value[i] = p->bool_val_to_struct[cn->bool_ids[i] - 1]->state;
312
/* loop through all possible combinations of values for bools in expression */
313
for(test = 0x0; test < (0x1 << cn->nbools) ; test++) {
314
/* temporarily set the value for all the bools in the
315
* expression using the corr. bit in test */
316
for(j = 0; j < cn->nbools; j++) {
317
p->bool_val_to_struct[cn->bool_ids[j] - 1]->state =
318
( test & (0x1 << j) ) ? 1 : 0;
320
k = cond_evaluate_expr(p, cn->expr);
322
printk("While testing expression, expression result "
323
"was undefined - this should never happen.\n");
326
/* set the bit if expression evaluates true */
327
if (k) cn->expr_pre_comp |= 0x1 << test;
330
/* restore bool default values */
331
for(i = 0; i < cn->nbools; i++)
332
p->bool_val_to_struct[cn->bool_ids[i] - 1]->state = orig_value[i] ;
337
int evaluate_conds(policydb_t *p)
342
for (cur = p->cond_list; cur != NULL; cur = cur->next) {
343
ret = evaluate_cond_node(p, cur);
350
int cond_policydb_init(policydb_t *p)
352
p->bool_val_to_struct = NULL;
354
if (avtab_init(&p->te_cond_avtab))
360
static void cond_av_list_destroy(cond_av_list_t *list)
362
cond_av_list_t *cur, *next;
363
for (cur = list; cur != NULL; cur = next) {
365
/* the avtab_ptr_t node is destroy by the avtab */
370
static void cond_node_destroy(cond_node_t *node)
372
cond_expr_t *cur_expr, *next_expr;
377
for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) {
378
next_expr = cur_expr->next;
381
cond_av_list_destroy(node->true_list);
382
cond_av_list_destroy(node->false_list);
386
static void cond_list_destroy(cond_list_t *list)
388
cond_node_t *next, *cur;
393
for (cur = list; cur != NULL; cur = next) {
395
cond_node_destroy(cur);
399
void cond_policydb_destroy(policydb_t *p)
401
if (p->bool_val_to_struct != NULL)
402
kfree(p->bool_val_to_struct);
403
avtab_destroy(&p->te_cond_avtab);
404
cond_list_destroy(p->cond_list);
407
int cond_init_bool_indexes(policydb_t *p)
409
if (p->bool_val_to_struct)
410
kfree(p->bool_val_to_struct);
411
p->bool_val_to_struct = (cond_bool_datum_t**)
412
kmalloc(p->p_bools.nprim * sizeof(cond_bool_datum_t*), GFP_KERNEL);
413
if (!p->bool_val_to_struct)
418
int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p)
426
int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
429
cond_bool_datum_t *booldatum;
434
if (!booldatum->value || booldatum->value > p->p_bools.nprim)
437
p->p_bool_val_to_name[booldatum->value - 1] = key;
438
p->bool_val_to_struct[booldatum->value -1] = booldatum;
443
int bool_isvalid(cond_bool_datum_t *b)
445
if (!(b->state == 0 || b->state == 1))
450
int cond_read_bool(policydb_t *p, hashtab_t h, struct policy_file *fp)
453
cond_bool_datum_t *booldatum;
456
booldatum = kmalloc(sizeof(cond_bool_datum_t), GFP_KERNEL);
459
memset(booldatum, 0, sizeof(cond_bool_datum_t));
461
buf = next_entry(fp, sizeof(__u32) * 3);
465
booldatum->value = le32_to_cpu(buf[0]);
466
booldatum->state = le32_to_cpu(buf[1]);
468
if (!bool_isvalid(booldatum))
471
len = le32_to_cpu(buf[2]);
473
buf = next_entry(fp, len);
476
key = kmalloc(len + 1, GFP_KERNEL);
479
memcpy(key, buf, len);
481
if (hashtab_insert(h, key, booldatum))
486
cond_destroy_bool(key, booldatum, 0);
490
static int cond_read_av_list(policydb_t *p, void *fp, cond_av_list_t **ret_list, cond_av_list_t *other)
492
cond_av_list_t *list, *last = NULL, *cur;
495
avtab_ptr_t node_ptr;
503
buf = next_entry(fp, sizeof(__u32));
507
len = le32_to_cpu(buf[0]);
512
for (i = 0; i < len; i++) {
513
if (avtab_read_item(fp, &datum, &key))
517
* For type rules we have to make certain there aren't any
518
* conflicting rules by searching the te_avtab and the
521
if (datum.specified & AVTAB_TYPE) {
522
if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) {
523
printk("security: type rule already exists outside of a conditional.");
527
* If we are reading the false list other will be a pointer to
528
* the true list. We can have duplicate entries if there is only
529
* 1 other entry and it is in our true list.
531
* If we are reading the true list (other == NULL) there shouldn't
532
* be any other entries.
535
node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE);
537
if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
538
printk("security: too many conflicting type rules.");
542
for (cur = other; cur != NULL; cur = cur->next) {
543
if (cur->node == node_ptr) {
549
printk("security: conflicting type rules.\n");
554
if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) {
555
printk("security: conflicting type rules when adding type rule for true.\n");
560
node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum);
562
printk("security: could not insert rule.");
566
list = kmalloc(sizeof(cond_av_list_t), GFP_KERNEL);
569
memset(list, 0, sizeof(cond_av_list_t));
571
list->node = node_ptr;
582
cond_av_list_destroy(*ret_list);
587
static int expr_isvalid(policydb_t *p, cond_expr_t *expr)
589
if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
590
printk("security: conditional expressions uses unknown operator.\n");
594
if (expr->bool > p->p_bools.nprim) {
595
printk("security: conditional expressions uses unknown bool.\n");
601
static int cond_read_node(policydb_t *p, cond_node_t *node, void *fp)
605
cond_expr_t *expr = NULL, *last = NULL;
607
buf = next_entry(fp, sizeof(__u32));
611
node->cur_state = le32_to_cpu(buf[0]);
614
buf = next_entry(fp, sizeof(__u32));
619
len = le32_to_cpu(buf[0]);
621
for (i = 0; i < len; i++ ) {
622
buf = next_entry(fp, sizeof(__u32) * 2);
626
expr = kmalloc(sizeof(cond_expr_t), GFP_KERNEL);
630
memset(expr, 0, sizeof(cond_expr_t));
632
expr->expr_type = le32_to_cpu(buf[0]);
633
expr->bool = le32_to_cpu(buf[1]);
635
if (!expr_isvalid(p, expr))
646
if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
648
if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0)
652
cond_node_destroy(node);
656
int cond_read_list(policydb_t *p, void *fp)
658
cond_node_t *node, *last = NULL;
662
buf = next_entry(fp, sizeof(__u32));
666
len = le32_to_cpu(buf[0]);
668
for (i = 0; i < len; i++) {
669
node = kmalloc(sizeof(cond_node_t), GFP_KERNEL);
672
memset(node, 0, sizeof(cond_node_t));
674
if (cond_read_node(p, node, fp) != 0)
689
/* Determine whether additional permissions are granted by the conditional
690
* av table, and if so, add them to the result
692
void cond_compute_av(avtab_t *ctab, avtab_key_t *key, struct av_decision *avd)
696
if(!ctab || !key || !avd)
699
for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL;
700
node = avtab_search_node_next(node, AVTAB_AV)) {
701
if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
702
(node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
703
avd->allowed |= avtab_allowed(&node->datum);
704
if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
705
(node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
706
/* Since a '0' in an auditdeny mask represents a
707
* permission we do NOT want to audit (dontaudit), we use
708
* the '&' operand to ensure that all '0's in the mask
709
* are retained (much unlike the allow and auditallow cases).
711
avd->auditdeny &= avtab_auditdeny(&node->datum);
712
if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
713
(node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
714
avd->auditallow |= avtab_auditallow(&node->datum);