LSM: Switch to lists of hooks

Instead of using a vector of security operations
with explicit, special case stacking of the capability
and yama hooks use lists of hooks with capability and
yama hooks included as appropriate.

The security_operations structure is no longer required.
Instead, there is a union of the function pointers that
allows all the hooks lists to use a common mechanism for
list management while retaining typing. Each module
supplies an array describing the hooks it provides instead
of a sparsely populated security_operations structure.
The description includes the element that gets put on
the hook list, avoiding the issues surrounding individual
element allocation.

The method for registering security modules is changed to
reflect the information available. The method for removing
a module, currently only used by SELinux, has also changed.
It should be generic now, however if there are potential
race conditions based on ordering of hook removal that needs
to be addressed by the calling module.

The security hooks are called from the lists and the first
failure is returned.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <keescook@chromium.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Acked-by:  Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <james.l.morris@oracle.com>
This commit is contained in:
Casey Schaufler
2015-05-02 15:11:42 -07:00
committed by James Morris
parent e20b043a69
commit b1d9e6b064
13 changed files with 628 additions and 388 deletions

View File

@@ -154,13 +154,9 @@ void yama_task_free(struct task_struct *task)
int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
int rc;
int rc = -ENOSYS;
struct task_struct *myself = current;
rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
if (rc != -ENOSYS)
return rc;
switch (option) {
case PR_SET_PTRACER:
/* Since a thread can call prctl(), find the group leader
@@ -279,17 +275,10 @@ static int ptracer_exception_found(struct task_struct *tracer,
*
* Returns 0 if following the ptrace is allowed, -ve on error.
*/
int yama_ptrace_access_check(struct task_struct *child,
static int yama_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
int rc;
/* If standard caps disallows it, so does Yama. We should
* only tighten restrictions further.
*/
rc = cap_ptrace_access_check(child, mode);
if (rc)
return rc;
int rc = 0;
/* require ptrace target be a child of ptracer on attach */
if (mode == PTRACE_MODE_ATTACH) {
@@ -335,14 +324,7 @@ int yama_ptrace_access_check(struct task_struct *child,
*/
int yama_ptrace_traceme(struct task_struct *parent)
{
int rc;
/* If standard caps disallows it, so does Yama. We should
* only tighten restrictions further.
*/
rc = cap_ptrace_traceme(parent);
if (rc)
return rc;
int rc = 0;
/* Only disallow PTRACE_TRACEME on more aggressive settings. */
switch (ptrace_scope) {
@@ -364,16 +346,17 @@ int yama_ptrace_traceme(struct task_struct *parent)
return rc;
}
#ifndef CONFIG_SECURITY_YAMA_STACKED
static struct security_operations yama_ops = {
LSM_HOOK_INIT(name, "yama"),
static struct security_hook_list yama_hooks[] = {
LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
LSM_HOOK_INIT(task_prctl, yama_task_prctl),
LSM_HOOK_INIT(task_free, yama_task_free),
};
#endif
void __init yama_add_hooks(void)
{
security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks));
}
#ifdef CONFIG_SYSCTL
static int yama_dointvec_minmax(struct ctl_table *table, int write,
@@ -418,16 +401,13 @@ static struct ctl_table yama_sysctl_table[] = {
static __init int yama_init(void)
{
#ifndef CONFIG_SECURITY_YAMA_STACKED
if (!security_module_enable(&yama_ops))
/*
* If yama is being stacked this is already taken care of.
*/
if (!security_module_enable("yama"))
return 0;
#endif
printk(KERN_INFO "Yama: becoming mindful.\n");
#ifndef CONFIG_SECURITY_YAMA_STACKED
if (register_security(&yama_ops))
panic("Yama: kernel registration failed.\n");
#endif
pr_info("Yama: becoming mindful.\n");
#ifdef CONFIG_SYSCTL
if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))