~ressu/+junk/xen-ubuntu

« back to all changes in this revision

Viewing changes to xen/xsm/flask/ss/services.c

  • Committer: sami at haahtinen
  • Author(s): Bastian Blank
  • Date: 2010-09-03 15:14:28 UTC
  • Revision ID: sami@haahtinen.name-20100903151428-f88eg54n2fdnak41
Tags: upstream-4.0.1
ImportĀ upstreamĀ versionĀ 4.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Implementation of the security services.
 
3
 *
 
4
 * Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
 
5
 *           James Morris <jmorris@redhat.com>
 
6
 *
 
7
 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
 
8
 *
 
9
 *    Support for enhanced MLS infrastructure.
 
10
 *
 
11
 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
 
12
 *
 
13
 *     Added conditional policy language extensions
 
14
 *
 
15
 * Updated: Hewlett-Packard <paul.moore@hp.com>
 
16
 *
 
17
 *      Added support for the policy capability bitmap
 
18
 *
 
19
 * Updated: Chad Sellers <csellers@tresys.com>
 
20
 *
 
21
 *  Added validation of kernel classes and permissions
 
22
 *
 
23
 * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
 
24
 *
 
25
 *  Added support for bounds domain and audit messaged on masked permissions
 
26
 *
 
27
 * Copyright (C) 2008, 2009 NEC Corporation
 
28
 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
 
29
 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
 
30
 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
 
31
 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
 
32
 *    This program is free software; you can redistribute it and/or modify
 
33
 *      it under the terms of the GNU General Public License as published by
 
34
 *    the Free Software Foundation, version 2.
 
35
 */
 
36
 
 
37
/* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
 
38
 
 
39
#include <xen/lib.h>
 
40
#include <xen/xmalloc.h>
 
41
#include <xen/string.h>
 
42
#include <xen/spinlock.h>
 
43
#include <xen/errno.h>
 
44
#include "flask.h"
 
45
#include "avc.h"
 
46
#include "avc_ss.h"
 
47
#include "security.h"
 
48
#include "context.h"
 
49
#include "policydb.h"
 
50
#include "sidtab.h"
 
51
#include "services.h"
 
52
#include "conditional.h"
 
53
#include "mls.h"
 
54
 
 
55
unsigned int policydb_loaded_version;
 
56
 
 
57
static DEFINE_RWLOCK(policy_rwlock);
 
58
#define POLICY_RDLOCK read_lock(&policy_rwlock)
 
59
#define POLICY_WRLOCK write_lock(&policy_rwlock)
 
60
#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
 
61
#define POLICY_WRUNLOCK write_unlock(&policy_rwlock)
 
62
 
 
63
static DEFINE_SPINLOCK(load_sem);
 
64
#define LOAD_LOCK spin_lock(&load_sem)
 
65
#define LOAD_UNLOCK spin_unlock(&load_sem)
 
66
 
 
67
static struct sidtab sidtab;
 
68
struct policydb policydb;
 
69
int ss_initialized = 0;
 
70
 
 
71
/*
 
72
 * The largest sequence number that has been used when
 
73
 * providing an access decision to the access vector cache.
 
74
 * The sequence number only changes when a policy change
 
75
 * occurs.
 
76
 */
 
77
static u32 latest_granting = 0;
 
78
 
 
79
/* Forward declaration. */
 
80
static int context_struct_to_string(struct context *context, char **scontext,
 
81
                                                            u32 *scontext_len);
 
82
 
 
83
static int context_struct_compute_av(struct context *scontext,
 
84
                                     struct context *tcontext,
 
85
                                     u16 tclass,
 
86
                                     u32 requested,
 
87
                                     struct av_decision *avd);
 
88
 
 
89
/*
 
90
 * Return the boolean value of a constraint expression
 
91
 * when it is applied to the specified source and target
 
92
 * security contexts.
 
93
 *
 
94
 * xcontext is a special beast...  It is used by the validatetrans rules
 
95
 * only.  For these rules, scontext is the context before the transition,
 
96
 * tcontext is the context after the transition, and xcontext is the context
 
97
 * of the process performing the transition.  All other callers of
 
98
 * constraint_expr_eval should pass in NULL for xcontext.
 
99
 */
 
100
static int constraint_expr_eval(struct context *scontext,
 
101
                            struct context *tcontext, struct context *xcontext, 
 
102
                                                struct constraint_expr *cexpr)
 
103
{
 
104
    u32 val1, val2;
 
105
    struct context *c;
 
106
    struct role_datum *r1, *r2;
 
107
    struct mls_level *l1, *l2;
 
108
    struct constraint_expr *e;
 
109
    int s[CEXPR_MAXDEPTH];
 
110
    int sp = -1;
 
111
 
 
112
    for ( e = cexpr; e; e = e->next )
 
113
    {
 
114
        switch ( e->expr_type )
 
115
        {
 
116
            case CEXPR_NOT:
 
117
                BUG_ON(sp < 0);
 
118
                s[sp] = !s[sp];
 
119
            break;
 
120
            case CEXPR_AND:
 
121
                BUG_ON(sp < 1);
 
122
                sp--;
 
123
                s[sp] &= s[sp+1];
 
124
            break;
 
125
            case CEXPR_OR:
 
126
                BUG_ON(sp < 1);
 
127
                sp--;
 
128
                s[sp] |= s[sp+1];
 
129
            break;
 
130
            case CEXPR_ATTR:
 
131
                if ( sp == (CEXPR_MAXDEPTH-1) )
 
132
                    return 0;
 
133
            switch ( e->attr )
 
134
            {
 
135
                case CEXPR_USER:
 
136
                    val1 = scontext->user;
 
137
                    val2 = tcontext->user;
 
138
                    break;
 
139
                case CEXPR_TYPE:
 
140
                    val1 = scontext->type;
 
141
                    val2 = tcontext->type;
 
142
                    break;
 
143
                case CEXPR_ROLE:
 
144
                    val1 = scontext->role;
 
145
                    val2 = tcontext->role;
 
146
                    r1 = policydb.role_val_to_struct[val1 - 1];
 
147
                    r2 = policydb.role_val_to_struct[val2 - 1];
 
148
                switch ( e->op )
 
149
                {
 
150
                    case CEXPR_DOM:
 
151
                        s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1);
 
152
                    continue;
 
153
                    case CEXPR_DOMBY:
 
154
                        s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1);
 
155
                    continue;
 
156
                    case CEXPR_INCOMP:
 
157
                        s[++sp] = ( !ebitmap_get_bit(&r1->dominates,
 
158
                                         val2 - 1) &&
 
159
                                !ebitmap_get_bit(&r2->dominates,
 
160
                                         val1 - 1) );
 
161
                    continue;
 
162
                    default:
 
163
                    break;
 
164
                }
 
165
                break;
 
166
                case CEXPR_L1L2:
 
167
                    l1 = &(scontext->range.level[0]);
 
168
                    l2 = &(tcontext->range.level[0]);
 
169
                    goto mls_ops;
 
170
                case CEXPR_L1H2:
 
171
                    l1 = &(scontext->range.level[0]);
 
172
                    l2 = &(tcontext->range.level[1]);
 
173
                    goto mls_ops;
 
174
                case CEXPR_H1L2:
 
175
                    l1 = &(scontext->range.level[1]);
 
176
                    l2 = &(tcontext->range.level[0]);
 
177
                    goto mls_ops;
 
178
                case CEXPR_H1H2:
 
179
                    l1 = &(scontext->range.level[1]);
 
180
                    l2 = &(tcontext->range.level[1]);
 
181
                    goto mls_ops;
 
182
                case CEXPR_L1H1:
 
183
                    l1 = &(scontext->range.level[0]);
 
184
                    l2 = &(scontext->range.level[1]);
 
185
                    goto mls_ops;
 
186
                case CEXPR_L2H2:
 
187
                    l1 = &(tcontext->range.level[0]);
 
188
                    l2 = &(tcontext->range.level[1]);
 
189
                    goto mls_ops;
 
190
mls_ops:
 
191
            switch ( e->op )
 
192
            {
 
193
                case CEXPR_EQ:
 
194
                    s[++sp] = mls_level_eq(l1, l2);
 
195
                continue;
 
196
                case CEXPR_NEQ:
 
197
                    s[++sp] = !mls_level_eq(l1, l2);
 
198
                continue;
 
199
                case CEXPR_DOM:
 
200
                    s[++sp] = mls_level_dom(l1, l2);
 
201
                continue;
 
202
                case CEXPR_DOMBY:
 
203
                    s[++sp] = mls_level_dom(l2, l1);
 
204
                continue;
 
205
                case CEXPR_INCOMP:
 
206
                    s[++sp] = mls_level_incomp(l2, l1);
 
207
                continue;
 
208
                default:
 
209
                    BUG();
 
210
                    return 0;
 
211
            }
 
212
            break;
 
213
            default:
 
214
                BUG();
 
215
                return 0;
 
216
            }
 
217
 
 
218
            switch ( e->op )
 
219
            {
 
220
                case CEXPR_EQ:
 
221
                    s[++sp] = (val1 == val2);
 
222
                break;
 
223
                case CEXPR_NEQ:
 
224
                    s[++sp] = (val1 != val2);
 
225
                break;
 
226
                default:
 
227
                    BUG();
 
228
                    return 0;
 
229
            }
 
230
            break;
 
231
            case CEXPR_NAMES:
 
232
                if ( sp == (CEXPR_MAXDEPTH-1) )
 
233
                    return 0;
 
234
                c = scontext;
 
235
                if ( e->attr & CEXPR_TARGET )
 
236
                    c = tcontext;
 
237
                else if ( e->attr & CEXPR_XTARGET )
 
238
                {
 
239
                    c = xcontext;
 
240
                    if ( !c )
 
241
                    {
 
242
                        BUG();
 
243
                        return 0;
 
244
                    }
 
245
                }
 
246
                if ( e->attr & CEXPR_USER )
 
247
                    val1 = c->user;
 
248
                else if ( e->attr & CEXPR_ROLE )
 
249
                    val1 = c->role;
 
250
                else if ( e->attr & CEXPR_TYPE )
 
251
                    val1 = c->type;
 
252
                else
 
253
                {
 
254
                    BUG();
 
255
                    return 0;
 
256
                }
 
257
 
 
258
            switch ( e->op )
 
259
            {
 
260
                case CEXPR_EQ:
 
261
                    s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
 
262
                break;
 
263
                case CEXPR_NEQ:
 
264
                    s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
 
265
                break;
 
266
                default:
 
267
                    BUG();
 
268
                    return 0;
 
269
            }
 
270
            break;
 
271
            default:
 
272
                BUG();
 
273
                return 0;
 
274
        }
 
275
    }
 
276
 
 
277
    BUG_ON(sp != 0);
 
278
    return s[0];
 
279
}
 
280
 
 
281
/*
 
282
 * security_dump_masked_av - dumps masked permissions during
 
283
 * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
 
284
 */
 
285
static int dump_masked_av_helper(void *k, void *d, void *args)
 
286
{
 
287
    struct perm_datum *pdatum = d;
 
288
    char **permission_names = args;
 
289
 
 
290
    BUG_ON(pdatum->value < 1 || pdatum->value > 32);
 
291
 
 
292
    permission_names[pdatum->value - 1] = (char *)k;
 
293
 
 
294
    return 0;
 
295
}
 
296
 
 
297
static void security_dump_masked_av(struct context *scontext,
 
298
                                    struct context *tcontext,
 
299
                                    u16 tclass,
 
300
                                    u32 permissions,
 
301
                                    const char *reason)
 
302
{
 
303
    struct common_datum *common_dat;
 
304
    struct class_datum *tclass_dat;
 
305
    char *tclass_name;
 
306
    char *scontext_name = NULL;
 
307
    char *tcontext_name = NULL;
 
308
    char *permission_names[32];
 
309
    int index;
 
310
    u32 length;
 
311
    unsigned char need_comma = 0;
 
312
 
 
313
    if ( !permissions )
 
314
        return;
 
315
 
 
316
    tclass_name = policydb.p_class_val_to_name[tclass - 1];
 
317
    tclass_dat = policydb.class_val_to_struct[tclass - 1];
 
318
    common_dat = tclass_dat->comdatum;
 
319
 
 
320
    /* init permission_names */
 
321
    if ( common_dat &&
 
322
         hashtab_map(common_dat->permissions.table,
 
323
                     dump_masked_av_helper, permission_names) < 0 )
 
324
        goto out;
 
325
 
 
326
    if ( hashtab_map(tclass_dat->permissions.table,
 
327
                    dump_masked_av_helper, permission_names) < 0 )
 
328
        goto out;
 
329
 
 
330
        /* get scontext/tcontext in text form */
 
331
    if ( context_struct_to_string(scontext,
 
332
                                 &scontext_name, &length) < 0 )
 
333
        goto out;
 
334
 
 
335
    if ( context_struct_to_string(tcontext,
 
336
                                 &tcontext_name, &length) < 0 )
 
337
        goto out;
 
338
 
 
339
    printk("Flask: op=security_compute_av reason=%s "
 
340
           "scontext=%s tcontext=%s tclass=%s perms=",
 
341
           reason, scontext_name, tcontext_name, tclass_name);
 
342
 
 
343
    for ( index = 0; index < 32; index++ )
 
344
    {
 
345
        u32 mask = (1 << index);
 
346
 
 
347
        if ( (mask & permissions) == 0 )
 
348
            continue;
 
349
 
 
350
        printk("%s%s",
 
351
               need_comma ? "," : "",
 
352
               permission_names[index]
 
353
               ? permission_names[index] : "????");
 
354
        need_comma = 1;
 
355
    }
 
356
    printk("\n");
 
357
out:
 
358
    /* release scontext/tcontext */
 
359
    xfree(tcontext_name);
 
360
    xfree(scontext_name);
 
361
 
 
362
    return;
 
363
}
 
364
 
 
365
/*
 
366
 * security_boundary_permission - drops violated permissions
 
367
 * on boundary constraint.
 
368
 */
 
369
static void type_attribute_bounds_av(struct context *scontext,
 
370
                                     struct context *tcontext,
 
371
                                     u16 tclass,
 
372
                                     u32 requested,
 
373
                                     struct av_decision *avd)
 
374
{
 
375
    struct context lo_scontext;
 
376
    struct context lo_tcontext;
 
377
    struct av_decision lo_avd;
 
378
    struct type_datum *source
 
379
        = policydb.type_val_to_struct[scontext->type - 1];
 
380
    struct type_datum *target
 
381
        = policydb.type_val_to_struct[tcontext->type - 1];
 
382
    u32 masked = 0;
 
383
 
 
384
    if ( source->bounds )
 
385
    {
 
386
        memset(&lo_avd, 0, sizeof(lo_avd));
 
387
 
 
388
        memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
 
389
        lo_scontext.type = source->bounds;
 
390
 
 
391
        context_struct_compute_av(&lo_scontext,
 
392
                                  tcontext,
 
393
                                  tclass,
 
394
                                  requested,
 
395
                                  &lo_avd);
 
396
        if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
 
397
            return;             /* no masked permission */
 
398
        masked = ~lo_avd.allowed & avd->allowed;
 
399
    }
 
400
 
 
401
    if ( target->bounds )
 
402
    {
 
403
        memset(&lo_avd, 0, sizeof(lo_avd));
 
404
 
 
405
        memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
 
406
        lo_tcontext.type = target->bounds;
 
407
 
 
408
        context_struct_compute_av(scontext,
 
409
                                  &lo_tcontext,
 
410
                                  tclass,
 
411
                                  requested,
 
412
                                  &lo_avd);
 
413
        if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
 
414
            return;             /* no masked permission */
 
415
        masked = ~lo_avd.allowed & avd->allowed;
 
416
    }
 
417
 
 
418
    if ( source->bounds && target->bounds )
 
419
    {
 
420
        memset(&lo_avd, 0, sizeof(lo_avd));
 
421
        /*
 
422
         * lo_scontext and lo_tcontext are already
 
423
         * set up.
 
424
         */
 
425
 
 
426
        context_struct_compute_av(&lo_scontext,
 
427
                                  &lo_tcontext,
 
428
                                  tclass,
 
429
                                  requested,
 
430
                                  &lo_avd);
 
431
        if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
 
432
            return;             /* no masked permission */
 
433
        masked = ~lo_avd.allowed & avd->allowed;
 
434
    }
 
435
 
 
436
    if ( masked )
 
437
    {
 
438
        /* mask violated permissions */
 
439
        avd->allowed &= ~masked;
 
440
 
 
441
        /* audit masked permissions */
 
442
        security_dump_masked_av(scontext, tcontext,
 
443
                                tclass, masked, "bounds");
 
444
    }
 
445
}
 
446
 
 
447
/*
 
448
 * Compute access vectors based on a context structure pair for
 
449
 * the permissions in a particular class.
 
450
 */
 
451
static int context_struct_compute_av(struct context *scontext,
 
452
                                     struct context *tcontext,
 
453
                                     u16 tclass,
 
454
                                     u32 requested,
 
455
                                     struct av_decision *avd)
 
456
{
 
457
    struct constraint_node *constraint;
 
458
    struct role_allow *ra;
 
459
    struct avtab_key avkey;
 
460
    struct avtab_node *node;
 
461
    struct class_datum *tclass_datum;
 
462
    struct ebitmap *sattr, *tattr;
 
463
    struct ebitmap_node *snode, *tnode;
 
464
    unsigned int i, j;
 
465
 
 
466
    /*
 
467
     * Initialize the access vectors to the default values.
 
468
     */
 
469
    avd->allowed = 0;
 
470
    avd->auditallow = 0;
 
471
    avd->auditdeny = 0xffffffff;
 
472
    avd->seqno = latest_granting;
 
473
    avd->flags = 0;
 
474
 
 
475
    /*
 
476
     * We do not presently support policydb.handle_unknown == allow in Xen.
 
477
     */
 
478
    if ( !tclass || tclass > policydb.p_classes.nprim )
 
479
        return -EINVAL;
 
480
 
 
481
    tclass_datum = policydb.class_val_to_struct[tclass - 1];
 
482
 
 
483
    /*
 
484
     * If a specific type enforcement rule was defined for
 
485
     * this permission check, then use it.
 
486
     */
 
487
    avkey.target_class = tclass;
 
488
    avkey.specified = AVTAB_AV;
 
489
    sattr = &policydb.type_attr_map[scontext->type - 1];
 
490
    tattr = &policydb.type_attr_map[tcontext->type - 1];
 
491
    ebitmap_for_each_positive_bit(sattr, snode, i)
 
492
    {
 
493
        ebitmap_for_each_positive_bit(tattr, tnode, j)
 
494
        {
 
495
            avkey.source_type = i + 1;
 
496
            avkey.target_type = j + 1;
 
497
            for ( node = avtab_search_node(&policydb.te_avtab, &avkey);
 
498
                 node != NULL;
 
499
                 node = avtab_search_node_next(node, avkey.specified) )
 
500
            {
 
501
                if ( node->key.specified == AVTAB_ALLOWED )
 
502
                    avd->allowed |= node->datum.data;
 
503
                else if ( node->key.specified == AVTAB_AUDITALLOW )
 
504
                    avd->auditallow |= node->datum.data;
 
505
                else if ( node->key.specified == AVTAB_AUDITDENY )
 
506
                    avd->auditdeny &= node->datum.data;
 
507
            }
 
508
 
 
509
            /* Check conditional av table for additional permissions */
 
510
            cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
 
511
 
 
512
        }
 
513
    }
 
514
 
 
515
    /*
 
516
     * Remove any permissions prohibited by a constraint (this includes
 
517
     * the MLS policy).
 
518
     */
 
519
    constraint = tclass_datum->constraints;
 
520
    while ( constraint )
 
521
    {
 
522
        if ( (constraint->permissions & (avd->allowed) ) &&
 
523
            !constraint_expr_eval(scontext, tcontext, NULL, constraint->expr))
 
524
        {
 
525
            avd->allowed &= ~(constraint->permissions);
 
526
        }
 
527
        constraint = constraint->next;
 
528
    }
 
529
 
 
530
    /*
 
531
     * If checking process transition permission and the
 
532
     * role is changing, then check the (current_role, new_role)
 
533
     * pair.
 
534
     */
 
535
    if ( tclass == SECCLASS_DOMAIN &&
 
536
         (avd->allowed & DOMAIN__TRANSITION) &&
 
537
         scontext->role != tcontext->role )
 
538
    {
 
539
        for ( ra = policydb.role_allow; ra; ra = ra->next )
 
540
        {
 
541
            if ( scontext->role == ra->role && tcontext->role == ra->new_role )
 
542
                break;
 
543
        }
 
544
        if (!ra)
 
545
            avd->allowed &= ~DOMAIN__TRANSITION;
 
546
    }
 
547
 
 
548
    /*
 
549
     * If the given source and target types have boundary
 
550
     * constraint, lazy checks have to mask any violated
 
551
     * permission and notice it to userspace via audit.
 
552
     */
 
553
    type_attribute_bounds_av(scontext, tcontext,
 
554
                             tclass, requested, avd);
 
555
    return 0;
 
556
}
 
557
 
 
558
static int security_validtrans_handle_fail(struct context *ocontext,
 
559
                struct context *ncontext, struct context *tcontext, u16 tclass)
 
560
{
 
561
    char *o = NULL, *n = NULL, *t = NULL;
 
562
    u32 olen, nlen, tlen;
 
563
 
 
564
    if ( context_struct_to_string(ocontext, &o, &olen) < 0 )
 
565
        goto out;
 
566
    if ( context_struct_to_string(ncontext, &n, &nlen) < 0 )
 
567
        goto out;
 
568
    if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
 
569
        goto out;
 
570
    printk("security_validate_transition:  denied for"
 
571
              " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
 
572
              o, n, t, policydb.p_class_val_to_name[tclass-1]);
 
573
out:
 
574
    xfree(o);
 
575
    xfree(n);
 
576
    xfree(t);
 
577
 
 
578
    if ( !flask_enforcing )
 
579
        return 0;
 
580
    return -EPERM;
 
581
}
 
582
 
 
583
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
 
584
                                 u16 tclass)
 
585
{
 
586
    struct context *ocontext;
 
587
    struct context *ncontext;
 
588
    struct context *tcontext;
 
589
    struct class_datum *tclass_datum;
 
590
    struct constraint_node *constraint;
 
591
    int rc = 0;
 
592
 
 
593
    if ( !ss_initialized )
 
594
        return 0;
 
595
 
 
596
    POLICY_RDLOCK;
 
597
 
 
598
    if ( !tclass || tclass > policydb.p_classes.nprim )
 
599
    {
 
600
        printk(KERN_ERR "security_validate_transition: "
 
601
                                            "unrecognized class %d\n", tclass);
 
602
        rc = -EINVAL;
 
603
        goto out;
 
604
    }
 
605
    tclass_datum = policydb.class_val_to_struct[tclass - 1];
 
606
 
 
607
    ocontext = sidtab_search(&sidtab, oldsid);
 
608
    if ( !ocontext )
 
609
    {
 
610
        printk(KERN_ERR "security_validate_transition: "
 
611
               " unrecognized SID %d\n", oldsid);
 
612
        rc = -EINVAL;
 
613
        goto out;
 
614
    }
 
615
 
 
616
    ncontext = sidtab_search(&sidtab, newsid);
 
617
    if ( !ncontext )
 
618
    {
 
619
        printk(KERN_ERR "security_validate_transition: "
 
620
               " unrecognized SID %d\n", newsid);
 
621
        rc = -EINVAL;
 
622
        goto out;
 
623
    }
 
624
 
 
625
    tcontext = sidtab_search(&sidtab, tasksid);
 
626
    if ( !tcontext )
 
627
    {
 
628
        printk(KERN_ERR "security_validate_transition: "
 
629
               " unrecognized SID %d\n", tasksid);
 
630
        rc = -EINVAL;
 
631
        goto out;
 
632
    }
 
633
 
 
634
    constraint = tclass_datum->validatetrans;
 
635
    while ( constraint )
 
636
    {
 
637
        if ( !constraint_expr_eval(ocontext, ncontext, tcontext,
 
638
                                                            constraint->expr) )
 
639
        {
 
640
            rc = security_validtrans_handle_fail(ocontext, ncontext,
 
641
                                                 tcontext, tclass);
 
642
            goto out;
 
643
        }
 
644
        constraint = constraint->next;
 
645
    }
 
646
 
 
647
out:
 
648
    POLICY_RDUNLOCK;
 
649
    return rc;
 
650
}
 
651
 
 
652
/**
 
653
 * security_compute_av - Compute access vector decisions.
 
654
 * @ssid: source security identifier
 
655
 * @tsid: target security identifier
 
656
 * @tclass: target security class
 
657
 * @requested: requested permissions
 
658
 * @avd: access vector decisions
 
659
 *
 
660
 * Compute a set of access vector decisions based on the
 
661
 * SID pair (@ssid, @tsid) for the permissions in @tclass.
 
662
 * Return -%EINVAL if any of the parameters are invalid or %0
 
663
 * if the access vector decisions were computed successfully.
 
664
 */
 
665
int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested,
 
666
                        struct av_decision *avd)
 
667
{
 
668
    struct context *scontext = NULL, *tcontext = NULL;
 
669
    int rc = 0;
 
670
 
 
671
    if ( !ss_initialized )
 
672
    {
 
673
        avd->allowed = 0xffffffff;
 
674
        avd->auditallow = 0;
 
675
        avd->auditdeny = 0xffffffff;
 
676
        avd->seqno = latest_granting;
 
677
        return 0;
 
678
    }
 
679
 
 
680
    POLICY_RDLOCK;
 
681
 
 
682
    scontext = sidtab_search(&sidtab, ssid);
 
683
    if ( !scontext )
 
684
    {
 
685
        printk("security_compute_av:  unrecognized SID %d\n", ssid);
 
686
        rc = -EINVAL;
 
687
        goto out;
 
688
    }
 
689
    tcontext = sidtab_search(&sidtab, tsid);
 
690
    if ( !tcontext )
 
691
    {
 
692
        printk("security_compute_av:  unrecognized SID %d\n", tsid);
 
693
        rc = -EINVAL;
 
694
        goto out;
 
695
    }
 
696
 
 
697
    rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd);
 
698
 
 
699
    /* permissive domain? */
 
700
    if ( ebitmap_get_bit(&policydb.permissive_map, scontext->type) )
 
701
        avd->flags |= AVD_FLAGS_PERMISSIVE;
 
702
out:
 
703
    POLICY_RDUNLOCK;
 
704
    return rc;
 
705
}
 
706
 
 
707
/*
 
708
 * Write the security context string representation of
 
709
 * the context structure `context' into a dynamically
 
710
 * allocated string of the correct size.  Set `*scontext'
 
711
 * to point to this string and set `*scontext_len' to
 
712
 * the length of the string.
 
713
 */
 
714
static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
 
715
{
 
716
    char *scontextp;
 
717
 
 
718
    *scontext = NULL;
 
719
    *scontext_len = 0;
 
720
 
 
721
    /* Compute the size of the context. */
 
722
    *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
 
723
    *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
 
724
    *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
 
725
    *scontext_len += mls_compute_context_len(context);
 
726
 
 
727
    /* Allocate space for the context; caller must free this space. */
 
728
    scontextp = xmalloc_array(char, *scontext_len);
 
729
    if ( !scontextp )
 
730
        return -ENOMEM;
 
731
 
 
732
    *scontext = scontextp;
 
733
 
 
734
    /*
 
735
     * Copy the user name, role name and type name into the context.
 
736
     */
 
737
    snprintf(scontextp, *scontext_len, "%s:%s:%s",
 
738
        policydb.p_user_val_to_name[context->user - 1],
 
739
        policydb.p_role_val_to_name[context->role - 1],
 
740
        policydb.p_type_val_to_name[context->type - 1]);
 
741
    scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
 
742
                 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
 
743
                 1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
 
744
 
 
745
    mls_sid_to_context(context, &scontextp);
 
746
 
 
747
    *scontextp = 0;
 
748
 
 
749
    return 0;
 
750
}
 
751
 
 
752
#include "initial_sid_to_string.h"
 
753
 
 
754
/**
 
755
 * security_sid_to_context - Obtain a context for a given SID.
 
756
 * @sid: security identifier, SID
 
757
 * @scontext: security context
 
758
 * @scontext_len: length in bytes
 
759
 *
 
760
 * Write the string representation of the context associated with @sid
 
761
 * into a dynamically allocated string of the correct size.  Set @scontext
 
762
 * to point to this string and set @scontext_len to the length of the string.
 
763
 */
 
764
int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
 
765
{
 
766
    struct context *context;
 
767
    int rc = 0;
 
768
 
 
769
    if ( !ss_initialized )
 
770
    {
 
771
        if ( sid <= SECINITSID_NUM )
 
772
        {
 
773
            char *scontextp;
 
774
 
 
775
            *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
 
776
            scontextp = xmalloc_array(char, *scontext_len);
 
777
            strlcpy(scontextp, initial_sid_to_string[sid], *scontext_len);
 
778
            *scontext = scontextp;
 
779
            goto out;
 
780
        }
 
781
        printk(KERN_ERR "security_sid_to_context:  called before initial "
 
782
               "load_policy on unknown SID %d\n", sid);
 
783
        rc = -EINVAL;
 
784
        goto out;
 
785
    }
 
786
    POLICY_RDLOCK;
 
787
    context = sidtab_search(&sidtab, sid);
 
788
    if ( !context )
 
789
    {
 
790
        printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
 
791
               "%d\n", sid);
 
792
        rc = -EINVAL;
 
793
        goto out_unlock;
 
794
    }
 
795
    rc = context_struct_to_string(context, scontext, scontext_len);
 
796
out_unlock:
 
797
    POLICY_RDUNLOCK;
 
798
out:
 
799
    return rc;
 
800
 
 
801
}
 
802
 
 
803
/**
 
804
 * security_context_to_sid - Obtain a SID for a given security context.
 
805
 * @scontext: security context
 
806
 * @scontext_len: length in bytes
 
807
 * @sid: security identifier, SID
 
808
 *
 
809
 * Obtains a SID associated with the security context that
 
810
 * has the string representation specified by @scontext.
 
811
 * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
 
812
 * memory is available, or 0 on success.
 
813
 */
 
814
int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
 
815
{
 
816
    char *scontext2;
 
817
    struct context context;
 
818
    struct role_datum *role;
 
819
    struct type_datum *typdatum;
 
820
    struct user_datum *usrdatum;
 
821
    char *scontextp, *p, oldc;
 
822
    int rc = 0;
 
823
 
 
824
    if ( !ss_initialized )
 
825
    {
 
826
        int i;
 
827
 
 
828
        for ( i = 1; i < SECINITSID_NUM; i++ )
 
829
        {
 
830
            if ( !strcmp(initial_sid_to_string[i], scontext) )
 
831
            {
 
832
                *sid = i;
 
833
                goto out;
 
834
            }
 
835
        }
 
836
        *sid = SECINITSID_XEN;
 
837
        goto out;
 
838
    }
 
839
    *sid = SECSID_NULL;
 
840
 
 
841
    /* Copy the string so that we can modify the copy as we parse it.
 
842
       The string should already by null terminated, but we append a
 
843
       null suffix to the copy to avoid problems with the existing
 
844
       attr package, which doesn't view the null terminator as part
 
845
       of the attribute value. */
 
846
    scontext2 = xmalloc_array(char, scontext_len+1);
 
847
    if ( !scontext2 )
 
848
    {
 
849
        rc = -ENOMEM;
 
850
        goto out;
 
851
    }
 
852
    memcpy(scontext2, scontext, scontext_len);
 
853
    scontext2[scontext_len] = 0;
 
854
 
 
855
    context_init(&context);
 
856
    *sid = SECSID_NULL;
 
857
 
 
858
    POLICY_RDLOCK;
 
859
 
 
860
    /* Parse the security context. */
 
861
 
 
862
    rc = -EINVAL;
 
863
    scontextp = (char *) scontext2;
 
864
 
 
865
    /* Extract the user. */
 
866
    p = scontextp;
 
867
    while ( *p && *p != ':' )
 
868
        p++;
 
869
 
 
870
    if (*p == 0)
 
871
        goto out_unlock;
 
872
 
 
873
    *p++ = 0;
 
874
 
 
875
    usrdatum = hashtab_search(policydb.p_users.table, scontextp);
 
876
    if ( !usrdatum )
 
877
        goto out_unlock;
 
878
 
 
879
    context.user = usrdatum->value;
 
880
 
 
881
    /* Extract role. */
 
882
    scontextp = p;
 
883
    while ( *p && *p != ':' )
 
884
        p++;
 
885
 
 
886
    if ( *p == 0 )
 
887
        goto out_unlock;
 
888
 
 
889
    *p++ = 0;
 
890
 
 
891
    role = hashtab_search(policydb.p_roles.table, scontextp);
 
892
    if ( !role )
 
893
        goto out_unlock;
 
894
    context.role = role->value;
 
895
 
 
896
    /* Extract type. */
 
897
    scontextp = p;
 
898
    while ( *p && *p != ':' )
 
899
        p++;
 
900
    oldc = *p;
 
901
    *p++ = 0;
 
902
 
 
903
    typdatum = hashtab_search(policydb.p_types.table, scontextp);
 
904
    if ( !typdatum || typdatum->attribute )
 
905
        goto out_unlock;
 
906
 
 
907
    context.type = typdatum->value;
 
908
 
 
909
    rc = mls_context_to_sid(oldc, &p, &context, &sidtab);
 
910
    if ( rc )
 
911
        goto out_unlock;
 
912
 
 
913
    if ( (p - scontext2) < scontext_len )
 
914
    {
 
915
        rc = -EINVAL;
 
916
        goto out_unlock;
 
917
    }
 
918
 
 
919
    /* Check the validity of the new context. */
 
920
    if ( !policydb_context_isvalid(&policydb, &context) )
 
921
    {
 
922
        rc = -EINVAL;
 
923
        goto out_unlock;
 
924
    }
 
925
    /* Obtain the new sid. */
 
926
    rc = sidtab_context_to_sid(&sidtab, &context, sid);
 
927
out_unlock:
 
928
    POLICY_RDUNLOCK;
 
929
    context_destroy(&context);
 
930
    xfree(scontext2);
 
931
out:
 
932
    return rc;
 
933
}
 
934
 
 
935
static int compute_sid_handle_invalid_context(
 
936
                struct context *scontext, struct context *tcontext, u16 tclass,
 
937
                                                    struct context *newcontext)
 
938
{
 
939
    char *s = NULL, *t = NULL, *n = NULL;
 
940
    u32 slen, tlen, nlen;
 
941
 
 
942
    if ( context_struct_to_string(scontext, &s, &slen) < 0 )
 
943
        goto out;
 
944
    if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
 
945
        goto out;
 
946
    if ( context_struct_to_string(newcontext, &n, &nlen) < 0 )
 
947
        goto out;
 
948
    printk("security_compute_sid:  invalid context %s"
 
949
          " for scontext=%s"
 
950
          " tcontext=%s"
 
951
          " tclass=%s",
 
952
          n, s, t, policydb.p_class_val_to_name[tclass-1]);
 
953
out:
 
954
    xfree(s);
 
955
    xfree(t);
 
956
    xfree(n);
 
957
    if ( !flask_enforcing )
 
958
        return 0;
 
959
    return -EACCES;
 
960
}
 
961
 
 
962
static int security_compute_sid(u32 ssid,
 
963
                u32 tsid,
 
964
                u16 tclass,
 
965
                u32 specified,
 
966
                u32 *out_sid)
 
967
{
 
968
    struct context *scontext = NULL, *tcontext = NULL, newcontext;
 
969
    struct role_trans *roletr = NULL;
 
970
    struct avtab_key avkey;
 
971
    struct avtab_datum *avdatum;
 
972
    struct avtab_node *node;
 
973
    int rc = 0;
 
974
 
 
975
    if ( !ss_initialized )
 
976
    {
 
977
        switch ( tclass )
 
978
        {
 
979
            case SECCLASS_DOMAIN:
 
980
                *out_sid = ssid;
 
981
            break;
 
982
            default:
 
983
                *out_sid = tsid;
 
984
            break;
 
985
        }
 
986
        goto out;
 
987
    }
 
988
 
 
989
    POLICY_RDLOCK;
 
990
 
 
991
    scontext = sidtab_search(&sidtab, ssid);
 
992
    if ( !scontext )
 
993
    {
 
994
        printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", ssid);
 
995
        rc = -EINVAL;
 
996
        goto out_unlock;
 
997
    }
 
998
    tcontext = sidtab_search(&sidtab, tsid);
 
999
    if ( !tcontext )
 
1000
    {
 
1001
        printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", tsid);
 
1002
        rc = -EINVAL;
 
1003
        goto out_unlock;
 
1004
    }
 
1005
 
 
1006
    context_init(&newcontext);
 
1007
 
 
1008
    /* Set the user identity. */
 
1009
    switch ( specified )
 
1010
    {
 
1011
        case AVTAB_TRANSITION:
 
1012
        case AVTAB_CHANGE:
 
1013
            /* Use the process user identity. */
 
1014
            newcontext.user = scontext->user;
 
1015
        break;
 
1016
        case AVTAB_MEMBER:
 
1017
            /* Use the related object owner. */
 
1018
            newcontext.user = tcontext->user;
 
1019
        break;
 
1020
    }
 
1021
 
 
1022
    /* Set the role and type to default values. */
 
1023
    switch ( tclass )
 
1024
    {
 
1025
        case SECCLASS_DOMAIN:
 
1026
            /* Use the current role and type of process. */
 
1027
            newcontext.role = scontext->role;
 
1028
            newcontext.type = scontext->type;
 
1029
        break;
 
1030
        default:
 
1031
            /* Use the well-defined object role. */
 
1032
            newcontext.role = OBJECT_R_VAL;
 
1033
            /* Use the type of the related object. */
 
1034
            newcontext.type = tcontext->type;
 
1035
    }
 
1036
 
 
1037
    /* Look for a type transition/member/change rule. */
 
1038
    avkey.source_type = scontext->type;
 
1039
    avkey.target_type = tcontext->type;
 
1040
    avkey.target_class = tclass;
 
1041
    avkey.specified = specified;
 
1042
    avdatum = avtab_search(&policydb.te_avtab, &avkey);
 
1043
 
 
1044
    /* If no permanent rule, also check for enabled conditional rules */
 
1045
    if ( !avdatum )
 
1046
    {
 
1047
        node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
 
1048
        for ( ; node != NULL; node = avtab_search_node_next(node, specified) )
 
1049
        {
 
1050
            if ( node->key.specified & AVTAB_ENABLED )
 
1051
            {
 
1052
                avdatum = &node->datum;
 
1053
                break;
 
1054
            }
 
1055
        }
 
1056
    }
 
1057
 
 
1058
    if ( avdatum )
 
1059
    {
 
1060
        /* Use the type from the type transition/member/change rule. */
 
1061
        newcontext.type = avdatum->data;
 
1062
    }
 
1063
 
 
1064
    /* Check for class-specific changes. */
 
1065
    switch ( tclass )
 
1066
    {
 
1067
        case SECCLASS_DOMAIN:
 
1068
            if ( specified & AVTAB_TRANSITION )
 
1069
            {
 
1070
                /* Look for a role transition rule. */
 
1071
                for ( roletr = policydb.role_tr; roletr; roletr = roletr->next )
 
1072
                {
 
1073
                    if ( roletr->role == scontext->role && 
 
1074
                                            roletr->type == tcontext->type )
 
1075
                    {
 
1076
                        /* Use the role transition rule. */
 
1077
                        newcontext.role = roletr->new_role;
 
1078
                        break;
 
1079
                    }
 
1080
                }
 
1081
            }
 
1082
        break;
 
1083
        default:
 
1084
        break;
 
1085
    }
 
1086
 
 
1087
    /* Set the MLS attributes.
 
1088
       This is done last because it may allocate memory. */
 
1089
    rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
 
1090
    if ( rc )
 
1091
        goto out_unlock;
 
1092
 
 
1093
    /* Check the validity of the context. */
 
1094
    if ( !policydb_context_isvalid(&policydb, &newcontext) )
 
1095
    {
 
1096
        rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass,
 
1097
                                                                &newcontext);
 
1098
        if ( rc )
 
1099
            goto out_unlock;
 
1100
    }
 
1101
    /* Obtain the sid for the context. */
 
1102
    rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
 
1103
out_unlock:
 
1104
    POLICY_RDUNLOCK;
 
1105
    context_destroy(&newcontext);
 
1106
out:
 
1107
    return rc;
 
1108
}
 
1109
 
 
1110
/**
 
1111
 * security_transition_sid - Compute the SID for a new subject/object.
 
1112
 * @ssid: source security identifier
 
1113
 * @tsid: target security identifier
 
1114
 * @tclass: target security class
 
1115
 * @out_sid: security identifier for new subject/object
 
1116
 *
 
1117
 * Compute a SID to use for labeling a new subject or object in the
 
1118
 * class @tclass based on a SID pair (@ssid, @tsid).
 
1119
 * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
 
1120
 * if insufficient memory is available, or %0 if the new SID was
 
1121
 * computed successfully.
 
1122
 */
 
1123
int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
 
1124
{
 
1125
    return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
 
1126
}
 
1127
 
 
1128
/**
 
1129
 * security_member_sid - Compute the SID for member selection.
 
1130
 * @ssid: source security identifier
 
1131
 * @tsid: target security identifier
 
1132
 * @tclass: target security class
 
1133
 * @out_sid: security identifier for selected member
 
1134
 *
 
1135
 * Compute a SID to use when selecting a member of a polyinstantiated
 
1136
 * object of class @tclass based on a SID pair (@ssid, @tsid).
 
1137
 * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
 
1138
 * if insufficient memory is available, or %0 if the SID was
 
1139
 * computed successfully.
 
1140
 */
 
1141
int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
 
1142
{
 
1143
    return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
 
1144
}
 
1145
 
 
1146
/**
 
1147
 * security_change_sid - Compute the SID for object relabeling.
 
1148
 * @ssid: source security identifier
 
1149
 * @tsid: target security identifier
 
1150
 * @tclass: target security class
 
1151
 * @out_sid: security identifier for selected member
 
1152
 *
 
1153
 * Compute a SID to use for relabeling an object of class @tclass
 
1154
 * based on a SID pair (@ssid, @tsid).
 
1155
 * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
 
1156
 * if insufficient memory is available, or %0 if the SID was
 
1157
 * computed successfully.
 
1158
 */
 
1159
int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
 
1160
{
 
1161
    return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
 
1162
}
 
1163
 
 
1164
/*
 
1165
 * Verify that each kernel class that is defined in the
 
1166
 * policy is correct
 
1167
 */
 
1168
static int validate_classes(struct policydb *p)
 
1169
{
 
1170
    int i, j;
 
1171
    struct class_datum *cladatum;
 
1172
    struct perm_datum *perdatum;
 
1173
    u32 nprim, tmp, common_pts_len, perm_val, pol_val;
 
1174
    u16 class_val;
 
1175
    const struct selinux_class_perm *kdefs = &selinux_class_perm;
 
1176
    const char *def_class, *def_perm, *pol_class;
 
1177
    struct symtab *perms;
 
1178
 
 
1179
    for ( i = 1; i < kdefs->cts_len; i++ )
 
1180
    {
 
1181
        def_class = kdefs->class_to_string[i];
 
1182
        if ( !def_class )
 
1183
            continue;
 
1184
        if ( i > p->p_classes.nprim )
 
1185
        {
 
1186
            printk(KERN_INFO
 
1187
                   "Flask:  class %s not defined in policy\n",
 
1188
                   def_class);
 
1189
            return -EINVAL;
 
1190
        }
 
1191
        pol_class = p->p_class_val_to_name[i-1];
 
1192
        if ( strcmp(pol_class, def_class) )
 
1193
        {
 
1194
            printk(KERN_ERR
 
1195
                   "Flask:  class %d is incorrect, found %s but should be %s\n",
 
1196
                   i, pol_class, def_class);
 
1197
            return -EINVAL;
 
1198
        }
 
1199
    }
 
1200
    for ( i = 0; i < kdefs->av_pts_len; i++ )
 
1201
    {
 
1202
        class_val = kdefs->av_perm_to_string[i].tclass;
 
1203
        perm_val = kdefs->av_perm_to_string[i].value;
 
1204
        def_perm = kdefs->av_perm_to_string[i].name;
 
1205
        if ( class_val > p->p_classes.nprim )
 
1206
            continue;
 
1207
        pol_class = p->p_class_val_to_name[class_val-1];
 
1208
        cladatum = hashtab_search(p->p_classes.table, pol_class);
 
1209
        BUG_ON( !cladatum );
 
1210
        perms = &cladatum->permissions;
 
1211
        nprim = 1 << (perms->nprim - 1);
 
1212
        if ( perm_val > nprim )
 
1213
        {
 
1214
            printk(KERN_INFO
 
1215
                   "Flask:  permission %s in class %s not defined in policy\n",
 
1216
                   def_perm, pol_class);
 
1217
            return -EINVAL;
 
1218
        }
 
1219
        perdatum = hashtab_search(perms->table, def_perm);
 
1220
        if ( perdatum == NULL )
 
1221
        {
 
1222
            printk(KERN_ERR
 
1223
                   "Flask:  permission %s in class %s not found in policy\n",
 
1224
                   def_perm, pol_class);
 
1225
            return -EINVAL;
 
1226
        }
 
1227
        pol_val = 1 << (perdatum->value - 1);
 
1228
        if ( pol_val != perm_val )
 
1229
        {
 
1230
            printk(KERN_ERR
 
1231
                   "Flask:  permission %s in class %s has incorrect value\n",
 
1232
                   def_perm, pol_class);
 
1233
            return -EINVAL;
 
1234
        }
 
1235
    }
 
1236
    for ( i = 0; i < kdefs->av_inherit_len; i++ )
 
1237
    {
 
1238
        class_val = kdefs->av_inherit[i].tclass;
 
1239
        if ( class_val > p->p_classes.nprim )
 
1240
            continue;
 
1241
        pol_class = p->p_class_val_to_name[class_val-1];
 
1242
        cladatum = hashtab_search(p->p_classes.table, pol_class);
 
1243
        BUG_ON( !cladatum );
 
1244
        if ( !cladatum->comdatum )
 
1245
        {
 
1246
            printk(KERN_ERR
 
1247
            "Flask:  class %s should have an inherits clause but does not\n",
 
1248
                   pol_class);
 
1249
            return -EINVAL;
 
1250
        }
 
1251
        tmp = kdefs->av_inherit[i].common_base;
 
1252
        common_pts_len = 0;
 
1253
        while ( !(tmp & 0x01) )
 
1254
        {
 
1255
            common_pts_len++;
 
1256
            tmp >>= 1;
 
1257
        }
 
1258
        perms = &cladatum->comdatum->permissions;
 
1259
        for ( j = 0; j < common_pts_len; j++ )
 
1260
        {
 
1261
            def_perm = kdefs->av_inherit[i].common_pts[j];
 
1262
            if ( j >= perms->nprim )
 
1263
            {
 
1264
                printk(KERN_INFO
 
1265
                "Flask:  permission %s in class %s not defined in policy\n",
 
1266
                       def_perm, pol_class);
 
1267
                return -EINVAL;
 
1268
            }
 
1269
            perdatum = hashtab_search(perms->table, def_perm);
 
1270
            if ( perdatum == NULL )
 
1271
            {
 
1272
                printk(KERN_ERR
 
1273
                       "Flask:  permission %s in class %s not found in policy\n",
 
1274
                       def_perm, pol_class);
 
1275
                return -EINVAL;
 
1276
            }
 
1277
            if ( perdatum->value != j + 1 )
 
1278
            {
 
1279
                printk(KERN_ERR
 
1280
                      "Flask:  permission %s in class %s has incorrect value\n",
 
1281
                       def_perm, pol_class);
 
1282
                return -EINVAL;
 
1283
            }
 
1284
        }
 
1285
    }
 
1286
    return 0;
 
1287
}
 
1288
 
 
1289
/* Clone the SID into the new SID table. */
 
1290
static int clone_sid(u32 sid, struct context *context, void *arg)
 
1291
{
 
1292
    struct sidtab *s = arg;
 
1293
 
 
1294
    return sidtab_insert(s, sid, context);
 
1295
}
 
1296
 
 
1297
static inline int convert_context_handle_invalid_context(struct context *context)
 
1298
{
 
1299
    int rc = 0;
 
1300
 
 
1301
    if ( flask_enforcing )
 
1302
        rc = -EINVAL;
 
1303
    else
 
1304
    {
 
1305
        char *s;
 
1306
        u32 len;
 
1307
 
 
1308
        context_struct_to_string(context, &s, &len);
 
1309
        printk(KERN_ERR "Flask:  context %s is invalid\n", s);
 
1310
        xfree(s);
 
1311
    }
 
1312
    return rc;
 
1313
}
 
1314
 
 
1315
struct convert_context_args {
 
1316
    struct policydb *oldp;
 
1317
    struct policydb *newp;
 
1318
};
 
1319
 
 
1320
/*
 
1321
 * Convert the values in the security context
 
1322
 * structure `c' from the values specified
 
1323
 * in the policy `p->oldp' to the values specified
 
1324
 * in the policy `p->newp'.  Verify that the
 
1325
 * context is valid under the new policy.
 
1326
 */
 
1327
static int convert_context(u32 key, struct context *c, void *p)
 
1328
{
 
1329
    struct convert_context_args *args;
 
1330
    struct context oldc;
 
1331
    struct role_datum *role;
 
1332
    struct type_datum *typdatum;
 
1333
    struct user_datum *usrdatum;
 
1334
    char *s;
 
1335
    u32 len;
 
1336
    int rc;
 
1337
 
 
1338
    args = p;
 
1339
 
 
1340
    rc = context_cpy(&oldc, c);
 
1341
    if ( rc )
 
1342
        goto out;
 
1343
 
 
1344
    rc = -EINVAL;
 
1345
 
 
1346
    /* Convert the user. */
 
1347
    usrdatum = hashtab_search(args->newp->p_users.table,
 
1348
                              args->oldp->p_user_val_to_name[c->user - 1]);
 
1349
    if ( !usrdatum )
 
1350
        goto bad;
 
1351
 
 
1352
    c->user = usrdatum->value;
 
1353
 
 
1354
    /* Convert the role. */
 
1355
    role = hashtab_search(args->newp->p_roles.table,
 
1356
                          args->oldp->p_role_val_to_name[c->role - 1]);
 
1357
    if ( !role )
 
1358
        goto bad;
 
1359
 
 
1360
    c->role = role->value;
 
1361
 
 
1362
    /* Convert the type. */
 
1363
    typdatum = hashtab_search(args->newp->p_types.table,
 
1364
                              args->oldp->p_type_val_to_name[c->type - 1]);
 
1365
    if ( !typdatum )
 
1366
        goto bad;
 
1367
 
 
1368
    c->type = typdatum->value;
 
1369
 
 
1370
    rc = mls_convert_context(args->oldp, args->newp, c);
 
1371
    if ( rc )
 
1372
        goto bad;
 
1373
 
 
1374
    /* Check the validity of the new context. */
 
1375
    if ( !policydb_context_isvalid(args->newp, c) )
 
1376
    {
 
1377
        rc = convert_context_handle_invalid_context(&oldc);
 
1378
        if ( rc )
 
1379
            goto bad;
 
1380
    }
 
1381
 
 
1382
    context_destroy(&oldc);
 
1383
out:
 
1384
    return rc;
 
1385
bad:
 
1386
    context_struct_to_string(&oldc, &s, &len);
 
1387
    context_destroy(&oldc);
 
1388
    printk(KERN_ERR "Flask:  invalidating context %s\n", s);
 
1389
    xfree(s);
 
1390
    goto out;
 
1391
}
 
1392
 
 
1393
static int security_preserve_bools(struct policydb *p);
 
1394
 
 
1395
/**
 
1396
 * security_load_policy - Load a security policy configuration.
 
1397
 * @data: binary policy data
 
1398
 * @len: length of data in bytes
 
1399
 *
 
1400
 * Load a new set of security policy configuration data,
 
1401
 * validate it and convert the SID table as necessary.
 
1402
 * This function will flush the access vector cache after
 
1403
 * loading the new policy.
 
1404
 */
 
1405
int security_load_policy(void *data, size_t len)
 
1406
{
 
1407
    struct policydb oldpolicydb, newpolicydb;
 
1408
    struct sidtab oldsidtab, newsidtab;
 
1409
    struct convert_context_args args;
 
1410
    u32 seqno;
 
1411
    int rc = 0;
 
1412
    struct policy_file file = { data, len }, *fp = &file;
 
1413
 
 
1414
    LOAD_LOCK;
 
1415
 
 
1416
    if ( !ss_initialized )
 
1417
    {
 
1418
        if ( policydb_read(&policydb, fp) )
 
1419
        {
 
1420
            LOAD_UNLOCK;
 
1421
            return -EINVAL;
 
1422
        }
 
1423
        if ( policydb_load_isids(&policydb, &sidtab) )
 
1424
        {
 
1425
            LOAD_UNLOCK;
 
1426
            policydb_destroy(&policydb);
 
1427
            return -EINVAL;
 
1428
        }
 
1429
        if ( validate_classes(&policydb) )
 
1430
        {
 
1431
            printk(KERN_ERR
 
1432
                   "Flask:  the definition of a class is incorrect\n");
 
1433
            sidtab_destroy(&sidtab);
 
1434
            policydb_destroy(&policydb);
 
1435
            return -EINVAL;
 
1436
        }
 
1437
        policydb_loaded_version = policydb.policyvers;
 
1438
        ss_initialized = 1;
 
1439
        seqno = ++latest_granting;
 
1440
        LOAD_UNLOCK;
 
1441
        avc_ss_reset(seqno);
 
1442
        return 0;
 
1443
    }
 
1444
 
 
1445
#if 0
 
1446
    sidtab_hash_eval(&sidtab, "sids");
 
1447
#endif
 
1448
 
 
1449
    if ( policydb_read(&newpolicydb, fp) )
 
1450
    {
 
1451
        LOAD_UNLOCK;
 
1452
        return -EINVAL;
 
1453
    }
 
1454
 
 
1455
    sidtab_init(&newsidtab);
 
1456
 
 
1457
    /* Verify that the kernel defined classes are correct. */
 
1458
    if ( validate_classes(&newpolicydb) )
 
1459
    {
 
1460
        printk(KERN_ERR
 
1461
               "Flask:  the definition of a class is incorrect\n");
 
1462
        rc = -EINVAL;
 
1463
        goto err;
 
1464
    }
 
1465
 
 
1466
    rc = security_preserve_bools(&newpolicydb);
 
1467
    if ( rc )
 
1468
    {
 
1469
        printk(KERN_ERR "Flask:  unable to preserve booleans\n");
 
1470
        goto err;
 
1471
    }
 
1472
 
 
1473
    /* Clone the SID table. */
 
1474
    sidtab_shutdown(&sidtab);
 
1475
    if ( sidtab_map(&sidtab, clone_sid, &newsidtab) )
 
1476
    {
 
1477
        rc = -ENOMEM;
 
1478
        goto err;
 
1479
    }
 
1480
 
 
1481
    /* Convert the internal representations of contexts
 
1482
       in the new SID table and remove invalid SIDs. */
 
1483
    args.oldp = &policydb;
 
1484
    args.newp = &newpolicydb;
 
1485
    sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
 
1486
 
 
1487
    /* Save the old policydb and SID table to free later. */
 
1488
    memcpy(&oldpolicydb, &policydb, sizeof policydb);
 
1489
    sidtab_set(&oldsidtab, &sidtab);
 
1490
 
 
1491
    /* Install the new policydb and SID table. */
 
1492
    POLICY_WRLOCK;
 
1493
    memcpy(&policydb, &newpolicydb, sizeof policydb);
 
1494
    sidtab_set(&sidtab, &newsidtab);
 
1495
    seqno = ++latest_granting;
 
1496
    policydb_loaded_version = policydb.policyvers;
 
1497
    POLICY_WRUNLOCK;
 
1498
    LOAD_UNLOCK;
 
1499
 
 
1500
    /* Free the old policydb and SID table. */
 
1501
    policydb_destroy(&oldpolicydb);
 
1502
    sidtab_destroy(&oldsidtab);
 
1503
 
 
1504
    avc_ss_reset(seqno);
 
1505
 
 
1506
    return 0;
 
1507
 
 
1508
err:
 
1509
    LOAD_UNLOCK;
 
1510
    sidtab_destroy(&newsidtab);
 
1511
    policydb_destroy(&newpolicydb);
 
1512
    return rc;
 
1513
 
 
1514
}
 
1515
 
 
1516
/**
 
1517
 * security_pirq_sid - Obtain the SID for a physical irq.
 
1518
 * @pirq: physical irq
 
1519
 * @out_sid: security identifier
 
1520
 */
 
1521
int security_pirq_sid(int pirq, u32 *out_sid)
 
1522
{
 
1523
    int rc = 0;
 
1524
    struct ocontext *c;
 
1525
 
 
1526
    POLICY_RDLOCK;
 
1527
 
 
1528
    c = policydb.ocontexts[OCON_PIRQ];
 
1529
    
 
1530
    while ( c )
 
1531
    {
 
1532
        if ( c->u.pirq == pirq )
 
1533
            break;
 
1534
        c = c->next;
 
1535
    }
 
1536
 
 
1537
    if ( c )
 
1538
    {
 
1539
        if ( !c->sid[0] )
 
1540
        {
 
1541
            rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
 
1542
            if ( rc )
 
1543
                goto out;
 
1544
        }
 
1545
        *out_sid = c->sid[0];
 
1546
    }
 
1547
    else
 
1548
    {
 
1549
        *out_sid = SECINITSID_PIRQ;
 
1550
    }
 
1551
 
 
1552
out:
 
1553
    POLICY_RDUNLOCK;
 
1554
    return rc;
 
1555
}
 
1556
 
 
1557
/**
 
1558
 * security_iomem_sid - Obtain the SID for a page of iomem.
 
1559
 * @mfn: iomem mfn
 
1560
 * @out_sid: security identifier
 
1561
 */
 
1562
int security_iomem_sid(unsigned long mfn, u32 *out_sid)
 
1563
{
 
1564
    struct ocontext *c;
 
1565
    int rc = 0;
 
1566
 
 
1567
    POLICY_RDLOCK;
 
1568
 
 
1569
    c = policydb.ocontexts[OCON_IOMEM];
 
1570
    while ( c )
 
1571
    {
 
1572
        if ( c->u.iomem.low_iomem <= mfn  && c->u.iomem.high_iomem >= mfn )
 
1573
            break;
 
1574
        c = c->next;
 
1575
    }
 
1576
 
 
1577
    if ( c )
 
1578
    {
 
1579
        if ( !c->sid[0] )
 
1580
        {
 
1581
            rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
 
1582
            if ( rc )
 
1583
                goto out;
 
1584
        }
 
1585
        *out_sid = c->sid[0];
 
1586
    }
 
1587
    else
 
1588
    {
 
1589
        *out_sid = SECINITSID_IOMEM;
 
1590
    }
 
1591
 
 
1592
out:
 
1593
    POLICY_RDUNLOCK;
 
1594
    return rc;
 
1595
}
 
1596
 
 
1597
/**
 
1598
 * security_ioport_sid - Obtain the SID for an ioport.
 
1599
 * @ioport: ioport
 
1600
 * @out_sid: security identifier
 
1601
 */
 
1602
int security_ioport_sid(u32 ioport, u32 *out_sid)
 
1603
{
 
1604
    struct ocontext *c;
 
1605
    int rc = 0;
 
1606
 
 
1607
    POLICY_RDLOCK;
 
1608
 
 
1609
    c = policydb.ocontexts[OCON_IOPORT];
 
1610
    while ( c )
 
1611
    {
 
1612
        if ( c->u.ioport.low_ioport <= ioport &&
 
1613
             c->u.ioport.high_ioport >= ioport )
 
1614
            break;
 
1615
        c = c->next;
 
1616
    }
 
1617
 
 
1618
    if ( c )
 
1619
    {
 
1620
        if ( !c->sid[0] )
 
1621
        {
 
1622
            rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
 
1623
            if ( rc )
 
1624
                goto out;
 
1625
        }
 
1626
        *out_sid = c->sid[0];
 
1627
    }
 
1628
    else
 
1629
    {
 
1630
        *out_sid = SECINITSID_IOPORT;
 
1631
    }
 
1632
 
 
1633
out:
 
1634
    POLICY_RDUNLOCK;
 
1635
    return rc;
 
1636
}
 
1637
 
 
1638
/**
 
1639
 * security_device_sid - Obtain the SID for a PCI device.
 
1640
 * @ioport: device
 
1641
 * @out_sid: security identifier
 
1642
 */
 
1643
int security_device_sid(u32 device, u32 *out_sid)
 
1644
{
 
1645
    struct ocontext *c;
 
1646
    int rc = 0;
 
1647
 
 
1648
    POLICY_RDLOCK;
 
1649
 
 
1650
    c = policydb.ocontexts[OCON_DEVICE];
 
1651
    while ( c )
 
1652
    {
 
1653
        if ( c->u.device == device )
 
1654
            break;
 
1655
        c = c->next;
 
1656
    }
 
1657
 
 
1658
    if ( c )
 
1659
    {
 
1660
        if ( !c->sid[0] )
 
1661
        {
 
1662
            rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
 
1663
            if ( rc )
 
1664
                goto out;
 
1665
        }
 
1666
        *out_sid = c->sid[0];
 
1667
    }
 
1668
    else
 
1669
    {
 
1670
        *out_sid = SECINITSID_DEVICE;
 
1671
    }
 
1672
 
 
1673
out:
 
1674
    POLICY_RDUNLOCK;
 
1675
    return rc;
 
1676
}
 
1677
 
 
1678
#define SIDS_NEL 25
 
1679
 
 
1680
/**
 
1681
 * security_get_user_sids - Obtain reachable SIDs for a user.
 
1682
 * @fromsid: starting SID
 
1683
 * @username: username
 
1684
 * @sids: array of reachable SIDs for user
 
1685
 * @nel: number of elements in @sids
 
1686
 *
 
1687
 * Generate the set of SIDs for legal security contexts
 
1688
 * for a given user that can be reached by @fromsid.
 
1689
 * Set *@sids to point to a dynamically allocated
 
1690
 * array containing the set of SIDs.  Set *@nel to the
 
1691
 * number of elements in the array.
 
1692
 */
 
1693
 
 
1694
int security_get_user_sids(u32 fromsid, char *username, u32 **sids, u32 *nel)
 
1695
{
 
1696
    struct context *fromcon, usercon;
 
1697
    u32 *mysids, *mysids2, sid;
 
1698
    u32 mynel = 0, maxnel = SIDS_NEL;
 
1699
    struct user_datum *user;
 
1700
    struct role_datum *role;
 
1701
    struct av_decision avd;
 
1702
    struct ebitmap_node *rnode, *tnode;
 
1703
    int rc = 0, i, j;
 
1704
 
 
1705
    if ( !ss_initialized )
 
1706
    {
 
1707
        *sids = NULL;
 
1708
        *nel = 0;
 
1709
        goto out;
 
1710
    }
 
1711
 
 
1712
    POLICY_RDLOCK;
 
1713
 
 
1714
    fromcon = sidtab_search(&sidtab, fromsid);
 
1715
    if ( !fromcon )
 
1716
    {
 
1717
        rc = -EINVAL;
 
1718
        goto out_unlock;
 
1719
    }
 
1720
 
 
1721
    user = hashtab_search(policydb.p_users.table, username);
 
1722
    if ( !user )
 
1723
    {
 
1724
        rc = -EINVAL;
 
1725
        goto out_unlock;
 
1726
    }
 
1727
    usercon.user = user->value;
 
1728
 
 
1729
    mysids = xmalloc_array(u32, maxnel);
 
1730
    if ( !mysids )
 
1731
    {
 
1732
        rc = -ENOMEM;
 
1733
        goto out_unlock;
 
1734
    }
 
1735
    memset(mysids, 0, maxnel*sizeof(*mysids));
 
1736
 
 
1737
    ebitmap_for_each_positive_bit(&user->roles, rnode, i)
 
1738
    {
 
1739
        role = policydb.role_val_to_struct[i];
 
1740
        usercon.role = i+1;
 
1741
        ebitmap_for_each_positive_bit(&role->types, tnode, j) {
 
1742
            usercon.type = j+1;
 
1743
 
 
1744
            if ( mls_setup_user_range(fromcon, user, &usercon) )
 
1745
                continue;
 
1746
 
 
1747
            rc = context_struct_compute_av(fromcon, &usercon,
 
1748
                               SECCLASS_DOMAIN,
 
1749
                               DOMAIN__TRANSITION,
 
1750
                               &avd);
 
1751
            if ( rc ||  !(avd.allowed & DOMAIN__TRANSITION) )
 
1752
                continue;
 
1753
            rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
 
1754
            if ( rc )
 
1755
            {
 
1756
                xfree(mysids);
 
1757
                goto out_unlock;
 
1758
            }
 
1759
            if ( mynel < maxnel )
 
1760
            {
 
1761
                mysids[mynel++] = sid;
 
1762
            }
 
1763
            else
 
1764
            {
 
1765
                maxnel += SIDS_NEL;
 
1766
                mysids2 = xmalloc_array(u32, maxnel);
 
1767
                if ( !mysids2 )
 
1768
                {
 
1769
                    rc = -ENOMEM;
 
1770
                    xfree(mysids);
 
1771
                    goto out_unlock;
 
1772
                }
 
1773
                memset(mysids2, 0, maxnel*sizeof(*mysids2));
 
1774
                memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
 
1775
                xfree(mysids);
 
1776
                mysids = mysids2;
 
1777
                mysids[mynel++] = sid;
 
1778
            }
 
1779
        }
 
1780
    }
 
1781
 
 
1782
    *sids = mysids;
 
1783
    *nel = mynel;
 
1784
 
 
1785
out_unlock:
 
1786
    POLICY_RDUNLOCK;
 
1787
out:
 
1788
    return rc;
 
1789
}
 
1790
 
 
1791
int security_get_bools(int *len, char ***names, int **values)
 
1792
{
 
1793
    int i, rc = -ENOMEM;
 
1794
 
 
1795
    POLICY_RDLOCK;
 
1796
    *names = NULL;
 
1797
    *values = NULL;
 
1798
 
 
1799
    *len = policydb.p_bools.nprim;
 
1800
    if ( !*len )
 
1801
    {
 
1802
        rc = 0;
 
1803
        goto out;
 
1804
    }
 
1805
 
 
1806
    *names = (char**)xmalloc_array(char*, *len);
 
1807
    if ( !*names )
 
1808
        goto err;
 
1809
    memset(*names, 0, sizeof(char*) * *len);
 
1810
 
 
1811
    *values = (int*)xmalloc_array(int, *len);
 
1812
    if ( !*values )
 
1813
        goto err;
 
1814
 
 
1815
    for ( i = 0; i < *len; i++ )
 
1816
    {
 
1817
        size_t name_len;
 
1818
        (*values)[i] = policydb.bool_val_to_struct[i]->state;
 
1819
        name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
 
1820
        (*names)[i] = (char*)xmalloc_array(char, name_len);
 
1821
        if ( !(*names)[i] )
 
1822
            goto err;
 
1823
        strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
 
1824
        (*names)[i][name_len - 1] = 0;
 
1825
    }
 
1826
    rc = 0;
 
1827
out:
 
1828
    POLICY_RDUNLOCK;
 
1829
    return rc;
 
1830
err:
 
1831
    if ( *names )
 
1832
    {
 
1833
        for ( i = 0; i < *len; i++ )
 
1834
            xfree((*names)[i]);
 
1835
    }
 
1836
    xfree(*values);
 
1837
    goto out;
 
1838
}
 
1839
 
 
1840
 
 
1841
int security_set_bools(int len, int *values)
 
1842
{
 
1843
    int i, rc = 0;
 
1844
    int lenp, seqno = 0;
 
1845
    struct cond_node *cur;
 
1846
 
 
1847
    POLICY_WRLOCK;
 
1848
 
 
1849
    lenp = policydb.p_bools.nprim;
 
1850
    if ( len != lenp )
 
1851
    {
 
1852
        rc = -EFAULT;
 
1853
        goto out;
 
1854
    }
 
1855
 
 
1856
    printk(KERN_INFO "Flask: committed booleans { ");
 
1857
    for ( i = 0; i < len; i++ )
 
1858
    {
 
1859
        if ( values[i] )
 
1860
        {
 
1861
            policydb.bool_val_to_struct[i]->state = 1;
 
1862
        }
 
1863
        else
 
1864
        {
 
1865
            policydb.bool_val_to_struct[i]->state = 0;
 
1866
        }
 
1867
        if ( i != 0 )
 
1868
            printk(", ");
 
1869
        printk("%s:%d", policydb.p_bool_val_to_name[i],
 
1870
               policydb.bool_val_to_struct[i]->state);
 
1871
    }
 
1872
    printk(" }\n");
 
1873
 
 
1874
    for ( cur = policydb.cond_list; cur != NULL; cur = cur->next )
 
1875
    {
 
1876
        rc = evaluate_cond_node(&policydb, cur);
 
1877
        if ( rc )
 
1878
            goto out;
 
1879
    }
 
1880
 
 
1881
    seqno = ++latest_granting;
 
1882
 
 
1883
out:
 
1884
    POLICY_WRUNLOCK;
 
1885
    if ( !rc )
 
1886
    {
 
1887
        avc_ss_reset(seqno);
 
1888
    }
 
1889
    return rc;
 
1890
}
 
1891
 
 
1892
int security_get_bool_value(int bool)
 
1893
{
 
1894
    int rc = 0;
 
1895
    int len;
 
1896
 
 
1897
    POLICY_RDLOCK;
 
1898
 
 
1899
    len = policydb.p_bools.nprim;
 
1900
    if ( bool >= len )
 
1901
    {
 
1902
        rc = -EFAULT;
 
1903
        goto out;
 
1904
    }
 
1905
 
 
1906
    rc = policydb.bool_val_to_struct[bool]->state;
 
1907
out:
 
1908
    POLICY_RDUNLOCK;
 
1909
    return rc;
 
1910
}
 
1911
 
 
1912
static int security_preserve_bools(struct policydb *p)
 
1913
{
 
1914
    int rc, nbools = 0, *bvalues = NULL, i;
 
1915
    char **bnames = NULL;
 
1916
    struct cond_bool_datum *booldatum;
 
1917
    struct cond_node *cur;
 
1918
 
 
1919
    rc = security_get_bools(&nbools, &bnames, &bvalues);
 
1920
    if ( rc )
 
1921
        goto out;
 
1922
    for ( i = 0; i < nbools; i++ )
 
1923
    {
 
1924
        booldatum = hashtab_search(p->p_bools.table, bnames[i]);
 
1925
        if ( booldatum )
 
1926
            booldatum->state = bvalues[i];
 
1927
    }
 
1928
    for ( cur = p->cond_list; cur; cur = cur->next )
 
1929
    {
 
1930
        rc = evaluate_cond_node(p, cur);
 
1931
        if ( rc )
 
1932
            goto out;
 
1933
    }
 
1934
 
 
1935
out:
 
1936
    if ( bnames )
 
1937
    {
 
1938
        for ( i = 0; i < nbools; i++ )
 
1939
            xfree(bnames[i]);
 
1940
    }
 
1941
    xfree(bnames);
 
1942
    xfree(bvalues);
 
1943
    return rc;
 
1944
}
 
1945
 
 
1946
int determine_ocontext( char *ocontext )
 
1947
{
 
1948
    if ( strcmp(ocontext, "pirq") == 0 )
 
1949
        return OCON_PIRQ;
 
1950
    else if ( strcmp(ocontext, "ioport") == 0 )
 
1951
        return OCON_IOPORT;
 
1952
    else if ( strcmp(ocontext, "iomem") == 0 )
 
1953
        return OCON_IOMEM;
 
1954
    else if ( strcmp(ocontext, "pcidevice") == 0 )
 
1955
        return OCON_DEVICE;
 
1956
    else
 
1957
        return -1;
 
1958
}
 
1959
 
 
1960
int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high
 
1961
                            ,u32 sid )
 
1962
{
 
1963
    int ret = 0;
 
1964
    int ocon = 0;
 
1965
    struct ocontext *c;
 
1966
    struct ocontext *add;
 
1967
 
 
1968
    if ( (ocon = determine_ocontext(ocontext)) < 0 )
 
1969
        return -EINVAL;
 
1970
    if ( (add = xmalloc(struct ocontext)) == NULL )
 
1971
        return -ENOMEM;
 
1972
    memset(add, 0, sizeof(struct ocontext));
 
1973
    add->sid[0] = sid;
 
1974
 
 
1975
    POLICY_WRLOCK;
 
1976
    switch( ocon )
 
1977
    {
 
1978
    case OCON_PIRQ:
 
1979
        add->u.pirq = (u16)low;
 
1980
        if ( high != low )
 
1981
        {
 
1982
            ret = -EINVAL;
 
1983
            break;
 
1984
        }
 
1985
 
 
1986
        c = policydb.ocontexts[OCON_PIRQ];
 
1987
        while ( c )
 
1988
        {
 
1989
            if ( c->u.pirq == add->u.pirq )
 
1990
            {
 
1991
                printk("%s: Duplicate pirq %d\n", __FUNCTION__, add->u.pirq);
 
1992
                ret = -EINVAL;
 
1993
                break;
 
1994
            }
 
1995
            c = c->next;
 
1996
        }
 
1997
 
 
1998
        if ( ret == 0 )
 
1999
        {
 
2000
            add->next = policydb.ocontexts[OCON_PIRQ];
 
2001
            policydb.ocontexts[OCON_PIRQ] = add;
 
2002
        }
 
2003
        break;
 
2004
 
 
2005
    case OCON_IOPORT:
 
2006
        add->u.ioport.low_ioport = low;
 
2007
        add->u.ioport.high_ioport = high;
 
2008
 
 
2009
        c = policydb.ocontexts[OCON_IOPORT];
 
2010
        while ( c )
 
2011
        {
 
2012
            if ( c->u.ioport.low_ioport <= add->u.ioport.high_ioport &&
 
2013
                 add->u.ioport.low_ioport <= c->u.ioport.high_ioport )
 
2014
            {
 
2015
                printk("%s: IO Port overlap with entry 0x%x - 0x%x\n",
 
2016
                       __FUNCTION__, c->u.ioport.low_ioport,
 
2017
                       c->u.ioport.high_ioport);
 
2018
                ret = -EINVAL;
 
2019
                break;
 
2020
            }
 
2021
            c = c->next;
 
2022
        }
 
2023
 
 
2024
        if ( ret == 0 )
 
2025
        {
 
2026
            add->next = policydb.ocontexts[OCON_IOPORT];
 
2027
            policydb.ocontexts[OCON_IOPORT] = add;
 
2028
        }
 
2029
        break;
 
2030
 
 
2031
    case OCON_IOMEM:
 
2032
        add->u.iomem.low_iomem = low;
 
2033
        add->u.iomem.high_iomem = high;
 
2034
 
 
2035
        c = policydb.ocontexts[OCON_IOMEM];
 
2036
        while ( c )
 
2037
        {
 
2038
            if ( c->u.iomem.low_iomem <= add->u.iomem.high_iomem &&
 
2039
                 add->u.iomem.low_iomem <= c->u.iomem.high_iomem )
 
2040
            {
 
2041
                printk("%s: IO Memory overlap with entry 0x%x - 0x%x\n",
 
2042
                       __FUNCTION__, c->u.iomem.low_iomem,
 
2043
                       c->u.iomem.high_iomem);
 
2044
                ret = -EINVAL;
 
2045
                break;
 
2046
            }
 
2047
            c = c->next;
 
2048
        }
 
2049
 
 
2050
        if ( ret == 0 )
 
2051
        {
 
2052
            add->next = policydb.ocontexts[OCON_IOMEM];
 
2053
            policydb.ocontexts[OCON_IOMEM] = add;
 
2054
        }
 
2055
        break;
 
2056
 
 
2057
     case OCON_DEVICE:
 
2058
        add->u.device = low;
 
2059
        if ( high != low )
 
2060
        {
 
2061
            ret = -EINVAL;
 
2062
            break;
 
2063
        }
 
2064
 
 
2065
        c = policydb.ocontexts[OCON_DEVICE];
 
2066
        while ( c )
 
2067
        {
 
2068
            if ( c->u.device == add->u.device )
 
2069
            {
 
2070
                printk("%s: Duplicate PCI Device 0x%x\n", __FUNCTION__,
 
2071
                        add->u.device);
 
2072
                ret = -EINVAL;
 
2073
                break;
 
2074
            }
 
2075
            c = c->next;
 
2076
        }
 
2077
 
 
2078
        if ( ret == 0 )
 
2079
        {
 
2080
            add->next = policydb.ocontexts[OCON_DEVICE];
 
2081
            policydb.ocontexts[OCON_DEVICE] = add;
 
2082
        }
 
2083
        break;
 
2084
 
 
2085
     default:
 
2086
         ret = -EINVAL;
 
2087
    }
 
2088
    POLICY_WRUNLOCK;
 
2089
 
 
2090
    if ( ret != 0 )
 
2091
        xfree(add);
 
2092
    return ret;
 
2093
}
 
2094
 
 
2095
int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high )
 
2096
{
 
2097
    int ret = 0;
 
2098
    int ocon = 0;
 
2099
    struct ocontext *c, *before_c;
 
2100
 
 
2101
    if ( (ocon = determine_ocontext(ocontext)) < 0 )
 
2102
        return -EINVAL;
 
2103
 
 
2104
    POLICY_WRLOCK;
 
2105
    switch( ocon )
 
2106
    {
 
2107
    case OCON_PIRQ:
 
2108
        for ( before_c = NULL, c = policydb.ocontexts[OCON_PIRQ];
 
2109
              c; before_c = c, c = c->next )
 
2110
        {
 
2111
            if ( c->u.pirq == low )
 
2112
            {
 
2113
                if ( before_c == NULL )
 
2114
                {
 
2115
                    policydb.ocontexts[OCON_PIRQ] = c->next;
 
2116
                    xfree(c);
 
2117
                    goto out;
 
2118
                }
 
2119
                else
 
2120
                {
 
2121
                    before_c->next = c->next;
 
2122
                    xfree(c);
 
2123
                    goto out;
 
2124
                }
 
2125
            }
 
2126
        }
 
2127
 
 
2128
        printk("%s: ocontext not found: pirq %d\n", __FUNCTION__, low);
 
2129
        ret = -EINVAL;
 
2130
        break;
 
2131
 
 
2132
    case OCON_IOPORT:
 
2133
        for ( before_c = NULL, c = policydb.ocontexts[OCON_IOPORT];
 
2134
              c; before_c = c, c = c->next )
 
2135
        {
 
2136
            if ( c->u.ioport.low_ioport == low &&
 
2137
                 c->u.ioport.high_ioport == high )
 
2138
            {
 
2139
                if ( before_c == NULL )
 
2140
                {
 
2141
                    policydb.ocontexts[OCON_IOPORT] = c->next;
 
2142
                    xfree(c);
 
2143
                    goto out;
 
2144
                }
 
2145
                else
 
2146
                {
 
2147
                    before_c->next = c->next;
 
2148
                    xfree(c);
 
2149
                    goto out;
 
2150
                }
 
2151
            }
 
2152
        }
 
2153
 
 
2154
        printk("%s: ocontext not found: ioport 0x%x - 0x%x\n", __FUNCTION__,
 
2155
                low, high);
 
2156
        ret = -EINVAL;
 
2157
        break;
 
2158
 
 
2159
    case OCON_IOMEM:
 
2160
        for ( before_c = NULL, c = policydb.ocontexts[OCON_IOMEM];
 
2161
              c; before_c = c, c = c->next )
 
2162
        {
 
2163
            if ( c->u.iomem.low_iomem == low &&
 
2164
                 c->u.iomem.high_iomem == high )
 
2165
            {
 
2166
                if ( before_c == NULL )
 
2167
                {
 
2168
                    policydb.ocontexts[OCON_IOMEM] = c->next;
 
2169
                    xfree(c);
 
2170
                    goto out;
 
2171
                }
 
2172
                else
 
2173
                {
 
2174
                    before_c->next = c->next;
 
2175
                    xfree(c);
 
2176
                    goto out;
 
2177
                }
 
2178
            }
 
2179
        }
 
2180
 
 
2181
        printk("%s: ocontext not found: iomem 0x%x - 0x%x\n", __FUNCTION__,
 
2182
                low, high);
 
2183
        ret = -EINVAL;
 
2184
        break;
 
2185
 
 
2186
    case OCON_DEVICE:
 
2187
        for ( before_c = NULL, c = policydb.ocontexts[OCON_DEVICE];
 
2188
              c; before_c = c, c = c->next )
 
2189
        {
 
2190
            if ( c->u.device == low )
 
2191
            {
 
2192
                if ( before_c == NULL )
 
2193
                {
 
2194
                    policydb.ocontexts[OCON_DEVICE] = c->next;
 
2195
                    xfree(c);
 
2196
                    goto out;
 
2197
                }
 
2198
                else
 
2199
                {
 
2200
                    before_c->next = c->next;
 
2201
                    xfree(c);
 
2202
                    goto out;
 
2203
                }
 
2204
            }
 
2205
        }
 
2206
 
 
2207
        printk("%s: ocontext not found: pcidevice 0x%x\n", __FUNCTION__, low);
 
2208
        ret = -EINVAL;
 
2209
        break;
 
2210
 
 
2211
    default:
 
2212
        ret = -EINVAL;
 
2213
    }
 
2214
 
 
2215
  out:
 
2216
    POLICY_WRUNLOCK;
 
2217
    return ret;
 
2218
}