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

Chase Douglas chase.douglas at canonical.com
Wed May 26 20:15:25 UTC 2010


On Wed, 2010-05-12 at 15:22 -0700, 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;

Why create a new variable just to store current? I think it would be
more readable to just use current where you use curtemp. I don't think
current should change from under you when you're here.

> +		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);
>  }





More information about the kernel-team mailing list