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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Implementation of the multi-level security (MLS) policy.
3
 *
4
 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5
 */
6
/*
7
 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8
 *
9
 *      Support for enhanced MLS infrastructure.
10
 *
11
 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
12
 */
13
/*
14
 * Updated: Hewlett-Packard <paul.moore@hp.com>
15
 *
16
 *      Added support to import/export the MLS label from NetLabel
17
 *
18
 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19
 */
20
 
21
#include <linux/kernel.h>
22
#include <linux/slab.h>
23
#include <linux/string.h>
24
#include <linux/errno.h>
25
#include <net/netlabel.h>
26
#include "sidtab.h"
27
#include "mls.h"
28
#include "policydb.h"
29
#include "services.h"
30
 
31
/*
32
 * Return the length in bytes for the MLS fields of the
33
 * security context string representation of `context'.
34
 */
35
int mls_compute_context_len(struct context * context)
36
{
37
        int i, l, len, head, prev;
38
        char *nm;
39
        struct ebitmap *e;
40
        struct ebitmap_node *node;
41
 
42
        if (!selinux_mls_enabled)
43
                return 0;
44
 
45
        len = 1; /* for the beginning ":" */
46
        for (l = 0; l < 2; l++) {
47
                int index_sens = context->range.level[l].sens;
48
                len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
49
 
50
                /* categories */
51
                head = -2;
52
                prev = -2;
53
                e = &context->range.level[l].cat;
54
                ebitmap_for_each_positive_bit(e, node, i) {
55
                        if (i - prev > 1) {
56
                                /* one or more negative bits are skipped */
57
                                if (head != prev) {
58
                                        nm = policydb.p_cat_val_to_name[prev];
59
                                        len += strlen(nm) + 1;
60
                                }
61
                                nm = policydb.p_cat_val_to_name[i];
62
                                len += strlen(nm) + 1;
63
                                head = i;
64
                        }
65
                        prev = i;
66
                }
67
                if (prev != head) {
68
                        nm = policydb.p_cat_val_to_name[prev];
69
                        len += strlen(nm) + 1;
70
                }
71
                if (l == 0) {
72
                        if (mls_level_eq(&context->range.level[0],
73
                                         &context->range.level[1]))
74
                                break;
75
                        else
76
                                len++;
77
                }
78
        }
79
 
80
        return len;
81
}
82
 
83
/*
84
 * Write the security context string representation of
85
 * the MLS fields of `context' into the string `*scontext'.
86
 * Update `*scontext' to point to the end of the MLS fields.
87
 */
88
void mls_sid_to_context(struct context *context,
89
                        char **scontext)
90
{
91
        char *scontextp, *nm;
92
        int i, l, head, prev;
93
        struct ebitmap *e;
94
        struct ebitmap_node *node;
95
 
96
        if (!selinux_mls_enabled)
97
                return;
98
 
99
        scontextp = *scontext;
100
 
101
        *scontextp = ':';
102
        scontextp++;
103
 
104
        for (l = 0; l < 2; l++) {
105
                strcpy(scontextp,
106
                       policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
107
                scontextp += strlen(scontextp);
108
 
109
                /* categories */
110
                head = -2;
111
                prev = -2;
112
                e = &context->range.level[l].cat;
113
                ebitmap_for_each_positive_bit(e, node, i) {
114
                        if (i - prev > 1) {
115
                                /* one or more negative bits are skipped */
116
                                if (prev != head) {
117
                                        if (prev - head > 1)
118
                                                *scontextp++ = '.';
119
                                        else
120
                                                *scontextp++ = ',';
121
                                        nm = policydb.p_cat_val_to_name[prev];
122
                                        strcpy(scontextp, nm);
123
                                        scontextp += strlen(nm);
124
                                }
125
                                if (prev < 0)
126
                                        *scontextp++ = ':';
127
                                else
128
                                        *scontextp++ = ',';
129
                                nm = policydb.p_cat_val_to_name[i];
130
                                strcpy(scontextp, nm);
131
                                scontextp += strlen(nm);
132
                                head = i;
133
                        }
134
                        prev = i;
135
                }
136
 
137
                if (prev != head) {
138
                        if (prev - head > 1)
139
                                *scontextp++ = '.';
140
                        else
141
                                *scontextp++ = ',';
142
                        nm = policydb.p_cat_val_to_name[prev];
143
                        strcpy(scontextp, nm);
144
                        scontextp += strlen(nm);
145
                }
146
 
147
                if (l == 0) {
148
                        if (mls_level_eq(&context->range.level[0],
149
                                         &context->range.level[1]))
150
                                break;
151
                        else
152
                                *scontextp++ = '-';
153
                }
154
        }
155
 
156
        *scontext = scontextp;
157
        return;
158
}
159
 
160
int mls_level_isvalid(struct policydb *p, struct mls_level *l)
161
{
162
        struct level_datum *levdatum;
163
        struct ebitmap_node *node;
164
        int i;
165
 
166
        if (!l->sens || l->sens > p->p_levels.nprim)
167
                return 0;
168
        levdatum = hashtab_search(p->p_levels.table,
169
                                  p->p_sens_val_to_name[l->sens - 1]);
170
        if (!levdatum)
171
                return 0;
172
 
173
        ebitmap_for_each_positive_bit(&l->cat, node, i) {
174
                if (i > p->p_cats.nprim)
175
                        return 0;
176
                if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
177
                        /*
178
                         * Category may not be associated with
179
                         * sensitivity.
180
                         */
181
                        return 0;
182
                }
183
        }
184
 
185
        return 1;
186
}
187
 
188
int mls_range_isvalid(struct policydb *p, struct mls_range *r)
189
{
190
        return (mls_level_isvalid(p, &r->level[0]) &&
191
                mls_level_isvalid(p, &r->level[1]) &&
192
                mls_level_dom(&r->level[1], &r->level[0]));
193
}
194
 
195
/*
196
 * Return 1 if the MLS fields in the security context
197
 * structure `c' are valid.  Return 0 otherwise.
198
 */
199
int mls_context_isvalid(struct policydb *p, struct context *c)
200
{
201
        struct user_datum *usrdatum;
202
 
203
        if (!selinux_mls_enabled)
204
                return 1;
205
 
206
        if (!mls_range_isvalid(p, &c->range))
207
                return 0;
208
 
209
        if (c->role == OBJECT_R_VAL)
210
                return 1;
211
 
212
        /*
213
         * User must be authorized for the MLS range.
214
         */
215
        if (!c->user || c->user > p->p_users.nprim)
216
                return 0;
217
        usrdatum = p->user_val_to_struct[c->user - 1];
218
        if (!mls_range_contains(usrdatum->range, c->range))
219
                return 0; /* user may not be associated with range */
220
 
221
        return 1;
222
}
223
 
224
/*
225
 * Set the MLS fields in the security context structure
226
 * `context' based on the string representation in
227
 * the string `*scontext'.  Update `*scontext' to
228
 * point to the end of the string representation of
229
 * the MLS fields.
230
 *
231
 * This function modifies the string in place, inserting
232
 * NULL characters to terminate the MLS fields.
233
 *
234
 * If a def_sid is provided and no MLS field is present,
235
 * copy the MLS field of the associated default context.
236
 * Used for upgraded to MLS systems where objects may lack
237
 * MLS fields.
238
 *
239
 * Policy read-lock must be held for sidtab lookup.
240
 *
241
 */
242
int mls_context_to_sid(char oldc,
243
                       char **scontext,
244
                       struct context *context,
245
                       struct sidtab *s,
246
                       u32 def_sid)
247
{
248
 
249
        char delim;
250
        char *scontextp, *p, *rngptr;
251
        struct level_datum *levdatum;
252
        struct cat_datum *catdatum, *rngdatum;
253
        int l, rc = -EINVAL;
254
 
255
        if (!selinux_mls_enabled) {
256
                if (def_sid != SECSID_NULL && oldc)
257
                        *scontext += strlen(*scontext)+1;
258
                return 0;
259
        }
260
 
261
        /*
262
         * No MLS component to the security context, try and map to
263
         * default if provided.
264
         */
265
        if (!oldc) {
266
                struct context *defcon;
267
 
268
                if (def_sid == SECSID_NULL)
269
                        goto out;
270
 
271
                defcon = sidtab_search(s, def_sid);
272
                if (!defcon)
273
                        goto out;
274
 
275
                rc = mls_context_cpy(context, defcon);
276
                goto out;
277
        }
278
 
279
        /* Extract low sensitivity. */
280
        scontextp = p = *scontext;
281
        while (*p && *p != ':' && *p != '-')
282
                p++;
283
 
284
        delim = *p;
285
        if (delim != 0)
286
                *p++ = 0;
287
 
288
        for (l = 0; l < 2; l++) {
289
                levdatum = hashtab_search(policydb.p_levels.table, scontextp);
290
                if (!levdatum) {
291
                        rc = -EINVAL;
292
                        goto out;
293
                }
294
 
295
                context->range.level[l].sens = levdatum->level->sens;
296
 
297
                if (delim == ':') {
298
                        /* Extract category set. */
299
                        while (1) {
300
                                scontextp = p;
301
                                while (*p && *p != ',' && *p != '-')
302
                                        p++;
303
                                delim = *p;
304
                                if (delim != 0)
305
                                        *p++ = 0;
306
 
307
                                /* Separate into range if exists */
308
                                if ((rngptr = strchr(scontextp, '.')) != NULL) {
309
                                        /* Remove '.' */
310
                                        *rngptr++ = 0;
311
                                }
312
 
313
                                catdatum = hashtab_search(policydb.p_cats.table,
314
                                                          scontextp);
315
                                if (!catdatum) {
316
                                        rc = -EINVAL;
317
                                        goto out;
318
                                }
319
 
320
                                rc = ebitmap_set_bit(&context->range.level[l].cat,
321
                                                     catdatum->value - 1, 1);
322
                                if (rc)
323
                                        goto out;
324
 
325
                                /* If range, set all categories in range */
326
                                if (rngptr) {
327
                                        int i;
328
 
329
                                        rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
330
                                        if (!rngdatum) {
331
                                                rc = -EINVAL;
332
                                                goto out;
333
                                        }
334
 
335
                                        if (catdatum->value >= rngdatum->value) {
336
                                                rc = -EINVAL;
337
                                                goto out;
338
                                        }
339
 
340
                                        for (i = catdatum->value; i < rngdatum->value; i++) {
341
                                                rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
342
                                                if (rc)
343
                                                        goto out;
344
                                        }
345
                                }
346
 
347
                                if (delim != ',')
348
                                        break;
349
                        }
350
                }
351
                if (delim == '-') {
352
                        /* Extract high sensitivity. */
353
                        scontextp = p;
354
                        while (*p && *p != ':')
355
                                p++;
356
 
357
                        delim = *p;
358
                        if (delim != 0)
359
                                *p++ = 0;
360
                } else
361
                        break;
362
        }
363
 
364
        if (l == 0) {
365
                context->range.level[1].sens = context->range.level[0].sens;
366
                rc = ebitmap_cpy(&context->range.level[1].cat,
367
                                 &context->range.level[0].cat);
368
                if (rc)
369
                        goto out;
370
        }
371
        *scontext = ++p;
372
        rc = 0;
373
out:
374
        return rc;
375
}
376
 
377
/*
378
 * Set the MLS fields in the security context structure
379
 * `context' based on the string representation in
380
 * the string `str'.  This function will allocate temporary memory with the
381
 * given constraints of gfp_mask.
382
 */
383
int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
384
{
385
        char *tmpstr, *freestr;
386
        int rc;
387
 
388
        if (!selinux_mls_enabled)
389
                return -EINVAL;
390
 
391
        /* we need freestr because mls_context_to_sid will change
392
           the value of tmpstr */
393
        tmpstr = freestr = kstrdup(str, gfp_mask);
394
        if (!tmpstr) {
395
                rc = -ENOMEM;
396
        } else {
397
                rc = mls_context_to_sid(':', &tmpstr, context,
398
                                        NULL, SECSID_NULL);
399
                kfree(freestr);
400
        }
401
 
402
        return rc;
403
}
404
 
405
/*
406
 * Copies the MLS range `range' into `context'.
407
 */
408
static inline int mls_range_set(struct context *context,
409
                                struct mls_range *range)
410
{
411
        int l, rc = 0;
412
 
413
        /* Copy the MLS range into the  context */
414
        for (l = 0; l < 2; l++) {
415
                context->range.level[l].sens = range->level[l].sens;
416
                rc = ebitmap_cpy(&context->range.level[l].cat,
417
                                 &range->level[l].cat);
418
                if (rc)
419
                        break;
420
        }
421
 
422
        return rc;
423
}
424
 
425
int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
426
                         struct context *usercon)
427
{
428
        if (selinux_mls_enabled) {
429
                struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
430
                struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
431
                struct mls_level *user_low = &(user->range.level[0]);
432
                struct mls_level *user_clr = &(user->range.level[1]);
433
                struct mls_level *user_def = &(user->dfltlevel);
434
                struct mls_level *usercon_sen = &(usercon->range.level[0]);
435
                struct mls_level *usercon_clr = &(usercon->range.level[1]);
436
 
437
                /* Honor the user's default level if we can */
438
                if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
439
                        *usercon_sen = *user_def;
440
                } else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
441
                        *usercon_sen = *fromcon_sen;
442
                } else if (mls_level_between(fromcon_clr, user_low, user_def)) {
443
                        *usercon_sen = *user_low;
444
                } else
445
                        return -EINVAL;
446
 
447
                /* Lower the clearance of available contexts
448
                   if the clearance of "fromcon" is lower than
449
                   that of the user's default clearance (but
450
                   only if the "fromcon" clearance dominates
451
                   the user's computed sensitivity level) */
452
                if (mls_level_dom(user_clr, fromcon_clr)) {
453
                        *usercon_clr = *fromcon_clr;
454
                } else if (mls_level_dom(fromcon_clr, user_clr)) {
455
                        *usercon_clr = *user_clr;
456
                } else
457
                        return -EINVAL;
458
        }
459
 
460
        return 0;
461
}
462
 
463
/*
464
 * Convert the MLS fields in the security context
465
 * structure `c' from the values specified in the
466
 * policy `oldp' to the values specified in the policy `newp'.
467
 */
468
int mls_convert_context(struct policydb *oldp,
469
                        struct policydb *newp,
470
                        struct context *c)
471
{
472
        struct level_datum *levdatum;
473
        struct cat_datum *catdatum;
474
        struct ebitmap bitmap;
475
        struct ebitmap_node *node;
476
        int l, i;
477
 
478
        if (!selinux_mls_enabled)
479
                return 0;
480
 
481
        for (l = 0; l < 2; l++) {
482
                levdatum = hashtab_search(newp->p_levels.table,
483
                        oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
484
 
485
                if (!levdatum)
486
                        return -EINVAL;
487
                c->range.level[l].sens = levdatum->level->sens;
488
 
489
                ebitmap_init(&bitmap);
490
                ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
491
                        int rc;
492
 
493
                        catdatum = hashtab_search(newp->p_cats.table,
494
                                                  oldp->p_cat_val_to_name[i]);
495
                        if (!catdatum)
496
                                return -EINVAL;
497
                        rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
498
                        if (rc)
499
                                return rc;
500
                }
501
                ebitmap_destroy(&c->range.level[l].cat);
502
                c->range.level[l].cat = bitmap;
503
        }
504
 
505
        return 0;
506
}
507
 
508
int mls_compute_sid(struct context *scontext,
509
                    struct context *tcontext,
510
                    u16 tclass,
511
                    u32 specified,
512
                    struct context *newcontext)
513
{
514
        struct range_trans *rtr;
515
 
516
        if (!selinux_mls_enabled)
517
                return 0;
518
 
519
        switch (specified) {
520
        case AVTAB_TRANSITION:
521
                /* Look for a range transition rule. */
522
                for (rtr = policydb.range_tr; rtr; rtr = rtr->next) {
523
                        if (rtr->source_type == scontext->type &&
524
                            rtr->target_type == tcontext->type &&
525
                            rtr->target_class == tclass) {
526
                                /* Set the range from the rule */
527
                                return mls_range_set(newcontext,
528
                                                     &rtr->target_range);
529
                        }
530
                }
531
                /* Fallthrough */
532
        case AVTAB_CHANGE:
533
                if (tclass == SECCLASS_PROCESS)
534
                        /* Use the process MLS attributes. */
535
                        return mls_context_cpy(newcontext, scontext);
536
                else
537
                        /* Use the process effective MLS attributes. */
538
                        return mls_context_cpy_low(newcontext, scontext);
539
        case AVTAB_MEMBER:
540
                /* Only polyinstantiate the MLS attributes if
541
                   the type is being polyinstantiated */
542
                if (newcontext->type != tcontext->type) {
543
                        /* Use the process effective MLS attributes. */
544
                        return mls_context_cpy_low(newcontext, scontext);
545
                } else {
546
                        /* Use the related object MLS attributes. */
547
                        return mls_context_cpy(newcontext, tcontext);
548
                }
549
        default:
550
                return -EINVAL;
551
        }
552
        return -EINVAL;
553
}
554
 
555
#ifdef CONFIG_NETLABEL
556
/**
557
 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
558
 * @context: the security context
559
 * @secattr: the NetLabel security attributes
560
 *
561
 * Description:
562
 * Given the security context copy the low MLS sensitivity level into the
563
 * NetLabel MLS sensitivity level field.
564
 *
565
 */
566
void mls_export_netlbl_lvl(struct context *context,
567
                           struct netlbl_lsm_secattr *secattr)
568
{
569
        if (!selinux_mls_enabled)
570
                return;
571
 
572
        secattr->mls_lvl = context->range.level[0].sens - 1;
573
        secattr->flags |= NETLBL_SECATTR_MLS_LVL;
574
}
575
 
576
/**
577
 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
578
 * @context: the security context
579
 * @secattr: the NetLabel security attributes
580
 *
581
 * Description:
582
 * Given the security context and the NetLabel security attributes, copy the
583
 * NetLabel MLS sensitivity level into the context.
584
 *
585
 */
586
void mls_import_netlbl_lvl(struct context *context,
587
                           struct netlbl_lsm_secattr *secattr)
588
{
589
        if (!selinux_mls_enabled)
590
                return;
591
 
592
        context->range.level[0].sens = secattr->mls_lvl + 1;
593
        context->range.level[1].sens = context->range.level[0].sens;
594
}
595
 
596
/**
597
 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
598
 * @context: the security context
599
 * @secattr: the NetLabel security attributes
600
 *
601
 * Description:
602
 * Given the security context copy the low MLS categories into the NetLabel
603
 * MLS category field.  Returns zero on success, negative values on failure.
604
 *
605
 */
606
int mls_export_netlbl_cat(struct context *context,
607
                          struct netlbl_lsm_secattr *secattr)
608
{
609
        int rc;
610
 
611
        if (!selinux_mls_enabled)
612
                return 0;
613
 
614
        rc = ebitmap_netlbl_export(&context->range.level[0].cat,
615
                                   &secattr->mls_cat);
616
        if (rc == 0 && secattr->mls_cat != NULL)
617
                secattr->flags |= NETLBL_SECATTR_MLS_CAT;
618
 
619
        return rc;
620
}
621
 
622
/**
623
 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
624
 * @context: the security context
625
 * @secattr: the NetLabel security attributes
626
 *
627
 * Description:
628
 * Copy the NetLabel security attributes into the SELinux context; since the
629
 * NetLabel security attribute only contains a single MLS category use it for
630
 * both the low and high categories of the context.  Returns zero on success,
631
 * negative values on failure.
632
 *
633
 */
634
int mls_import_netlbl_cat(struct context *context,
635
                          struct netlbl_lsm_secattr *secattr)
636
{
637
        int rc;
638
 
639
        if (!selinux_mls_enabled)
640
                return 0;
641
 
642
        rc = ebitmap_netlbl_import(&context->range.level[0].cat,
643
                                   secattr->mls_cat);
644
        if (rc != 0)
645
                goto import_netlbl_cat_failure;
646
 
647
        rc = ebitmap_cpy(&context->range.level[1].cat,
648
                         &context->range.level[0].cat);
649
        if (rc != 0)
650
                goto import_netlbl_cat_failure;
651
 
652
        return 0;
653
 
654
import_netlbl_cat_failure:
655
        ebitmap_destroy(&context->range.level[0].cat);
656
        ebitmap_destroy(&context->range.level[1].cat);
657
        return rc;
658
}
659
#endif /* CONFIG_NETLABEL */

powered by: WebSVN 2.1.0

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