aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/policydb.c
diff options
context:
space:
mode:
authorOndrej Mosnacek <omosnace@redhat.com>2020-07-09 21:19:51 +0200
committerPaul Moore <paul@paul-moore.com>2020-07-09 19:05:36 -0400
commit24def7bb92c19337cee26d506f87dc4eeeba7a19 (patch)
tree1c33bb5b711918c8ffd0f45e3b97c7ac38a0d427 /security/selinux/ss/policydb.c
parentselinux: specialize symtab insert and search functions (diff)
downloadlinux-dev-24def7bb92c19337cee26d506f87dc4eeeba7a19.tar.xz
linux-dev-24def7bb92c19337cee26d506f87dc4eeeba7a19.zip
selinux: prepare for inlining of hashtab functions
Refactor searching and inserting into hashtabs to pave the way for converting hashtab_search() and hashtab_insert() to inline functions in the next patch. This will avoid indirect calls and allow the compiler to better optimize individual callers, leading to a significant performance improvement. In order to avoid the indirect calls, the key hashing and comparison callbacks need to be extracted from the hashtab struct and passed directly to hashtab_search()/_insert() by the callers so that the callback address is always known at compile time. The kernel's rhashtable library (<linux/rhashtable*.h>) does the same thing. This of course makes the hashtab functions slightly easier to misuse by passing a wrong callback set, but unfortunately there is no better way to implement a hash table that is both generic and efficient in C. This patch tries to somewhat mitigate this by only calling the hashtab functions in the same file where the corresponding callbacks are defined (wrapping them into more specialized functions as needed). Note that this patch doesn't bring any benefit without also moving the definitions of hashtab_search() and -_insert() to the header file, which is done in a follow-up patch for easier review of the hashtab.c changes in this patch. Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r--security/selinux/ss/policydb.c76
1 files changed, 54 insertions, 22 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 02b722c5c189..9fccf417006b 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -411,7 +411,7 @@ out:
return rc;
}
-static u32 filenametr_hash(struct hashtab *h, const void *k)
+static u32 filenametr_hash(const void *k)
{
const struct filename_trans_key *ft = k;
unsigned long hash;
@@ -423,10 +423,10 @@ static u32 filenametr_hash(struct hashtab *h, const void *k)
byte_num = 0;
while ((focus = ft->name[byte_num++]))
hash = partial_name_hash(focus, hash);
- return hash & (h->size - 1);
+ return hash;
}
-static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
+static int filenametr_cmp(const void *k1, const void *k2)
{
const struct filename_trans_key *ft1 = k1;
const struct filename_trans_key *ft2 = k2;
@@ -444,15 +444,26 @@ static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
}
-static u32 rangetr_hash(struct hashtab *h, const void *k)
+static const struct hashtab_key_params filenametr_key_params = {
+ .hash = filenametr_hash,
+ .cmp = filenametr_cmp,
+};
+
+struct filename_trans_datum *policydb_filenametr_search(
+ struct policydb *p, struct filename_trans_key *key)
+{
+ return hashtab_search(&p->filename_trans, key, filenametr_key_params);
+}
+
+static u32 rangetr_hash(const void *k)
{
const struct range_trans *key = k;
- return (key->source_type + (key->target_type << 3) +
- (key->target_class << 5)) & (h->size - 1);
+ return key->source_type + (key->target_type << 3) +
+ (key->target_class << 5);
}
-static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
+static int rangetr_cmp(const void *k1, const void *k2)
{
const struct range_trans *key1 = k1, *key2 = k2;
int v;
@@ -470,15 +481,25 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
return v;
}
-static u32 role_trans_hash(struct hashtab *h, const void *k)
+static const struct hashtab_key_params rangetr_key_params = {
+ .hash = rangetr_hash,
+ .cmp = rangetr_cmp,
+};
+
+struct mls_range *policydb_rangetr_search(struct policydb *p,
+ struct range_trans *key)
+{
+ return hashtab_search(&p->range_tr, key, rangetr_key_params);
+}
+
+static u32 role_trans_hash(const void *k)
{
const struct role_trans_key *key = k;
- return (key->role + (key->type << 3) + (key->tclass << 5)) &
- (h->size - 1);
+ return key->role + (key->type << 3) + (key->tclass << 5);
}
-static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
+static int role_trans_cmp(const void *k1, const void *k2)
{
const struct role_trans_key *key1 = k1, *key2 = k2;
int v;
@@ -494,6 +515,17 @@ static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
return key1->tclass - key2->tclass;
}
+static const struct hashtab_key_params roletr_key_params = {
+ .hash = role_trans_hash,
+ .cmp = role_trans_cmp,
+};
+
+struct role_trans_datum *policydb_roletr_search(struct policydb *p,
+ struct role_trans_key *key)
+{
+ return hashtab_search(&p->role_tr, key, roletr_key_params);
+}
+
/*
* Initialize a policy database structure.
*/
@@ -1796,7 +1828,7 @@ static int range_read(struct policydb *p, void *fp)
nel = le32_to_cpu(buf[0]);
- rc = hashtab_init(&p->range_tr, rangetr_hash, rangetr_cmp, nel);
+ rc = hashtab_init(&p->range_tr, nel);
if (rc)
return rc;
@@ -1841,7 +1873,7 @@ static int range_read(struct policydb *p, void *fp)
goto out;
}
- rc = hashtab_insert(&p->range_tr, rt, r);
+ rc = hashtab_insert(&p->range_tr, rt, r, rangetr_key_params);
if (rc)
goto out;
@@ -1888,7 +1920,7 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
otype = le32_to_cpu(buf[3]);
last = NULL;
- datum = hashtab_search(&p->filename_trans, &key);
+ datum = policydb_filenametr_search(p, &key);
while (datum) {
if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
/* conflicting/duplicate rules are ignored */
@@ -1918,7 +1950,8 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
if (!ft)
goto out;
- rc = hashtab_insert(&p->filename_trans, ft, datum);
+ rc = hashtab_insert(&p->filename_trans, ft, datum,
+ filenametr_key_params);
if (rc)
goto out;
name = NULL;
@@ -2006,7 +2039,8 @@ static int filename_trans_read_helper(struct policydb *p, void *fp)
ft->tclass = tclass;
ft->name = name;
- rc = hashtab_insert(&p->filename_trans, ft, first);
+ rc = hashtab_insert(&p->filename_trans, ft, first,
+ filenametr_key_params);
if (rc == -EEXIST)
pr_err("SELinux: Duplicate filename transition key\n");
if (rc)
@@ -2044,8 +2078,7 @@ static int filename_trans_read(struct policydb *p, void *fp)
if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
p->compat_filename_trans_count = nel;
- rc = hashtab_init(&p->filename_trans, filenametr_hash,
- filenametr_cmp, (1 << 11));
+ rc = hashtab_init(&p->filename_trans, (1 << 11));
if (rc)
return rc;
@@ -2055,8 +2088,7 @@ static int filename_trans_read(struct policydb *p, void *fp)
return rc;
}
} else {
- rc = hashtab_init(&p->filename_trans, filenametr_hash,
- filenametr_cmp, nel);
+ rc = hashtab_init(&p->filename_trans, nel);
if (rc)
return rc;
@@ -2539,7 +2571,7 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
nel = le32_to_cpu(buf[0]);
- rc = hashtab_init(&p->role_tr, role_trans_hash, role_trans_cmp, nel);
+ rc = hashtab_init(&p->role_tr, nel);
if (rc)
goto bad;
for (i = 0; i < nel; i++) {
@@ -2576,7 +2608,7 @@ int policydb_read(struct policydb *p, void *fp)
!policydb_role_isvalid(p, rtd->new_role))
goto bad;
- rc = hashtab_insert(&p->role_tr, rtk, rtd);
+ rc = hashtab_insert(&p->role_tr, rtk, rtd, roletr_key_params);
if (rc)
goto bad;