/* * Return 1 if the MLS fields in the security context * structure `c' are valid. Return 0 otherwise. */ 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; int i, l; /* * 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))) /* High does not dominate low. */ return 0; for (l = 0; l < 2; l++) { if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim) return 0; levdatum = hashtab_search(p->p_levels.table, p->p_sens_val_to_name[c->range.level[l].sens - 1]); 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)) { if (i > p->p_cats.nprim) return 0; if (!ebitmap_get_bit(&levdatum->level->cat, i - 1)) /* * Category may not be associated with * sensitivity in low level. */ return 0; } } } if (c->role == OBJECT_R_VAL) return 1; /* * User must be authorized for the MLS range. */ 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; return 1; }
/* * Write the security context string representation of * 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) { char *scontextp; int i, l; scontextp = *scontext; for (l = 0; l < 2; l++) { 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++; } if (mls_level_relation(context->range.level[0], context->range.level[1]) != MLS_RELATION_EQ) { scontextp--; sprintf(scontextp, "-"); scontextp++; } else { break; } } *scontext = scontextp; return 0; }
static bool is_type_of_attribute_set(policydb_t *policydb, const char *type_name, ebitmap_t *attr_set) { struct type_datum *type = hashtab_search(policydb->p_types.table, (char *)type_name); if (!type) { fprintf(stderr, "Error: \"%s\" is not defined in this policy.\n", type_name); return false; } if (type->flavor != TYPE_TYPE) { fprintf(stderr, "Error: \"%s\" is not a type in this policy.\n", type_name); return false; } ebitmap_t dst; ebitmap_init(&dst); /* Take the intersection, if the set is empty, then its a failure */ int rc = ebitmap_and(&dst, attr_set, &policydb->type_attr_map[type->s.value - 1]); if (rc) { fprintf(stderr, "Error: Could not perform ebitmap_and: %d\n", rc); exit(1); } bool res = (bool)ebitmap_length(&dst); ebitmap_destroy(&dst); return res; }
/* * 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; len = 0; 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; } return len; }
static int validate(char **contextp) { bool res; char *context = *contextp; sepol_context_t *ctx; int rc = sepol_context_from_string(global_state.sepolicy.handle, context, &ctx); if (rc < 0) { fprintf(stderr, "Error: Could not allocate context from string"); exit(1); } rc = sepol_context_check(global_state.sepolicy.handle, global_state.sepolicy.sdb, ctx); if (rc < 0) { goto out; } const char *type_name = sepol_context_get_type(ctx); uint32_t len = ebitmap_length(&global_state.assert.set); if (len > 0) { res = !is_type_of_attribute_set(global_state.sepolicy.pdb, type_name, &global_state.assert.set); if (res) { fprintf(stderr, "Error: type \"%s\" is not of set: ", type_name); dump_char_array(stderr, global_state.assert.attrs); fprintf(stderr, "\n"); /* The calls above did not affect rc, so set error before going to out */ rc = -1; goto out; } } /* Success: Although it should be 0, we explicitly set rc to 0 for clarity */ rc = 0; out: sepol_context_free(ctx); return rc; }
/* * Convert the MLS fields in the security context * structure `c' from the values specified in the * policy `oldp' to the values specified in the policy `newp'. */ int mls_convert_context(struct policydb *oldp, struct policydb *newp, struct context *c) { struct level_datum *levdatum; struct cat_datum *catdatum; struct ebitmap bitmap; int l, i; 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]); if (!levdatum) return -EINVAL; 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)) { int rc; catdatum = hashtab_search(newp->p_cats.table, oldp->p_cat_val_to_name[i - 1]); if (!catdatum) return -EINVAL; rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); if (rc) return rc; } } ebitmap_destroy(&c->range.level[l].cat); c->range.level[l].cat = bitmap; } return 0; }
int security_get_user_sids(u32 fromsid, char *username, u32 **sids, u32 *nel) { struct context *fromcon, usercon; u32 *mysids, *mysids2, sid; u32 mynel = 0, maxnel = SIDS_NEL; struct user_datum *user; struct role_datum *role; struct av_decision avd; int rc = 0, i, j; if (!ss_initialized) { *sids = NULL; *nel = 0; goto out; } POLICY_RDLOCK; fromcon = sidtab_search(&sidtab, fromsid); if (!fromcon) { rc = -EINVAL; goto out_unlock; } user = hashtab_search(policydb.p_users.table, username); if (!user) { rc = -EINVAL; goto out_unlock; } usercon.user = user->value; mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC); if (!mysids) { rc = -ENOMEM; goto out_unlock; } memset(mysids, 0, maxnel*sizeof(*mysids)); for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) { if (!ebitmap_get_bit(&user->roles, i)) continue; role = policydb.role_val_to_struct[i]; usercon.role = i+1; for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) { if (!ebitmap_get_bit(&role->types, j)) continue; usercon.type = j+1; if (usercon.type == fromcon->type) continue; mls_for_user_ranges(user,usercon) { rc = context_struct_compute_av(fromcon, &usercon, SECCLASS_PROCESS, PROCESS__TRANSITION, &avd); if (rc || !(avd.allowed & PROCESS__TRANSITION)) continue; rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); if (rc) { kfree(mysids); goto out_unlock; } if (mynel < maxnel) { mysids[mynel++] = sid; } else { maxnel += SIDS_NEL; mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC); if (!mysids2) { rc = -ENOMEM; kfree(mysids); goto out_unlock; } memset(mysids2, 0, maxnel*sizeof(*mysids2)); memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); kfree(mysids); mysids = mysids2; mysids[mynel++] = sid; } } mls_end_user_ranges; } }