X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=security%2Fselinux%2Fss%2Fmls.c;h=4a8bab2f3c712445f020fbe3a42a8aa4f172442c;hb=refs%2Fheads%2Fvserver;hp=f54ad88d487331f960170298b5c183ab4daf53c9;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index f54ad88d4..4a8bab2f3 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -3,88 +3,74 @@ * * Author : Stephen Smalley, */ +/* + * Updated: Trusted Computer Solutions, Inc. + * + * Support for enhanced MLS infrastructure. + * + * 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" -/* - * 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; @@ -95,40 +81,82 @@ int mls_compute_context_len(struct context * context) * 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; } /* @@ -137,20 +165,20 @@ int mls_sid_to_context(struct context *context, */ 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; @@ -162,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. @@ -185,18 +213,12 @@ int mls_context_isvalid(struct policydb *p, struct context *c) 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; } - /* * Set the MLS fields in the security context structure * `context' based on the string representation in @@ -206,28 +228,49 @@ 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; - 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_context_cpy(context, defcon); goto out; } @@ -242,13 +285,15 @@ int mls_context_to_sid(char oldc, 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 != '-') @@ -257,15 +302,46 @@ int mls_context_to_sid(char oldc, 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; } @@ -297,19 +373,46 @@ 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. + */ +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 MLS range `range' into `context'. */ -static inline int mls_copy_context(struct context *dst, - struct context *src) +static inline int mls_range_set(struct context *context, + struct mls_range *range) { int l, rc = 0; - /* Copy the MLS range from the source context */ + /* Copy the MLS range into the 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); + context->range.level[l].sens = range->level[l].sens; + rc = ebitmap_cpy(&context->range.level[l].cat, + &range->level[l].cat); if (rc) break; } @@ -317,6 +420,44 @@ static inline int mls_copy_context(struct context *dst, 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 @@ -329,8 +470,12 @@ 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) + 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]); @@ -340,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); @@ -366,20 +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: + /* 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: - /* Use the process MLS attributes. */ - return mls_copy_context(newcontext, scontext); + if (tclass == SECCLASS_PROCESS) + /* Use the process MLS attributes. */ + return mls_context_cpy(newcontext, scontext); + else + /* Use the process effective MLS attributes. */ + 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 MLS attributes. */ - return mls_copy_context(newcontext, scontext); + /* Use the process effective MLS attributes. */ + 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; @@ -387,368 +552,108 @@ int mls_compute_sid(struct context *scontext, 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. +#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. + * */ -struct mls_level *mls_read_level(void *fp) +void mls_export_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) { - 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; + if (!selinux_mls_enabled) + return; -bad: - kfree(l); - return NULL; + secattr->mls_lvl = context->range.level[0].sens - 1; + secattr->flags |= NETLBL_SECATTR_MLS_LVL; } - -/* - * Read a MLS range structure from a policydb binary - * representation file. +/** + * 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. + * */ -static int mls_read_range_helper(struct mls_range *r, void *fp) +void mls_import_netlbl_lvl(struct context *context, + struct netlbl_lsm_secattr *secattr) { - 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; -} + if (!selinux_mls_enabled) + return; -int mls_read_range(struct context *c, void *fp) -{ - return mls_read_range_helper(&c->range, fp); + context->range.level[0].sens = secattr->mls_lvl + 1; + context->range.level[1].sens = context->range.level[0].sens; } - -/* - * Read a MLS perms structure from a policydb binary - * representation file. +/** + * 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_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) +int mls_export_netlbl_cat(struct context *context, + struct netlbl_lsm_secattr *secattr) { - kfree(key); - kfree(datum); - return 0; -} - -int sens_read(struct policydb *p, struct hashtab *h, void *fp) -{ - char *key = 0; - 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; + if (!selinux_mls_enabled) + return 0; - levdatum->level = mls_read_level(fp); - if (!levdatum->level) { - rc = -EINVAL; - goto bad; - } + 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; - 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) +/** + * 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) { - char *key = 0; - 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)); + if (!selinux_mls_enabled) + return 0; - buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - rc = -EINVAL; - goto bad; - } + rc = ebitmap_netlbl_import(&context->range.level[0].cat, + secattr->mls_cat); + if (rc != 0) + goto import_netlbl_cat_failure; - len = le32_to_cpu(buf[0]); - catdatum->value = le32_to_cpu(buf[1]); - catdatum->isalias = le32_to_cpu(buf[2]); + rc = ebitmap_cpy(&context->range.level[1].cat, + &context->range.level[0].cat); + if (rc != 0) + goto import_netlbl_cat_failure; - 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; + return 0; - rc = hashtab_insert(h, key, catdatum); - if (rc) - goto bad; -out: +import_netlbl_cat_failure: + ebitmap_destroy(&context->range.level[0].cat); + ebitmap_destroy(&context->range.level[1].cat); return rc; - -bad: - cat_destroy(key, catdatum, NULL); - goto out; } +#endif /* CONFIG_NETLABEL */