aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Edge <jake@lwn.net>2009-05-04 12:51:14 -0600
committerWilly Tarreau <w@1wt.eu>2009-09-13 10:46:56 +0200
commita337045e6d985d090b516fdf51065e08aa4bd1dc (patch)
tree478268366cd287b4fbe87a333e6adbbd198dad91
parent3222e4523e0f35471c9fb3015d812c51cda95e33 (diff)
downloadlinux-2.4-a337045e6d985d090b516fdf51065e08aa4bd1dc.tar.gz
proc: avoid information leaks to non-privileged processes
(backported from 2.6 commit f83ce3e6b02d5e48b3a43b001390e2b58820389d) 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@kernel.org> Signed-off-by: Jake Edge <jake@lwn.net> Acked-by: Arjan van de Ven <arjan@linux.intel.com> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> [wt: 2.4 has no wchan file and no aslr, still we don't want to leak these potentially sensible information] Signed-off-by: Willy Tarreau <w@1wt.eu>
-rw-r--r--fs/proc/array.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 214e2327837f5f..335226246dcafa 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -303,18 +303,23 @@ int proc_pid_status(struct task_struct *task, char * buffer)
int proc_pid_stat(struct task_struct *task, char * buffer)
{
- unsigned long vsize, eip, esp, wchan;
+ unsigned long vsize, eip, esp, wchan = ~0UL;
long priority, nice;
int tty_pgrp = -1, tty_nr = 0;
sigset_t sigign, sigcatch;
char state;
int res;
pid_t ppid;
+ int permitted;
struct mm_struct *mm;
char tcomm[sizeof(task->comm)];
state = *get_task_state(task);
vsize = eip = esp = 0;
+ permitted = capable(CAP_SYS_PTRACE) ||
+ (current->uid == task->euid && current->uid == task->suid &&
+ current->uid == task->uid && current->gid == task->egid &&
+ current->gid == task->sgid && current->gid == task->gid);
task_lock(task);
mm = task->mm;
if(mm)
@@ -332,14 +337,17 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
vsize += vma->vm_end - vma->vm_start;
vma = vma->vm_next;
}
- eip = KSTK_EIP(task);
- esp = KSTK_ESP(task);
+ if (permitted) {
+ eip = KSTK_EIP(task);
+ esp = KSTK_ESP(task);
+ }
up_read(&mm->mmap_sem);
}
get_task_comm(tcomm, task);
- wchan = get_wchan(task);
+ if (permitted)
+ wchan = get_wchan(task);
collect_sigign_sigcatch(task, &sigign, &sigcatch);
@@ -382,7 +390,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
task->rlim[RLIMIT_RSS].rlim_cur,
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.