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