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>
This commit is contained in:
parent
8156b451f3
commit
389da25f93
|
@ -34,7 +34,7 @@ parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still
|
||||||
work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID"
|
work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID"
|
||||||
still work as root).
|
still work as root).
|
||||||
|
|
||||||
For software that has defined application-specific relationships
|
In mode 1, software that has defined application-specific relationships
|
||||||
between a debugging process and its inferior (crash handlers, etc),
|
between a debugging process and its inferior (crash handlers, etc),
|
||||||
prctl(PR_SET_PTRACER, pid, ...) can be used. An inferior can declare which
|
prctl(PR_SET_PTRACER, pid, ...) can be used. An inferior can declare which
|
||||||
other process (and its descendents) are allowed to call PTRACE_ATTACH
|
other process (and its descendents) are allowed to call PTRACE_ATTACH
|
||||||
|
@ -46,6 +46,8 @@ restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)
|
||||||
so that any otherwise allowed process (even those in external pid namespaces)
|
so that any otherwise allowed process (even those in external pid namespaces)
|
||||||
may attach.
|
may attach.
|
||||||
|
|
||||||
|
These restrictions do not change how ptrace via PTRACE_TRACEME operates.
|
||||||
|
|
||||||
The sysctl settings are:
|
The sysctl settings are:
|
||||||
|
|
||||||
0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
|
0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
|
||||||
|
@ -60,6 +62,12 @@ The sysctl settings are:
|
||||||
inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
|
inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
|
||||||
an allowed debugger PID to call PTRACE_ATTACH on the inferior.
|
an allowed debugger PID to call PTRACE_ATTACH on the inferior.
|
||||||
|
|
||||||
|
2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace
|
||||||
|
with PTRACE_ATTACH.
|
||||||
|
|
||||||
|
3 - no attach: no processes may use ptrace with PTRACE_ATTACH. Once set,
|
||||||
|
this sysctl cannot be changed to a lower value.
|
||||||
|
|
||||||
The original children-only logic was based on the restrictions in grsecurity.
|
The original children-only logic was based on the restrictions in grsecurity.
|
||||||
|
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
|
@ -18,7 +18,12 @@
|
||||||
#include <linux/prctl.h>
|
#include <linux/prctl.h>
|
||||||
#include <linux/ratelimit.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 */
|
/* describe a ptrace relationship for potential exception */
|
||||||
struct ptrace_relation {
|
struct ptrace_relation {
|
||||||
|
@ -251,17 +256,32 @@ static int yama_ptrace_access_check(struct task_struct *child,
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* require ptrace target be a child of ptracer on attach */
|
/* require ptrace target be a child of ptracer on attach */
|
||||||
if (mode == PTRACE_MODE_ATTACH &&
|
if (mode == PTRACE_MODE_ATTACH) {
|
||||||
ptrace_scope &&
|
switch (ptrace_scope) {
|
||||||
!task_is_descendant(current, child) &&
|
case YAMA_SCOPE_DISABLED:
|
||||||
|
/* No additional restrictions. */
|
||||||
|
break;
|
||||||
|
case YAMA_SCOPE_RELATIONAL:
|
||||||
|
if (!task_is_descendant(current, child) &&
|
||||||
!ptracer_exception_found(current, child) &&
|
!ptracer_exception_found(current, child) &&
|
||||||
!capable(CAP_SYS_PTRACE))
|
!capable(CAP_SYS_PTRACE))
|
||||||
rc = -EPERM;
|
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) {
|
if (rc) {
|
||||||
char name[sizeof(current->comm)];
|
char name[sizeof(current->comm)];
|
||||||
printk_ratelimited(KERN_NOTICE "ptrace of non-child"
|
printk_ratelimited(KERN_NOTICE
|
||||||
" pid %d was attempted by: %s (pid %d)\n",
|
"ptrace of pid %d was attempted by: %s (pid %d)\n",
|
||||||
child->pid,
|
child->pid,
|
||||||
get_task_comm(name, current),
|
get_task_comm(name, current),
|
||||||
current->pid);
|
current->pid);
|
||||||
|
@ -279,8 +299,28 @@ static struct security_operations yama_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#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 zero;
|
||||||
static int one = 1;
|
static int one = 1;
|
||||||
|
static int max_scope = YAMA_SCOPE_NO_ATTACH;
|
||||||
|
|
||||||
struct ctl_path yama_sysctl_path[] = {
|
struct ctl_path yama_sysctl_path[] = {
|
||||||
{ .procname = "kernel", },
|
{ .procname = "kernel", },
|
||||||
|
@ -294,9 +334,9 @@ static struct ctl_table yama_sysctl_table[] = {
|
||||||
.data = &ptrace_scope,
|
.data = &ptrace_scope,
|
||||||
.maxlen = sizeof(int),
|
.maxlen = sizeof(int),
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec_minmax,
|
.proc_handler = yama_dointvec_minmax,
|
||||||
.extra1 = &zero,
|
.extra1 = &zero,
|
||||||
.extra2 = &one,
|
.extra2 = &max_scope,
|
||||||
},
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user