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 (!selinux_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(policydb.p_sens_val_to_name[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 = 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
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 (!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
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 = 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
160int 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
179
180
181 return 0;
182 }
183 }
184
185 return 1;
186}
187
188int 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
197
198
199int 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
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;
220
221 return 1;
222}
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242int mls_context_to_sid(struct policydb *pol,
243 char oldc,
244 char **scontext,
245 struct context *context,
246 struct sidtab *s,
247 u32 def_sid)
248{
249
250 char delim;
251 char *scontextp, *p, *rngptr;
252 struct level_datum *levdatum;
253 struct cat_datum *catdatum, *rngdatum;
254 int l, rc = -EINVAL;
255
256 if (!selinux_mls_enabled) {
257 if (def_sid != SECSID_NULL && oldc)
258 *scontext += strlen(*scontext)+1;
259 return 0;
260 }
261
262
263
264
265
266 if (!oldc) {
267 struct context *defcon;
268
269 if (def_sid == SECSID_NULL)
270 goto out;
271
272 defcon = sidtab_search(s, def_sid);
273 if (!defcon)
274 goto out;
275
276 rc = mls_context_cpy(context, defcon);
277 goto out;
278 }
279
280
281 scontextp = p = *scontext;
282 while (*p && *p != ':' && *p != '-')
283 p++;
284
285 delim = *p;
286 if (delim != '\0')
287 *p++ = '\0';
288
289 for (l = 0; l < 2; l++) {
290 levdatum = hashtab_search(pol->p_levels.table, scontextp);
291 if (!levdatum) {
292 rc = -EINVAL;
293 goto out;
294 }
295
296 context->range.level[l].sens = levdatum->level->sens;
297
298 if (delim == ':') {
299
300 while (1) {
301 scontextp = p;
302 while (*p && *p != ',' && *p != '-')
303 p++;
304 delim = *p;
305 if (delim != '\0')
306 *p++ = '\0';
307
308
309 rngptr = strchr(scontextp, '.');
310 if (rngptr != NULL) {
311
312 *rngptr++ = '\0';
313 }
314
315 catdatum = hashtab_search(pol->p_cats.table,
316 scontextp);
317 if (!catdatum) {
318 rc = -EINVAL;
319 goto out;
320 }
321
322 rc = ebitmap_set_bit(&context->range.level[l].cat,
323 catdatum->value - 1, 1);
324 if (rc)
325 goto out;
326
327
328 if (rngptr) {
329 int i;
330
331 rngdatum = hashtab_search(pol->p_cats.table, rngptr);
332 if (!rngdatum) {
333 rc = -EINVAL;
334 goto out;
335 }
336
337 if (catdatum->value >= rngdatum->value) {
338 rc = -EINVAL;
339 goto out;
340 }
341
342 for (i = catdatum->value; i < rngdatum->value; i++) {
343 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
344 if (rc)
345 goto out;
346 }
347 }
348
349 if (delim != ',')
350 break;
351 }
352 }
353 if (delim == '-') {
354
355 scontextp = p;
356 while (*p && *p != ':')
357 p++;
358
359 delim = *p;
360 if (delim != '\0')
361 *p++ = '\0';
362 } else
363 break;
364 }
365
366 if (l == 0) {
367 context->range.level[1].sens = context->range.level[0].sens;
368 rc = ebitmap_cpy(&context->range.level[1].cat,
369 &context->range.level[0].cat);
370 if (rc)
371 goto out;
372 }
373 *scontext = ++p;
374 rc = 0;
375out:
376 return rc;
377}
378
379
380
381
382
383
384
385int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
386{
387 char *tmpstr, *freestr;
388 int rc;
389
390 if (!selinux_mls_enabled)
391 return -EINVAL;
392
393
394
395 tmpstr = freestr = kstrdup(str, gfp_mask);
396 if (!tmpstr) {
397 rc = -ENOMEM;
398 } else {
399 rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
400 NULL, SECSID_NULL);
401 kfree(freestr);
402 }
403
404 return rc;
405}
406
407
408
409
410static inline int mls_range_set(struct context *context,
411 struct mls_range *range)
412{
413 int l, rc = 0;
414
415
416 for (l = 0; l < 2; l++) {
417 context->range.level[l].sens = range->level[l].sens;
418 rc = ebitmap_cpy(&context->range.level[l].cat,
419 &range->level[l].cat);
420 if (rc)
421 break;
422 }
423
424 return rc;
425}
426
427int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
428 struct context *usercon)
429{
430 if (selinux_mls_enabled) {
431 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
432 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
433 struct mls_level *user_low = &(user->range.level[0]);
434 struct mls_level *user_clr = &(user->range.level[1]);
435 struct mls_level *user_def = &(user->dfltlevel);
436 struct mls_level *usercon_sen = &(usercon->range.level[0]);
437 struct mls_level *usercon_clr = &(usercon->range.level[1]);
438
439
440 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
441 *usercon_sen = *user_def;
442 else if (mls_level_between(fromcon_sen, user_def, user_clr))
443 *usercon_sen = *fromcon_sen;
444 else if (mls_level_between(fromcon_clr, user_low, user_def))
445 *usercon_sen = *user_low;
446 else
447 return -EINVAL;
448
449
450
451
452
453
454 if (mls_level_dom(user_clr, fromcon_clr))
455 *usercon_clr = *fromcon_clr;
456 else if (mls_level_dom(fromcon_clr, user_clr))
457 *usercon_clr = *user_clr;
458 else
459 return -EINVAL;
460 }
461
462 return 0;
463}
464
465
466
467
468
469
470int mls_convert_context(struct policydb *oldp,
471 struct policydb *newp,
472 struct context *c)
473{
474 struct level_datum *levdatum;
475 struct cat_datum *catdatum;
476 struct ebitmap bitmap;
477 struct ebitmap_node *node;
478 int l, i;
479
480 if (!selinux_mls_enabled)
481 return 0;
482
483 for (l = 0; l < 2; l++) {
484 levdatum = hashtab_search(newp->p_levels.table,
485 oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
486
487 if (!levdatum)
488 return -EINVAL;
489 c->range.level[l].sens = levdatum->level->sens;
490
491 ebitmap_init(&bitmap);
492 ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
493 int rc;
494
495 catdatum = hashtab_search(newp->p_cats.table,
496 oldp->p_cat_val_to_name[i]);
497 if (!catdatum)
498 return -EINVAL;
499 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
500 if (rc)
501 return rc;
502 }
503 ebitmap_destroy(&c->range.level[l].cat);
504 c->range.level[l].cat = bitmap;
505 }
506
507 return 0;
508}
509
510int mls_compute_sid(struct context *scontext,
511 struct context *tcontext,
512 u16 tclass,
513 u32 specified,
514 struct context *newcontext)
515{
516 struct range_trans *rtr;
517
518 if (!selinux_mls_enabled)
519 return 0;
520
521 switch (specified) {
522 case AVTAB_TRANSITION:
523
524 for (rtr = policydb.range_tr; rtr; rtr = rtr->next) {
525 if (rtr->source_type == scontext->type &&
526 rtr->target_type == tcontext->type &&
527 rtr->target_class == tclass) {
528
529 return mls_range_set(newcontext,
530 &rtr->target_range);
531 }
532 }
533
534 case AVTAB_CHANGE:
535 if (tclass == SECCLASS_PROCESS)
536
537 return mls_context_cpy(newcontext, scontext);
538 else
539
540 return mls_context_cpy_low(newcontext, scontext);
541 case AVTAB_MEMBER:
542
543 return mls_context_cpy_low(newcontext, scontext);
544 default:
545 return -EINVAL;
546 }
547 return -EINVAL;
548}
549
550#ifdef CONFIG_NETLABEL
551
552
553
554
555
556
557
558
559
560
561void mls_export_netlbl_lvl(struct context *context,
562 struct netlbl_lsm_secattr *secattr)
563{
564 if (!selinux_mls_enabled)
565 return;
566
567 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
568 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
569}
570
571
572
573
574
575
576
577
578
579
580
581void mls_import_netlbl_lvl(struct context *context,
582 struct netlbl_lsm_secattr *secattr)
583{
584 if (!selinux_mls_enabled)
585 return;
586
587 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
588 context->range.level[1].sens = context->range.level[0].sens;
589}
590
591
592
593
594
595
596
597
598
599
600
601int mls_export_netlbl_cat(struct context *context,
602 struct netlbl_lsm_secattr *secattr)
603{
604 int rc;
605
606 if (!selinux_mls_enabled)
607 return 0;
608
609 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
610 &secattr->attr.mls.cat);
611 if (rc == 0 && secattr->attr.mls.cat != NULL)
612 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
613
614 return rc;
615}
616
617
618
619
620
621
622
623
624
625
626
627
628
629int mls_import_netlbl_cat(struct context *context,
630 struct netlbl_lsm_secattr *secattr)
631{
632 int rc;
633
634 if (!selinux_mls_enabled)
635 return 0;
636
637 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
638 secattr->attr.mls.cat);
639 if (rc != 0)
640 goto import_netlbl_cat_failure;
641
642 rc = ebitmap_cpy(&context->range.level[1].cat,
643 &context->range.level[0].cat);
644 if (rc != 0)
645 goto import_netlbl_cat_failure;
646
647 return 0;
648
649import_netlbl_cat_failure:
650 ebitmap_destroy(&context->range.level[0].cat);
651 ebitmap_destroy(&context->range.level[1].cat);
652 return rc;
653}
654#endif
655