From d0021b252eaf65ca07ed14f0d66425dd9ccab9a6 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 3 Mar 2010 08:31:23 +0000 Subject: 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 CC: Allan Stephens CC: David S. Miller CC: tipc-discussion@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 --- net/tipc/net.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'net/tipc/net.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index 7906608bf510..f25b1cdb64eb 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; } -- cgit v1.2.2 From a570f095eac34b7439eed2df6728381708c55bdc Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 24 Mar 2010 07:57:29 +0000 Subject: tipc: remove trailing space in messages Signed-off-by: Frans Pop Cc: Per Liden Cc: Jon Maloy Cc: Allan Stephens Signed-off-by: David S. Miller --- net/tipc/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/tipc/net.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index f25b1cdb64eb..79ce8fa2b77a 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -291,6 +291,6 @@ void tipc_net_stop(void) tipc_bclink_stop(); net_stop(); write_unlock_bh(&tipc_net_lock); - info("Left network mode \n"); + info("Left network mode\n"); } -- cgit v1.2.2 From 8379d07031e59a5d72bc73a6060c4d63aac956ce Mon Sep 17 00:00:00 2001 From: Hagen Paul Pfeifer Date: Tue, 30 Mar 2010 14:24:12 +0000 Subject: tipc: define needless global scoped variable static struct _zone *tipc_zones has local scope level and should defined with the correct scoping. CC: Per Liden Signed-off-by: Hagen Paul Pfeifer Signed-off-by: David S. Miller --- net/tipc/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/tipc/net.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index 79ce8fa2b77a..d7cd1e064a80 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -116,7 +116,7 @@ */ DEFINE_RWLOCK(tipc_net_lock); -struct _zone *tipc_zones[256] = { NULL, }; +static struct _zone *tipc_zones[256] = { NULL, }; struct network tipc_net = { tipc_zones }; struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) -- cgit v1.2.2 From c68ca7b72017f8f52e7aed0d2a6ecfaede133b6b Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 11 May 2010 14:30:12 +0000 Subject: tipc: add tipc_ prefix to fcns targeted for un-inlining These functions have enough code in them such that they seem like sensible targets for un-inlining. Prior to doing that, this adds the tipc_ prefix to the functions, so that in the event of a panic dump or similar, the subsystem from which the functions come from is immediately clear. Signed-off-by: Allan Stephens Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/tipc/net.c') diff --git a/net/tipc/net.c b/net/tipc/net.c index d7cd1e064a80..f61b7694138b 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -219,7 +219,7 @@ void tipc_net_route_msg(struct sk_buff *buf) /* Handle message for this node */ dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); - if (in_scope(dnode, tipc_own_addr)) { + if (tipc_in_scope(dnode, tipc_own_addr)) { if (msg_isdata(msg)) { if (msg_mcast(msg)) tipc_port_recv_mcast(buf, NULL); @@ -277,7 +277,7 @@ int tipc_net_start(u32 addr) info("Started in network mode\n"); info("Own node address %s, network identity %u\n", - addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); + tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); return 0; } -- cgit v1.2.2