*
* Support for enhanced MLS infrastructure.
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
+ */
+/*
+ * Updated: Hewlett-Packard <paul.moore@hp.com>
+ *
+ * Added support to import/export the MLS label from NetLabel
+ *
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <net/netlabel.h>
+#include "sidtab.h"
#include "mls.h"
#include "policydb.h"
#include "services.h"
int mls_compute_context_len(struct context * context)
{
int i, l, len, range;
+ struct ebitmap_node *node;
if (!selinux_mls_enabled)
return 0;
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],
{
char *scontextp;
int i, l, range, wrote_sep;
+ struct ebitmap_node *node;
if (!selinux_mls_enabled)
return;
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;
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) {
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;
}
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) {
{
struct level_datum *levdatum;
struct user_datum *usrdatum;
+ struct ebitmap_node *node;
int i, l;
if (!selinux_mls_enabled)
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.
*
* 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;
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;
}
/*
- * 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;
struct level_datum *levdatum;
struct cat_datum *catdatum;
struct ebitmap bitmap;
+ struct ebitmap_node *node;
int l, i;
if (!selinux_mls_enabled)
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);
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;
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 */