X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=security%2Fselinux%2Fss%2Fmls.c;h=4a8bab2f3c712445f020fbe3a42a8aa4f172442c;hb=refs%2Fheads%2Fvserver;hp=756036bcc243190858f997a0eb1af79942f3869d;hpb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;p=linux-2.6.git diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 756036bcc..4a8bab2f3 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -8,13 +8,22 @@ * * Support for enhanced MLS infrastructure. * - * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. + */ +/* + * Updated: Hewlett-Packard + * + * Added support to import/export the MLS label from NetLabel + * + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 */ #include #include #include #include +#include +#include "sidtab.h" #include "mls.h" #include "policydb.h" #include "services.h" @@ -26,6 +35,7 @@ int mls_compute_context_len(struct context * context) { int i, l, len, range; + struct ebitmap_node *node; if (!selinux_mls_enabled) return 0; @@ -35,24 +45,24 @@ int mls_compute_context_len(struct context * context) range = 0; len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); - for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { - if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { + ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { + if (ebitmap_node_get_bit(node, i)) { if (range) { range++; continue; } - len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; + len += strlen(policydb.p_cat_val_to_name[i]) + 1; range++; } else { if (range > 1) - len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; + len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; range = 0; } } /* Handle case where last category is the end of range */ if (range > 1) - len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; + len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; if (l == 0) { if (mls_level_eq(&context->range.level[0], @@ -76,6 +86,7 @@ void mls_sid_to_context(struct context *context, { char *scontextp; int i, l, range, wrote_sep; + struct ebitmap_node *node; if (!selinux_mls_enabled) return; @@ -93,8 +104,8 @@ void mls_sid_to_context(struct context *context, scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); /* categories */ - for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { - if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { + ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { + if (ebitmap_node_get_bit(node, i)) { if (range) { range++; continue; @@ -105,8 +116,8 @@ void mls_sid_to_context(struct context *context, wrote_sep = 1; } else *scontextp++ = ','; - strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); - scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); + strcpy(scontextp, policydb.p_cat_val_to_name[i]); + scontextp += strlen(policydb.p_cat_val_to_name[i]); range++; } else { if (range > 1) { @@ -115,8 +126,8 @@ void mls_sid_to_context(struct context *context, else *scontextp++ = ','; - strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); - scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); + strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); + scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); } range = 0; } @@ -129,8 +140,8 @@ void mls_sid_to_context(struct context *context, else *scontextp++ = ','; - strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); - scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); + strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); + scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); } if (l == 0) { @@ -156,6 +167,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) { struct level_datum *levdatum; struct user_datum *usrdatum; + struct ebitmap_node *node; int i, l; if (!selinux_mls_enabled) @@ -178,11 +190,11 @@ int mls_context_isvalid(struct policydb *p, struct context *c) if (!levdatum) return 0; - for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { - if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { + ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { + if (ebitmap_node_get_bit(node, i)) { if (i > p->p_cats.nprim) return 0; - if (!ebitmap_get_bit(&levdatum->level->cat, i - 1)) + if (!ebitmap_get_bit(&levdatum->level->cat, i)) /* * Category may not be associated with * sensitivity in low level. @@ -216,10 +228,20 @@ int mls_context_isvalid(struct policydb *p, struct context *c) * * This function modifies the string in place, inserting * NULL characters to terminate the MLS fields. + * + * If a def_sid is provided and no MLS field is present, + * copy the MLS field of the associated default context. + * Used for upgraded to MLS systems where objects may lack + * MLS fields. + * + * Policy read-lock must be held for sidtab lookup. + * */ int mls_context_to_sid(char oldc, char **scontext, - struct context *context) + struct context *context, + struct sidtab *s, + u32 def_sid) { char delim; @@ -228,12 +250,29 @@ int mls_context_to_sid(char oldc, struct cat_datum *catdatum, *rngdatum; int l, rc = -EINVAL; - if (!selinux_mls_enabled) + if (!selinux_mls_enabled) { + if (def_sid != SECSID_NULL && oldc) + *scontext += strlen(*scontext)+1; return 0; + } - /* No MLS component to the security context. */ - if (!oldc) + /* + * No MLS component to the security context, try and map to + * default if provided. + */ + if (!oldc) { + struct context *defcon; + + if (def_sid == SECSID_NULL) + goto out; + + defcon = sidtab_search(s, def_sid); + if (!defcon) + goto out; + + rc = mls_context_cpy(context, defcon); goto out; + } /* Extract low sensitivity. */ scontextp = p = *scontext; @@ -334,40 +373,28 @@ out: } /* - * Copies the MLS range from `src' into `dst'. + * Set the MLS fields in the security context structure + * `context' based on the string representation in + * the string `str'. This function will allocate temporary memory with the + * given constraints of gfp_mask. */ -static inline int mls_copy_context(struct context *dst, - struct context *src) +int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) { - int l, rc = 0; - - /* Copy the MLS range from the source context */ - for (l = 0; l < 2; l++) { - dst->range.level[l].sens = src->range.level[l].sens; - rc = ebitmap_cpy(&dst->range.level[l].cat, - &src->range.level[l].cat); - if (rc) - break; - } + char *tmpstr, *freestr; + int rc; - return rc; -} - -/* - * Copies the effective MLS range from `src' into `dst'. - */ -static inline int mls_scopy_context(struct context *dst, - struct context *src) -{ - int l, rc = 0; + if (!selinux_mls_enabled) + return -EINVAL; - /* Copy the MLS range from the source context */ - for (l = 0; l < 2; l++) { - dst->range.level[l].sens = src->range.level[0].sens; - rc = ebitmap_cpy(&dst->range.level[l].cat, - &src->range.level[0].cat); - if (rc) - break; + /* we need freestr because mls_context_to_sid will change + the value of tmpstr */ + tmpstr = freestr = kstrdup(str, gfp_mask); + if (!tmpstr) { + rc = -ENOMEM; + } else { + rc = mls_context_to_sid(':', &tmpstr, context, + NULL, SECSID_NULL); + kfree(freestr); } return rc; @@ -443,6 +470,7 @@ int mls_convert_context(struct policydb *oldp, struct level_datum *levdatum; struct cat_datum *catdatum; struct ebitmap bitmap; + struct ebitmap_node *node; int l, i; if (!selinux_mls_enabled) @@ -457,12 +485,12 @@ int mls_convert_context(struct policydb *oldp, c->range.level[l].sens = levdatum->level->sens; ebitmap_init(&bitmap); - for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { - if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { + ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { + if (ebitmap_node_get_bit(node, i)) { int rc; catdatum = hashtab_search(newp->p_cats.table, - oldp->p_cat_val_to_name[i - 1]); + oldp->p_cat_val_to_name[i]); if (!catdatum) return -EINVAL; rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); @@ -483,41 +511,40 @@ int mls_compute_sid(struct context *scontext, u32 specified, struct context *newcontext) { + struct range_trans *rtr; + if (!selinux_mls_enabled) return 0; switch (specified) { case AVTAB_TRANSITION: - if (tclass == SECCLASS_PROCESS) { - struct range_trans *rangetr; - /* Look for a range transition rule. */ - for (rangetr = policydb.range_tr; rangetr; - rangetr = rangetr->next) { - if (rangetr->dom == scontext->type && - rangetr->type == tcontext->type) { - /* Set the range from the rule */ - return mls_range_set(newcontext, - &rangetr->range); - } + /* Look for a range transition rule. */ + for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { + if (rtr->source_type == scontext->type && + rtr->target_type == tcontext->type && + rtr->target_class == tclass) { + /* Set the range from the rule */ + return mls_range_set(newcontext, + &rtr->target_range); } } /* Fallthrough */ case AVTAB_CHANGE: if (tclass == SECCLASS_PROCESS) /* Use the process MLS attributes. */ - return mls_copy_context(newcontext, scontext); + return mls_context_cpy(newcontext, scontext); else /* Use the process effective MLS attributes. */ - return mls_scopy_context(newcontext, scontext); + return mls_context_cpy_low(newcontext, scontext); case AVTAB_MEMBER: /* Only polyinstantiate the MLS attributes if the type is being polyinstantiated */ if (newcontext->type != tcontext->type) { /* Use the process effective MLS attributes. */ - return mls_scopy_context(newcontext, scontext); + return mls_context_cpy_low(newcontext, scontext); } else { /* Use the related object MLS attributes. */ - return mls_copy_context(newcontext, tcontext); + return mls_context_cpy(newcontext, tcontext); } default: return -EINVAL; @@ -525,3 +552,108 @@ int mls_compute_sid(struct context *scontext, return -EINVAL; } +#ifdef CONFIG_NETLABEL +/** + * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel + * @context: the security context + * @secattr: the NetLabel security attributes + * + * Description: + * Given the security context copy the low MLS sensitivity level into the + * NetLabel MLS sensitivity level field. + * + */ +void mls_export_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + if (!selinux_mls_enabled) + return; + + secattr->mls_lvl = context->range.level[0].sens - 1; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; +} + +/** + * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels + * @context: the security context + * @secattr: the NetLabel security attributes + * + * Description: + * Given the security context and the NetLabel security attributes, copy the + * NetLabel MLS sensitivity level into the context. + * + */ +void mls_import_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + if (!selinux_mls_enabled) + return; + + context->range.level[0].sens = secattr->mls_lvl + 1; + context->range.level[1].sens = context->range.level[0].sens; +} + +/** + * mls_export_netlbl_cat - Export the MLS categories to NetLabel + * @context: the security context + * @secattr: the NetLabel security attributes + * + * Description: + * Given the security context copy the low MLS categories into the NetLabel + * MLS category field. Returns zero on success, negative values on failure. + * + */ +int mls_export_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + int rc; + + if (!selinux_mls_enabled) + return 0; + + rc = ebitmap_netlbl_export(&context->range.level[0].cat, + &secattr->mls_cat); + if (rc == 0 && secattr->mls_cat != NULL) + secattr->flags |= NETLBL_SECATTR_MLS_CAT; + + return rc; +} + +/** + * mls_import_netlbl_cat - Import the MLS categories from NetLabel + * @context: the security context + * @secattr: the NetLabel security attributes + * + * Description: + * Copy the NetLabel security attributes into the SELinux context; since the + * NetLabel security attribute only contains a single MLS category use it for + * both the low and high categories of the context. Returns zero on success, + * negative values on failure. + * + */ +int mls_import_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) +{ + int rc; + + if (!selinux_mls_enabled) + return 0; + + rc = ebitmap_netlbl_import(&context->range.level[0].cat, + secattr->mls_cat); + if (rc != 0) + goto import_netlbl_cat_failure; + + rc = ebitmap_cpy(&context->range.level[1].cat, + &context->range.level[0].cat); + if (rc != 0) + goto import_netlbl_cat_failure; + + return 0; + +import_netlbl_cat_failure: + ebitmap_destroy(&context->range.level[0].cat); + ebitmap_destroy(&context->range.level[1].cat); + return rc; +} +#endif /* CONFIG_NETLABEL */