0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <linux/kernel.h>
0023 #include <linux/slab.h>
0024 #include <linux/string.h>
0025 #include <linux/errno.h>
0026 #include <net/netlabel.h>
0027 #include "sidtab.h"
0028 #include "mls.h"
0029 #include "policydb.h"
0030 #include "services.h"
0031
0032
0033
0034
0035
0036 int mls_compute_context_len(struct policydb *p, struct context *context)
0037 {
0038 int i, l, len, head, prev;
0039 char *nm;
0040 struct ebitmap *e;
0041 struct ebitmap_node *node;
0042
0043 if (!p->mls_enabled)
0044 return 0;
0045
0046 len = 1;
0047 for (l = 0; l < 2; l++) {
0048 int index_sens = context->range.level[l].sens;
0049 len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1));
0050
0051
0052 head = -2;
0053 prev = -2;
0054 e = &context->range.level[l].cat;
0055 ebitmap_for_each_positive_bit(e, node, i) {
0056 if (i - prev > 1) {
0057
0058 if (head != prev) {
0059 nm = sym_name(p, SYM_CATS, prev);
0060 len += strlen(nm) + 1;
0061 }
0062 nm = sym_name(p, SYM_CATS, i);
0063 len += strlen(nm) + 1;
0064 head = i;
0065 }
0066 prev = i;
0067 }
0068 if (prev != head) {
0069 nm = sym_name(p, SYM_CATS, prev);
0070 len += strlen(nm) + 1;
0071 }
0072 if (l == 0) {
0073 if (mls_level_eq(&context->range.level[0],
0074 &context->range.level[1]))
0075 break;
0076 else
0077 len++;
0078 }
0079 }
0080
0081 return len;
0082 }
0083
0084
0085
0086
0087
0088
0089 void mls_sid_to_context(struct policydb *p,
0090 struct context *context,
0091 char **scontext)
0092 {
0093 char *scontextp, *nm;
0094 int i, l, head, prev;
0095 struct ebitmap *e;
0096 struct ebitmap_node *node;
0097
0098 if (!p->mls_enabled)
0099 return;
0100
0101 scontextp = *scontext;
0102
0103 *scontextp = ':';
0104 scontextp++;
0105
0106 for (l = 0; l < 2; l++) {
0107 strcpy(scontextp, sym_name(p, SYM_LEVELS,
0108 context->range.level[l].sens - 1));
0109 scontextp += strlen(scontextp);
0110
0111
0112 head = -2;
0113 prev = -2;
0114 e = &context->range.level[l].cat;
0115 ebitmap_for_each_positive_bit(e, node, i) {
0116 if (i - prev > 1) {
0117
0118 if (prev != head) {
0119 if (prev - head > 1)
0120 *scontextp++ = '.';
0121 else
0122 *scontextp++ = ',';
0123 nm = sym_name(p, SYM_CATS, prev);
0124 strcpy(scontextp, nm);
0125 scontextp += strlen(nm);
0126 }
0127 if (prev < 0)
0128 *scontextp++ = ':';
0129 else
0130 *scontextp++ = ',';
0131 nm = sym_name(p, SYM_CATS, i);
0132 strcpy(scontextp, nm);
0133 scontextp += strlen(nm);
0134 head = i;
0135 }
0136 prev = i;
0137 }
0138
0139 if (prev != head) {
0140 if (prev - head > 1)
0141 *scontextp++ = '.';
0142 else
0143 *scontextp++ = ',';
0144 nm = sym_name(p, SYM_CATS, prev);
0145 strcpy(scontextp, nm);
0146 scontextp += strlen(nm);
0147 }
0148
0149 if (l == 0) {
0150 if (mls_level_eq(&context->range.level[0],
0151 &context->range.level[1]))
0152 break;
0153 else
0154 *scontextp++ = '-';
0155 }
0156 }
0157
0158 *scontext = scontextp;
0159 }
0160
0161 int mls_level_isvalid(struct policydb *p, struct mls_level *l)
0162 {
0163 struct level_datum *levdatum;
0164
0165 if (!l->sens || l->sens > p->p_levels.nprim)
0166 return 0;
0167 levdatum = symtab_search(&p->p_levels,
0168 sym_name(p, SYM_LEVELS, l->sens - 1));
0169 if (!levdatum)
0170 return 0;
0171
0172
0173
0174
0175
0176
0177 return ebitmap_contains(&levdatum->level->cat, &l->cat,
0178 p->p_cats.nprim);
0179 }
0180
0181 int mls_range_isvalid(struct policydb *p, struct mls_range *r)
0182 {
0183 return (mls_level_isvalid(p, &r->level[0]) &&
0184 mls_level_isvalid(p, &r->level[1]) &&
0185 mls_level_dom(&r->level[1], &r->level[0]));
0186 }
0187
0188
0189
0190
0191
0192 int mls_context_isvalid(struct policydb *p, struct context *c)
0193 {
0194 struct user_datum *usrdatum;
0195
0196 if (!p->mls_enabled)
0197 return 1;
0198
0199 if (!mls_range_isvalid(p, &c->range))
0200 return 0;
0201
0202 if (c->role == OBJECT_R_VAL)
0203 return 1;
0204
0205
0206
0207
0208 if (!c->user || c->user > p->p_users.nprim)
0209 return 0;
0210 usrdatum = p->user_val_to_struct[c->user - 1];
0211 if (!mls_range_contains(usrdatum->range, c->range))
0212 return 0;
0213
0214 return 1;
0215 }
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 int mls_context_to_sid(struct policydb *pol,
0234 char oldc,
0235 char *scontext,
0236 struct context *context,
0237 struct sidtab *s,
0238 u32 def_sid)
0239 {
0240 char *sensitivity, *cur_cat, *next_cat, *rngptr;
0241 struct level_datum *levdatum;
0242 struct cat_datum *catdatum, *rngdatum;
0243 int l, rc, i;
0244 char *rangep[2];
0245
0246 if (!pol->mls_enabled) {
0247
0248
0249
0250
0251 if (oldc && def_sid == SECSID_NULL)
0252 return -EINVAL;
0253 return 0;
0254 }
0255
0256
0257
0258
0259
0260 if (!oldc) {
0261 struct context *defcon;
0262
0263 if (def_sid == SECSID_NULL)
0264 return -EINVAL;
0265
0266 defcon = sidtab_search(s, def_sid);
0267 if (!defcon)
0268 return -EINVAL;
0269
0270 return mls_context_cpy(context, defcon);
0271 }
0272
0273
0274
0275
0276
0277 rangep[0] = scontext;
0278 rangep[1] = strchr(scontext, '-');
0279 if (rangep[1]) {
0280 rangep[1][0] = '\0';
0281 rangep[1]++;
0282 }
0283
0284
0285 for (l = 0; l < 2; l++) {
0286
0287 sensitivity = rangep[l];
0288 if (sensitivity == NULL)
0289 break;
0290 next_cat = strchr(sensitivity, ':');
0291 if (next_cat)
0292 *(next_cat++) = '\0';
0293
0294
0295 levdatum = symtab_search(&pol->p_levels, sensitivity);
0296 if (!levdatum)
0297 return -EINVAL;
0298 context->range.level[l].sens = levdatum->level->sens;
0299
0300
0301 while (next_cat != NULL) {
0302 cur_cat = next_cat;
0303 next_cat = strchr(next_cat, ',');
0304 if (next_cat != NULL)
0305 *(next_cat++) = '\0';
0306
0307
0308 rngptr = strchr(cur_cat, '.');
0309 if (rngptr != NULL) {
0310
0311 *rngptr++ = '\0';
0312 }
0313
0314 catdatum = symtab_search(&pol->p_cats, cur_cat);
0315 if (!catdatum)
0316 return -EINVAL;
0317
0318 rc = ebitmap_set_bit(&context->range.level[l].cat,
0319 catdatum->value - 1, 1);
0320 if (rc)
0321 return rc;
0322
0323
0324 if (rngptr == NULL)
0325 continue;
0326
0327 rngdatum = symtab_search(&pol->p_cats, rngptr);
0328 if (!rngdatum)
0329 return -EINVAL;
0330
0331 if (catdatum->value >= rngdatum->value)
0332 return -EINVAL;
0333
0334 for (i = catdatum->value; i < rngdatum->value; i++) {
0335 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
0336 if (rc)
0337 return rc;
0338 }
0339 }
0340 }
0341
0342
0343 if (rangep[1] == NULL) {
0344 context->range.level[1].sens = context->range.level[0].sens;
0345 rc = ebitmap_cpy(&context->range.level[1].cat,
0346 &context->range.level[0].cat);
0347 if (rc)
0348 return rc;
0349 }
0350
0351 return 0;
0352 }
0353
0354
0355
0356
0357
0358
0359
0360 int mls_from_string(struct policydb *p, char *str, struct context *context,
0361 gfp_t gfp_mask)
0362 {
0363 char *tmpstr;
0364 int rc;
0365
0366 if (!p->mls_enabled)
0367 return -EINVAL;
0368
0369 tmpstr = kstrdup(str, gfp_mask);
0370 if (!tmpstr) {
0371 rc = -ENOMEM;
0372 } else {
0373 rc = mls_context_to_sid(p, ':', tmpstr, context,
0374 NULL, SECSID_NULL);
0375 kfree(tmpstr);
0376 }
0377
0378 return rc;
0379 }
0380
0381
0382
0383
0384 int mls_range_set(struct context *context,
0385 struct mls_range *range)
0386 {
0387 int l, rc = 0;
0388
0389
0390 for (l = 0; l < 2; l++) {
0391 context->range.level[l].sens = range->level[l].sens;
0392 rc = ebitmap_cpy(&context->range.level[l].cat,
0393 &range->level[l].cat);
0394 if (rc)
0395 break;
0396 }
0397
0398 return rc;
0399 }
0400
0401 int mls_setup_user_range(struct policydb *p,
0402 struct context *fromcon, struct user_datum *user,
0403 struct context *usercon)
0404 {
0405 if (p->mls_enabled) {
0406 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
0407 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
0408 struct mls_level *user_low = &(user->range.level[0]);
0409 struct mls_level *user_clr = &(user->range.level[1]);
0410 struct mls_level *user_def = &(user->dfltlevel);
0411 struct mls_level *usercon_sen = &(usercon->range.level[0]);
0412 struct mls_level *usercon_clr = &(usercon->range.level[1]);
0413
0414
0415 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
0416 *usercon_sen = *user_def;
0417 else if (mls_level_between(fromcon_sen, user_def, user_clr))
0418 *usercon_sen = *fromcon_sen;
0419 else if (mls_level_between(fromcon_clr, user_low, user_def))
0420 *usercon_sen = *user_low;
0421 else
0422 return -EINVAL;
0423
0424
0425
0426
0427
0428
0429 if (mls_level_dom(user_clr, fromcon_clr))
0430 *usercon_clr = *fromcon_clr;
0431 else if (mls_level_dom(fromcon_clr, user_clr))
0432 *usercon_clr = *user_clr;
0433 else
0434 return -EINVAL;
0435 }
0436
0437 return 0;
0438 }
0439
0440
0441
0442
0443
0444
0445
0446 int mls_convert_context(struct policydb *oldp,
0447 struct policydb *newp,
0448 struct context *oldc,
0449 struct context *newc)
0450 {
0451 struct level_datum *levdatum;
0452 struct cat_datum *catdatum;
0453 struct ebitmap_node *node;
0454 int l, i;
0455
0456 if (!oldp->mls_enabled || !newp->mls_enabled)
0457 return 0;
0458
0459 for (l = 0; l < 2; l++) {
0460 char *name = sym_name(oldp, SYM_LEVELS,
0461 oldc->range.level[l].sens - 1);
0462
0463 levdatum = symtab_search(&newp->p_levels, name);
0464
0465 if (!levdatum)
0466 return -EINVAL;
0467 newc->range.level[l].sens = levdatum->level->sens;
0468
0469 ebitmap_for_each_positive_bit(&oldc->range.level[l].cat,
0470 node, i) {
0471 int rc;
0472
0473 catdatum = symtab_search(&newp->p_cats,
0474 sym_name(oldp, SYM_CATS, i));
0475 if (!catdatum)
0476 return -EINVAL;
0477 rc = ebitmap_set_bit(&newc->range.level[l].cat,
0478 catdatum->value - 1, 1);
0479 if (rc)
0480 return rc;
0481 }
0482 }
0483
0484 return 0;
0485 }
0486
0487 int mls_compute_sid(struct policydb *p,
0488 struct context *scontext,
0489 struct context *tcontext,
0490 u16 tclass,
0491 u32 specified,
0492 struct context *newcontext,
0493 bool sock)
0494 {
0495 struct range_trans rtr;
0496 struct mls_range *r;
0497 struct class_datum *cladatum;
0498 int default_range = 0;
0499
0500 if (!p->mls_enabled)
0501 return 0;
0502
0503 switch (specified) {
0504 case AVTAB_TRANSITION:
0505
0506 rtr.source_type = scontext->type;
0507 rtr.target_type = tcontext->type;
0508 rtr.target_class = tclass;
0509 r = policydb_rangetr_search(p, &rtr);
0510 if (r)
0511 return mls_range_set(newcontext, r);
0512
0513 if (tclass && tclass <= p->p_classes.nprim) {
0514 cladatum = p->class_val_to_struct[tclass - 1];
0515 if (cladatum)
0516 default_range = cladatum->default_range;
0517 }
0518
0519 switch (default_range) {
0520 case DEFAULT_SOURCE_LOW:
0521 return mls_context_cpy_low(newcontext, scontext);
0522 case DEFAULT_SOURCE_HIGH:
0523 return mls_context_cpy_high(newcontext, scontext);
0524 case DEFAULT_SOURCE_LOW_HIGH:
0525 return mls_context_cpy(newcontext, scontext);
0526 case DEFAULT_TARGET_LOW:
0527 return mls_context_cpy_low(newcontext, tcontext);
0528 case DEFAULT_TARGET_HIGH:
0529 return mls_context_cpy_high(newcontext, tcontext);
0530 case DEFAULT_TARGET_LOW_HIGH:
0531 return mls_context_cpy(newcontext, tcontext);
0532 case DEFAULT_GLBLUB:
0533 return mls_context_glblub(newcontext,
0534 scontext, tcontext);
0535 }
0536
0537 fallthrough;
0538 case AVTAB_CHANGE:
0539 if ((tclass == p->process_class) || sock)
0540
0541 return mls_context_cpy(newcontext, scontext);
0542 else
0543
0544 return mls_context_cpy_low(newcontext, scontext);
0545 case AVTAB_MEMBER:
0546
0547 return mls_context_cpy_low(newcontext, scontext);
0548 }
0549 return -EINVAL;
0550 }
0551
0552 #ifdef CONFIG_NETLABEL
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564 void mls_export_netlbl_lvl(struct policydb *p,
0565 struct context *context,
0566 struct netlbl_lsm_secattr *secattr)
0567 {
0568 if (!p->mls_enabled)
0569 return;
0570
0571 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
0572 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
0573 }
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586 void mls_import_netlbl_lvl(struct policydb *p,
0587 struct context *context,
0588 struct netlbl_lsm_secattr *secattr)
0589 {
0590 if (!p->mls_enabled)
0591 return;
0592
0593 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
0594 context->range.level[1].sens = context->range.level[0].sens;
0595 }
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608 int mls_export_netlbl_cat(struct policydb *p,
0609 struct context *context,
0610 struct netlbl_lsm_secattr *secattr)
0611 {
0612 int rc;
0613
0614 if (!p->mls_enabled)
0615 return 0;
0616
0617 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
0618 &secattr->attr.mls.cat);
0619 if (rc == 0 && secattr->attr.mls.cat != NULL)
0620 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
0621
0622 return rc;
0623 }
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638 int mls_import_netlbl_cat(struct policydb *p,
0639 struct context *context,
0640 struct netlbl_lsm_secattr *secattr)
0641 {
0642 int rc;
0643
0644 if (!p->mls_enabled)
0645 return 0;
0646
0647 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
0648 secattr->attr.mls.cat);
0649 if (rc)
0650 goto import_netlbl_cat_failure;
0651 memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
0652 sizeof(context->range.level[0].cat));
0653
0654 return 0;
0655
0656 import_netlbl_cat_failure:
0657 ebitmap_destroy(&context->range.level[0].cat);
0658 return rc;
0659 }
0660 #endif