diff options
author | Kees Cook <keescook@chromium.org> | 2012-04-16 11:56:45 -0700 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-04-19 13:39:56 +1000 |
commit | 389da25f93eea8ff64181ae7e3e87da68acaef2e (patch) | |
tree | 09277860746b3372cbb49ea82868709cbae99ec3 /security/yama | |
parent | 8156b451f37898d3c3652b4e988a4d62ae16eaac (diff) |
Yama: add additional ptrace scopes
This expands the available Yama ptrace restrictions to include two more
modes. Mode 2 requires CAP_SYS_PTRACE for PTRACE_ATTACH, and mode 3
completely disables PTRACE_ATTACH (and locks the sysctl).
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: James Morris <james.l.morris@oracle.com>
Diffstat (limited to 'security/yama')
-rw-r--r-- | security/yama/yama_lsm.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 573723843a04..afb04cbb6971 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -18,7 +18,12 @@ #include <linux/prctl.h> #include <linux/ratelimit.h> -static int ptrace_scope = 1; +#define YAMA_SCOPE_DISABLED 0 +#define YAMA_SCOPE_RELATIONAL 1 +#define YAMA_SCOPE_CAPABILITY 2 +#define YAMA_SCOPE_NO_ATTACH 3 + +static int ptrace_scope = YAMA_SCOPE_RELATIONAL; /* describe a ptrace relationship for potential exception */ struct ptrace_relation { @@ -251,17 +256,32 @@ static int yama_ptrace_access_check(struct task_struct *child, return rc; /* require ptrace target be a child of ptracer on attach */ - if (mode == PTRACE_MODE_ATTACH && - ptrace_scope && - !task_is_descendant(current, child) && - !ptracer_exception_found(current, child) && - !capable(CAP_SYS_PTRACE)) - rc = -EPERM; + if (mode == PTRACE_MODE_ATTACH) { + switch (ptrace_scope) { + case YAMA_SCOPE_DISABLED: + /* No additional restrictions. */ + break; + case YAMA_SCOPE_RELATIONAL: + if (!task_is_descendant(current, child) && + !ptracer_exception_found(current, child) && + !capable(CAP_SYS_PTRACE)) + rc = -EPERM; + break; + case YAMA_SCOPE_CAPABILITY: + if (!capable(CAP_SYS_PTRACE)) + rc = -EPERM; + break; + case YAMA_SCOPE_NO_ATTACH: + default: + rc = -EPERM; + break; + } + } if (rc) { char name[sizeof(current->comm)]; - printk_ratelimited(KERN_NOTICE "ptrace of non-child" - " pid %d was attempted by: %s (pid %d)\n", + printk_ratelimited(KERN_NOTICE + "ptrace of pid %d was attempted by: %s (pid %d)\n", child->pid, get_task_comm(name, current), current->pid); @@ -279,8 +299,28 @@ static struct security_operations yama_ops = { }; #ifdef CONFIG_SYSCTL +static int yama_dointvec_minmax(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int rc; + + if (write && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + rc = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + if (rc) + return rc; + + /* Lock the max value if it ever gets set. */ + if (write && *(int *)table->data == *(int *)table->extra2) + table->extra1 = table->extra2; + + return rc; +} + static int zero; static int one = 1; +static int max_scope = YAMA_SCOPE_NO_ATTACH; struct ctl_path yama_sysctl_path[] = { { .procname = "kernel", }, @@ -294,9 +334,9 @@ static struct ctl_table yama_sysctl_table[] = { .data = &ptrace_scope, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = yama_dointvec_minmax, .extra1 = &zero, - .extra2 = &one, + .extra2 = &max_scope, }, { } }; |