/* * 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; }
bool selinux_make_permissive(policydb_t *pdb, const std::string &type_str) { type_datum_t *type; type = (type_datum_t *) hashtab_search( pdb->p_types.table, (hashtab_key_t) type_str.c_str()); if (!type) { LOGV("Type %s not found in policy", type_str.c_str()); return false; } if (ebitmap_get_bit(&pdb->permissive_map, type->s.value)) { LOGV("Type %s is already permissive", type_str.c_str()); return true; } if (ebitmap_set_bit(&pdb->permissive_map, type->s.value, 1) < 0) { LOGE("Failed to set bit for type %s in the permissive map", type_str.c_str()); return false; } LOGD("Type %s is now permissive", type_str.c_str()); return true; }
/* * 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; }
/* * 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; 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; }
int qpol_user_get_role_iter(const qpol_policy_t * policy, const qpol_user_t * datum, qpol_iterator_t ** roles) { user_datum_t *internal_datum = NULL; int error = 0; ebitmap_state_t *es = NULL; if (policy == NULL || datum == NULL || roles == NULL) { if (roles != NULL) *roles = NULL; ERR(policy, "%s", strerror(EINVAL)); errno = EINVAL; return STATUS_ERR; } internal_datum = (user_datum_t *) datum; es = calloc(1, sizeof(ebitmap_state_t)); if (es == NULL) { error = errno; ERR(policy, "%s", strerror(ENOMEM)); errno = error; return STATUS_ERR; } es->bmap = &(internal_datum->roles.roles); es->cur = es->bmap->node ? es->bmap->node->startbit : 0; if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_role, ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, roles)) { free(es); return STATUS_ERR; } if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur)) ebitmap_state_next(*roles); return STATUS_SUCCESS; }
/* * 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; }
/* * Return the boolean value of a constraint expression * when it is applied to the specified source and target * security contexts. */ static int constraint_expr_eval(struct context *scontext, struct context *tcontext, struct constraint_expr *cexpr) { u32 val1, val2; struct context *c; struct role_datum *r1, *r2; struct constraint_expr *e; int s[CEXPR_MAXDEPTH]; int sp = -1; for (e = cexpr; e; e = e->next) { switch (e->expr_type) { case CEXPR_NOT: BUG_ON(sp < 0); s[sp] = !s[sp]; break; case CEXPR_AND: BUG_ON(sp < 1); sp--; s[sp] &= s[sp+1]; break; case CEXPR_OR: BUG_ON(sp < 1); sp--; s[sp] |= s[sp+1]; break; case CEXPR_ATTR: if (sp == (CEXPR_MAXDEPTH-1)) return 0; switch (e->attr) { case CEXPR_USER: val1 = scontext->user; val2 = tcontext->user; break; case CEXPR_TYPE: val1 = scontext->type; val2 = tcontext->type; break; case CEXPR_ROLE: val1 = scontext->role; val2 = tcontext->role; r1 = policydb.role_val_to_struct[val1 - 1]; r2 = policydb.role_val_to_struct[val2 - 1]; switch (e->op) { case CEXPR_DOM: s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1); continue; case CEXPR_DOMBY: s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1); continue; case CEXPR_INCOMP: s[++sp] = ( !ebitmap_get_bit(&r1->dominates, val2 - 1) && !ebitmap_get_bit(&r2->dominates, val1 - 1) ); continue; default: break; } break; default: BUG(); return 0; } switch (e->op) { case CEXPR_EQ: s[++sp] = (val1 == val2); break; case CEXPR_NEQ: s[++sp] = (val1 != val2); break; default: BUG(); return 0; } break; case CEXPR_NAMES: if (sp == (CEXPR_MAXDEPTH-1)) return 0; c = scontext; if (e->attr & CEXPR_TARGET) c = tcontext; if (e->attr & CEXPR_USER) val1 = c->user; else if (e->attr & CEXPR_ROLE) val1 = c->role; else if (e->attr & CEXPR_TYPE) val1 = c->type; else { BUG(); return 0; } switch (e->op) { case CEXPR_EQ: s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); break; case CEXPR_NEQ: s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); break; default: BUG(); return 0; } break; default: BUG(); return 0; } } BUG_ON(sp != 0); return s[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; } }