aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/security/selinux/ss/sidtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/sidtab.c')
-rw-r--r--security/selinux/ss/sidtab.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index f511ffccb131..eb6d27b5aeb4 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -54,14 +54,15 @@ int sidtab_init(struct sidtab *s)
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;
@@ -74,6 +75,7 @@ static u32 context_to_sid(struct sidtab *s, struct context *context)
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)
@@ -90,15 +92,18 @@ int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context)
#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;
@@ -259,12 +264,12 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
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;
@@ -272,12 +277,11 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
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;
- /* read entries only after reading count */
- count = smp_load_acquire(&s->count);
+ count = s->count;
convert = s->convert;
/* bail out if we already reached max entries */
@@ -292,6 +296,7 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
goto out_unlock;
dst->sid = index_to_sid(count);
+ dst->hash = hash;
rc = context_cpy(&dst->context, context);
if (rc)
@@ -316,10 +321,11 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
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)
@@ -330,7 +336,7 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context,
/* 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:
@@ -346,10 +352,9 @@ static void sidtab_convert_hashtable(struct sidtab *s, u32 count)
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);
}
}