From patchwork Wed May 12 22:22:30 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 52410 X-Patchwork-Delegate: leann.ogasawara@canonical.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 387ABB7D90 for ; Thu, 13 May 2010 08:22:41 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1OCKK1-0000qG-Ii; Wed, 12 May 2010 23:22:33 +0100 Received: from smtp.outflux.net ([198.145.64.163]) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1OCKJz-0000qB-SU for kernel-team@lists.ubuntu.com; Wed, 12 May 2010 23:22:32 +0100 Received: from www.outflux.net (serenity-end.outflux.net [10.2.0.2]) by vinyl.outflux.net (8.14.3/8.14.3/Debian-9.1ubuntu1) with ESMTP id o4CMMUBr022996 for ; Wed, 12 May 2010 15:22:30 -0700 Date: Wed, 12 May 2010 15:22:30 -0700 From: Kees Cook To: kernel-team@lists.ubuntu.com Subject: [PATCH] UBUNTU: SAUCE: ptrace: restrict ptrace scope to children Message-ID: <20100512222230.GL4433@outflux.net> MIME-Version: 1.0 Content-Disposition: inline Organization: Ubuntu X-MIMEDefang-Filter: outflux$Revision: 1.316 $ X-HELO: www.outflux.net X-Scanned-By: MIMEDefang 2.67 on 10.2.0.1 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com 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 Acked-by: Tim Gardner --- 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 #include +/* 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),