diff options
author | Jake Edge <jake@lwn.net> | 2009-05-04 12:51:14 -0600 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2009-09-13 10:46:56 +0200 |
commit | a337045e6d985d090b516fdf51065e08aa4bd1dc (patch) | |
tree | 478268366cd287b4fbe87a333e6adbbd198dad91 | |
parent | 3222e4523e0f35471c9fb3015d812c51cda95e33 (diff) | |
download | linux-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.c | 18 |
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. |