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 an as-needed basis when
userspace reads "/sys/kernel/security/lsm".

Signed-off-by: Paul Moore <p...@paul-moore.com>
---
 include/linux/lsm_hooks.h |  1 -
 security/inode.c          | 27 +++++++++++++++++++--
 security/lsm_init.c       | 49 ---------------------------------------
 3 files changed, 25 insertions(+), 52 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 4cd17c9a229f..bc477fb20d02 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -169,7 +169,6 @@ struct lsm_info {
 
 
 /* DO NOT tamper with these variables outside of the LSM framework */
-extern char *lsm_names;
 extern struct lsm_static_calls_table static_calls_table __ro_after_init;
 
 /**
diff --git a/security/inode.c b/security/inode.c
index da3ab44c8e57..49bc3578bd23 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;
 
@@ -343,8 +345,29 @@ 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;
+       char *str;
+       ssize_t rc, len = 0;
+
+       for (i = 0; i < lsm_count; i++)
+               /* the '+ 1' accounts for either a comma or a NUL terminator */
+               len += strlen(lsm_order[i]->id->name) + 1;
+
+       str = kmalloc(len, GFP_KERNEL);
+       if (!str)
+               return -ENOMEM;
+       str[0] = '\0';
+
+       i = 0;
+       while (i < lsm_count) {
+               strcat(str, lsm_order[i]->id->name);
+               if (++i < lsm_count)
+                       strcat(str, ",");
+       }
+
+       rc = simple_read_from_buffer(buf, count, ppos, str, len);
+       kfree(str);
+       return rc;
 }
 
 static const struct file_operations lsm_ops = {
diff --git a/security/lsm_init.c b/security/lsm_init.c
index 981ddb20f48e..978bb81b58fa 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -10,8 +10,6 @@
 
 #include "lsm.h"
 
-char *lsm_names;
-
 /* Pointers to LSM sections defined in include/asm-generic/vmlinux.lds.h */
 extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
 extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
@@ -363,42 +361,6 @@ static void __init lsm_init_ordered(void)
        }
 }
 
-static bool match_last_lsm(const char *list, const char *lsm)
-{
-       const char *last;
-
-       if (WARN_ON(!list || !lsm))
-               return false;
-       last = strrchr(list, ',');
-       if (last)
-               /* Pass the comma, strcmp() will check for '\0' */
-               last++;
-       else
-               last = list;
-       return !strcmp(last, lsm);
-}
-
-static int lsm_append(const char *new, char **result)
-{
-       char *cp;
-
-       if (*result == NULL) {
-               *result = kstrdup(new, GFP_KERNEL);
-               if (*result == NULL)
-                       return -ENOMEM;
-       } else {
-               /* Check if it is the last registered name */
-               if (match_last_lsm(*result, new))
-                       return 0;
-               cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new);
-               if (cp == NULL)
-                       return -ENOMEM;
-               kfree(*result);
-               *result = cp;
-       }
-       return 0;
-}
-
 static void __init lsm_static_call_init(struct security_hook_list *hl)
 {
        struct lsm_static_call *scall = hl->scalls;
@@ -435,15 +397,6 @@ void __init security_add_hooks(struct security_hook_list 
*hooks, int count,
                hooks[i].lsmid = lsmid;
                lsm_static_call_init(&hooks[i]);
        }
-
-       /*
-        * Don't try to append during early_security_init(), we'll come back
-        * and fix this up afterwards.
-        */
-       if (slab_is_available()) {
-               if (lsm_append(lsmid->name, &lsm_names) < 0)
-                       panic("%s - Cannot get early memory.\n", __func__);
-       }
 }
 
 int __init early_security_init(void)
@@ -480,8 +433,6 @@ int __init security_init(void)
        lsm_early_for_each_raw(lsm) {
                init_debug("  early started: %s (%s)\n", lsm->id->name,
                           is_enabled(lsm) ? "enabled" : "disabled");
-               if (lsm->enabled)
-                       lsm_append(lsm->id->name, &lsm_names);
        }
 
        /* Load LSMs in specified order. */
-- 
2.49.0


Reply via email to