Skip to content

Commit

Permalink
Merge branch 'tipc-socket-connection-hangs'
Browse files Browse the repository at this point in the history
Parthasarathy Bhuvaragan says:

====================
tipc: fix hanging socket connections

This patch series contains fixes for the socket layer to
prevent hanging / stale connections.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Apr 28, 2017
2 parents f832460 + c1be775 commit c518471
Showing 1 changed file with 31 additions and 5 deletions.
36 changes: 31 additions & 5 deletions net/tipc/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,14 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
if (!tsk_peer_msg(tsk, hdr))
goto exit;

if (unlikely(msg_errcode(hdr))) {
tipc_set_sk_state(sk, TIPC_DISCONNECTING);
tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
tsk_peer_port(tsk));
sk->sk_state_change(sk);
goto exit;
}

tsk->probe_unacked = false;

if (mtyp == CONN_PROBE) {
Expand Down Expand Up @@ -1259,7 +1267,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
struct sock *sk = sock->sk;
DEFINE_WAIT(wait);
long timeo = *timeop;
int err;
int err = sock_error(sk);

if (err)
return err;

for (;;) {
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
Expand All @@ -1281,6 +1292,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
err = sock_intr_errno(timeo);
if (signal_pending(current))
break;

err = sock_error(sk);
if (err)
break;
}
finish_wait(sk_sleep(sk), &wait);
*timeop = timeo;
Expand Down Expand Up @@ -1551,25 +1566,37 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
struct sock *sk = &tsk->sk;
struct net *net = sock_net(sk);
struct tipc_msg *hdr = buf_msg(skb);
u32 pport = msg_origport(hdr);
u32 pnode = msg_orignode(hdr);

if (unlikely(msg_mcast(hdr)))
return false;

switch (sk->sk_state) {
case TIPC_CONNECTING:
/* Accept only ACK or NACK message */
if (unlikely(!msg_connected(hdr)))
return false;
if (unlikely(!msg_connected(hdr))) {
if (pport != tsk_peer_port(tsk) ||
pnode != tsk_peer_node(tsk))
return false;

tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = ECONNREFUSED;
sk->sk_state_change(sk);
return true;
}

if (unlikely(msg_errcode(hdr))) {
tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = ECONNREFUSED;
sk->sk_state_change(sk);
return true;
}

if (unlikely(!msg_isdata(hdr))) {
tipc_set_sk_state(sk, TIPC_DISCONNECTING);
sk->sk_err = EINVAL;
sk->sk_state_change(sk);
return true;
}

Expand All @@ -1581,8 +1608,7 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
return true;

/* If empty 'ACK-' message, wake up sleeping connect() */
if (waitqueue_active(sk_sleep(sk)))
wake_up_interruptible(sk_sleep(sk));
sk->sk_data_ready(sk);

/* 'ACK-' message is neither accepted nor rejected: */
msg_set_dest_droppable(hdr, 1);
Expand Down

0 comments on commit c518471

Please sign in to comment.