*
* Support for enhanced MLS infrastructure.
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.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.
return 1;
}
+/*
+ * Copies the MLS range from `src' into `dst'.
+ */
+static inline int mls_copy_context(struct context *dst,
+ struct context *src)
+{
+ 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;
+ }
+
+ return rc;
+}
+
/*
* Set the MLS fields in the security context structure
* `context' based on the string representation in
*
* 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_copy_context(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;
+ char *tmpstr, *freestr;
+ int rc;
- /* 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;
+ if (!selinux_mls_enabled)
+ return -EINVAL;
+
+ /* 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);