*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * 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"
-/*
- * Remove any permissions from `allowed' that are
- * denied by the MLS policy.
- */
-void mls_compute_av(struct context *scontext,
- struct context *tcontext,
- struct class_datum *tclass,
- u32 *allowed)
-{
- unsigned int rel[2];
- int l;
-
- for (l = 0; l < 2; l++)
- rel[l] = mls_level_relation(scontext->range.level[l],
- tcontext->range.level[l]);
-
- if (rel[1] != MLS_RELATION_EQ) {
- if (rel[1] != MLS_RELATION_DOM &&
- !ebitmap_get_bit(&policydb.trustedreaders, scontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
- /* read(s,t) = (s.high >= t.high) = False */
- *allowed = (*allowed) & ~(tclass->mlsperms.read);
- }
- if (rel[1] != MLS_RELATION_DOMBY &&
- !ebitmap_get_bit(&policydb.trustedreaders, tcontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
- /* readby(s,t) = read(t,s) = False */
- *allowed = (*allowed) & ~(tclass->mlsperms.readby);
- }
- }
- if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) ||
- ((!mls_level_eq(tcontext->range.level[0],
- tcontext->range.level[1])) &&
- (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) &&
- !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
- /*
- * write(s,t) = ((s.low <= t.low = t.high) or (s.low
- * <= t.low <= t.high <= s.high)) = False
- */
- *allowed = (*allowed) & ~(tclass->mlsperms.write);
- }
-
- if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) ||
- ((!mls_level_eq(scontext->range.level[0],
- scontext->range.level[1])) &&
- (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) &&
- !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
- /* writeby(s,t) = write(t,s) = False */
- *allowed = (*allowed) & ~(tclass->mlsperms.writeby);
- }
-}
-
/*
* Return the length in bytes for the MLS fields of the
* security context string representation of `context'.
*/
int mls_compute_context_len(struct context * context)
{
- int i, l, len;
+ int i, l, len, range;
+ struct ebitmap_node *node;
+ if (!selinux_mls_enabled)
+ return 0;
- len = 0;
+ len = 1; /* for the beginning ":" */
for (l = 0; l < 2; l++) {
- len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]) + 1;
-
- for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
- if (ebitmap_get_bit(&context->range.level[l].cat, i - 1))
- len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
-
- if (mls_level_relation(context->range.level[0], context->range.level[1])
- == MLS_RELATION_EQ)
- break;
+ range = 0;
+ len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 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;
+ range++;
+ } else {
+ if (range > 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 - 1]) + 1;
+
+ if (l == 0) {
+ if (mls_level_eq(&context->range.level[0],
+ &context->range.level[1]))
+ break;
+ else
+ len++;
+ }
}
return len;
* the MLS fields of `context' into the string `*scontext'.
* Update `*scontext' to point to the end of the MLS fields.
*/
-int mls_sid_to_context(struct context *context,
- char **scontext)
+void mls_sid_to_context(struct context *context,
+ char **scontext)
{
char *scontextp;
- int i, l;
+ int i, l, range, wrote_sep;
+ struct ebitmap_node *node;
+
+ if (!selinux_mls_enabled)
+ return;
scontextp = *scontext;
+ *scontextp = ':';
+ scontextp++;
+
for (l = 0; l < 2; l++) {
+ range = 0;
+ wrote_sep = 0;
strcpy(scontextp,
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
- *scontextp = ':';
- scontextp++;
- for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
- if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
- strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
- scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
- *scontextp = ',';
- scontextp++;
+
+ /* categories */
+ ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
+ if (ebitmap_node_get_bit(node, i)) {
+ if (range) {
+ range++;
+ continue;
+ }
+
+ if (!wrote_sep) {
+ *scontextp++ = ':';
+ wrote_sep = 1;
+ } else
+ *scontextp++ = ',';
+ strcpy(scontextp, policydb.p_cat_val_to_name[i]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i]);
+ range++;
+ } else {
+ if (range > 1) {
+ if (range > 2)
+ *scontextp++ = '.';
+ else
+ *scontextp++ = ',';
+
+ strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+ }
+ range = 0;
}
- if (mls_level_relation(context->range.level[0], context->range.level[1])
- != MLS_RELATION_EQ) {
- scontextp--;
- sprintf(scontextp, "-");
- scontextp++;
+ }
- } else {
- break;
+ /* Handle case where last category is the end of range */
+ if (range > 1) {
+ if (range > 2)
+ *scontextp++ = '.';
+ else
+ *scontextp++ = ',';
+
+ strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
+ }
+
+ if (l == 0) {
+ if (mls_level_eq(&context->range.level[0],
+ &context->range.level[1]))
+ break;
+ else {
+ *scontextp = '-';
+ scontextp++;
+ }
}
}
*scontext = scontextp;
- return 0;
+ return;
}
/*
*/
int mls_context_isvalid(struct policydb *p, struct context *c)
{
- unsigned int relation;
struct level_datum *levdatum;
struct user_datum *usrdatum;
- struct mls_range_list *rnode;
+ struct ebitmap_node *node;
int i, l;
+ if (!selinux_mls_enabled)
+ return 1;
+
/*
* MLS range validity checks: high must dominate low, low level must
* be valid (category set <-> sensitivity check), and high level must
* be valid (category set <-> sensitivity check)
*/
- relation = mls_level_relation(c->range.level[1],
- c->range.level[0]);
- if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ)))
+ if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
/* High does not dominate low. */
return 0;
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.
if (!c->user || c->user > p->p_users.nprim)
return 0;
usrdatum = p->user_val_to_struct[c->user - 1];
- for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) {
- if (mls_range_contains(rnode->range, c->range))
- break;
- }
- if (!rnode)
- /* user may not be associated with range */
- return 0;
+ if (!mls_range_contains(usrdatum->range, c->range))
+ return 0; /* user may not be associated with range */
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
*
* 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;
- char *scontextp, *p;
+ char *scontextp, *p, *rngptr;
struct level_datum *levdatum;
- struct cat_datum *catdatum;
+ struct cat_datum *catdatum, *rngdatum;
int l, rc = -EINVAL;
+ if (!selinux_mls_enabled) {
+ if (def_sid != SECSID_NULL && oldc)
+ *scontext += strlen(*scontext)+1;
+ return 0;
+ }
+
+ /*
+ * No MLS component to the security context, try and map to
+ * default if provided.
+ */
if (!oldc) {
- /* No MLS component to the security context. Try
- to use a default 'unclassified' value. */
- levdatum = hashtab_search(policydb.p_levels.table,
- "unclassified");
- if (!levdatum)
+ struct context *defcon;
+
+ if (def_sid == SECSID_NULL)
goto out;
- context->range.level[0].sens = levdatum->level->sens;
- context->range.level[1].sens = context->range.level[0].sens;
- rc = 0;
+
+ defcon = sidtab_search(s, def_sid);
+ if (!defcon)
+ goto out;
+
+ rc = mls_copy_context(context, defcon);
goto out;
}
for (l = 0; l < 2; l++) {
levdatum = hashtab_search(policydb.p_levels.table, scontextp);
- if (!levdatum)
+ if (!levdatum) {
+ rc = -EINVAL;
goto out;
+ }
context->range.level[l].sens = levdatum->level->sens;
if (delim == ':') {
- /* Extract low category set. */
+ /* Extract category set. */
while (1) {
scontextp = p;
while (*p && *p != ',' && *p != '-')
if (delim != 0)
*p++ = 0;
+ /* Separate into range if exists */
+ if ((rngptr = strchr(scontextp, '.')) != NULL) {
+ /* Remove '.' */
+ *rngptr++ = 0;
+ }
+
catdatum = hashtab_search(policydb.p_cats.table,
scontextp);
- if (!catdatum)
+ if (!catdatum) {
+ rc = -EINVAL;
goto out;
+ }
rc = ebitmap_set_bit(&context->range.level[l].cat,
catdatum->value - 1, 1);
if (rc)
goto out;
+
+ /* If range, set all categories in range */
+ if (rngptr) {
+ int i;
+
+ rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
+ if (!rngdatum) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (catdatum->value >= rngdatum->value) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ for (i = catdatum->value; i < rngdatum->value; i++) {
+ rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
+ if (rc)
+ goto out;
+ }
+ }
+
if (delim != ',')
break;
}
}
/*
- * 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)
+{
+ char *tmpstr, *freestr;
+ int rc;
+
+ 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;
+}
+
+/*
+ * 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;
/* Copy the MLS range from the source context */
for (l = 0; l < 2; l++) {
-
- dst->range.level[l].sens = src->range.level[l].sens;
+ dst->range.level[l].sens = src->range.level[0].sens;
rc = ebitmap_cpy(&dst->range.level[l].cat,
- &src->range.level[l].cat);
+ &src->range.level[0].cat);
if (rc)
break;
}
return rc;
}
+/*
+ * Copies the MLS range `range' into `context'.
+ */
+static inline int mls_range_set(struct context *context,
+ struct mls_range *range)
+{
+ int l, rc = 0;
+
+ /* Copy the MLS range into the context */
+ for (l = 0; l < 2; l++) {
+ context->range.level[l].sens = range->level[l].sens;
+ rc = ebitmap_cpy(&context->range.level[l].cat,
+ &range->level[l].cat);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
+int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+ struct context *usercon)
+{
+ if (selinux_mls_enabled) {
+ struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
+ struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
+ struct mls_level *user_low = &(user->range.level[0]);
+ struct mls_level *user_clr = &(user->range.level[1]);
+ struct mls_level *user_def = &(user->dfltlevel);
+ struct mls_level *usercon_sen = &(usercon->range.level[0]);
+ struct mls_level *usercon_clr = &(usercon->range.level[1]);
+
+ /* Honor the user's default level if we can */
+ if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
+ *usercon_sen = *user_def;
+ } else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
+ *usercon_sen = *fromcon_sen;
+ } else if (mls_level_between(fromcon_clr, user_low, user_def)) {
+ *usercon_sen = *user_low;
+ } else
+ return -EINVAL;
+
+ /* Lower the clearance of available contexts
+ if the clearance of "fromcon" is lower than
+ that of the user's default clearance (but
+ only if the "fromcon" clearance dominates
+ the user's computed sensitivity level) */
+ if (mls_level_dom(user_clr, fromcon_clr)) {
+ *usercon_clr = *fromcon_clr;
+ } else if (mls_level_dom(fromcon_clr, user_clr)) {
+ *usercon_clr = *user_clr;
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* Convert the MLS fields in the security context
* structure `c' from the values specified in the
struct level_datum *levdatum;
struct cat_datum *catdatum;
struct ebitmap bitmap;
+ struct ebitmap_node *node;
int l, i;
+ if (!selinux_mls_enabled)
+ return 0;
+
for (l = 0; l < 2; l++) {
levdatum = hashtab_search(newp->p_levels.table,
oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
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)
{
+ 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);
+ }
+ }
+ }
+ /* Fallthrough */
case AVTAB_CHANGE:
- /* Use the process MLS attributes. */
- return mls_copy_context(newcontext, scontext);
+ if (tclass == SECCLASS_PROCESS)
+ /* Use the process MLS attributes. */
+ return mls_copy_context(newcontext, scontext);
+ else
+ /* Use the process effective MLS attributes. */
+ return mls_scopy_context(newcontext, scontext);
case AVTAB_MEMBER:
/* Only polyinstantiate the MLS attributes if
the type is being polyinstantiated */
if (newcontext->type != tcontext->type) {
- /* Use the process MLS attributes. */
- return mls_copy_context(newcontext, scontext);
+ /* Use the process effective MLS attributes. */
+ return mls_scopy_context(newcontext, scontext);
} else {
/* Use the related object MLS attributes. */
return mls_copy_context(newcontext, tcontext);
return -EINVAL;
}
-void mls_user_destroy(struct user_datum *usrdatum)
-{
- struct mls_range_list *rnode, *rtmp;
- rnode = usrdatum->ranges;
- while (rnode) {
- rtmp = rnode;
- rnode = rnode->next;
- ebitmap_destroy(&rtmp->range.level[0].cat);
- ebitmap_destroy(&rtmp->range.level[1].cat);
- kfree(rtmp);
- }
-}
-
-int mls_read_perm(struct perm_datum *perdatum, void *fp)
-{
- u32 *buf;
-
- buf = next_entry(fp, sizeof(u32));
- if (!buf)
- return -EINVAL;
- perdatum->base_perms = le32_to_cpu(buf[0]);
- return 0;
-}
-
-/*
- * Read a MLS level structure from a policydb binary
- * representation file.
- */
-struct mls_level *mls_read_level(void *fp)
-{
- struct mls_level *l;
- u32 *buf;
-
- l = kmalloc(sizeof(*l), GFP_ATOMIC);
- if (!l) {
- printk(KERN_ERR "security: mls: out of memory\n");
- return NULL;
- }
- memset(l, 0, sizeof(*l));
-
- buf = next_entry(fp, sizeof(u32));
- if (!buf) {
- printk(KERN_ERR "security: mls: truncated level\n");
- goto bad;
- }
- l->sens = cpu_to_le32(buf[0]);
-
- if (ebitmap_read(&l->cat, fp)) {
- printk(KERN_ERR "security: mls: error reading level "
- "categories\n");
- goto bad;
- }
- return l;
-
-bad:
- kfree(l);
- return NULL;
-}
-
-
-/*
- * Read a MLS range structure from a policydb binary
- * representation file.
- */
-static int mls_read_range_helper(struct mls_range *r, void *fp)
-{
- u32 *buf;
- int items, rc = -EINVAL;
-
- buf = next_entry(fp, sizeof(u32));
- if (!buf)
- goto out;
-
- items = le32_to_cpu(buf[0]);
- buf = next_entry(fp, sizeof(u32) * items);
- if (!buf) {
- printk(KERN_ERR "security: mls: truncated range\n");
- goto out;
- }
- r->level[0].sens = le32_to_cpu(buf[0]);
- if (items > 1) {
- r->level[1].sens = le32_to_cpu(buf[1]);
- } else {
- r->level[1].sens = r->level[0].sens;
- }
-
- rc = ebitmap_read(&r->level[0].cat, fp);
- if (rc) {
- printk(KERN_ERR "security: mls: error reading low "
- "categories\n");
- goto out;
- }
- if (items > 1) {
- rc = ebitmap_read(&r->level[1].cat, fp);
- if (rc) {
- printk(KERN_ERR "security: mls: error reading high "
- "categories\n");
- goto bad_high;
- }
- } else {
- rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
- if (rc) {
- printk(KERN_ERR "security: mls: out of memory\n");
- goto bad_high;
- }
- }
-
- rc = 0;
-out:
- return rc;
-bad_high:
- ebitmap_destroy(&r->level[0].cat);
- goto out;
-}
-
-int mls_read_range(struct context *c, void *fp)
-{
- return mls_read_range_helper(&c->range, fp);
-}
-
-
-/*
- * Read a MLS perms structure from a policydb binary
- * representation file.
- */
-int mls_read_class(struct class_datum *cladatum, void *fp)
-{
- struct mls_perms *p = &cladatum->mlsperms;
- u32 *buf;
-
- buf = next_entry(fp, sizeof(u32)*4);
- if (!buf) {
- printk(KERN_ERR "security: mls: truncated mls permissions\n");
- return -EINVAL;
- }
- p->read = le32_to_cpu(buf[0]);
- p->readby = le32_to_cpu(buf[1]);
- p->write = le32_to_cpu(buf[2]);
- p->writeby = le32_to_cpu(buf[3]);
- return 0;
-}
-
-int mls_read_user(struct user_datum *usrdatum, void *fp)
-{
- struct mls_range_list *r, *l;
- int rc = 0;
- u32 nel, i;
- u32 *buf;
-
- buf = next_entry(fp, sizeof(u32));
- if (!buf) {
- rc = -EINVAL;
- goto out;
- }
- nel = le32_to_cpu(buf[0]);
- l = NULL;
- for (i = 0; i < nel; i++) {
- r = kmalloc(sizeof(*r), GFP_ATOMIC);
- if (!r) {
- rc = -ENOMEM;
- goto out;
- }
- memset(r, 0, sizeof(*r));
-
- rc = mls_read_range_helper(&r->range, fp);
- if (rc) {
- kfree(r);
- goto out;
- }
-
- if (l)
- l->next = r;
- else
- usrdatum->ranges = r;
- l = r;
- }
-out:
- return rc;
-}
-
-int mls_read_nlevels(struct policydb *p, void *fp)
-{
- u32 *buf;
-
- buf = next_entry(fp, sizeof(u32));
- if (!buf)
- return -EINVAL;
- p->nlevels = le32_to_cpu(buf[0]);
- return 0;
-}
-
-int mls_read_trusted(struct policydb *p, void *fp)
-{
- int rc = 0;
-
- rc = ebitmap_read(&p->trustedreaders, fp);
- if (rc)
- goto out;
- rc = ebitmap_read(&p->trustedwriters, fp);
- if (rc)
- goto bad;
- rc = ebitmap_read(&p->trustedobjects, fp);
- if (rc)
- goto bad2;
-out:
- return rc;
-bad2:
- ebitmap_destroy(&p->trustedwriters);
-bad:
- ebitmap_destroy(&p->trustedreaders);
- goto out;
-}
-
-int sens_index(void *key, void *datum, void *datap)
-{
- struct policydb *p;
- struct level_datum *levdatum;
-
-
- levdatum = datum;
- p = datap;
-
- if (!levdatum->isalias)
- p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
-
- return 0;
-}
-
-int cat_index(void *key, void *datum, void *datap)
-{
- struct policydb *p;
- struct cat_datum *catdatum;
-
-
- catdatum = datum;
- p = datap;
-
-
- if (!catdatum->isalias)
- p->p_cat_val_to_name[catdatum->value - 1] = key;
-
- return 0;
-}
-
-int sens_destroy(void *key, void *datum, void *p)
-{
- struct level_datum *levdatum;
-
- kfree(key);
- levdatum = datum;
- if (!levdatum->isalias) {
- ebitmap_destroy(&levdatum->level->cat);
- kfree(levdatum->level);
- }
- kfree(datum);
- return 0;
-}
-
-int cat_destroy(void *key, void *datum, void *p)
-{
- kfree(key);
- kfree(datum);
- return 0;
-}
-
-int sens_read(struct policydb *p, struct hashtab *h, void *fp)
-{
- char *key = NULL;
- struct level_datum *levdatum;
- int rc;
- u32 *buf, len;
-
- levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
- if (!levdatum) {
- rc = -ENOMEM;
- goto out;
- }
- memset(levdatum, 0, sizeof(*levdatum));
-
- buf = next_entry(fp, sizeof(u32)*2);
- if (!buf) {
- rc = -EINVAL;
- goto bad;
- }
-
- len = le32_to_cpu(buf[0]);
- levdatum->isalias = le32_to_cpu(buf[1]);
-
- buf = next_entry(fp, len);
- if (!buf) {
- rc = -EINVAL;
- goto bad;
- }
- key = kmalloc(len + 1,GFP_ATOMIC);
- if (!key) {
- rc = -ENOMEM;
- goto bad;
- }
- memcpy(key, buf, len);
- key[len] = 0;
-
- levdatum->level = mls_read_level(fp);
- if (!levdatum->level) {
- rc = -EINVAL;
- goto bad;
- }
-
- rc = hashtab_insert(h, key, levdatum);
- if (rc)
- goto bad;
-out:
- return rc;
-bad:
- sens_destroy(key, levdatum, NULL);
- goto out;
-}
-
-
-int cat_read(struct policydb *p, struct hashtab *h, void *fp)
-{
- char *key = NULL;
- struct cat_datum *catdatum;
- int rc;
- u32 *buf, len;
-
- catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
- if (!catdatum) {
- rc = -ENOMEM;
- goto out;
- }
- memset(catdatum, 0, sizeof(*catdatum));
-
- buf = next_entry(fp, sizeof(u32)*3);
- if (!buf) {
- rc = -EINVAL;
- goto bad;
- }
-
- len = le32_to_cpu(buf[0]);
- catdatum->value = le32_to_cpu(buf[1]);
- catdatum->isalias = le32_to_cpu(buf[2]);
-
- buf = next_entry(fp, len);
- if (!buf) {
- rc = -EINVAL;
- goto bad;
- }
- key = kmalloc(len + 1,GFP_ATOMIC);
- if (!key) {
- rc = -ENOMEM;
- goto bad;
- }
- memcpy(key, buf, len);
- key[len] = 0;
-
- rc = hashtab_insert(h, key, catdatum);
- if (rc)
- goto bad;
-out:
- return rc;
-
-bad:
- cat_destroy(key, catdatum, NULL);
- goto out;
-}