From patchwork Tue Jun 21 09:35:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Whitcroft X-Patchwork-Id: 101262 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 4F249B6F8B for ; Tue, 21 Jun 2011 19:36:02 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1QYxNF-0007qa-LX; Tue, 21 Jun 2011 09:35:57 +0000 Received: from adelie.canonical.com ([91.189.90.139]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1QYxMs-0007lH-TZ for kernel-team@lists.ubuntu.com; Tue, 21 Jun 2011 09:35:34 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1QYxMo-0004lv-7r; Tue, 21 Jun 2011 09:35:30 +0000 Received: from 212-139-215-176.dynamic.dsl.as9105.com ([212.139.215.176] helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1QYxMo-00020q-1V; Tue, 21 Jun 2011 09:35:30 +0000 From: Andy Whitcroft To: kernel-team@lists.ubuntu.com Subject: [hardy CVE 1/2] proc: avoid information leaks to non-privileged processes Date: Tue, 21 Jun 2011 10:35:23 +0100 Message-Id: <1308648925-13204-2-git-send-email-apw@canonical.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1308648925-13204-1-git-send-email-apw@canonical.com> References: <1308648925-13204-1-git-send-email-apw@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Jake Edge By using the same test as is used for /proc/pid/maps and /proc/pid/smaps, only allow processes that can ptrace() a given process to see information that might be used to bypass address space layout randomization (ASLR). These include eip, esp, wchan, and start_stack in /proc/pid/stat as well as the non-symbolic output from /proc/pid/wchan. ASLR can be bypassed by sampling eip as shown by the proof-of-concept code at http://code.google.com/p/fuzzyaslr/ As part of a presentation (http://www.cr0.org/paper/to-jt-linux-alsr-leak.pdf) esp and wchan were also noted as possibly usable information leaks as well. The start_stack address also leaks potentially useful information. Cc: Stable Team Signed-off-by: Jake Edge Acked-by: Arjan van de Ven Acked-by: "Eric W. Biederman" Signed-off-by: Linus Torvalds (backported from commit f83ce3e6b02d5e48b3a43b001390e2b58820389d) CVE-2011-0726 BugLink: http://bugs.launchpad.net/bugs/799906 Signed-off-by: Andy Whitcroft --- fs/proc/array.c | 13 +++++++++---- fs/proc/base.c | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index eb97f28..87902dd 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -78,6 +78,7 @@ #include #include #include +#include #include #include @@ -396,6 +397,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) int res; pid_t ppid = 0, pgid = -1, sid = -1; int num_threads = 0; + int permitted; struct mm_struct *mm; unsigned long long start_time; unsigned long cmin_flt = 0, cmaj_flt = 0; @@ -411,11 +413,14 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) state = *get_task_state(task); vsize = eip = esp = 0; + permitted = ptrace_may_attach(task); mm = get_task_mm(task); if (mm) { vsize = task_vsize(mm); - eip = KSTK_EIP(task); - esp = KSTK_ESP(task); + if (permitted) { + eip = KSTK_EIP(task); + esp = KSTK_ESP(task); + } } get_task_comm(tcomm, task); @@ -471,7 +476,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) } rcu_read_unlock(); - if (!whole || num_threads < 2) + if (permitted && (!whole || num_threads < 2)) wchan = get_wchan(task); if (!whole) { min_flt = task->min_flt; @@ -523,7 +528,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) rsslim, mm ? mm->start_code : 0, mm ? mm->end_code : 0, - mm ? mm->start_stack : 0, + (permitted && mm) ? mm->start_stack : 0, esp, eip, /* The signal information here is obsolete. diff --git a/fs/proc/base.c b/fs/proc/base.c index a91dc82..338097a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -291,7 +291,10 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) wchan = get_wchan(task); if (lookup_symbol_name(wchan, symname) < 0) - return sprintf(buffer, "%lu", wchan); + if (!ptrace_may_attach(task)) + return 0; + else + return sprintf(buffer, "%lu", wchan); else return sprintf(buffer, "%s", symname); }