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

Dann Frazier dannf at alioth.debian.org
Fri Apr 30 06:41:01 UTC 2010


Author: dannf
Date: Fri Apr 30 06:40:47 2010
New Revision: 15590

Log:
tipc: Fix oops on send prior to entering networked mode (CVE-2010-1187)

Added:
   dists/sid/linux-2.6/debian/patches/bugfix/all/tipc-fix-oops-on-send-prior-to-entering-networked-mode.patch
Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/series/12

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	Fri Apr 30 06:34:55 2010	(r15589)
+++ dists/sid/linux-2.6/debian/changelog	Fri Apr 30 06:40:47 2010	(r15590)
@@ -65,6 +65,7 @@
   * sctp: Fix skb_over_panic resulting from multiple invalid parameter
     errors (CVE-2010-1173)
   * [CIFS] Allow null nd (as nfs server uses) on create (CVE-2010-1148)
+  * tipc: Fix oops on send prior to entering networked mode (CVE-2010-1187)
 
   [ Aurelien Jarno ]
   * [sh4] Add a sh7751r flavour.

Added: dists/sid/linux-2.6/debian/patches/bugfix/all/tipc-fix-oops-on-send-prior-to-entering-networked-mode.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/tipc-fix-oops-on-send-prior-to-entering-networked-mode.patch	Fri Apr 30 06:40:47 2010	(r15590)
@@ -0,0 +1,209 @@
+commit d0021b252eaf65ca07ed14f0d66425dd9ccab9a6
+Author: Neil Horman <nhorman at tuxdriver.com>
+Date:   Wed Mar 3 08:31:23 2010 +0000
+
+    tipc: Fix oops on send prior to entering networked mode (v3)
+    
+    Fix TIPC to disallow sending to remote addresses prior to entering NET_MODE
+    
+    user programs can oops the kernel by sending datagrams via AF_TIPC prior to
+    entering networked mode.  The following backtrace has been observed:
+    
+    ID: 13459  TASK: ffff810014640040  CPU: 0   COMMAND: "tipc-client"
+    [exception RIP: tipc_node_select_next_hop+90]
+    RIP: ffffffff8869d3c3  RSP: ffff81002d9a5ab8  RFLAGS: 00010202
+    RAX: 0000000000000001  RBX: 0000000000000001  RCX: 0000000000000001
+    RDX: 0000000000000000  RSI: 0000000000000001  RDI: 0000000001001001
+    RBP: 0000000001001001   R8: 0074736575716552   R9: 0000000000000000
+    R10: ffff81003fbd0680  R11: 00000000000000c8  R12: 0000000000000008
+    R13: 0000000000000001  R14: 0000000000000001  R15: ffff810015c6ca00
+    ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0018
+    RIP: 0000003cbd8d49a3  RSP: 00007fffc84e0be8  RFLAGS: 00010206
+    RAX: 000000000000002c  RBX: ffffffff8005d116  RCX: 0000000000000000
+    RDX: 0000000000000008  RSI: 00007fffc84e0c00  RDI: 0000000000000003
+    RBP: 0000000000000000   R8: 00007fffc84e0c10   R9: 0000000000000010
+    R10: 0000000000000000  R11: 0000000000000246  R12: 0000000000000000
+    R13: 00007fffc84e0d10  R14: 0000000000000000  R15: 00007fffc84e0c30
+    ORIG_RAX: 000000000000002c  CS: 0033  SS: 002b
+    
+    What happens is that, when the tipc module in inserted it enters a standalone
+    node mode in which communication to its own address is allowed <0.0.0> but not
+    to other addresses, since the appropriate data structures have not been
+    allocated yet (specifically the tipc_net pointer).  There is nothing stopping a
+    client from trying to send such a message however, and if that happens, we
+    attempt to dereference tipc_net.zones while the pointer is still NULL, and
+    explode.  The fix is pretty straightforward.  Since these oopses all arise from
+    the dereference of global pointers prior to their assignment to allocated
+    values, and since these allocations are small (about 2k total), lets convert
+    these pointers to static arrays of the appropriate size.  All the accesses to
+    these bits consider 0/NULL to be a non match when searching, so all the lookups
+    still work properly, and there is no longer a chance of a bad dererence
+    anywhere.  As a bonus, this lets us eliminate the setup/teardown routines for
+    those pointers, and elimnates the need to preform any locking around them to
+    prevent access while their being allocated/freed.
+    
+    I've updated the tipc_net structure to behave this way to fix the exact reported
+    problem, and also fixed up the tipc_bearers and media_list arrays to fix an
+    obvious simmilar problem that arises from issuing tipc-config commands to
+    manipulate bearers/links prior to entering networked mode
+    
+    I've tested this for a few hours by running the sanity tests and stress test
+    with the tipcutils suite, and nothing has fallen over.  There have been a few
+    lockdep warnings, but those were there before, and can be addressed later, as
+    they didn't actually result in any deadlock.
+    
+    Signed-off-by: Neil Horman <nhorman at tuxdriver.com>
+    CC: Allan Stephens <allan.stephens at windriver.com>
+    CC: David S. Miller <davem at davemloft.net>
+    CC: tipc-discussion at lists.sourceforge.net
+    
+     bearer.c |   37 ++++++-------------------------------
+     bearer.h |    2 +-
+     net.c    |   25 ++++---------------------
+     3 files changed, 11 insertions(+), 53 deletions(-)
+    Signed-off-by: David S. Miller <davem at davemloft.net>
+
+diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
+index 327011f..7809137 100644
+--- a/net/tipc/bearer.c
++++ b/net/tipc/bearer.c
+@@ -45,10 +45,10 @@
+ 
+ #define MAX_ADDR_STR 32
+ 
+-static struct media *media_list = NULL;
++static struct media media_list[MAX_MEDIA];
+ static u32 media_count = 0;
+ 
+-struct bearer *tipc_bearers = NULL;
++struct bearer tipc_bearers[MAX_BEARERS];
+ 
+ /**
+  * media_name_valid - validate media name
+@@ -108,9 +108,11 @@ int  tipc_register_media(u32 media_type,
+ 	int res = -EINVAL;
+ 
+ 	write_lock_bh(&tipc_net_lock);
+-	if (!media_list)
+-		goto exit;
+ 
++	if (tipc_mode != TIPC_NET_MODE) {
++		warn("Media <%s> rejected, not in networked mode yet\n", name);
++		goto exit;
++	}
+ 	if (!media_name_valid(name)) {
+ 		warn("Media <%s> rejected, illegal name\n", name);
+ 		goto exit;
+@@ -660,33 +662,10 @@ int tipc_disable_bearer(const char *name)
+ 
+ 
+ 
+-int tipc_bearer_init(void)
+-{
+-	int res;
+-
+-	write_lock_bh(&tipc_net_lock);
+-	tipc_bearers = kcalloc(MAX_BEARERS, sizeof(struct bearer), GFP_ATOMIC);
+-	media_list = kcalloc(MAX_MEDIA, sizeof(struct media), GFP_ATOMIC);
+-	if (tipc_bearers && media_list) {
+-		res = 0;
+-	} else {
+-		kfree(tipc_bearers);
+-		kfree(media_list);
+-		tipc_bearers = NULL;
+-		media_list = NULL;
+-		res = -ENOMEM;
+-	}
+-	write_unlock_bh(&tipc_net_lock);
+-	return res;
+-}
+-
+ void tipc_bearer_stop(void)
+ {
+ 	u32 i;
+ 
+-	if (!tipc_bearers)
+-		return;
+-
+ 	for (i = 0; i < MAX_BEARERS; i++) {
+ 		if (tipc_bearers[i].active)
+ 			tipc_bearers[i].publ.blocked = 1;
+@@ -695,10 +674,6 @@ void tipc_bearer_stop(void)
+ 		if (tipc_bearers[i].active)
+ 			bearer_disable(tipc_bearers[i].publ.name);
+ 	}
+-	kfree(tipc_bearers);
+-	kfree(media_list);
+-	tipc_bearers = NULL;
+-	media_list = NULL;
+ 	media_count = 0;
+ }
+ 
+diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
+index ca57348..000228e 100644
+--- a/net/tipc/bearer.h
++++ b/net/tipc/bearer.h
+@@ -114,7 +114,7 @@ struct bearer_name {
+ 
+ struct link;
+ 
+-extern struct bearer *tipc_bearers;
++extern struct bearer tipc_bearers[];
+ 
+ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
+ struct sk_buff *tipc_media_get_names(void);
+diff --git a/net/tipc/net.c b/net/tipc/net.c
+index 7906608..f25b1cd 100644
+--- a/net/tipc/net.c
++++ b/net/tipc/net.c
+@@ -116,7 +116,8 @@
+ */
+ 
+ DEFINE_RWLOCK(tipc_net_lock);
+-struct network tipc_net = { NULL };
++struct _zone *tipc_zones[256] = { NULL, };
++struct network tipc_net = { tipc_zones };
+ 
+ struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref)
+ {
+@@ -158,28 +159,12 @@ void tipc_net_send_external_routes(u32 dest)
+ 	}
+ }
+ 
+-static int net_init(void)
+-{
+-	memset(&tipc_net, 0, sizeof(tipc_net));
+-	tipc_net.zones = kcalloc(tipc_max_zones + 1, sizeof(struct _zone *), GFP_ATOMIC);
+-	if (!tipc_net.zones) {
+-		return -ENOMEM;
+-	}
+-	return 0;
+-}
+-
+ static void net_stop(void)
+ {
+ 	u32 z_num;
+ 
+-	if (!tipc_net.zones)
+-		return;
+-
+-	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
++	for (z_num = 1; z_num <= tipc_max_zones; z_num++)
+ 		tipc_zone_delete(tipc_net.zones[z_num]);
+-	}
+-	kfree(tipc_net.zones);
+-	tipc_net.zones = NULL;
+ }
+ 
+ static void net_route_named_msg(struct sk_buff *buf)
+@@ -282,9 +267,7 @@ int tipc_net_start(u32 addr)
+ 	tipc_named_reinit();
+ 	tipc_port_reinit();
+ 
+-	if ((res = tipc_bearer_init()) ||
+-	    (res = net_init()) ||
+-	    (res = tipc_cltr_init()) ||
++	if ((res = tipc_cltr_init()) ||
+ 	    (res = tipc_bclink_init())) {
+ 		return res;
+ 	}

Modified: dists/sid/linux-2.6/debian/patches/series/12
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/12	Fri Apr 30 06:34:55 2010	(r15589)
+++ dists/sid/linux-2.6/debian/patches/series/12	Fri Apr 30 06:40:47 2010	(r15590)
@@ -61,3 +61,4 @@
 + bugfix/all/virtio_net-Make-delayed-refill-more-reliable.patch
 + bugfix/all/sctp-fix-skb_over_panic-resulting-from-multiple-invalid-parameter-errors.patch
 + bugfix/all/cifs-allow-null-nd-on-create.patch
++ bugfix/all/tipc-fix-oops-on-send-prior-to-entering-networked-mode.patch



More information about the Kernel-svn-changes mailing list