OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [security/] [selinux/] [ss/] [conditional.c] - Blame information for rev 67

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2
 *          Frank Mayer <mayerf@tresys.com>
3
 *
4
 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
5
 *      This program is free software; you can redistribute it and/or modify
6
 *      it under the terms of the GNU General Public License as published by
7
 *      the Free Software Foundation, version 2.
8
 */
9
 
10
#include <linux/kernel.h>
11
#include <linux/errno.h>
12
#include <linux/string.h>
13
#include <linux/spinlock.h>
14
#include <asm/semaphore.h>
15
#include <linux/slab.h>
16
 
17
#include "security.h"
18
#include "conditional.h"
19
 
20
/*
21
 * cond_evaluate_expr evaluates a conditional expr
22
 * in reverse polish notation. It returns true (1), false (0),
23
 * or undefined (-1). Undefined occurs when the expression
24
 * exceeds the stack depth of COND_EXPR_MAXDEPTH.
25
 */
26
static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
27
{
28
 
29
        struct cond_expr *cur;
30
        int s[COND_EXPR_MAXDEPTH];
31
        int sp = -1;
32
 
33
        for (cur = expr; cur != NULL; cur = cur->next) {
34
                switch (cur->expr_type) {
35
                case COND_BOOL:
36
                        if (sp == (COND_EXPR_MAXDEPTH - 1))
37
                                return -1;
38
                        sp++;
39
                        s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
40
                        break;
41
                case COND_NOT:
42
                        if (sp < 0)
43
                                return -1;
44
                        s[sp] = !s[sp];
45
                        break;
46
                case COND_OR:
47
                        if (sp < 1)
48
                                return -1;
49
                        sp--;
50
                        s[sp] |= s[sp + 1];
51
                        break;
52
                case COND_AND:
53
                        if (sp < 1)
54
                                return -1;
55
                        sp--;
56
                        s[sp] &= s[sp + 1];
57
                        break;
58
                case COND_XOR:
59
                        if (sp < 1)
60
                                return -1;
61
                        sp--;
62
                        s[sp] ^= s[sp + 1];
63
                        break;
64
                case COND_EQ:
65
                        if (sp < 1)
66
                                return -1;
67
                        sp--;
68
                        s[sp] = (s[sp] == s[sp + 1]);
69
                        break;
70
                case COND_NEQ:
71
                        if (sp < 1)
72
                                return -1;
73
                        sp--;
74
                        s[sp] = (s[sp] != s[sp + 1]);
75
                        break;
76
                default:
77
                        return -1;
78
                }
79
        }
80
        return s[0];
81
}
82
 
83
/*
84
 * evaluate_cond_node evaluates the conditional stored in
85
 * a struct cond_node and if the result is different than the
86
 * current state of the node it sets the rules in the true/false
87
 * list appropriately. If the result of the expression is undefined
88
 * all of the rules are disabled for safety.
89
 */
90
int evaluate_cond_node(struct policydb *p, struct cond_node *node)
91
{
92
        int new_state;
93
        struct cond_av_list* cur;
94
 
95
        new_state = cond_evaluate_expr(p, node->expr);
96
        if (new_state != node->cur_state) {
97
                node->cur_state = new_state;
98
                if (new_state == -1)
99
                        printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
100
                /* turn the rules on or off */
101
                for (cur = node->true_list; cur != NULL; cur = cur->next) {
102
                        if (new_state <= 0) {
103
                                cur->node->key.specified &= ~AVTAB_ENABLED;
104
                        } else {
105
                                cur->node->key.specified |= AVTAB_ENABLED;
106
                        }
107
                }
108
 
109
                for (cur = node->false_list; cur != NULL; cur = cur->next) {
110
                        /* -1 or 1 */
111
                        if (new_state) {
112
                                cur->node->key.specified &= ~AVTAB_ENABLED;
113
                        } else {
114
                                cur->node->key.specified |= AVTAB_ENABLED;
115
                        }
116
                }
117
        }
118
        return 0;
119
}
120
 
121
int cond_policydb_init(struct policydb *p)
122
{
123
        p->bool_val_to_struct = NULL;
124
        p->cond_list = NULL;
125
        if (avtab_init(&p->te_cond_avtab))
126
                return -1;
127
 
128
        return 0;
129
}
130
 
131
static void cond_av_list_destroy(struct cond_av_list *list)
132
{
133
        struct cond_av_list *cur, *next;
134
        for (cur = list; cur != NULL; cur = next) {
135
                next = cur->next;
136
                /* the avtab_ptr_t node is destroy by the avtab */
137
                kfree(cur);
138
        }
139
}
140
 
141
static void cond_node_destroy(struct cond_node *node)
142
{
143
        struct cond_expr *cur_expr, *next_expr;
144
 
145
        for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) {
146
                next_expr = cur_expr->next;
147
                kfree(cur_expr);
148
        }
149
        cond_av_list_destroy(node->true_list);
150
        cond_av_list_destroy(node->false_list);
151
        kfree(node);
152
}
153
 
154
static void cond_list_destroy(struct cond_node *list)
155
{
156
        struct cond_node *next, *cur;
157
 
158
        if (list == NULL)
159
                return;
160
 
161
        for (cur = list; cur != NULL; cur = next) {
162
                next = cur->next;
163
                cond_node_destroy(cur);
164
        }
165
}
166
 
167
void cond_policydb_destroy(struct policydb *p)
168
{
169
        kfree(p->bool_val_to_struct);
170
        avtab_destroy(&p->te_cond_avtab);
171
        cond_list_destroy(p->cond_list);
172
}
173
 
174
int cond_init_bool_indexes(struct policydb *p)
175
{
176
        kfree(p->bool_val_to_struct);
177
        p->bool_val_to_struct = (struct cond_bool_datum**)
178
                kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
179
        if (!p->bool_val_to_struct)
180
                return -1;
181
        return 0;
182
}
183
 
184
int cond_destroy_bool(void *key, void *datum, void *p)
185
{
186
        kfree(key);
187
        kfree(datum);
188
        return 0;
189
}
190
 
191
int cond_index_bool(void *key, void *datum, void *datap)
192
{
193
        struct policydb *p;
194
        struct cond_bool_datum *booldatum;
195
 
196
        booldatum = datum;
197
        p = datap;
198
 
199
        if (!booldatum->value || booldatum->value > p->p_bools.nprim)
200
                return -EINVAL;
201
 
202
        p->p_bool_val_to_name[booldatum->value - 1] = key;
203
        p->bool_val_to_struct[booldatum->value -1] = booldatum;
204
 
205
        return 0;
206
}
207
 
208
static int bool_isvalid(struct cond_bool_datum *b)
209
{
210
        if (!(b->state == 0 || b->state == 1))
211
                return 0;
212
        return 1;
213
}
214
 
215
int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
216
{
217
        char *key = NULL;
218
        struct cond_bool_datum *booldatum;
219
        __le32 buf[3];
220
        u32 len;
221
        int rc;
222
 
223
        booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
224
        if (!booldatum)
225
                return -1;
226
 
227
        rc = next_entry(buf, fp, sizeof buf);
228
        if (rc < 0)
229
                goto err;
230
 
231
        booldatum->value = le32_to_cpu(buf[0]);
232
        booldatum->state = le32_to_cpu(buf[1]);
233
 
234
        if (!bool_isvalid(booldatum))
235
                goto err;
236
 
237
        len = le32_to_cpu(buf[2]);
238
 
239
        key = kmalloc(len + 1, GFP_KERNEL);
240
        if (!key)
241
                goto err;
242
        rc = next_entry(key, fp, len);
243
        if (rc < 0)
244
                goto err;
245
        key[len] = 0;
246
        if (hashtab_insert(h, key, booldatum))
247
                goto err;
248
 
249
        return 0;
250
err:
251
        cond_destroy_bool(key, booldatum, NULL);
252
        return -1;
253
}
254
 
255
struct cond_insertf_data
256
{
257
        struct policydb *p;
258
        struct cond_av_list *other;
259
        struct cond_av_list *head;
260
        struct cond_av_list *tail;
261
};
262
 
263
static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
264
{
265
        struct cond_insertf_data *data = ptr;
266
        struct policydb *p = data->p;
267
        struct cond_av_list *other = data->other, *list, *cur;
268
        struct avtab_node *node_ptr;
269
        u8 found;
270
 
271
 
272
        /*
273
         * For type rules we have to make certain there aren't any
274
         * conflicting rules by searching the te_avtab and the
275
         * cond_te_avtab.
276
         */
277
        if (k->specified & AVTAB_TYPE) {
278
                if (avtab_search(&p->te_avtab, k)) {
279
                        printk("security: type rule already exists outside of a conditional.");
280
                        goto err;
281
                }
282
                /*
283
                 * If we are reading the false list other will be a pointer to
284
                 * the true list. We can have duplicate entries if there is only
285
                 * 1 other entry and it is in our true list.
286
                 *
287
                 * If we are reading the true list (other == NULL) there shouldn't
288
                 * be any other entries.
289
                 */
290
                if (other) {
291
                        node_ptr = avtab_search_node(&p->te_cond_avtab, k);
292
                        if (node_ptr) {
293
                                if (avtab_search_node_next(node_ptr, k->specified)) {
294
                                        printk("security: too many conflicting type rules.");
295
                                        goto err;
296
                                }
297
                                found = 0;
298
                                for (cur = other; cur != NULL; cur = cur->next) {
299
                                        if (cur->node == node_ptr) {
300
                                                found = 1;
301
                                                break;
302
                                        }
303
                                }
304
                                if (!found) {
305
                                        printk("security: conflicting type rules.\n");
306
                                        goto err;
307
                                }
308
                        }
309
                } else {
310
                        if (avtab_search(&p->te_cond_avtab, k)) {
311
                                printk("security: conflicting type rules when adding type rule for true.\n");
312
                                goto err;
313
                        }
314
                }
315
        }
316
 
317
        node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
318
        if (!node_ptr) {
319
                printk("security: could not insert rule.");
320
                goto err;
321
        }
322
 
323
        list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL);
324
        if (!list)
325
                goto err;
326
 
327
        list->node = node_ptr;
328
        if (!data->head)
329
                data->head = list;
330
        else
331
                data->tail->next = list;
332
        data->tail = list;
333
        return 0;
334
 
335
err:
336
        cond_av_list_destroy(data->head);
337
        data->head = NULL;
338
        return -1;
339
}
340
 
341
static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
342
{
343
        int i, rc;
344
        __le32 buf[1];
345
        u32 len;
346
        struct cond_insertf_data data;
347
 
348
        *ret_list = NULL;
349
 
350
        len = 0;
351
        rc = next_entry(buf, fp, sizeof(u32));
352
        if (rc < 0)
353
                return -1;
354
 
355
        len = le32_to_cpu(buf[0]);
356
        if (len == 0) {
357
                return 0;
358
        }
359
 
360
        data.p = p;
361
        data.other = other;
362
        data.head = NULL;
363
        data.tail = NULL;
364
        for (i = 0; i < len; i++) {
365
                rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
366
                                     &data);
367
                if (rc)
368
                        return rc;
369
 
370
        }
371
 
372
        *ret_list = data.head;
373
        return 0;
374
}
375
 
376
static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
377
{
378
        if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
379
                printk("security: conditional expressions uses unknown operator.\n");
380
                return 0;
381
        }
382
 
383
        if (expr->bool > p->p_bools.nprim) {
384
                printk("security: conditional expressions uses unknown bool.\n");
385
                return 0;
386
        }
387
        return 1;
388
}
389
 
390
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
391
{
392
        __le32 buf[2];
393
        u32 len, i;
394
        int rc;
395
        struct cond_expr *expr = NULL, *last = NULL;
396
 
397
        rc = next_entry(buf, fp, sizeof(u32));
398
        if (rc < 0)
399
                return -1;
400
 
401
        node->cur_state = le32_to_cpu(buf[0]);
402
 
403
        len = 0;
404
        rc = next_entry(buf, fp, sizeof(u32));
405
        if (rc < 0)
406
                return -1;
407
 
408
        /* expr */
409
        len = le32_to_cpu(buf[0]);
410
 
411
        for (i = 0; i < len; i++ ) {
412
                rc = next_entry(buf, fp, sizeof(u32) * 2);
413
                if (rc < 0)
414
                        goto err;
415
 
416
                expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
417
                if (!expr) {
418
                        goto err;
419
                }
420
 
421
                expr->expr_type = le32_to_cpu(buf[0]);
422
                expr->bool = le32_to_cpu(buf[1]);
423
 
424
                if (!expr_isvalid(p, expr)) {
425
                        kfree(expr);
426
                        goto err;
427
                }
428
 
429
                if (i == 0) {
430
                        node->expr = expr;
431
                } else {
432
                        last->next = expr;
433
                }
434
                last = expr;
435
        }
436
 
437
        if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
438
                goto err;
439
        if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0)
440
                goto err;
441
        return 0;
442
err:
443
        cond_node_destroy(node);
444
        return -1;
445
}
446
 
447
int cond_read_list(struct policydb *p, void *fp)
448
{
449
        struct cond_node *node, *last = NULL;
450
        __le32 buf[1];
451
        u32 i, len;
452
        int rc;
453
 
454
        rc = next_entry(buf, fp, sizeof buf);
455
        if (rc < 0)
456
                return -1;
457
 
458
        len = le32_to_cpu(buf[0]);
459
 
460
        rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
461
        if (rc)
462
                goto err;
463
 
464
        for (i = 0; i < len; i++) {
465
                node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
466
                if (!node)
467
                        goto err;
468
 
469
                if (cond_read_node(p, node, fp) != 0)
470
                        goto err;
471
 
472
                if (i == 0) {
473
                        p->cond_list = node;
474
                } else {
475
                        last->next = node;
476
                }
477
                last = node;
478
        }
479
        return 0;
480
err:
481
        cond_list_destroy(p->cond_list);
482
        p->cond_list = NULL;
483
        return -1;
484
}
485
 
486
/* Determine whether additional permissions are granted by the conditional
487
 * av table, and if so, add them to the result
488
 */
489
void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd)
490
{
491
        struct avtab_node *node;
492
 
493
        if(!ctab || !key || !avd)
494
                return;
495
 
496
        for(node = avtab_search_node(ctab, key); node != NULL;
497
                                node = avtab_search_node_next(node, key->specified)) {
498
                if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
499
                     (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
500
                        avd->allowed |= node->datum.data;
501
                if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
502
                     (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
503
                        /* Since a '0' in an auditdeny mask represents a
504
                         * permission we do NOT want to audit (dontaudit), we use
505
                         * the '&' operand to ensure that all '0's in the mask
506
                         * are retained (much unlike the allow and auditallow cases).
507
                         */
508
                        avd->auditdeny &= node->datum.data;
509
                if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
510
                     (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
511
                        avd->auditallow |= node->datum.data;
512
        }
513
        return;
514
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.