Commit d69dece5 authored by Casey Schaufler's avatar Casey Schaufler Committed by James Morris

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: default avatarCasey Schaufler <casey@schaufler-ca.com>
Acked-by: default avatarJohn Johansen <john.johansen@canonical.com>
Acked-by: default avatarPaul Moore <paul@paul-moore.com>
Acked-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarJames Morris <james.l.morris@oracle.com>
parent 3ccb76c5
......@@ -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
......
......@@ -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
/*
......
......@@ -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;
......
......@@ -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 */
......@@ -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;
return retval;
}
#ifdef CONFIG_SECURITY
lsm_dentry = securityfs_create_file("lsm", 0444, NULL, NULL,
&lsm_ops);
#endif
return 0;
}
core_initcall(securityfs_init);
......
......@@ -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). */
......
......@@ -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.
*
......
......@@ -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");
......
......@@ -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;
}
......
......@@ -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();
......
......@@ -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();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment