summaryrefslogtreecommitdiff
path: root/security/selinux/ss/hashtab.h
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/hashtab.h')
-rw-r--r--security/selinux/ss/hashtab.h107
1 files changed, 87 insertions, 20 deletions
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h
index 953872cd84ab..deba82d78c3a 100644
--- a/security/selinux/ss/hashtab.h
+++ b/security/selinux/ss/hashtab.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* A hash table (hashtab) maintains associations between
* key values and datum values. The type of the key values
@@ -5,12 +6,22 @@
* functions for hash computation and key comparison are
* provided by the creator of the table.
*
- * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
*/
+
#ifndef _SS_HASHTAB_H_
#define _SS_HASHTAB_H_
-#define HASHTAB_MAX_NODES 0xffffffff
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#define HASHTAB_MAX_NODES U32_MAX
+
+struct hashtab_key_params {
+ u32 (*hash)(const void *key); /* hash func */
+ int (*cmp)(const void *key1, const void *key2); /* comparison func */
+};
struct hashtab_node {
void *key;
@@ -19,29 +30,26 @@ struct hashtab_node {
};
struct hashtab {
- struct hashtab_node **htable; /* hash table */
- u32 size; /* number of slots in hash table */
- u32 nel; /* number of elements in hash table */
- u32 (*hash_value)(struct hashtab *h, const void *key);
- /* hash function */
- int (*keycmp)(struct hashtab *h, const void *key1, const void *key2);
- /* key comparison function */
+ struct hashtab_node **htable; /* hash table */
+ u32 size; /* number of slots in hash table */
+ u32 nel; /* number of elements in hash table */
};
struct hashtab_info {
u32 slots_used;
u32 max_chain_len;
+ u64 chain2_len_sum;
};
/*
- * Creates a new hash table with the specified characteristics.
+ * Initializes a new hash table with the specified characteristics.
*
- * Returns NULL if insufficent space is available or
- * the new hash table otherwise.
+ * Returns -ENOMEM if insufficient space is available or 0 otherwise.
*/
-struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
- int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
- u32 size);
+int hashtab_init(struct hashtab *h, u32 nel_hint);
+
+int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst, void *key,
+ void *datum);
/*
* Inserts the specified (key, datum) pair into the specified hash table.
@@ -51,7 +59,34 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *
* -EINVAL for general errors or
0 otherwise.
*/
-int hashtab_insert(struct hashtab *h, void *k, void *d);
+static inline int hashtab_insert(struct hashtab *h, void *key, void *datum,
+ struct hashtab_key_params key_params)
+{
+ u32 hvalue;
+ struct hashtab_node *prev, *cur;
+
+ cond_resched();
+
+ if (!h->size || h->nel == HASHTAB_MAX_NODES)
+ return -EINVAL;
+
+ hvalue = key_params.hash(key) & (h->size - 1);
+ prev = NULL;
+ cur = h->htable[hvalue];
+ while (cur) {
+ int cmp = key_params.cmp(key, cur->key);
+
+ if (cmp == 0)
+ return -EEXIST;
+ if (cmp < 0)
+ break;
+ prev = cur;
+ cur = cur->next;
+ }
+
+ return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue], key,
+ datum);
+}
/*
* Searches for the entry with the specified key in the hash table.
@@ -59,7 +94,28 @@ int hashtab_insert(struct hashtab *h, void *k, void *d);
* Returns NULL if no entry has the specified key or
* the datum of the entry otherwise.
*/
-void *hashtab_search(struct hashtab *h, const void *k);
+static inline void *hashtab_search(struct hashtab *h, const void *key,
+ struct hashtab_key_params key_params)
+{
+ u32 hvalue;
+ struct hashtab_node *cur;
+
+ if (!h->size)
+ return NULL;
+
+ hvalue = key_params.hash(key) & (h->size - 1);
+ cur = h->htable[hvalue];
+ while (cur) {
+ int cmp = key_params.cmp(key, cur->key);
+
+ if (cmp == 0)
+ return cur->datum;
+ if (cmp < 0)
+ break;
+ cur = cur->next;
+ }
+ return NULL;
+}
/*
* Destroys the specified hash table.
@@ -77,11 +133,22 @@ void hashtab_destroy(struct hashtab *h);
* iterating through the hash table and will propagate the error
* return to its caller.
*/
-int hashtab_map(struct hashtab *h,
- int (*apply)(void *k, void *d, void *args),
+int hashtab_map(struct hashtab *h, int (*apply)(void *k, void *d, void *args),
void *args);
+int hashtab_duplicate(struct hashtab *new, const struct hashtab *orig,
+ int (*copy)(struct hashtab_node *new,
+ const struct hashtab_node *orig, void *args),
+ int (*destroy)(void *k, void *d, void *args), void *args);
+
+#ifdef CONFIG_SECURITY_SELINUX_DEBUG
/* Fill info with some hash table statistics */
void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
+#else
+static inline void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
+{
+ return;
+}
+#endif
-#endif /* _SS_HASHTAB_H */
+#endif /* _SS_HASHTAB_H */