2 * Implementation of the multi-level security (MLS) policy.
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
9 * Support for enhanced MLS infrastructure.
11 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
14 * Updated: Hewlett-Packard <paul.moore@hp.com>
16 * Added support to import/export the MLS label
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
21 #include <linux/kernel.h>
22 #include <linux/slab.h>
23 #include <linux/string.h>
24 #include <linux/errno.h>
31 * Return the length in bytes for the MLS fields of the
32 * security context string representation of `context'.
34 int mls_compute_context_len(struct context * context)
37 struct ebitmap_node *node;
39 if (!selinux_mls_enabled)
42 len = 1; /* for the beginning ":" */
43 for (l = 0; l < 2; l++) {
45 len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
47 ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
48 if (ebitmap_node_get_bit(node, i)) {
54 len += strlen(policydb.p_cat_val_to_name[i]) + 1;
58 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
62 /* Handle case where last category is the end of range */
64 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
67 if (mls_level_eq(&context->range.level[0],
68 &context->range.level[1]))
79 * Write the security context string representation of
80 * the MLS fields of `context' into the string `*scontext'.
81 * Update `*scontext' to point to the end of the MLS fields.
83 void mls_sid_to_context(struct context *context,
87 int i, l, range, wrote_sep;
88 struct ebitmap_node *node;
90 if (!selinux_mls_enabled)
93 scontextp = *scontext;
98 for (l = 0; l < 2; l++) {
102 policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
103 scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
106 ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
107 if (ebitmap_node_get_bit(node, i)) {
118 strcpy(scontextp, policydb.p_cat_val_to_name[i]);
119 scontextp += strlen(policydb.p_cat_val_to_name[i]);
128 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
129 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
135 /* Handle case where last category is the end of range */
142 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
143 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
147 if (mls_level_eq(&context->range.level[0],
148 &context->range.level[1]))
157 *scontext = scontextp;
162 * Return 1 if the MLS fields in the security context
163 * structure `c' are valid. Return 0 otherwise.
165 int mls_context_isvalid(struct policydb *p, struct context *c)
167 struct level_datum *levdatum;
168 struct user_datum *usrdatum;
169 struct ebitmap_node *node;
172 if (!selinux_mls_enabled)
176 * MLS range validity checks: high must dominate low, low level must
177 * be valid (category set <-> sensitivity check), and high level must
178 * be valid (category set <-> sensitivity check)
180 if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
181 /* High does not dominate low. */
184 for (l = 0; l < 2; l++) {
185 if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim)
187 levdatum = hashtab_search(p->p_levels.table,
188 p->p_sens_val_to_name[c->range.level[l].sens - 1]);
192 ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
193 if (ebitmap_node_get_bit(node, i)) {
194 if (i > p->p_cats.nprim)
196 if (!ebitmap_get_bit(&levdatum->level->cat, i))
198 * Category may not be associated with
199 * sensitivity in low level.
206 if (c->role == OBJECT_R_VAL)
210 * User must be authorized for the MLS range.
212 if (!c->user || c->user > p->p_users.nprim)
214 usrdatum = p->user_val_to_struct[c->user - 1];
215 if (!mls_range_contains(usrdatum->range, c->range))
216 return 0; /* user may not be associated with range */
222 * Set the MLS fields in the security context structure
223 * `context' based on the string representation in
224 * the string `*scontext'. Update `*scontext' to
225 * point to the end of the string representation of
228 * This function modifies the string in place, inserting
229 * NULL characters to terminate the MLS fields.
231 * If a def_sid is provided and no MLS field is present,
232 * copy the MLS field of the associated default context.
233 * Used for upgraded to MLS systems where objects may lack
236 * Policy read-lock must be held for sidtab lookup.
239 int mls_context_to_sid(char oldc,
241 struct context *context,
247 char *scontextp, *p, *rngptr;
248 struct level_datum *levdatum;
249 struct cat_datum *catdatum, *rngdatum;
252 if (!selinux_mls_enabled) {
253 if (def_sid != SECSID_NULL && oldc)
254 *scontext += strlen(*scontext)+1;
259 * No MLS component to the security context, try and map to
260 * default if provided.
263 struct context *defcon;
265 if (def_sid == SECSID_NULL)
268 defcon = sidtab_search(s, def_sid);
272 rc = mls_copy_context(context, defcon);
276 /* Extract low sensitivity. */
277 scontextp = p = *scontext;
278 while (*p && *p != ':' && *p != '-')
285 for (l = 0; l < 2; l++) {
286 levdatum = hashtab_search(policydb.p_levels.table, scontextp);
292 context->range.level[l].sens = levdatum->level->sens;
295 /* Extract category set. */
298 while (*p && *p != ',' && *p != '-')
304 /* Separate into range if exists */
305 if ((rngptr = strchr(scontextp, '.')) != NULL) {
310 catdatum = hashtab_search(policydb.p_cats.table,
317 rc = ebitmap_set_bit(&context->range.level[l].cat,
318 catdatum->value - 1, 1);
322 /* If range, set all categories in range */
326 rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
332 if (catdatum->value >= rngdatum->value) {
337 for (i = catdatum->value; i < rngdatum->value; i++) {
338 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
349 /* Extract high sensitivity. */
351 while (*p && *p != ':')
362 context->range.level[1].sens = context->range.level[0].sens;
363 rc = ebitmap_cpy(&context->range.level[1].cat,
364 &context->range.level[0].cat);
375 * Set the MLS fields in the security context structure
376 * `context' based on the string representation in
377 * the string `str'. This function will allocate temporary memory with the
378 * given constraints of gfp_mask.
380 int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
382 char *tmpstr, *freestr;
385 if (!selinux_mls_enabled)
388 /* we need freestr because mls_context_to_sid will change
389 the value of tmpstr */
390 tmpstr = freestr = kstrdup(str, gfp_mask);
394 rc = mls_context_to_sid(':', &tmpstr, context,
403 * Copies the effective MLS range from `src' into `dst'.
405 static inline int mls_scopy_context(struct context *dst,
410 /* Copy the MLS range from the source context */
411 for (l = 0; l < 2; l++) {
412 dst->range.level[l].sens = src->range.level[0].sens;
413 rc = ebitmap_cpy(&dst->range.level[l].cat,
414 &src->range.level[0].cat);
423 * Copies the MLS range `range' into `context'.
425 static inline int mls_range_set(struct context *context,
426 struct mls_range *range)
430 /* Copy the MLS range into the context */
431 for (l = 0; l < 2; l++) {
432 context->range.level[l].sens = range->level[l].sens;
433 rc = ebitmap_cpy(&context->range.level[l].cat,
434 &range->level[l].cat);
442 int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
443 struct context *usercon)
445 if (selinux_mls_enabled) {
446 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
447 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
448 struct mls_level *user_low = &(user->range.level[0]);
449 struct mls_level *user_clr = &(user->range.level[1]);
450 struct mls_level *user_def = &(user->dfltlevel);
451 struct mls_level *usercon_sen = &(usercon->range.level[0]);
452 struct mls_level *usercon_clr = &(usercon->range.level[1]);
454 /* Honor the user's default level if we can */
455 if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
456 *usercon_sen = *user_def;
457 } else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
458 *usercon_sen = *fromcon_sen;
459 } else if (mls_level_between(fromcon_clr, user_low, user_def)) {
460 *usercon_sen = *user_low;
464 /* Lower the clearance of available contexts
465 if the clearance of "fromcon" is lower than
466 that of the user's default clearance (but
467 only if the "fromcon" clearance dominates
468 the user's computed sensitivity level) */
469 if (mls_level_dom(user_clr, fromcon_clr)) {
470 *usercon_clr = *fromcon_clr;
471 } else if (mls_level_dom(fromcon_clr, user_clr)) {
472 *usercon_clr = *user_clr;
481 * Convert the MLS fields in the security context
482 * structure `c' from the values specified in the
483 * policy `oldp' to the values specified in the policy `newp'.
485 int mls_convert_context(struct policydb *oldp,
486 struct policydb *newp,
489 struct level_datum *levdatum;
490 struct cat_datum *catdatum;
491 struct ebitmap bitmap;
492 struct ebitmap_node *node;
495 if (!selinux_mls_enabled)
498 for (l = 0; l < 2; l++) {
499 levdatum = hashtab_search(newp->p_levels.table,
500 oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
504 c->range.level[l].sens = levdatum->level->sens;
506 ebitmap_init(&bitmap);
507 ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
508 if (ebitmap_node_get_bit(node, i)) {
511 catdatum = hashtab_search(newp->p_cats.table,
512 oldp->p_cat_val_to_name[i]);
515 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
520 ebitmap_destroy(&c->range.level[l].cat);
521 c->range.level[l].cat = bitmap;
527 int mls_compute_sid(struct context *scontext,
528 struct context *tcontext,
531 struct context *newcontext)
533 if (!selinux_mls_enabled)
537 case AVTAB_TRANSITION:
538 if (tclass == SECCLASS_PROCESS) {
539 struct range_trans *rangetr;
540 /* Look for a range transition rule. */
541 for (rangetr = policydb.range_tr; rangetr;
542 rangetr = rangetr->next) {
543 if (rangetr->dom == scontext->type &&
544 rangetr->type == tcontext->type) {
545 /* Set the range from the rule */
546 return mls_range_set(newcontext,
553 if (tclass == SECCLASS_PROCESS)
554 /* Use the process MLS attributes. */
555 return mls_copy_context(newcontext, scontext);
557 /* Use the process effective MLS attributes. */
558 return mls_scopy_context(newcontext, scontext);
560 /* Only polyinstantiate the MLS attributes if
561 the type is being polyinstantiated */
562 if (newcontext->type != tcontext->type) {
563 /* Use the process effective MLS attributes. */
564 return mls_scopy_context(newcontext, scontext);
566 /* Use the related object MLS attributes. */
567 return mls_copy_context(newcontext, tcontext);
576 * mls_export_lvl - Export the MLS sensitivity levels
577 * @context: the security context
578 * @low: the low sensitivity level
579 * @high: the high sensitivity level
582 * Given the security context copy the low MLS sensitivity level into lvl_low
583 * and the high sensitivity level in lvl_high. The MLS levels are only
584 * exported if the pointers are not NULL, if they are NULL then that level is
588 void mls_export_lvl(const struct context *context, u32 *low, u32 *high)
590 if (!selinux_mls_enabled)
594 *low = context->range.level[0].sens - 1;
596 *high = context->range.level[1].sens - 1;
600 * mls_import_lvl - Import the MLS sensitivity levels
601 * @context: the security context
602 * @low: the low sensitivity level
603 * @high: the high sensitivity level
606 * Given the security context and the two sensitivty levels, set the MLS levels
607 * in the context according the two given as parameters. Returns zero on
608 * success, negative values on failure.
611 void mls_import_lvl(struct context *context, u32 low, u32 high)
613 if (!selinux_mls_enabled)
616 context->range.level[0].sens = low + 1;
617 context->range.level[1].sens = high + 1;
621 * mls_export_cat - Export the MLS categories
622 * @context: the security context
623 * @low: the low category
624 * @low_len: length of the cat_low bitmap in bytes
625 * @high: the high category
626 * @high_len: length of the cat_high bitmap in bytes
629 * Given the security context export the low MLS category bitmap into cat_low
630 * and the high category bitmap into cat_high. The MLS categories are only
631 * exported if the pointers are not NULL, if they are NULL then that level is
632 * not exported. The caller is responsibile for freeing the memory when
633 * finished. Returns zero on success, negative values on failure.
636 int mls_export_cat(const struct context *context,
639 unsigned char **high,
644 if (!selinux_mls_enabled)
648 rc = ebitmap_export(&context->range.level[0].cat,
652 goto export_cat_failure;
655 rc = ebitmap_export(&context->range.level[1].cat,
659 goto export_cat_failure;
673 * mls_import_cat - Import the MLS categories
674 * @context: the security context
675 * @low: the low category
676 * @low_len: length of the cat_low bitmap in bytes
677 * @high: the high category
678 * @high_len: length of the cat_high bitmap in bytes
681 * Given the security context and the two category bitmap strings import the
682 * categories into the security context. The MLS categories are only imported
683 * if the pointers are not NULL, if they are NULL they are skipped. Returns
684 * zero on success, negative values on failure.
687 int mls_import_cat(struct context *context,
688 const unsigned char *low,
690 const unsigned char *high,
695 if (!selinux_mls_enabled)
699 rc = ebitmap_import(low,
701 &context->range.level[0].cat);
703 goto import_cat_failure;
707 rc = ebitmap_cpy(&context->range.level[1].cat,
708 &context->range.level[0].cat);
710 rc = ebitmap_import(high,
712 &context->range.level[1].cat);
714 goto import_cat_failure;
720 ebitmap_destroy(&context->range.level[0].cat);
721 ebitmap_destroy(&context->range.level[1].cat);