[kernel] r17998 - in dists/squeeze-security/linux-2.6/debian: . patches/bugfix/all patches/features/all/vserver patches/series

Dann Frazier dannf at alioth.debian.org
Thu Aug 25 01:39:56 UTC 2011


Author: dannf
Date: Thu Aug 25 01:39:55 2011
New Revision: 17998

Log:
restrict access to /proc/pid/* after setuid exec (CVE-2011-1020)

Added:
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/auxv-require-the-target-or-self-to-be-traceable.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/close-race-in-proc-pid-environ.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/pagemap-close-races-with-suid-execve.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/proc-map-report-errors-sanely.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/proc-syscall-stack-personality-races.patch
Modified:
   dists/squeeze-security/linux-2.6/debian/changelog
   dists/squeeze-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.36.29.6.patch
   dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze1

Modified: dists/squeeze-security/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/changelog	Thu Aug 25 01:00:52 2011	(r17997)
+++ dists/squeeze-security/linux-2.6/debian/changelog	Thu Aug 25 01:39:55 2011	(r17998)
@@ -13,6 +13,7 @@
   * net_sched: Fix qdisc_notify() (CVE-2011-2525)
   * gro: Only reset frag0 when skb can be pulled (CVE-2011-2723)
   * comedi: fix infoleak to userspace (CVE-2011-2909)
+  * restrict access to /proc/pid/* after setuid exec (CVE-2011-1020)
 
   [ Moritz Muehlenhoff ]
   * si4713-i2c: avoid potential buffer overflow on si4713 (CVE-2011-2700)

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/auxv-require-the-target-or-self-to-be-traceable.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/auxv-require-the-target-or-self-to-be-traceable.patch	Thu Aug 25 01:39:55 2011	(r17998)
@@ -0,0 +1,28 @@
+commit 2fadaef41283aad7100fa73f01998cddaca25833
+Author: Al Viro <viro at zeniv.linux.org.uk>
+Date:   Tue Feb 15 22:52:11 2011 -0500
+
+    auxv: require the target to be tracable (or yourself)
+    
+    same as for environ, except that we didn't do any checks to
+    prevent access after suid execve
+    
+    Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index fc471b8..e94b58b 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -281,9 +281,9 @@ out:
+ 
+ static int proc_pid_auxv(struct task_struct *task, char *buffer)
+ {
+-	int res = 0;
+-	struct mm_struct *mm = get_task_mm(task);
+-	if (mm) {
++	struct mm_struct *mm = mm_for_maps(task);
++	int res = PTR_ERR(mm);
++	if (mm && !IS_ERR(mm)) {
+ 		unsigned int nwords = 0;
+ 		do {
+ 			nwords += 2;

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/close-race-in-proc-pid-environ.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/close-race-in-proc-pid-environ.patch	Thu Aug 25 01:39:55 2011	(r17998)
@@ -0,0 +1,40 @@
+commit d6f64b89d7ff22ce05896ab4a93a653e8d0b123d
+Author: Al Viro <viro at zeniv.linux.org.uk>
+Date:   Tue Feb 15 22:26:01 2011 -0500
+
+    close race in /proc/*/environ
+    
+    Switch to mm_for_maps().  Maybe we ought to make it r--r--r--,
+    since we do checks on IO anyway...
+    
+    Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index c282811..fc471b8 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -919,20 +919,18 @@ static ssize_t environ_read(struct file *file, char __user *buf,
+ 	if (!task)
+ 		goto out_no_task;
+ 
+-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+-		goto out;
+-
+ 	ret = -ENOMEM;
+ 	page = (char *)__get_free_page(GFP_TEMPORARY);
+ 	if (!page)
+ 		goto out;
+ 
+-	ret = 0;
+ 
+-	mm = get_task_mm(task);
+-	if (!mm)
++	mm = mm_for_maps(task);
++	ret = PTR_ERR(mm);
++	if (!mm || IS_ERR(mm))
+ 		goto out_free;
+ 
++	ret = 0;
+ 	while (count > 0) {
+ 		int this_len, retval, max_len;
+ 

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/pagemap-close-races-with-suid-execve.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/pagemap-close-races-with-suid-execve.patch	Thu Aug 25 01:39:55 2011	(r17998)
@@ -0,0 +1,58 @@
+commit ca6b0bf0e086513b9ee5efc0aa5770ecb57778af
+Author: Al Viro <viro at zeniv.linux.org.uk>
+Date:   Tue Feb 15 22:04:37 2011 -0500
+
+    pagemap: close races with suid execve
+    
+    just use mm_for_maps()
+    
+    Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+    [dannf: backported to Debian's 2.6.32]
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index ae485ab..aca5390 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -2552,7 +2552,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ 	REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
+ 	REG("smaps",      S_IRUGO, proc_smaps_operations),
+-	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
++	REG("pagemap",    S_IRUGO, proc_pagemap_operations),
+ #endif
+ #ifdef CONFIG_SECURITY
+ 	DIR("attr",       S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
+@@ -2890,7 +2890,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ 	REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
+ 	REG("smaps",     S_IRUGO, proc_smaps_operations),
+-	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
++	REG("pagemap",    S_IRUGO, proc_pagemap_operations),
+ #endif
+ #ifdef CONFIG_SECURITY
+ 	DIR("attr",      S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 3b7b82a..6e7b065 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -682,7 +682,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ 		goto out;
+ 
+ 	ret = -EACCES;
+-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
++	mm = mm_for_maps(task);
++	if (!mm)
+ 		goto out_task;
+ 
+ 	ret = -EINVAL;
+@@ -695,10 +696,6 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ 	if (!count)
+ 		goto out_task;
+ 
+-	mm = get_task_mm(task);
+-	if (!mm)
+-		goto out_task;
+-
+ 
+ 	uaddr = (unsigned long)buf & PAGE_MASK;
+ 	uend = (unsigned long)(buf + count);

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/proc-map-report-errors-sanely.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/proc-map-report-errors-sanely.patch	Thu Aug 25 01:39:55 2011	(r17998)
@@ -0,0 +1,86 @@
+commit ec6fd8a4355cda81cd9f06bebc048e83eb514ac7
+Author: Al Viro <viro at zeniv.linux.org.uk>
+Date:   Tue Feb 15 22:22:54 2011 -0500
+
+    report errors in /proc/*/*map* sanely
+    
+    Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+    [dannf: backported to Debian's 2.6.32]
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index aca5390..b7567b2 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -235,15 +235,17 @@ static int check_mem_permission(struct task_struct *task)
+ struct mm_struct *mm_for_maps(struct task_struct *task)
+ {
+ 	struct mm_struct *mm;
++	int err;
+ 
+-	if (mutex_lock_killable(&task->cred_guard_mutex))
+-		return NULL;
++	err = mutex_lock_killable(&task->cred_guard_mutex);
++	if (err)
++		return ERR_PTR(err);
+ 
+ 	mm = get_task_mm(task);
+ 	if (mm && mm != current->mm &&
+ 			!ptrace_may_access(task, PTRACE_MODE_READ)) {
+ 		mmput(mm);
+-		mm = NULL;
++		mm = ERR_PTR(-EACCESS);
+ 	}
+ 	mutex_unlock(&task->cred_guard_mutex);
+ 
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 6e7b065..e62af9b 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -114,11 +114,11 @@ static void *m_start(struct seq_file *m, loff_t *pos)
+ 
+ 	priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+ 	if (!priv->task)
+-		return NULL;
++		return ERR_PTR(-ESRCH);
+ 
+ 	mm = mm_for_maps(priv->task);
+-	if (!mm)
+-		return NULL;
++	if (!mm || IS_ERR(mm))
++		return mm;
+ 	down_read(&mm->mmap_sem);
+ 
+ 	tail_vma = get_gate_vma(priv->task);
+@@ -681,9 +681,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ 	if (!task)
+ 		goto out;
+ 
+-	ret = -EACCES;
+ 	mm = mm_for_maps(task);
+-	if (!mm)
++	ret = PTR_ERR(mm);
++	if (!mm || IS_ERR(mm))
+ 		goto out_task;
+ 
+ 	ret = -EINVAL;
+diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
+index 8f5c05d..522c1e1 100644
+--- a/fs/proc/task_nommu.c
++++ b/fs/proc/task_nommu.c
+@@ -181,13 +181,13 @@ static void *m_start(struct seq_file *m, loff_t *pos)
+ 	/* pin the task and mm whilst we play with them */
+ 	priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+ 	if (!priv->task)
+-		return NULL;
++		return ERR_PTR(-ESRCH);
+ 
+ 	mm = mm_for_maps(priv->task);
+-	if (!mm) {
++	if (!mm || IS_ERR(mm)) {
+ 		put_task_struct(priv->task);
+ 		priv->task = NULL;
+-		return NULL;
++		return mm;
+ 	}
+ 	down_read(&mm->mmap_sem);
+ 

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/proc-syscall-stack-personality-races.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/all/proc-syscall-stack-personality-races.patch	Thu Aug 25 01:39:55 2011	(r17998)
@@ -0,0 +1,172 @@
+commit a9712bc12c40c172e393f85a9b2ba8db4bf59509
+Author: Al Viro <viro at zeniv.linux.org.uk>
+Date:   Wed Mar 23 15:52:50 2011 -0400
+
+    deal with races in /proc/*/{syscall,stack,personality}
+    
+    All of those are rw-r--r-- and all are broken for suid - if you open
+    a file before the target does suid-root exec, you'll be still able
+    to access it.  For personality it's not a big deal, but for syscall
+    and stack it's a real problem.
+    
+    Fix: check that task is tracable for you at the time of read().
+    
+    Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+    [dannf: backported to Debian's 2.6.32]
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 1be8cb2..8dad8fd 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -330,6 +330,23 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
+ }
+ #endif /* CONFIG_KALLSYMS */
+ 
++static int lock_trace(struct task_struct *task)
++{
++	int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
++	if (err)
++		return err;
++	if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
++		mutex_unlock(&task->signal->cred_guard_mutex);
++		return -EPERM;
++	}
++	return 0;
++}
++
++static void unlock_trace(struct task_struct *task)
++{
++	mutex_unlock(&task->signal->cred_guard_mutex);
++}
++
+ #ifdef CONFIG_STACKTRACE
+ 
+ #define MAX_STACK_TRACE_DEPTH	64
+@@ -339,6 +356,7 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
+ {
+ 	struct stack_trace trace;
+ 	unsigned long *entries;
++	int err;
+ 	int i;
+ 
+ 	entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
+@@ -349,15 +367,20 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
+ 	trace.max_entries	= MAX_STACK_TRACE_DEPTH;
+ 	trace.entries		= entries;
+ 	trace.skip		= 0;
+-	save_stack_trace_tsk(task, &trace);
+ 
+-	for (i = 0; i < trace.nr_entries; i++) {
+-		seq_printf(m, "[<%p>] %pS\n",
+-			   (void *)entries[i], (void *)entries[i]);
++	err = lock_trace(task);
++	if (!err) {
++		save_stack_trace_tsk(task, &trace);
++
++		for (i = 0; i < trace.nr_entries; i++) {
++			seq_printf(m, "[<%p>] %pS\n",
++				   (void *)entries[i], (void *)entries[i]);
++		}
++		unlock_trace(task);
+ 	}
+ 	kfree(entries);
+ 
+-	return 0;
++	return err;
+ }
+ #endif
+ 
+@@ -529,18 +552,22 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer)
+ {
+ 	long nr;
+ 	unsigned long args[6], sp, pc;
++	int res = lock_trace(task);
++	if (res)
++		return res;
+ 
+ 	if (task_current_syscall(task, &nr, args, 6, &sp, &pc))
+-		return sprintf(buffer, "running\n");
+-
+-	if (nr < 0)
+-		return sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc);
+-
+-	return sprintf(buffer,
++		res = sprintf(buffer, "running\n");
++	else if (nr < 0)
++		res = sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc);
++	else
++		res = sprintf(buffer,
+ 		       "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ 		       nr,
+ 		       args[0], args[1], args[2], args[3], args[4], args[5],
+ 		       sp, pc);
++	unlock_trace(task);
++	return res;
+ }
+ #endif /* CONFIG_HAVE_ARCH_TRACEHOOK */
+ 
+@@ -2507,8 +2534,12 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer)
+ static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns,
+ 				struct pid *pid, struct task_struct *task)
+ {
+-	seq_printf(m, "%08x\n", task->personality);
+-	return 0;
++	int err = lock_trace(task);
++	if (!err) {
++		seq_printf(m, "%08x\n", task->personality);
++		unlock_trace(task);
++	}
++	return err;
+ }
+ 
+ /*
+@@ -2527,13 +2558,13 @@ static const struct pid_entry tgid_base_stuff[] = {
+ 	REG("environ",    S_IRUSR, proc_environ_operations),
+ 	INF("auxv",       S_IRUSR, proc_pid_auxv),
+ 	ONE("status",     S_IRUGO, proc_pid_status),
+-	ONE("personality", S_IRUSR, proc_pid_personality),
++	ONE("personality", S_IRUGO, proc_pid_personality),
+ 	INF("limits",	  S_IRUSR, proc_pid_limits),
+ #ifdef CONFIG_SCHED_DEBUG
+ 	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
+ #endif
+ #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+-	INF("syscall",    S_IRUSR, proc_pid_syscall),
++	INF("syscall",    S_IRUGO, proc_pid_syscall),
+ #endif
+ 	INF("cmdline",    S_IRUGO, proc_pid_cmdline),
+ 	ONE("stat",       S_IRUGO, proc_tgid_stat),
+@@ -2561,7 +2592,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ 	INF("wchan",      S_IRUGO, proc_pid_wchan),
+ #endif
+ #ifdef CONFIG_STACKTRACE
+-	ONE("stack",      S_IRUSR, proc_pid_stack),
++	ONE("stack",      S_IRUGO, proc_pid_stack),
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+ 	INF("schedstat",  S_IRUGO, proc_pid_schedstat),
+@@ -2866,13 +2897,13 @@ static const struct pid_entry tid_base_stuff[] = {
+ 	REG("environ",   S_IRUSR, proc_environ_operations),
+ 	INF("auxv",      S_IRUSR, proc_pid_auxv),
+ 	ONE("status",    S_IRUGO, proc_pid_status),
+-	ONE("personality", S_IRUSR, proc_pid_personality),
++	ONE("personality", S_IRUGO, proc_pid_personality),
+ 	INF("limits",	 S_IRUSR, proc_pid_limits),
+ #ifdef CONFIG_SCHED_DEBUG
+ 	REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
+ #endif
+ #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
+-	INF("syscall",   S_IRUSR, proc_pid_syscall),
++	INF("syscall",   S_IRUGO, proc_pid_syscall),
+ #endif
+ 	INF("cmdline",   S_IRUGO, proc_pid_cmdline),
+ 	ONE("stat",      S_IRUGO, proc_tid_stat),
+@@ -2899,7 +2930,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ 	INF("wchan",     S_IRUGO, proc_pid_wchan),
+ #endif
+ #ifdef CONFIG_STACKTRACE
+-	ONE("stack",      S_IRUSR, proc_pid_stack),
++	ONE("stack",      S_IRUGO, proc_pid_stack),
+ #endif
+ #ifdef CONFIG_SCHEDSTATS
+ 	INF("schedstat", S_IRUGO, proc_pid_schedstat),

Modified: dists/squeeze-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.36.29.6.patch
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.36.29.6.patch	Thu Aug 25 01:00:52 2011	(r17997)
+++ dists/squeeze-security/linux-2.6/debian/patches/features/all/vserver/vs2.3.0.36.29.6.patch	Thu Aug 25 01:39:55 2011	(r17998)
@@ -6869,9 +6869,9 @@
  	INF("oom_score",  S_IRUGO, proc_oom_score),
  	REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adjust_operations),
  #ifdef CONFIG_AUDITSYSCALL
-@@ -2577,6 +2598,7 @@ static const struct pid_entry tgid_base_
+@@ -2621,6 +2642,7 @@ static const struct pid_entry tgid_base_
  #ifdef CONFIG_TASK_IO_ACCOUNTING
- 	INF("io",	S_IRUGO, proc_tgid_io_accounting),
+ 	INF("io",	S_IRUSR, proc_tgid_io_accounting),
  #endif
 +	ONE("nsproxy",	S_IRUGO, proc_pid_nsproxy),
  };

Modified: dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze1
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze1	Thu Aug 25 01:00:52 2011	(r17997)
+++ dists/squeeze-security/linux-2.6/debian/patches/series/35squeeze1	Thu Aug 25 01:39:55 2011	(r17998)
@@ -16,3 +16,8 @@
 + bugfix/all/gro-only-reset-frag0-when-skb-can-be-pulled.patch
 + bugfix/all/comedi-fix-infoleak-to-userspace.patch
 + bugfix/all/CVE-2011-3188.patch
++ bugfix/all/pagemap-close-races-with-suid-execve.patch
++ bugfix/all/proc-map-report-errors-sanely.patch
++ bugfix/all/close-race-in-proc-pid-environ.patch
++ bugfix/all/auxv-require-the-target-or-self-to-be-traceable.patch
++ bugfix/all/proc-syscall-stack-personality-races.patch



More information about the Kernel-svn-changes mailing list