diff options
Diffstat (limited to 'security/selinux/ss/mls.c')
-rw-r--r-- | security/selinux/ss/mls.c | 113 |
1 files changed, 71 insertions, 42 deletions
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 756036b..aaefac2 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/errno.h> +#include "sidtab.h" #include "mls.h" #include "policydb.h" #include "services.h" @@ -26,6 +27,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 +37,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 +78,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 +96,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 +108,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 +118,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 +132,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 +159,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 +182,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. @@ -208,6 +212,26 @@ int mls_context_isvalid(struct policydb *p, struct context *c) } /* + * 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 * the string `*scontext'. Update `*scontext' to @@ -216,10 +240,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; @@ -231,9 +265,23 @@ int mls_context_to_sid(char oldc, if (!selinux_mls_enabled) 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; @@ -334,26 +382,6 @@ out: } /* - * 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; -} - -/* * Copies the effective MLS range from `src' into `dst'. */ static inline int mls_scopy_context(struct context *dst, @@ -443,6 +471,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 +486,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); |