summaryrefslogtreecommitdiff
path: root/security/selinux/ss/avtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/avtab.c')
-rw-r--r--security/selinux/ss/avtab.c103
1 files changed, 58 insertions, 45 deletions
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 8c5800750fa8..c97695ae508f 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -23,13 +23,13 @@
#include "avtab.h"
#include "policydb.h"
-static struct kmem_cache *avtab_node_cachep;
-static struct kmem_cache *avtab_xperms_cachep;
+static struct kmem_cache *avtab_node_cachep __ro_after_init;
+static struct kmem_cache *avtab_xperms_cachep __ro_after_init;
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.
*/
-static inline int avtab_hash(struct avtab_key *keyp, u32 mask)
+static inline int avtab_hash(const struct avtab_key *keyp, u32 mask)
{
static const u32 c1 = 0xcc9e2d51;
static const u32 c2 = 0x1b873593;
@@ -68,7 +68,7 @@ static inline int avtab_hash(struct avtab_key *keyp, u32 mask)
static struct avtab_node*
avtab_insert_node(struct avtab *h, int hvalue,
struct avtab_node *prev, struct avtab_node *cur,
- struct avtab_key *key, struct avtab_datum *datum)
+ const struct avtab_key *key, const struct avtab_datum *datum)
{
struct avtab_node *newnode;
struct avtab_extended_perms *xperms;
@@ -103,13 +103,14 @@ avtab_insert_node(struct avtab *h, int hvalue,
return newnode;
}
-static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
+static int avtab_insert(struct avtab *h, const struct avtab_key *key,
+ const struct avtab_datum *datum)
{
int hvalue;
struct avtab_node *prev, *cur, *newnode;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->nslot)
return -EINVAL;
hvalue = avtab_hash(key, h->mask);
@@ -147,14 +148,15 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
* key/specified mask into the table, as needed by the conditional avtab.
* It also returns a pointer to the node inserted.
*/
-struct avtab_node *
-avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
+struct avtab_node *avtab_insert_nonunique(struct avtab *h,
+ const struct avtab_key *key,
+ const struct avtab_datum *datum)
{
int hvalue;
struct avtab_node *prev, *cur;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->nslot)
return NULL;
hvalue = avtab_hash(key, h->mask);
for (prev = NULL, cur = h->htable[hvalue];
@@ -178,13 +180,13 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
return avtab_insert_node(h, hvalue, prev, cur, key, datum);
}
-struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
+struct avtab_datum *avtab_search(struct avtab *h, const struct avtab_key *key)
{
int hvalue;
struct avtab_node *cur;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->nslot)
return NULL;
hvalue = avtab_hash(key, h->mask);
@@ -213,14 +215,14 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
/* This search function returns a node pointer, and can be used in
* conjunction with avtab_search_next_node()
*/
-struct avtab_node*
-avtab_search_node(struct avtab *h, struct avtab_key *key)
+struct avtab_node *avtab_search_node(struct avtab *h,
+ const struct avtab_key *key)
{
int hvalue;
struct avtab_node *cur;
u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
- if (!h)
+ if (!h || !h->nslot)
return NULL;
hvalue = avtab_hash(key, h->mask);
@@ -295,52 +297,63 @@ void avtab_destroy(struct avtab *h)
}
kvfree(h->htable);
h->htable = NULL;
+ h->nel = 0;
h->nslot = 0;
h->mask = 0;
}
-int avtab_init(struct avtab *h)
+void avtab_init(struct avtab *h)
{
- kvfree(h->htable);
h->htable = NULL;
h->nel = 0;
+ h->nslot = 0;
+ h->mask = 0;
+}
+
+static int avtab_alloc_common(struct avtab *h, u32 nslot)
+{
+ if (!nslot)
+ return 0;
+
+ h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL);
+ if (!h->htable)
+ return -ENOMEM;
+
+ h->nslot = nslot;
+ h->mask = nslot - 1;
return 0;
}
int avtab_alloc(struct avtab *h, u32 nrules)
{
- u32 mask = 0;
- u32 shift = 0;
- u32 work = nrules;
+ int rc;
u32 nslot = 0;
- if (nrules == 0)
- goto avtab_alloc_out;
+ if (nrules != 0) {
+ u32 shift = 1;
+ u32 work = nrules >> 3;
+ while (work) {
+ work >>= 1;
+ shift++;
+ }
+ nslot = 1 << shift;
+ if (nslot > MAX_AVTAB_HASH_BUCKETS)
+ nslot = MAX_AVTAB_HASH_BUCKETS;
- while (work) {
- work = work >> 1;
- shift++;
+ rc = avtab_alloc_common(h, nslot);
+ if (rc)
+ return rc;
}
- if (shift > 2)
- shift = shift - 2;
- nslot = 1 << shift;
- if (nslot > MAX_AVTAB_HASH_BUCKETS)
- nslot = MAX_AVTAB_HASH_BUCKETS;
- mask = nslot - 1;
-
- h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL);
- if (!h->htable)
- return -ENOMEM;
- avtab_alloc_out:
- h->nel = 0;
- h->nslot = nslot;
- h->mask = mask;
- pr_debug("SELinux: %d avtab hash slots, %d rules.\n",
- h->nslot, nrules);
+ pr_debug("SELinux: %d avtab hash slots, %d rules.\n", nslot, nrules);
return 0;
}
+int avtab_alloc_dup(struct avtab *new, const struct avtab *orig)
+{
+ return avtab_alloc_common(new, orig->nslot);
+}
+
void avtab_hash_eval(struct avtab *h, char *tag)
{
int i, chain_len, slots_used, max_chain_len;
@@ -385,8 +398,8 @@ static uint16_t spec_order[] = {
};
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
- int (*insertf)(struct avtab *a, struct avtab_key *k,
- struct avtab_datum *d, void *p),
+ int (*insertf)(struct avtab *a, const struct avtab_key *k,
+ const struct avtab_datum *d, void *p),
void *p)
{
__le16 buf16[4];
@@ -546,8 +559,8 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
return insertf(a, &key, &datum, p);
}
-static int avtab_insertf(struct avtab *a, struct avtab_key *k,
- struct avtab_datum *d, void *p)
+static int avtab_insertf(struct avtab *a, const struct avtab_key *k,
+ const struct avtab_datum *d, void *p)
{
return avtab_insert(a, k, d);
}
@@ -596,7 +609,7 @@ bad:
goto out;
}
-int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
+int avtab_write_item(struct policydb *p, const struct avtab_node *cur, void *fp)
{
__le16 buf16[4];
__le32 buf32[ARRAY_SIZE(cur->datum.u.xperms->perms.p)];