From def81f69bfbd70a3278a7592a4ab8717300cbac1 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Thu, 23 Apr 2015 09:37:38 -0400 Subject: tipc: fix topology server broken issue When a new topology server is launched in a new namespace, its listening socket is inserted into the "init ns" namespace's socket hash table rather than the one owned by the new namespace. Although the socket's namespace is forcedly changed to the new namespace later, the socket is still stored in the socket hash table of "init ns" namespace. When a client created in the new namespace connects its own topology server, the connection is failed as its server's socket could not be found from its own namespace's socket table. If __sock_create() instead of original sock_create_kern() is used to create the server's socket through specifying an expected namesapce, the socket will be inserted into the specified namespace's socket table, thereby avoiding to the topology server broken issue. Fixes: 76100a8a64bc ("tipc: fix netns refcnt leak") Reported-by: Erik Hugne Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/server.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/tipc/server.c b/net/tipc/server.c index ab6183cdb121..77ff03ed1e18 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -102,7 +102,7 @@ static void tipc_conn_kref_release(struct kref *kref) } saddr->scope = -TIPC_NODE_SCOPE; kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); - sk_release_kernel(sk); + sock_release(sock); con->sock = NULL; } @@ -321,12 +321,9 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) struct socket *sock = NULL; int ret; - ret = sock_create_kern(AF_TIPC, SOCK_SEQPACKET, 0, &sock); + ret = __sock_create(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock, 1); if (ret < 0) return NULL; - - sk_change_net(sock->sk, s->net); - ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, (char *)&s->imp, sizeof(s->imp)); if (ret < 0) @@ -376,7 +373,7 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) create_err: kernel_sock_shutdown(sock, SHUT_RDWR); - sk_release_kernel(sock->sk); + sock_release(sock); return NULL; } -- cgit v1.2.3 From 9871b27f6705fc6e0ba633b136369a289b2bfb99 Mon Sep 17 00:00:00 2001 From: Erik Hugne Date: Thu, 23 Apr 2015 09:37:39 -0400 Subject: tipc: fix random link reset problem In the function tipc_sk_rcv(), the stack variable 'err' is only initialized to TIPC_ERR_NO_PORT for the first iteration over the link input queue. If a chain of messages are received from a link, failure to lookup the socket for any but the first message will cause the message to bounce back out on a random link. We fix this by properly initializing err. Signed-off-by: Erik Hugne Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index ee90d74d7516..9074b5cede38 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1764,13 +1764,14 @@ static int tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) { u32 dnode, dport = 0; - int err = -TIPC_ERR_NO_PORT; + int err; struct sk_buff *skb; struct tipc_sock *tsk; struct tipc_net *tn; struct sock *sk; while (skb_queue_len(inputq)) { + err = -TIPC_ERR_NO_PORT; skb = NULL; dport = tipc_skb_peek_port(inputq, dport); tsk = tipc_sk_lookup(net, dport); -- cgit v1.2.3 From 73a317377303b5ec14d4703d73ba87efffbb779d Mon Sep 17 00:00:00 2001 From: Erik Hugne Date: Thu, 23 Apr 2015 09:37:40 -0400 Subject: tipc: fix node refcount issue When link statistics is dumped over netlink, we iterate over the list of peer nodes and append each links statistics to the netlink msg. In the case where the dump is resumed after filling up a nlmsg, the node refcnt is decremented without having been incremented previously which may cause the node reference to be freed. When this happens, the following info/stacktrace will be generated, followed by a crash or undefined behavior. We fix this by removing the erroneous call to tipc_node_put inside the loop that iterates over nodes. [ 384.312303] INFO: trying to register non-static key. [ 384.313110] the code is fine but needs lockdep annotation. [ 384.313290] turning off the locking correctness validator. [ 384.313290] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.0.0+ #13 [ 384.313290] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 384.313290] ffff88003c6d0290 ffff88003cc03ca8 ffffffff8170adf1 0000000000000007 [ 384.313290] ffffffff82728730 ffff88003cc03d38 ffffffff810a6a6d 00000000001d7200 [ 384.313290] ffff88003c6d0ab0 ffff88003cc03ce8 0000000000000285 0000000000000001 [ 384.313290] Call Trace: [ 384.313290] [] dump_stack+0x4c/0x65 [ 384.313290] [] __lock_acquire+0xf3d/0xf50 [ 384.313290] [] lock_acquire+0xd5/0x290 [ 384.313290] [] ? link_timeout+0x1c/0x170 [tipc] [ 384.313290] [] ? link_state_event+0x4e0/0x4e0 [tipc] [ 384.313290] [] _raw_spin_lock_bh+0x40/0x80 [ 384.313290] [] ? link_timeout+0x1c/0x170 [tipc] [ 384.313290] [] link_timeout+0x1c/0x170 [tipc] [ 384.313290] [] call_timer_fn+0xb8/0x490 [ 384.313290] [] ? process_timeout+0x10/0x10 [ 384.313290] [] run_timer_softirq+0x21c/0x420 [ 384.313290] [] ? link_state_event+0x4e0/0x4e0 [tipc] [ 384.313290] [] __do_softirq+0xf4/0x630 [ 384.313290] [] irq_exit+0x5d/0x60 [ 384.313290] [] smp_apic_timer_interrupt+0x41/0x50 [ 384.313290] [] apic_timer_interrupt+0x70/0x80 [ 384.313290] [] ? default_idle+0x20/0x210 [ 384.313290] [] ? default_idle+0x1e/0x210 [ 384.313290] [] arch_cpu_idle+0xa/0x10 [ 384.313290] [] cpu_startup_entry+0x2c3/0x530 [ 384.313290] [] ? clockevents_register_device+0x113/0x200 [ 384.313290] [] start_secondary+0x13f/0x170 Fixes: 8a0f6ebe8494 ("tipc: involve reference counter for node structure") Signed-off-by: Erik Hugne Signed-off-by: Jon Maloy Signed-off-by: David S. Miller --- net/tipc/link.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index a6b30df6ec02..57be6e6aff99 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2143,7 +2143,6 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) err = __tipc_nl_add_node_links(net, &msg, node, &prev_link); tipc_node_unlock(node); - tipc_node_put(node); if (err) goto out; -- cgit v1.2.3