[PATCH] UBUNTU: SAUCE: ptrace: restrict ptrace scope to children

Stefan Bader stefan.bader at canonical.com
Thu May 27 12:56:52 UTC 2010


It seems the implementation itself is not so much questioned here than the
resulting behaviour (beside I probably would name the variable ptrace_testricted
to be clearer, though that is a bit nitpick).

>From the resulting behaviour itself I am probably less strongly biased. The
inconvenience of running 'sudo strace -p#' I don't see as that bad. But on the
other hand the security gain is maybe not worth the effort. What prevents
malware from just adding a wrapper script to target applications while ptracing
them as their parent?

If the answer is nothing I think this just adds too much false sense of
security. And for Lucid SRU the default would likely need to be classic anyway
(as long as it cannot guarantee to completely get rid of the issue, which it
does not seem to be able).

Could the goal be reached through extending apparmor to impose restrictions like
that based on profiles? (maybe that already exists and I am just to be blamed
for ignorance on it).

-Stefan

On 05/13/2010 12:22 AM, Kees Cook wrote:
> As Linux grows in popularity, it will become a growing target for
> malware. One particularly troubling weakness of the Linux process
> interfaces is that a single user is able to examine the memory and
> running state of any of their processes. For example, if one application
> (e.g. Empathy) was compromised, it would be possible for an attacker to
> attach to other processes (e.g. Firefox) to extract additional credentials
> and continue to expand the scope of their attack.
> 
> For a solution, some applications use prctl() to specifically disallow
> such PTRACE attachment (e.g. ssh-agent). A more general solution is to
> only allow PTRACE directly from a parent to a child process (i.e. direct
> gdb and strace still work), or as the root user (i.e. gdb BIN PID,
> and strace -p PID still work as root).
> 
> This patch is based on the patch in grsecurity. I have added a sysctl to
> toggle the behavior back to the old scope via /proc/sys/kernel/ptrace_scope.
> 
> Signed-off-by: Kees Cook <kees.cook at canonical.com>
> ---
>  kernel/ptrace.c |   24 ++++++++++++++++++++++++
>  kernel/sysctl.c |   10 ++++++++++
>  2 files changed, 34 insertions(+), 0 deletions(-)
> 
> diff --git a/kernel/ptrace.c b/kernel/ptrace.c
> index 42ad8ae..ad80b43 100644
> --- a/kernel/ptrace.c
> +++ b/kernel/ptrace.c
> @@ -24,6 +24,8 @@
>  #include <linux/uaccess.h>
>  #include <linux/regset.h>
>  
> +/* sysctl for defining allowed scope of PTRACE */
> +int ptrace_scope = 1;
>  
>  /*
>   * ptrace a task: make the debugger its new parent and
> @@ -129,6 +131,10 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
>  	 * ptrace_attach denies several cases that /proc allows
>  	 * because setting up the necessary parent/child relationship
>  	 * or halting the specified task is impossible.
> +	 *
> +	 * PTRACE scope can be define as:
> +	 *  0 - classic: CAP_SYS_PTRACE and same uid can ptrace non-setuid
> +	 *  1 - restricted: as above, but only children of ptracing process
>  	 */
>  	int dumpable = 0;
>  	/* Don't let security modules deny introspection */
> @@ -152,6 +158,24 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
>  		dumpable = get_dumpable(task->mm);
>  	if (!dumpable && !capable(CAP_SYS_PTRACE))
>  		return -EPERM;
> +	if (ptrace_scope && !capable(CAP_SYS_PTRACE)) {
> +		/* require ptrace target be a child of ptracer */
> +		struct task_struct *tmp = task;
> +		struct task_struct *curtemp = current;
> +		int rc = 0;
> +
> +		read_lock(&tasklist_lock);
> +		while (tmp->pid > 0) {
> +			if (tmp == curtemp)
> +				break;
> +			tmp = tmp->parent;
> +		}
> +		if (tmp->pid == 0)
> +			rc = -EPERM;
> +		read_unlock(&tasklist_lock);
> +		if (rc)
> +			return rc;
> +	}
>  
>  	return security_ptrace_access_check(task, mode);
>  }
> diff --git a/kernel/sysctl.c b/kernel/sysctl.c
> index 4f3ffd0..992eba9 100644
> --- a/kernel/sysctl.c
> +++ b/kernel/sysctl.c
> @@ -84,6 +84,7 @@ extern int sysctl_panic_on_oom;
>  extern int sysctl_oom_kill_allocating_task;
>  extern int sysctl_oom_dump_tasks;
>  extern int max_threads;
> +extern int ptrace_scope;
>  extern int core_uses_pid;
>  extern int suid_dumpable;
>  extern int weak_sticky_symlinks;
> @@ -382,6 +383,15 @@ static struct ctl_table kern_table[] = {
>  		.proc_handler	= proc_dointvec,
>  	},
>  	{
> +		.procname	= "ptrace_scope",
> +		.data		= &ptrace_scope,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec_minmax,
> +		.extra1		= &zero,
> +		.extra2		= &one,
> +	},
> +	{
>  		.procname	= "core_uses_pid",
>  		.data		= &core_uses_pid,
>  		.maxlen		= sizeof(int),





More information about the kernel-team mailing list