aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-04-28 12:20:43 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-28 12:20:43 -0400
commitc51847171162212618b3227812f007a654de2f4b (patch)
tree105f419e4111501b0aee0067d9d566776d07dbc3
parentf83246089ca09308425175d47f5e71e6da68b2ef (diff)
parentc1be7756284b0fdbfe8aea8da968ce054697e0c5 (diff)
Merge branch 'tipc-socket-connection-hangs'
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 <davem@davemloft.net>
-rw-r--r--net/tipc/socket.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 566906795c8c..bdce99f9407a 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -866,6 +866,14 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
866 if (!tsk_peer_msg(tsk, hdr)) 866 if (!tsk_peer_msg(tsk, hdr))
867 goto exit; 867 goto exit;
868 868
869 if (unlikely(msg_errcode(hdr))) {
870 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
871 tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
872 tsk_peer_port(tsk));
873 sk->sk_state_change(sk);
874 goto exit;
875 }
876
869 tsk->probe_unacked = false; 877 tsk->probe_unacked = false;
870 878
871 if (mtyp == CONN_PROBE) { 879 if (mtyp == CONN_PROBE) {
@@ -1259,7 +1267,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1259 struct sock *sk = sock->sk; 1267 struct sock *sk = sock->sk;
1260 DEFINE_WAIT(wait); 1268 DEFINE_WAIT(wait);
1261 long timeo = *timeop; 1269 long timeo = *timeop;
1262 int err; 1270 int err = sock_error(sk);
1271
1272 if (err)
1273 return err;
1263 1274
1264 for (;;) { 1275 for (;;) {
1265 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1276 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
@@ -1281,6 +1292,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1281 err = sock_intr_errno(timeo); 1292 err = sock_intr_errno(timeo);
1282 if (signal_pending(current)) 1293 if (signal_pending(current))
1283 break; 1294 break;
1295
1296 err = sock_error(sk);
1297 if (err)
1298 break;
1284 } 1299 }
1285 finish_wait(sk_sleep(sk), &wait); 1300 finish_wait(sk_sleep(sk), &wait);
1286 *timeop = timeo; 1301 *timeop = timeo;
@@ -1551,6 +1566,8 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1551 struct sock *sk = &tsk->sk; 1566 struct sock *sk = &tsk->sk;
1552 struct net *net = sock_net(sk); 1567 struct net *net = sock_net(sk);
1553 struct tipc_msg *hdr = buf_msg(skb); 1568 struct tipc_msg *hdr = buf_msg(skb);
1569 u32 pport = msg_origport(hdr);
1570 u32 pnode = msg_orignode(hdr);
1554 1571
1555 if (unlikely(msg_mcast(hdr))) 1572 if (unlikely(msg_mcast(hdr)))
1556 return false; 1573 return false;
@@ -1558,18 +1575,28 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1558 switch (sk->sk_state) { 1575 switch (sk->sk_state) {
1559 case TIPC_CONNECTING: 1576 case TIPC_CONNECTING:
1560 /* Accept only ACK or NACK message */ 1577 /* Accept only ACK or NACK message */
1561 if (unlikely(!msg_connected(hdr))) 1578 if (unlikely(!msg_connected(hdr))) {
1562 return false; 1579 if (pport != tsk_peer_port(tsk) ||
1580 pnode != tsk_peer_node(tsk))
1581 return false;
1582
1583 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
1584 sk->sk_err = ECONNREFUSED;
1585 sk->sk_state_change(sk);
1586 return true;
1587 }
1563 1588
1564 if (unlikely(msg_errcode(hdr))) { 1589 if (unlikely(msg_errcode(hdr))) {
1565 tipc_set_sk_state(sk, TIPC_DISCONNECTING); 1590 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
1566 sk->sk_err = ECONNREFUSED; 1591 sk->sk_err = ECONNREFUSED;
1592 sk->sk_state_change(sk);
1567 return true; 1593 return true;
1568 } 1594 }
1569 1595
1570 if (unlikely(!msg_isdata(hdr))) { 1596 if (unlikely(!msg_isdata(hdr))) {
1571 tipc_set_sk_state(sk, TIPC_DISCONNECTING); 1597 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
1572 sk->sk_err = EINVAL; 1598 sk->sk_err = EINVAL;
1599 sk->sk_state_change(sk);
1573 return true; 1600 return true;
1574 } 1601 }
1575 1602
@@ -1581,8 +1608,7 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1581 return true; 1608 return true;
1582 1609
1583 /* If empty 'ACK-' message, wake up sleeping connect() */ 1610 /* If empty 'ACK-' message, wake up sleeping connect() */
1584 if (waitqueue_active(sk_sleep(sk))) 1611 sk->sk_data_ready(sk);
1585 wake_up_interruptible(sk_sleep(sk));
1586 1612
1587 /* 'ACK-' message is neither accepted nor rejected: */ 1613 /* 'ACK-' message is neither accepted nor rejected: */
1588 msg_set_dest_droppable(hdr, 1); 1614 msg_set_dest_droppable(hdr, 1);