summaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/hashtab.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-10-13 16:29:55 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-10-13 16:29:55 -0700
commit7b540812cc0635e6c7e508359115c7cb6886fd2f (patch)
treea8e753d90bd36925a88dc9b86b5b1386bec6436c /security/selinux/ss/hashtab.c
parent01fb1e2f42d607ef5eb7a7ca54a0f0901fb5856c (diff)
parent0d50f059c4cdc9e436f6f4db8779ac0795bfdadf (diff)
Merge tag 'selinux-pr-20201012' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore: "A decent number of SELinux patches for v5.10, twenty two in total. The highlights are listed below, but all of the patches pass our test suite and merge cleanly. - A number of changes to how the SELinux policy is loaded and managed inside the kernel with the goal of improving the atomicity of a SELinux policy load operation. These changes account for the bulk of the diffstat as well as the patch count. A special thanks to everyone who contributed patches and fixes for this work. - Convert the SELinux policy read-write lock to RCU. - A tracepoint was added for audited SELinux access control events; this should help provide a more unified backtrace across kernel and userspace. - Allow the removal of security.selinux xattrs when a SELinux policy is not loaded. - Enable policy capabilities in SELinux policies created with the scripts/selinux/mdp tool. - Provide some "no sooner than" dates for the SELinux checkreqprot sysfs deprecation" * tag 'selinux-pr-20201012' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: (22 commits) selinux: provide a "no sooner than" date for the checkreqprot removal selinux: Add helper functions to get and set checkreqprot selinux: access policycaps with READ_ONCE/WRITE_ONCE selinux: simplify away security_policydb_len() selinux: move policy mutex to selinux_state, use in lockdep checks selinux: fix error handling bugs in security_load_policy() selinux: convert policy read-write lock to RCU selinux: delete repeated words in comments selinux: add basic filtering for audit trace events selinux: add tracepoint on audited events selinux: Create new booleans and class dirs out of tree selinux: Standardize string literal usage for selinuxfs directory names selinux: Refactor selinuxfs directory populating functions selinux: Create function for selinuxfs directory cleanup selinux: permit removing security.selinux xattr before policy load selinux: fix memdup.cocci warnings selinux: avoid dereferencing the policy prior to initialization selinux: fix allocation failure check on newpolicy->sidtab selinux: refactor changing booleans selinux: move policy commit after updating selinuxfs ...
Diffstat (limited to 'security/selinux/ss/hashtab.c')
-rw-r--r--security/selinux/ss/hashtab.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index d9287bb4bfeb..dab8c25c739b 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -122,6 +122,59 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
info->max_chain_len = max_chain_len;
}
+int hashtab_duplicate(struct hashtab *new, struct hashtab *orig,
+ int (*copy)(struct hashtab_node *new,
+ struct hashtab_node *orig, void *args),
+ int (*destroy)(void *k, void *d, void *args),
+ void *args)
+{
+ struct hashtab_node *cur, *tmp, *tail;
+ int i, rc;
+
+ memset(new, 0, sizeof(*new));
+
+ new->htable = kcalloc(orig->size, sizeof(*new->htable), GFP_KERNEL);
+ if (!new->htable)
+ return -ENOMEM;
+
+ new->size = orig->size;
+
+ for (i = 0; i < orig->size; i++) {
+ tail = NULL;
+ for (cur = orig->htable[i]; cur; cur = cur->next) {
+ tmp = kmem_cache_zalloc(hashtab_node_cachep,
+ GFP_KERNEL);
+ if (!tmp)
+ goto error;
+ rc = copy(tmp, cur, args);
+ if (rc) {
+ kmem_cache_free(hashtab_node_cachep, tmp);
+ goto error;
+ }
+ tmp->next = NULL;
+ if (!tail)
+ new->htable[i] = tmp;
+ else
+ tail->next = tmp;
+ tail = tmp;
+ new->nel++;
+ }
+ }
+
+ return 0;
+
+ error:
+ for (i = 0; i < new->size; i++) {
+ for (cur = new->htable[i]; cur; cur = tmp) {
+ tmp = cur->next;
+ destroy(cur->key, cur->datum, args);
+ kmem_cache_free(hashtab_node_cachep, cur);
+ }
+ }
+ kmem_cache_free(hashtab_node_cachep, new);
+ return -ENOMEM;
+}
+
void __init hashtab_cache_init(void)
{
hashtab_node_cachep = kmem_cache_create("hashtab_node",