1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
33
34
35int 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 (!policydb.mls_enabled)
43 return 0;
44
45 len = 1;
46 for (l = 0; l < 2; l++) {
47 int index_sens = context->range.level[l].sens;
48 len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
49
50
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
57 if (head != prev) {
58 nm = sym_name(&policydb, SYM_CATS, prev);
59 len += strlen(nm) + 1;
60 }
61 nm = sym_name(&policydb, SYM_CATS, i);
62 len += strlen(nm) + 1;
63 head = i;
64 }
65 prev = i;
66 }
67 if (prev != head) {
68 nm = sym_name(&policydb, SYM_CATS, 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
85
86
87
88void 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 (!policydb.mls_enabled)
97 return;
98
99 scontextp = *scontext;
100
101 *scontextp = ':';
102 scontextp++;
103
104 for (l = 0; l < 2; l++) {
105 strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
106 context->range.level[l].sens - 1));
107 scontextp += strlen(scontextp);
108
109
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
116 if (prev != head) {
117 if (prev - head > 1)
118 *scontextp++ = '.';
119 else
120 *scontextp++ = ',';
121 nm = sym_name(&policydb, SYM_CATS, prev);
122 strcpy(scontextp, nm);
123 scontextp += strlen(nm);
124 }
125 if (prev < 0)
126 *scontextp++ = ':';
127 else
128 *scontextp++ = ',';
129 nm = sym_name(&policydb, SYM_CATS, 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 = sym_name(&policydb, SYM_CATS, 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
160int mls_level_isvalid(struct policydb *p, struct mls_level *l)
161{
162 struct level_datum *levdatum;
163
164 if (!l->sens || l->sens > p->p_levels.nprim)
165 return 0;
166 levdatum = hashtab_search(p->p_levels.table,
167 sym_name(p, SYM_LEVELS, l->sens - 1));
168 if (!levdatum)
169 return 0;
170
171
172
173
174
175
176 return ebitmap_contains(&levdatum->level->cat, &l->cat,
177 p->p_cats.nprim);
178}
179
180int mls_range_isvalid(struct policydb *p, struct mls_range *r)
181{
182 return (mls_level_isvalid(p, &r->level[0]) &&
183 mls_level_isvalid(p, &r->level[1]) &&
184 mls_level_dom(&r->level[1], &r->level[0]));
185}
186
187
188
189
190
191int mls_context_isvalid(struct policydb *p, struct context *c)
192{
193 struct user_datum *usrdatum;
194
195 if (!p->mls_enabled)
196 return 1;
197
198 if (!mls_range_isvalid(p, &c->range))
199 return 0;
200
201 if (c->role == OBJECT_R_VAL)
202 return 1;
203
204
205
206
207 if (!c->user || c->user > p->p_users.nprim)
208 return 0;
209 usrdatum = p->user_val_to_struct[c->user - 1];
210 if (!mls_range_contains(usrdatum->range, c->range))
211 return 0;
212
213 return 1;
214}
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234int mls_context_to_sid(struct policydb *pol,
235 char oldc,
236 char **scontext,
237 struct context *context,
238 struct sidtab *s,
239 u32 def_sid)
240{
241
242 char delim;
243 char *scontextp, *p, *rngptr;
244 struct level_datum *levdatum;
245 struct cat_datum *catdatum, *rngdatum;
246 int l, rc = -EINVAL;
247
248 if (!pol->mls_enabled) {
249 if (def_sid != SECSID_NULL && oldc)
250 *scontext += strlen(*scontext) + 1;
251 return 0;
252 }
253
254
255
256
257
258 if (!oldc) {
259 struct context *defcon;
260
261 if (def_sid == SECSID_NULL)
262 goto out;
263
264 defcon = sidtab_search(s, def_sid);
265 if (!defcon)
266 goto out;
267
268 rc = mls_context_cpy(context, defcon);
269 goto out;
270 }
271
272
273 scontextp = p = *scontext;
274 while (*p && *p != ':' && *p != '-')
275 p++;
276
277 delim = *p;
278 if (delim != '\0')
279 *p++ = '\0';
280
281 for (l = 0; l < 2; l++) {
282 levdatum = hashtab_search(pol->p_levels.table, scontextp);
283 if (!levdatum) {
284 rc = -EINVAL;
285 goto out;
286 }
287
288 context->range.level[l].sens = levdatum->level->sens;
289
290 if (delim == ':') {
291
292 while (1) {
293 scontextp = p;
294 while (*p && *p != ',' && *p != '-')
295 p++;
296 delim = *p;
297 if (delim != '\0')
298 *p++ = '\0';
299
300
301 rngptr = strchr(scontextp, '.');
302 if (rngptr != NULL) {
303
304 *rngptr++ = '\0';
305 }
306
307 catdatum = hashtab_search(pol->p_cats.table,
308 scontextp);
309 if (!catdatum) {
310 rc = -EINVAL;
311 goto out;
312 }
313
314 rc = ebitmap_set_bit(&context->range.level[l].cat,
315 catdatum->value - 1, 1);
316 if (rc)
317 goto out;
318
319
320 if (rngptr) {
321 int i;
322
323 rngdatum = hashtab_search(pol->p_cats.table, rngptr);
324 if (!rngdatum) {
325 rc = -EINVAL;
326 goto out;
327 }
328
329 if (catdatum->value >= rngdatum->value) {
330 rc = -EINVAL;
331 goto out;
332 }
333
334 for (i = catdatum->value; i < rngdatum->value; i++) {
335 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
336 if (rc)
337 goto out;
338 }
339 }
340
341 if (delim != ',')
342 break;
343 }
344 }
345 if (delim == '-') {
346
347 scontextp = p;
348 while (*p && *p != ':')
349 p++;
350
351 delim = *p;
352 if (delim != '\0')
353 *p++ = '\0';
354 } else
355 break;
356 }
357
358 if (l == 0) {
359 context->range.level[1].sens = context->range.level[0].sens;
360 rc = ebitmap_cpy(&context->range.level[1].cat,
361 &context->range.level[0].cat);
362 if (rc)
363 goto out;
364 }
365 *scontext = ++p;
366 rc = 0;
367out:
368 return rc;
369}
370
371
372
373
374
375
376
377int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
378{
379 char *tmpstr, *freestr;
380 int rc;
381
382 if (!policydb.mls_enabled)
383 return -EINVAL;
384
385
386
387 tmpstr = freestr = kstrdup(str, gfp_mask);
388 if (!tmpstr) {
389 rc = -ENOMEM;
390 } else {
391 rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
392 NULL, SECSID_NULL);
393 kfree(freestr);
394 }
395
396 return rc;
397}
398
399
400
401
402int mls_range_set(struct context *context,
403 struct mls_range *range)
404{
405 int l, rc = 0;
406
407
408 for (l = 0; l < 2; l++) {
409 context->range.level[l].sens = range->level[l].sens;
410 rc = ebitmap_cpy(&context->range.level[l].cat,
411 &range->level[l].cat);
412 if (rc)
413 break;
414 }
415
416 return rc;
417}
418
419int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
420 struct context *usercon)
421{
422 if (policydb.mls_enabled) {
423 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
424 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
425 struct mls_level *user_low = &(user->range.level[0]);
426 struct mls_level *user_clr = &(user->range.level[1]);
427 struct mls_level *user_def = &(user->dfltlevel);
428 struct mls_level *usercon_sen = &(usercon->range.level[0]);
429 struct mls_level *usercon_clr = &(usercon->range.level[1]);
430
431
432 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
433 *usercon_sen = *user_def;
434 else if (mls_level_between(fromcon_sen, user_def, user_clr))
435 *usercon_sen = *fromcon_sen;
436 else if (mls_level_between(fromcon_clr, user_low, user_def))
437 *usercon_sen = *user_low;
438 else
439 return -EINVAL;
440
441
442
443
444
445
446 if (mls_level_dom(user_clr, fromcon_clr))
447 *usercon_clr = *fromcon_clr;
448 else if (mls_level_dom(fromcon_clr, user_clr))
449 *usercon_clr = *user_clr;
450 else
451 return -EINVAL;
452 }
453
454 return 0;
455}
456
457
458
459
460
461
462int mls_convert_context(struct policydb *oldp,
463 struct policydb *newp,
464 struct context *c)
465{
466 struct level_datum *levdatum;
467 struct cat_datum *catdatum;
468 struct ebitmap bitmap;
469 struct ebitmap_node *node;
470 int l, i;
471
472 if (!policydb.mls_enabled)
473 return 0;
474
475 for (l = 0; l < 2; l++) {
476 levdatum = hashtab_search(newp->p_levels.table,
477 sym_name(oldp, SYM_LEVELS,
478 c->range.level[l].sens - 1));
479
480 if (!levdatum)
481 return -EINVAL;
482 c->range.level[l].sens = levdatum->level->sens;
483
484 ebitmap_init(&bitmap);
485 ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
486 int rc;
487
488 catdatum = hashtab_search(newp->p_cats.table,
489 sym_name(oldp, SYM_CATS, i));
490 if (!catdatum)
491 return -EINVAL;
492 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
493 if (rc)
494 return rc;
495
496 cond_resched();
497 }
498 ebitmap_destroy(&c->range.level[l].cat);
499 c->range.level[l].cat = bitmap;
500 }
501
502 return 0;
503}
504
505int mls_compute_sid(struct context *scontext,
506 struct context *tcontext,
507 u16 tclass,
508 u32 specified,
509 struct context *newcontext,
510 bool sock)
511{
512 struct range_trans rtr;
513 struct mls_range *r;
514 struct class_datum *cladatum;
515 int default_range = 0;
516
517 if (!policydb.mls_enabled)
518 return 0;
519
520 switch (specified) {
521 case AVTAB_TRANSITION:
522
523 rtr.source_type = scontext->type;
524 rtr.target_type = tcontext->type;
525 rtr.target_class = tclass;
526 r = hashtab_search(policydb.range_tr, &rtr);
527 if (r)
528 return mls_range_set(newcontext, r);
529
530 if (tclass && tclass <= policydb.p_classes.nprim) {
531 cladatum = policydb.class_val_to_struct[tclass - 1];
532 if (cladatum)
533 default_range = cladatum->default_range;
534 }
535
536 switch (default_range) {
537 case DEFAULT_SOURCE_LOW:
538 return mls_context_cpy_low(newcontext, scontext);
539 case DEFAULT_SOURCE_HIGH:
540 return mls_context_cpy_high(newcontext, scontext);
541 case DEFAULT_SOURCE_LOW_HIGH:
542 return mls_context_cpy(newcontext, scontext);
543 case DEFAULT_TARGET_LOW:
544 return mls_context_cpy_low(newcontext, tcontext);
545 case DEFAULT_TARGET_HIGH:
546 return mls_context_cpy_high(newcontext, tcontext);
547 case DEFAULT_TARGET_LOW_HIGH:
548 return mls_context_cpy(newcontext, tcontext);
549 }
550
551
552 case AVTAB_CHANGE:
553 if ((tclass == policydb.process_class) || (sock == true))
554
555 return mls_context_cpy(newcontext, scontext);
556 else
557
558 return mls_context_cpy_low(newcontext, scontext);
559 case AVTAB_MEMBER:
560
561 return mls_context_cpy_low(newcontext, scontext);
562
563
564 }
565 return -EINVAL;
566}
567
568#ifdef CONFIG_NETLABEL
569
570
571
572
573
574
575
576
577
578
579void mls_export_netlbl_lvl(struct context *context,
580 struct netlbl_lsm_secattr *secattr)
581{
582 if (!policydb.mls_enabled)
583 return;
584
585 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
586 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
587}
588
589
590
591
592
593
594
595
596
597
598
599void mls_import_netlbl_lvl(struct context *context,
600 struct netlbl_lsm_secattr *secattr)
601{
602 if (!policydb.mls_enabled)
603 return;
604
605 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
606 context->range.level[1].sens = context->range.level[0].sens;
607}
608
609
610
611
612
613
614
615
616
617
618
619int mls_export_netlbl_cat(struct context *context,
620 struct netlbl_lsm_secattr *secattr)
621{
622 int rc;
623
624 if (!policydb.mls_enabled)
625 return 0;
626
627 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
628 &secattr->attr.mls.cat);
629 if (rc == 0 && secattr->attr.mls.cat != NULL)
630 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
631
632 return rc;
633}
634
635
636
637
638
639
640
641
642
643
644
645
646
647int mls_import_netlbl_cat(struct context *context,
648 struct netlbl_lsm_secattr *secattr)
649{
650 int rc;
651
652 if (!policydb.mls_enabled)
653 return 0;
654
655 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
656 secattr->attr.mls.cat);
657 if (rc)
658 goto import_netlbl_cat_failure;
659 memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
660 sizeof(context->range.level[0].cat));
661
662 return 0;
663
664import_netlbl_cat_failure:
665 ebitmap_destroy(&context->range.level[0].cat);
666 return rc;
667}
668#endif
669