LSM: Add /sys/kernel/security/lsm

I am still tired of having to find indirect ways to determine
what security modules are active on a system. I have added
/sys/kernel/security/lsm, which contains a comma separated
list of the active security modules. No more groping around
in /proc/filesystems or other clever hacks.

Unchanged from previous versions except for being updated
to the latest security next branch.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Paul Moore <paul@paul-moore.com>
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: James Morris <james.l.morris@oracle.com>
This commit is contained in:
Casey Schaufler 2017-01-18 17:09:05 -08:00 committed by James Morris
parent 3ccb76c5df
commit d69dece5f5
11 changed files with 82 additions and 17 deletions

View File

@ -22,6 +22,13 @@ system, building their checks on top of the defined capability hooks.
For more details on capabilities, see capabilities(7) in the Linux
man-pages project.
A list of the active security modules can be found by reading
/sys/kernel/security/lsm. This is a comma separated list, and
will always include the capability module. The list reflects the
order in which checks are made. The capability module will always
be first, followed by any "minor" modules (e.g. Yama) and then
the one "major" module (e.g. SELinux) if there is one configured.
Based on https://lkml.org/lkml/2007/10/26/215,
a new LSM is accepted into the kernel when its intent (a description of
what it tries to protect against and in what cases one would expect to

View File

@ -1875,6 +1875,7 @@ struct security_hook_list {
struct list_head list;
struct list_head *head;
union security_list_options hook;
char *lsm;
};
/*
@ -1887,15 +1888,10 @@ struct security_hook_list {
{ .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }
extern struct security_hook_heads security_hook_heads;
extern char *lsm_names;
static inline void security_add_hooks(struct security_hook_list *hooks,
int count)
{
int i;
for (i = 0; i < count; i++)
list_add_tail_rcu(&hooks[i].list, hooks[i].head);
}
extern void security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm);
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
/*

View File

@ -999,7 +999,8 @@ static int __init apparmor_init(void)
aa_free_root_ns();
goto buffers_out;
}
security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks));
security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),
"apparmor");
/* Report that AppArmor successfully initialized */
apparmor_initialized = 1;

View File

@ -1093,7 +1093,8 @@ struct security_hook_list capability_hooks[] = {
void __init capability_add_hooks(void)
{
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
"capability");
}
#endif /* CONFIG_SECURITY */

View File

@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/security.h>
#include <linux/lsm_hooks.h>
#include <linux/magic.h>
static struct vfsmount *mount;
@ -204,6 +205,21 @@ void securityfs_remove(struct dentry *dentry)
}
EXPORT_SYMBOL_GPL(securityfs_remove);
#ifdef CONFIG_SECURITY
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));
}
static const struct file_operations lsm_ops = {
.read = lsm_read,
.llseek = generic_file_llseek,
};
#endif
static int __init securityfs_init(void)
{
int retval;
@ -213,9 +229,15 @@ static int __init securityfs_init(void)
return retval;
retval = register_filesystem(&fs_type);
if (retval)
if (retval) {
sysfs_remove_mount_point(kernel_kobj, "security");
return retval;
}
#ifdef CONFIG_SECURITY
lsm_dentry = securityfs_create_file("lsm", 0444, NULL, NULL,
&lsm_ops);
#endif
return 0;
}
core_initcall(securityfs_init);

View File

@ -182,7 +182,7 @@ static struct security_hook_list loadpin_hooks[] = {
void __init loadpin_add_hooks(void)
{
pr_info("ready to pin (currently %sabled)", enabled ? "en" : "dis");
security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks));
security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
}
/* Should not be mutable after boot, so not listed in sysfs (perm == 0). */

View File

@ -32,6 +32,7 @@
/* Maximum number of letters for an LSM name string */
#define SECURITY_NAME_MAX 10
char *lsm_names;
/* Boot-time LSM user choice */
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
CONFIG_DEFAULT_SECURITY;
@ -78,6 +79,22 @@ static int __init choose_lsm(char *str)
}
__setup("security=", choose_lsm);
static int lsm_append(char *new, char **result)
{
char *cp;
if (*result == NULL) {
*result = kstrdup(new, GFP_KERNEL);
} else {
cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new);
if (cp == NULL)
return -ENOMEM;
kfree(*result);
*result = cp;
}
return 0;
}
/**
* security_module_enable - Load given security module on boot ?
* @module: the name of the module
@ -97,6 +114,27 @@ int __init security_module_enable(const char *module)
return !strcmp(module, chosen_lsm);
}
/**
* security_add_hooks - Add a modules hooks to the hook lists.
* @hooks: the hooks to add
* @count: the number of hooks to add
* @lsm: the name of the security module
*
* Each LSM has to register its hooks with the infrastructure.
*/
void __init security_add_hooks(struct security_hook_list *hooks, int count,
char *lsm)
{
int i;
for (i = 0; i < count; i++) {
hooks[i].lsm = lsm;
list_add_tail_rcu(&hooks[i].list, hooks[i].head);
}
if (lsm_append(lsm, &lsm_names) < 0)
panic("%s - Cannot get early memory.\n", __func__);
}
/*
* Hook list operation macros.
*

View File

@ -6349,7 +6349,7 @@ static __init int selinux_init(void)
0, SLAB_PANIC, NULL);
avc_init();
security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
panic("SELinux: Unable to register AVC netcache callback\n");

View File

@ -4819,7 +4819,7 @@ static __init int smack_init(void)
/*
* Register with LSM
*/
security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks));
security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack");
return 0;
}

View File

@ -542,7 +542,7 @@ static int __init tomoyo_init(void)
if (!security_module_enable("tomoyo"))
return 0;
/* register ourselves with the security framework */
security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks));
security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
printk(KERN_INFO "TOMOYO Linux initialized\n");
cred->security = &tomoyo_kernel_domain;
tomoyo_mm_init();

View File

@ -485,6 +485,6 @@ static inline void yama_init_sysctl(void) { }
void __init yama_add_hooks(void)
{
pr_info("Yama: becoming mindful.\n");
security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks));
security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
yama_init_sysctl();
}