[kernel] r16690 - in dists/sid/linux-2.6/debian: . patches/bugfix/all patches/series

Ben Hutchings benh at alioth.debian.org
Fri Dec 10 04:17:20 UTC 2010


Author: benh
Date: Fri Dec 10 04:17:15 2010
New Revision: 16690

Log:
Add 2 security patches already queued for lenny-security

Added:
   dists/sid/linux-2.6/debian/patches/bugfix/all/filter-make-sure-filters-dont-read-uninitialized-mem.patch
   dists/sid/linux-2.6/debian/patches/bugfix/all/posix-cpu-timers-workaround-to-suppress-the-problems-with-mt-exec.patch
Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/series/29

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	Fri Dec 10 03:19:38 2010	(r16689)
+++ dists/sid/linux-2.6/debian/changelog	Fri Dec 10 04:17:15 2010	(r16690)
@@ -59,6 +59,9 @@
     - ivtvfb: prevent reading uninitialized stack memory (CVE-2010-4079)
     - net/sched: fix some kernel information leaks
   * TTY: Fix error return from tty_ldisc_open() (regression in 2.6.32.27)
+  * filter: make sure filters dont read uninitialized memory (CVE-2010-4158)
+  * posix-cpu-timers: workaround to suppress the problems with mt exec
+    (CVE-2010-4248)
 
   [ Ian Campbell ]
   * xen: disable ACPI NUMA for PV guests and allow IRQ desc allocation on any

Added: dists/sid/linux-2.6/debian/patches/bugfix/all/filter-make-sure-filters-dont-read-uninitialized-mem.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/filter-make-sure-filters-dont-read-uninitialized-mem.patch	Fri Dec 10 04:17:15 2010	(r16690)
@@ -0,0 +1,231 @@
+From: David S. Miller <davem at davemloft.net>
+Date: Wed, 10 Nov 2010 10:38:24 -0800
+Subject: [PATCH] filter: make sure filters dont read uninitialized memory
+
+commit 57fe93b374a6b8711995c2d466c502af9f3a08bb upstream.
+
+There is a possibility malicious users can get limited information about
+uninitialized stack mem array. Even if sk_run_filter() result is bound
+to packet length (0 .. 65535), we could imagine this can be used by
+hostile user.
+
+Initializing mem[] array, like Dan Rosenberg suggested in his patch is
+expensive since most filters dont even use this array.
+
+Its hard to make the filter validation in sk_chk_filter(), because of
+the jumps. This might be done later.
+
+In this patch, I use a bitmap (a single long var) so that only filters
+using mem[] loads/stores pay the price of added security checks.
+
+For other filters, additional cost is a single instruction.
+
+[ Since we access fentry->k a lot now, cache it in a local variable
+  and mark filter entry pointer as const. -DaveM ]
+
+Reported-by: Dan Rosenberg <drosenberg at vsecurity.com>
+Signed-off-by: Eric Dumazet <eric.dumazet at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+[Backported by dann frazier <dannf at debian.org>]
+---
+diff --git a/net/core/filter.c b/net/core/filter.c
+index df37443..506a7d1 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -111,39 +111,41 @@ EXPORT_SYMBOL(sk_filter);
+  */
+ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
+ {
+-	struct sock_filter *fentry;	/* We walk down these */
+ 	void *ptr;
+ 	u32 A = 0;			/* Accumulator */
+ 	u32 X = 0;			/* Index Register */
+ 	u32 mem[BPF_MEMWORDS];		/* Scratch Memory Store */
++	unsigned long memvalid = 0;
+ 	u32 tmp;
+ 	int k;
+ 	int pc;
+ 
++	BUILD_BUG_ON(BPF_MEMWORDS > BITS_PER_LONG);
+ 	/*
+ 	 * Process array of filter instructions.
+ 	 */
+ 	for (pc = 0; pc < flen; pc++) {
+-		fentry = &filter[pc];
++		const struct sock_filter *fentry = &filter[pc];
++		u32 f_k = fentry->k;
+ 
+ 		switch (fentry->code) {
+ 		case BPF_ALU|BPF_ADD|BPF_X:
+ 			A += X;
+ 			continue;
+ 		case BPF_ALU|BPF_ADD|BPF_K:
+-			A += fentry->k;
++			A += f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_SUB|BPF_X:
+ 			A -= X;
+ 			continue;
+ 		case BPF_ALU|BPF_SUB|BPF_K:
+-			A -= fentry->k;
++			A -= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_MUL|BPF_X:
+ 			A *= X;
+ 			continue;
+ 		case BPF_ALU|BPF_MUL|BPF_K:
+-			A *= fentry->k;
++			A *= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_DIV|BPF_X:
+ 			if (X == 0)
+@@ -151,49 +153,49 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
+ 			A /= X;
+ 			continue;
+ 		case BPF_ALU|BPF_DIV|BPF_K:
+-			A /= fentry->k;
++			A /= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_AND|BPF_X:
+ 			A &= X;
+ 			continue;
+ 		case BPF_ALU|BPF_AND|BPF_K:
+-			A &= fentry->k;
++			A &= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_OR|BPF_X:
+ 			A |= X;
+ 			continue;
+ 		case BPF_ALU|BPF_OR|BPF_K:
+-			A |= fentry->k;
++			A |= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_LSH|BPF_X:
+ 			A <<= X;
+ 			continue;
+ 		case BPF_ALU|BPF_LSH|BPF_K:
+-			A <<= fentry->k;
++			A <<= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_RSH|BPF_X:
+ 			A >>= X;
+ 			continue;
+ 		case BPF_ALU|BPF_RSH|BPF_K:
+-			A >>= fentry->k;
++			A >>= f_k;
+ 			continue;
+ 		case BPF_ALU|BPF_NEG:
+ 			A = -A;
+ 			continue;
+ 		case BPF_JMP|BPF_JA:
+-			pc += fentry->k;
++			pc += f_k;
+ 			continue;
+ 		case BPF_JMP|BPF_JGT|BPF_K:
+-			pc += (A > fentry->k) ? fentry->jt : fentry->jf;
++			pc += (A > f_k) ? fentry->jt : fentry->jf;
+ 			continue;
+ 		case BPF_JMP|BPF_JGE|BPF_K:
+-			pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
++			pc += (A >= f_k) ? fentry->jt : fentry->jf;
+ 			continue;
+ 		case BPF_JMP|BPF_JEQ|BPF_K:
+-			pc += (A == fentry->k) ? fentry->jt : fentry->jf;
++			pc += (A == f_k) ? fentry->jt : fentry->jf;
+ 			continue;
+ 		case BPF_JMP|BPF_JSET|BPF_K:
+-			pc += (A & fentry->k) ? fentry->jt : fentry->jf;
++			pc += (A & f_k) ? fentry->jt : fentry->jf;
+ 			continue;
+ 		case BPF_JMP|BPF_JGT|BPF_X:
+ 			pc += (A > X) ? fentry->jt : fentry->jf;
+@@ -208,7 +210,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
+ 			pc += (A & X) ? fentry->jt : fentry->jf;
+ 			continue;
+ 		case BPF_LD|BPF_W|BPF_ABS:
+-			k = fentry->k;
++			k = f_k;
+ load_w:
+ 			ptr = load_pointer(skb, k, 4, &tmp);
+ 			if (ptr != NULL) {
+@@ -217,7 +219,7 @@ load_w:
+ 			}
+ 			break;
+ 		case BPF_LD|BPF_H|BPF_ABS:
+-			k = fentry->k;
++			k = f_k;
+ load_h:
+ 			ptr = load_pointer(skb, k, 2, &tmp);
+ 			if (ptr != NULL) {
+@@ -226,7 +228,7 @@ load_h:
+ 			}
+ 			break;
+ 		case BPF_LD|BPF_B|BPF_ABS:
+-			k = fentry->k;
++			k = f_k;
+ load_b:
+ 			ptr = load_pointer(skb, k, 1, &tmp);
+ 			if (ptr != NULL) {
+@@ -241,32 +243,34 @@ load_b:
+ 			X = skb->len;
+ 			continue;
+ 		case BPF_LD|BPF_W|BPF_IND:
+-			k = X + fentry->k;
++			k = X + f_k;
+ 			goto load_w;
+ 		case BPF_LD|BPF_H|BPF_IND:
+-			k = X + fentry->k;
++			k = X + f_k;
+ 			goto load_h;
+ 		case BPF_LD|BPF_B|BPF_IND:
+-			k = X + fentry->k;
++			k = X + f_k;
+ 			goto load_b;
+ 		case BPF_LDX|BPF_B|BPF_MSH:
+-			ptr = load_pointer(skb, fentry->k, 1, &tmp);
++			ptr = load_pointer(skb, f_k, 1, &tmp);
+ 			if (ptr != NULL) {
+ 				X = (*(u8 *)ptr & 0xf) << 2;
+ 				continue;
+ 			}
+ 			return 0;
+ 		case BPF_LD|BPF_IMM:
+-			A = fentry->k;
++			A = f_k;
+ 			continue;
+ 		case BPF_LDX|BPF_IMM:
+-			X = fentry->k;
++			X = f_k;
+ 			continue;
+ 		case BPF_LD|BPF_MEM:
+-			A = mem[fentry->k];
++			A = (memvalid & (1UL << f_k)) ?
++				mem[f_k] : 0;
+ 			continue;
+ 		case BPF_LDX|BPF_MEM:
+-			X = mem[fentry->k];
++			X = (memvalid & (1UL << f_k)) ?
++				mem[f_k] : 0;
+ 			continue;
+ 		case BPF_MISC|BPF_TAX:
+ 			X = A;
+@@ -275,14 +279,16 @@ load_b:
+ 			A = X;
+ 			continue;
+ 		case BPF_RET|BPF_K:
+-			return fentry->k;
++			return f_k;
+ 		case BPF_RET|BPF_A:
+ 			return A;
+ 		case BPF_ST:
+-			mem[fentry->k] = A;
++			memvalid |= 1UL << f_k;
++			mem[f_k] = A;
+ 			continue;
+ 		case BPF_STX:
+-			mem[fentry->k] = X;
++			memvalid |= 1UL << f_k;
++			mem[f_k] = X;
+ 			continue;
+ 		default:
+ 			WARN_ON(1);

Added: dists/sid/linux-2.6/debian/patches/bugfix/all/posix-cpu-timers-workaround-to-suppress-the-problems-with-mt-exec.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/posix-cpu-timers-workaround-to-suppress-the-problems-with-mt-exec.patch	Fri Dec 10 04:17:15 2010	(r16690)
@@ -0,0 +1,59 @@
+From: Oleg Nesterov <oleg at redhat.com>
+Date: Fri, 5 Nov 2010 16:53:42 +0100
+Subject: [PATCH] posix-cpu-timers: workaround to suppress the problems with mt exec
+
+commit e0a70217107e6f9844628120412cb27bb4cea194 upstream.
+
+posix-cpu-timers.c correctly assumes that the dying process does
+posix_cpu_timers_exit_group() and removes all !CPUCLOCK_PERTHREAD
+timers from signal->cpu_timers list.
+
+But, it also assumes that timer->it.cpu.task is always the group
+leader, and thus the dead ->task means the dead thread group.
+
+This is obviously not true after de_thread() changes the leader.
+After that almost every posix_cpu_timer_ method has problems.
+
+It is not simple to fix this bug correctly. First of all, I think
+that timer->it.cpu should use struct pid instead of task_struct.
+Also, the locking should be reworked completely. In particular,
+tasklist_lock should not be used at all. This all needs a lot of
+nontrivial and hard-to-test changes.
+
+Change __exit_signal() to do posix_cpu_timers_exit_group() when
+the old leader dies during exec. This is not the fix, just the
+temporary hack to hide the problem for 2.6.37 and stable. IOW,
+this is obviously wrong but this is what we currently have anyway:
+cpu timers do not work after mt exec.
+
+In theory this change adds another race. The exiting leader can
+detach the timers which were attached to the new leader. However,
+the window between de_thread() and release_task() is small, we
+can pretend that sys_timer_create() was called before de_thread().
+
+Signed-off-by: Oleg Nesterov <oleg at redhat.com>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+[Backported by dann frazier <dannf at debian.org>]
+---
+ kernel/exit.c |    8 ++++++++
+ 1 files changed, 8 insertions(+), 0 deletions(-)
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 2bd672d..b3b6377 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -93,6 +93,14 @@ static void __exit_signal(struct task_struct *tsk)
+ 		posix_cpu_timers_exit_group(tsk);
+ 	else {
+ 		/*
++		 * This can only happen if the caller is de_thread().
++		 * FIXME: this is the temporary hack, we should teach
++		 * posix-cpu-timers to handle this case correctly.
++		 */
++		if (unlikely(has_group_leader_pid(tsk)))
++			posix_cpu_timers_exit_group(tsk);
++
++		/*
+ 		 * If there is any task waiting for the group exit
+ 		 * then notify it:
+ 		 */

Modified: dists/sid/linux-2.6/debian/patches/series/29
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/29	Fri Dec 10 03:19:38 2010	(r16689)
+++ dists/sid/linux-2.6/debian/patches/series/29	Fri Dec 10 04:17:15 2010	(r16690)
@@ -37,3 +37,5 @@
 + bugfix/all/stable/2.6.32.27.patch
 + debian/block-Avoid-ABI-change-from-fix-to-blk_queue_physica.patch
 + bugfix/all/TTY-Fix-error-return-from-tty_ldisc_open.patch
++ bugfix/all/filter-make-sure-filters-dont-read-uninitialized-mem.patch
++ bugfix/all/posix-cpu-timers-workaround-to-suppress-the-problems-with-mt-exec.patch



More information about the Kernel-svn-changes mailing list