aboutsummaryrefslogtreecommitdiffstats
path: root/security/inode.c
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2025-02-13 17:34:12 -0500
committerPaul Moore <paul@paul-moore.com>2025-10-22 19:24:19 -0400
commit935d508d4d7ab9d19c603bd7eb2937249551d507 (patch)
treebcbb3eb0ba2e56b02fea8eecb6da0291e91fd82d /security/inode.c
parent250898ca335f337bc032a9693dc0a30a1cb85825 (diff)
downloadnet-935d508d4d7ab9d19c603bd7eb2937249551d507.tar.gz
lsm: get rid of the lsm_names list and do some cleanup
The LSM currently has a lot of code to maintain a list of the currently active LSMs in a human readable string, with the only user being the "/sys/kernel/security/lsm" code. Let's drop all of that code and generate the string on first use and then cache it for subsequent use. Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security/inode.c')
-rw-r--r--security/inode.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/security/inode.c b/security/inode.c
index 43382ef8896e1d..6620c3e42af263 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -22,6 +22,8 @@
#include <linux/lsm_hooks.h>
#include <linux/magic.h>
+#include "lsm.h"
+
static struct vfsmount *mount;
static int mount_count;
@@ -315,12 +317,49 @@ void securityfs_remove(struct dentry *dentry)
EXPORT_SYMBOL_GPL(securityfs_remove);
#ifdef CONFIG_SECURITY
+#include <linux/spinlock.h>
+
static struct dentry *lsm_dentry;
+
static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count,
loff_t *ppos)
{
- return simple_read_from_buffer(buf, count, ppos, lsm_names,
- strlen(lsm_names));
+ int i;
+ static char *str;
+ static size_t len;
+ static DEFINE_SPINLOCK(lock);
+
+ /* NOTE: we never free or modify the string once it is set */
+
+ if (unlikely(!str || !len)) {
+ char *str_tmp;
+ size_t len_tmp = 0;
+
+ for (i = 0; i < lsm_active_cnt; i++)
+ /* the '+ 1' accounts for either a comma or a NUL */
+ len_tmp += strlen(lsm_idlist[i]->name) + 1;
+
+ str_tmp = kmalloc(len_tmp, GFP_KERNEL);
+ if (!str_tmp)
+ return -ENOMEM;
+ str_tmp[0] = '\0';
+
+ for (i = 0; i < lsm_active_cnt; i++) {
+ if (i > 0)
+ strcat(str_tmp, ",");
+ strcat(str_tmp, lsm_idlist[i]->name);
+ }
+
+ spin_lock(&lock);
+ if (!str) {
+ str = str_tmp;
+ len = len_tmp - 1;
+ } else
+ kfree(str_tmp);
+ spin_unlock(&lock);
+ }
+
+ return simple_read_from_buffer(buf, count, ppos, str, len);
}
static const struct file_operations lsm_ops = {