aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJacob Satterfield <jsatterfield.linux@gmail.com>2023-09-06 15:46:06 +0000
committerPaul Moore <paul@paul-moore.com>2023-09-13 13:52:17 -0400
commit9d140885e35dac6dff2c56eccacc13f4fc96188a (patch)
treef8f766ad743b6ef106d76e7371e70d2c3efde84a /security
parent37b7ea3ca3062f5b7f02c2b335f203e4d411793d (diff)
downloadlinux-9d140885e35dac6dff2c56eccacc13f4fc96188a.tar.gz
selinux: hweight optimization in avtab_read_item
avtab_read_item() is a hot function called when reading each rule in a binary policydb. With the current Fedora policy and refpolicy, this function is called nearly 100,000 times per policy load. A single avtab node is only permitted to have a single specifier to describe the data it holds. As such, a check is performed to make sure only one specifier is set. Previously this was done via a for-loop. However, there is already an optimal function for finding the number of bits set (hamming weight) and on some architectures, dedicated instructions (popcount) which can be executed much more efficiently. Even when using -mcpu=generic on a x86-64 Fedora 38 VM, this commit results in a modest 2-4% speedup for policy loading due to a substantial reduction in the number of instructions executed. Signed-off-by: Jacob Satterfield <jsatterfield.linux@gmail.com> Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/ss/avtab.c7
1 files changed, 2 insertions, 5 deletions
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 1d1ffe085b35c..095b8cd248065 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -17,6 +17,7 @@
* Tuned number of hash slots for avtab to reduce memory usage
*/
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
@@ -471,11 +472,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
return -EINVAL;
}
- set = 0;
- for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
- if (key.specified & spec_order[i])
- set++;
- }
+ set = hweight16(key.specified & (AVTAB_XPERMS | AVTAB_TYPE | AVTAB_AV));
if (!set || set > 1) {
pr_err("SELinux: avtab: more than one specifier\n");
return -EINVAL;