[patch 17/18] proc: avoid information leaks to non-privileged processes

From: Greg KH
Date: Wed May 06 2009 - 16:45:48 EST


2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------

From: Jake Edge <jake@xxxxxxx>

commit f83ce3e6b02d5e48b3a43b001390e2b58820389d upstream.

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 <stable@xxxxxxxxxx>
Signed-off-by: Jake Edge <jake@xxxxxxx>
Acked-by: Arjan van de Ven <arjan@xxxxxxxxxxxxxxx>
Acked-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
fs/proc/array.c | 13 +++++++++----
fs/proc/base.c | 5 ++++-
2 files changed, 13 insertions(+), 5 deletions(-)

--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -80,6 +80,7 @@
#include <linux/delayacct.h>
#include <linux/seq_file.h>
#include <linux/pid_namespace.h>
+#include <linux/ptrace.h>
#include <linux/tracehook.h>

#include <asm/pgtable.h>
@@ -347,6 +348,7 @@ static int do_task_stat(struct seq_file
char state;
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;
@@ -359,11 +361,14 @@ static int do_task_stat(struct seq_file

state = *get_task_state(task);
vsize = eip = esp = 0;
+ permitted = ptrace_may_access(task, PTRACE_MODE_READ);
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);
@@ -419,7 +424,7 @@ static int do_task_stat(struct seq_file
unlock_task_sighand(task, &flags);
}

- if (!whole || num_threads < 2)
+ if (permitted && (!whole || num_threads < 2))
wchan = get_wchan(task);
if (!whole) {
min_flt = task->min_flt;
@@ -471,7 +476,7 @@ static int do_task_stat(struct seq_file
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.
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -327,7 +327,10 @@ static int proc_pid_wchan(struct task_st
wchan = get_wchan(task);

if (lookup_symbol_name(wchan, symname) < 0)
- return sprintf(buffer, "%lu", wchan);
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ return 0;
+ else
+ return sprintf(buffer, "%lu", wchan);
else
return sprintf(buffer, "%s", symname);
}


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/