return rc;
}
-static int context_struct_to_sid(struct selinux_state *state,
- struct context *context, u32 *sid)
-{
- struct sidtab *sidtab = state->ss->sidtab;
-
- if (!context->hash)
- context_add_hash(context);
-
- return sidtab_context_to_sid(sidtab, context, sid);
-}
-
static int security_context_to_sid_core(struct selinux_state *state,
const char *scontext, u32 scontext_len,
u32 *sid, u32 def_sid, gfp_t gfp_flags,
str = NULL;
} else if (rc)
goto out_unlock;
- rc = context_struct_to_sid(state, &context, sid);
+ rc = sidtab_context_to_sid(sidtab, &context, sid);
context_destroy(&context);
out_unlock:
read_unlock(&state->ss->policy_rwlock);
goto out_unlock;
}
/* Obtain the sid for the context. */
- rc = context_struct_to_sid(state, &newcontext, out_sid);
+ rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
out_unlock:
read_unlock(&state->ss->policy_rwlock);
context_destroy(&newcontext);
context_init(newc);
newc->str = s;
newc->len = oldc->len;
- newc->hash = oldc->hash;
return 0;
}
kfree(s);
goto bad;
}
- context_add_hash(newc);
-
return 0;
bad:
/* Map old representation to string and save it. */
context_destroy(newc);
newc->str = s;
newc->len = len;
- context_add_hash(newc);
pr_info("SELinux: Context %s became invalid (unmapped).\n",
newc->str);
return 0;
u8 protocol, u16 port, u32 *out_sid)
{
struct policydb *policydb;
+ struct sidtab *sidtab;
struct ocontext *c;
int rc = 0;
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policydb;
+ sidtab = state->ss->sidtab;
c = policydb->ocontexts[OCON_PORT];
while (c) {
if (c) {
if (!c->sid[0]) {
- rc = context_struct_to_sid(state, &c->context[0],
+ rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc)
goto out;
u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
{
struct policydb *policydb;
+ struct sidtab *sidtab;
struct ocontext *c;
int rc = 0;
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policydb;
+ sidtab = state->ss->sidtab;
c = policydb->ocontexts[OCON_IBPKEY];
while (c) {
if (c) {
if (!c->sid[0]) {
- rc = context_struct_to_sid(state,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
const char *dev_name, u8 port_num, u32 *out_sid)
{
struct policydb *policydb;
+ struct sidtab *sidtab;
struct ocontext *c;
int rc = 0;
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policydb;
+ sidtab = state->ss->sidtab;
c = policydb->ocontexts[OCON_IBENDPORT];
while (c) {
if (c) {
if (!c->sid[0]) {
- rc = context_struct_to_sid(state, &c->context[0],
+ rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc)
goto out;
char *name, u32 *if_sid)
{
struct policydb *policydb;
+ struct sidtab *sidtab;
int rc = 0;
struct ocontext *c;
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policydb;
+ sidtab = state->ss->sidtab;
c = policydb->ocontexts[OCON_NETIF];
while (c) {
if (c) {
if (!c->sid[0] || !c->sid[1]) {
- rc = context_struct_to_sid(state, &c->context[0],
+ rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc)
goto out;
- rc = context_struct_to_sid(state, &c->context[1],
+ rc = sidtab_context_to_sid(sidtab, &c->context[1],
&c->sid[1]);
if (rc)
goto out;
u32 *out_sid)
{
struct policydb *policydb;
+ struct sidtab *sidtab;
int rc;
struct ocontext *c;
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policydb;
+ sidtab = state->ss->sidtab;
switch (domain) {
case AF_INET: {
if (c) {
if (!c->sid[0]) {
- rc = context_struct_to_sid(state,
+ rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc)
usercon.role = i + 1;
ebitmap_for_each_positive_bit(&role->types, tnode, j) {
usercon.type = j + 1;
- /*
- * The same context struct is reused here so the hash
- * must be reset.
- */
- usercon.hash = 0;
if (mls_setup_user_range(policydb, fromcon, user,
&usercon))
continue;
- rc = context_struct_to_sid(state, &usercon, &sid);
+ rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
if (rc)
goto out_unlock;
if (mynel < maxnel) {
u32 *sid)
{
struct policydb *policydb = &state->ss->policydb;
+ struct sidtab *sidtab = state->ss->sidtab;
int len;
u16 sclass;
struct genfs *genfs;
goto out;
if (!c->sid[0]) {
- rc = context_struct_to_sid(state, &c->context[0], &c->sid[0]);
+ rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]);
if (rc)
goto out;
}
int security_fs_use(struct selinux_state *state, struct super_block *sb)
{
struct policydb *policydb;
+ struct sidtab *sidtab;
int rc = 0;
struct ocontext *c;
struct superblock_security_struct *sbsec = sb->s_security;
read_lock(&state->ss->policy_rwlock);
policydb = &state->ss->policydb;
+ sidtab = state->ss->sidtab;
c = policydb->ocontexts[OCON_FSUSE];
while (c) {
if (c) {
sbsec->behavior = c->v.behavior;
if (!c->sid[0]) {
- rc = context_struct_to_sid(state, &c->context[0],
+ rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc)
goto out;
goto out_unlock;
}
}
- rc = context_struct_to_sid(state, &newcon, new_sid);
+ rc = sidtab_context_to_sid(sidtab, &newcon, new_sid);
out_unlock:
read_unlock(&state->ss->policy_rwlock);
context_destroy(&newcon);
if (!mls_context_isvalid(policydb, &ctx_new))
goto out_free;
- rc = context_struct_to_sid(state, &ctx_new, sid);
+ rc = sidtab_context_to_sid(sidtab, &ctx_new, sid);
if (rc)
goto out_free;
return 0;
}
-static u32 context_to_sid(struct sidtab *s, struct context *context)
+static u32 context_to_sid(struct sidtab *s, struct context *context, u32 hash)
{
struct sidtab_entry *entry;
u32 sid = 0;
rcu_read_lock();
- hash_for_each_possible_rcu(s->context_to_sid, entry, list,
- context->hash) {
+ hash_for_each_possible_rcu(s->context_to_sid, entry, list, hash) {
+ if (entry->hash != hash)
+ continue;
if (context_cmp(&entry->context, context)) {
sid = entry->sid;
break;
int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context)
{
struct sidtab_isid_entry *isid;
+ u32 hash;
int rc;
if (sid == 0 || sid > SECINITSID_NUM)
#endif
isid->set = 1;
+ hash = context_compute_hash(context);
+
/*
* Multiple initial sids may map to the same context. Check that this
* context is not already represented in the context_to_sid hashtable
* to avoid duplicate entries and long linked lists upon hash
* collision.
*/
- if (!context_to_sid(s, context)) {
+ if (!context_to_sid(s, context, hash)) {
isid->entry.sid = sid;
- hash_add(s->context_to_sid, &isid->entry.list, context->hash);
+ isid->entry.hash = hash;
+ hash_add(s->context_to_sid, &isid->entry.list, hash);
}
return 0;
u32 *sid)
{
unsigned long flags;
- u32 count;
+ u32 count, hash = context_compute_hash(context);
struct sidtab_convert_params *convert;
struct sidtab_entry *dst, *dst_convert;
int rc;
- *sid = context_to_sid(s, context);
+ *sid = context_to_sid(s, context, hash);
if (*sid)
return 0;
spin_lock_irqsave(&s->lock, flags);
rc = 0;
- *sid = context_to_sid(s, context);
+ *sid = context_to_sid(s, context, hash);
if (*sid)
goto out_unlock;
goto out_unlock;
dst->sid = index_to_sid(count);
+ dst->hash = hash;
rc = context_cpy(&dst->context, context);
if (rc)
goto out_unlock;
}
dst_convert->sid = index_to_sid(count);
+ dst_convert->hash = context_compute_hash(&dst_convert->context);
convert->target->count = count + 1;
hash_add_rcu(convert->target->context_to_sid,
- &dst_convert->list, dst_convert->context.hash);
+ &dst_convert->list, dst_convert->hash);
}
if (context->len)
/* write entries before updating count */
smp_store_release(&s->count, count + 1);
- hash_add_rcu(s->context_to_sid, &dst->list, dst->context.hash);
+ hash_add_rcu(s->context_to_sid, &dst->list, dst->hash);
rc = 0;
out_unlock:
for (i = 0; i < count; i++) {
entry = sidtab_do_lookup(s, i, 0);
entry->sid = index_to_sid(i);
+ entry->hash = context_compute_hash(&entry->context);
- hash_add_rcu(s->context_to_sid, &entry->list,
- entry->context.hash);
-
+ hash_add_rcu(s->context_to_sid, &entry->list, entry->hash);
}
}