]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'selinux/next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 9 Apr 2015 04:34:50 +0000 (14:34 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 9 Apr 2015 04:34:50 +0000 (14:34 +1000)
security/selinux/avc.c
security/selinux/ss/avtab.c
security/selinux/ss/avtab.h
security/selinux/ss/mls.c
security/selinux/ss/services.c

index afcc0aed9393a6d1917b6167bf68403729dccea8..3c17dda9571d4e97f7f460e162a6195bf215758b 100644 (file)
@@ -724,12 +724,10 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
        rcu_read_lock();
 
        node = avc_lookup(ssid, tsid, tclass);
-       if (unlikely(!node)) {
+       if (unlikely(!node))
                node = avc_compute_av(ssid, tsid, tclass, avd);
-       } else {
+       else
                memcpy(avd, &node->ae.avd, sizeof(*avd));
-               avd = &node->ae.avd;
-       }
 
        denied = requested & ~(avd->allowed);
        if (unlikely(denied))
index a3dd9faa19c01eda269b13f7cfcd7ab6da6aa098..b64f2772b030194d6ff3ca55e4cc86007ec9f193 100644 (file)
 
 static struct kmem_cache *avtab_node_cachep;
 
-static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+/* Based on MurmurHash3, written by Austin Appleby and placed in the
+ * public domain.
+ */
+static inline int avtab_hash(struct avtab_key *keyp, u32 mask)
 {
-       return ((keyp->target_class + (keyp->target_type << 2) +
-                (keyp->source_type << 9)) & mask);
+       static const u32 c1 = 0xcc9e2d51;
+       static const u32 c2 = 0x1b873593;
+       static const u32 r1 = 15;
+       static const u32 r2 = 13;
+       static const u32 m  = 5;
+       static const u32 n  = 0xe6546b64;
+
+       u32 hash = 0;
+
+#define mix(input) { \
+       u32 v = input; \
+       v *= c1; \
+       v = (v << r1) | (v >> (32 - r1)); \
+       v *= c2; \
+       hash ^= v; \
+       hash = (hash << r2) | (hash >> (32 - r2)); \
+       hash = hash * m + n; \
+}
+
+       mix(keyp->target_class);
+       mix(keyp->target_type);
+       mix(keyp->source_type);
+
+#undef mix
+
+       hash ^= hash >> 16;
+       hash *= 0x85ebca6b;
+       hash ^= hash >> 13;
+       hash *= 0xc2b2ae35;
+       hash ^= hash >> 16;
+
+       return hash & mask;
 }
 
 static struct avtab_node*
@@ -46,8 +79,12 @@ avtab_insert_node(struct avtab *h, int hvalue,
                newnode->next = prev->next;
                prev->next = newnode;
        } else {
-               newnode->next = h->htable[hvalue];
-               h->htable[hvalue] = newnode;
+               newnode->next = flex_array_get_ptr(h->htable, hvalue);
+               if (flex_array_put_ptr(h->htable, hvalue, newnode,
+                                      GFP_KERNEL|__GFP_ZERO)) {
+                       kmem_cache_free(avtab_node_cachep, newnode);
+                       return NULL;
+               }
        }
 
        h->nel++;
@@ -64,7 +101,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
                return -EINVAL;
 
        hvalue = avtab_hash(key, h->mask);
-       for (prev = NULL, cur = h->htable[hvalue];
+       for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
             cur;
             prev = cur, cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
@@ -104,7 +141,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
        if (!h || !h->htable)
                return NULL;
        hvalue = avtab_hash(key, h->mask);
-       for (prev = NULL, cur = h->htable[hvalue];
+       for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
             cur;
             prev = cur, cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
@@ -135,7 +172,8 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
                return NULL;
 
        hvalue = avtab_hash(key, h->mask);
-       for (cur = h->htable[hvalue]; cur; cur = cur->next) {
+       for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
+            cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
                    key->target_type == cur->key.target_type &&
                    key->target_class == cur->key.target_class &&
@@ -170,7 +208,8 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
                return NULL;
 
        hvalue = avtab_hash(key, h->mask);
-       for (cur = h->htable[hvalue]; cur; cur = cur->next) {
+       for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
+            cur = cur->next) {
                if (key->source_type == cur->key.source_type &&
                    key->target_type == cur->key.target_type &&
                    key->target_class == cur->key.target_class &&
@@ -228,15 +267,14 @@ void avtab_destroy(struct avtab *h)
                return;
 
        for (i = 0; i < h->nslot; i++) {
-               cur = h->htable[i];
+               cur = flex_array_get_ptr(h->htable, i);
                while (cur) {
                        temp = cur;
                        cur = cur->next;
                        kmem_cache_free(avtab_node_cachep, temp);
                }
-               h->htable[i] = NULL;
        }
-       kfree(h->htable);
+       flex_array_free(h->htable);
        h->htable = NULL;
        h->nslot = 0;
        h->mask = 0;
@@ -251,7 +289,7 @@ int avtab_init(struct avtab *h)
 
 int avtab_alloc(struct avtab *h, u32 nrules)
 {
-       u16 mask = 0;
+       u32 mask = 0;
        u32 shift = 0;
        u32 work = nrules;
        u32 nslot = 0;
@@ -270,7 +308,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
                nslot = MAX_AVTAB_HASH_BUCKETS;
        mask = nslot - 1;
 
-       h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
+       h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot,
+                                    GFP_KERNEL | __GFP_ZERO);
        if (!h->htable)
                return -ENOMEM;
 
@@ -293,7 +332,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
        max_chain_len = 0;
        chain2_len_sum = 0;
        for (i = 0; i < h->nslot; i++) {
-               cur = h->htable[i];
+               cur = flex_array_get_ptr(h->htable, i);
                if (cur) {
                        slots_used++;
                        chain_len = 0;
@@ -534,7 +573,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
                return rc;
 
        for (i = 0; i < a->nslot; i++) {
-               for (cur = a->htable[i]; cur; cur = cur->next) {
+               for (cur = flex_array_get_ptr(a->htable, i); cur;
+                    cur = cur->next) {
                        rc = avtab_write_item(p, cur, fp);
                        if (rc)
                                return rc;
index 63ce2f9e441da5ed929c3341228bde3a8652f1e4..adb451cd44f9d3175ba84e1686bfeeae06a803d2 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef _SS_AVTAB_H_
 #define _SS_AVTAB_H_
 
+#include <linux/flex_array.h>
+
 struct avtab_key {
        u16 source_type;        /* source type */
        u16 target_type;        /* target type */
@@ -51,10 +53,10 @@ struct avtab_node {
 };
 
 struct avtab {
-       struct avtab_node **htable;
+       struct flex_array *htable;
        u32 nel;        /* number of elements */
        u32 nslot;      /* number of hash slots */
-       u16 mask;       /* mask to compute hash func */
+       u32 mask;       /* mask to compute hash func */
 
 };
 
@@ -84,7 +86,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified
 void avtab_cache_init(void);
 void avtab_cache_destroy(void);
 
-#define MAX_AVTAB_HASH_BITS 11
+#define MAX_AVTAB_HASH_BITS 16
 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
 
 #endif /* _SS_AVTAB_H_ */
index d307b37ddc2b3b3a993c5196c9205620433aa379..e1088842232c6aefd334c2bf96c51549d8a55363 100644 (file)
@@ -654,19 +654,15 @@ int mls_import_netlbl_cat(struct context *context,
 
        rc = ebitmap_netlbl_import(&context->range.level[0].cat,
                                   secattr->attr.mls.cat);
-       if (rc != 0)
-               goto import_netlbl_cat_failure;
-
-       rc = ebitmap_cpy(&context->range.level[1].cat,
-                        &context->range.level[0].cat);
-       if (rc != 0)
+       if (rc)
                goto import_netlbl_cat_failure;
+       memcpy(&context->range.level[1].cat, &context->range.level[0].cat,
+              sizeof(context->range.level[0].cat));
 
        return 0;
 
 import_netlbl_cat_failure:
        ebitmap_destroy(&context->range.level[0].cat);
-       ebitmap_destroy(&context->range.level[1].cat);
        return rc;
 }
 #endif /* CONFIG_NETLABEL */
index a1d3944751b9e2fbfd23e18b694b00cd150880dc..9e2d82070915366333e193b99aca5badf16af72c 100644 (file)
@@ -3179,13 +3179,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                ctx_new.type = ctx->type;
                mls_import_netlbl_lvl(&ctx_new, secattr);
                if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
-                       rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
-                                                  secattr->attr.mls.cat);
+                       rc = mls_import_netlbl_cat(&ctx_new, secattr);
                        if (rc)
                                goto out;
-                       memcpy(&ctx_new.range.level[1].cat,
-                              &ctx_new.range.level[0].cat,
-                              sizeof(ctx_new.range.level[0].cat));
                }
                rc = -EIDRM;
                if (!mls_context_isvalid(&policydb, &ctx_new))