mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	proc: avoid information leaks to non-privileged processes
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>
This commit is contained in:
		
							parent
							
								
									7fdf523067
								
							
						
					
					
						commit
						f83ce3e6b0
					
				
					 2 changed files with 13 additions and 5 deletions
				
			
		| 
						 | 
					@ -80,6 +80,7 @@
 | 
				
			||||||
#include <linux/delayacct.h>
 | 
					#include <linux/delayacct.h>
 | 
				
			||||||
#include <linux/seq_file.h>
 | 
					#include <linux/seq_file.h>
 | 
				
			||||||
#include <linux/pid_namespace.h>
 | 
					#include <linux/pid_namespace.h>
 | 
				
			||||||
 | 
					#include <linux/ptrace.h>
 | 
				
			||||||
#include <linux/tracehook.h>
 | 
					#include <linux/tracehook.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm/pgtable.h>
 | 
					#include <asm/pgtable.h>
 | 
				
			||||||
| 
						 | 
					@ -352,6 +353,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 | 
				
			||||||
	char state;
 | 
						char state;
 | 
				
			||||||
	pid_t ppid = 0, pgid = -1, sid = -1;
 | 
						pid_t ppid = 0, pgid = -1, sid = -1;
 | 
				
			||||||
	int num_threads = 0;
 | 
						int num_threads = 0;
 | 
				
			||||||
 | 
						int permitted;
 | 
				
			||||||
	struct mm_struct *mm;
 | 
						struct mm_struct *mm;
 | 
				
			||||||
	unsigned long long start_time;
 | 
						unsigned long long start_time;
 | 
				
			||||||
	unsigned long cmin_flt = 0, cmaj_flt = 0;
 | 
						unsigned long cmin_flt = 0, cmaj_flt = 0;
 | 
				
			||||||
| 
						 | 
					@ -364,12 +366,15 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state = *get_task_state(task);
 | 
						state = *get_task_state(task);
 | 
				
			||||||
	vsize = eip = esp = 0;
 | 
						vsize = eip = esp = 0;
 | 
				
			||||||
 | 
						permitted = ptrace_may_access(task, PTRACE_MODE_READ);
 | 
				
			||||||
	mm = get_task_mm(task);
 | 
						mm = get_task_mm(task);
 | 
				
			||||||
	if (mm) {
 | 
						if (mm) {
 | 
				
			||||||
		vsize = task_vsize(mm);
 | 
							vsize = task_vsize(mm);
 | 
				
			||||||
 | 
							if (permitted) {
 | 
				
			||||||
			eip = KSTK_EIP(task);
 | 
								eip = KSTK_EIP(task);
 | 
				
			||||||
			esp = KSTK_ESP(task);
 | 
								esp = KSTK_ESP(task);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	get_task_comm(tcomm, task);
 | 
						get_task_comm(tcomm, task);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,7 +429,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 | 
				
			||||||
		unlock_task_sighand(task, &flags);
 | 
							unlock_task_sighand(task, &flags);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!whole || num_threads < 2)
 | 
						if (permitted && (!whole || num_threads < 2))
 | 
				
			||||||
		wchan = get_wchan(task);
 | 
							wchan = get_wchan(task);
 | 
				
			||||||
	if (!whole) {
 | 
						if (!whole) {
 | 
				
			||||||
		min_flt = task->min_flt;
 | 
							min_flt = task->min_flt;
 | 
				
			||||||
| 
						 | 
					@ -476,7 +481,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 | 
				
			||||||
		rsslim,
 | 
							rsslim,
 | 
				
			||||||
		mm ? mm->start_code : 0,
 | 
							mm ? mm->start_code : 0,
 | 
				
			||||||
		mm ? mm->end_code : 0,
 | 
							mm ? mm->end_code : 0,
 | 
				
			||||||
		mm ? mm->start_stack : 0,
 | 
							(permitted && mm) ? mm->start_stack : 0,
 | 
				
			||||||
		esp,
 | 
							esp,
 | 
				
			||||||
		eip,
 | 
							eip,
 | 
				
			||||||
		/* The signal information here is obsolete.
 | 
							/* The signal information here is obsolete.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -322,6 +322,9 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
 | 
				
			||||||
	wchan = get_wchan(task);
 | 
						wchan = get_wchan(task);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (lookup_symbol_name(wchan, symname) < 0)
 | 
						if (lookup_symbol_name(wchan, symname) < 0)
 | 
				
			||||||
 | 
							if (!ptrace_may_access(task, PTRACE_MODE_READ))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
			return sprintf(buffer, "%lu", wchan);
 | 
								return sprintf(buffer, "%lu", wchan);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return sprintf(buffer, "%s", symname);
 | 
							return sprintf(buffer, "%s", symname);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue