aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorParthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>2017-04-26 04:05:01 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-28 12:20:42 -0400
commit4e0df4951e9ecb7ec026a1330ed59f12e8937a95 (patch)
tree695516ff85fe9a7a30f99f5abda5ce1efd98da5d /net/tipc
parent42b531de17d2f6bb9293f23398f6d9bb94635c3e (diff)
tipc: improve error validations for sockets in CONNECTING state
Until now, the checks for sockets in CONNECTING state was based on the assumption that the incoming message was always from the peer's accepted data socket. However an application using a non-blocking socket sends an implicit connect, this socket which is in CONNECTING state can receive error messages from the peer's listening socket. As we discard these messages, the application socket hangs as there due to inactivity. In addition to this, there are other places where we process errors but do not notify the user. In this commit, we process such incoming error messages and notify our users about them using sk_state_change(). Signed-off-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3b8df510a80c..38c367f6ced4 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1259,7 +1259,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1259 struct sock *sk = sock->sk; 1259 struct sock *sk = sock->sk;
1260 DEFINE_WAIT(wait); 1260 DEFINE_WAIT(wait);
1261 long timeo = *timeop; 1261 long timeo = *timeop;
1262 int err; 1262 int err = sock_error(sk);
1263
1264 if (err)
1265 return err;
1263 1266
1264 for (;;) { 1267 for (;;) {
1265 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1268 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
@@ -1281,6 +1284,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
1281 err = sock_intr_errno(timeo); 1284 err = sock_intr_errno(timeo);
1282 if (signal_pending(current)) 1285 if (signal_pending(current))
1283 break; 1286 break;
1287
1288 err = sock_error(sk);
1289 if (err)
1290 break;
1284 } 1291 }
1285 finish_wait(sk_sleep(sk), &wait); 1292 finish_wait(sk_sleep(sk), &wait);
1286 *timeop = timeo; 1293 *timeop = timeo;
@@ -1551,6 +1558,8 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1551 struct sock *sk = &tsk->sk; 1558 struct sock *sk = &tsk->sk;
1552 struct net *net = sock_net(sk); 1559 struct net *net = sock_net(sk);
1553 struct tipc_msg *hdr = buf_msg(skb); 1560 struct tipc_msg *hdr = buf_msg(skb);
1561 u32 pport = msg_origport(hdr);
1562 u32 pnode = msg_orignode(hdr);
1554 1563
1555 if (unlikely(msg_mcast(hdr))) 1564 if (unlikely(msg_mcast(hdr)))
1556 return false; 1565 return false;
@@ -1558,18 +1567,28 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
1558 switch (sk->sk_state) { 1567 switch (sk->sk_state) {
1559 case TIPC_CONNECTING: 1568 case TIPC_CONNECTING:
1560 /* Accept only ACK or NACK message */ 1569 /* Accept only ACK or NACK message */
1561 if (unlikely(!msg_connected(hdr))) 1570 if (unlikely(!msg_connected(hdr))) {
1562 return false; 1571 if (pport != tsk_peer_port(tsk) ||
1572 pnode != tsk_peer_node(tsk))
1573 return false;
1574
1575 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
1576 sk->sk_err = ECONNREFUSED;
1577 sk->sk_state_change(sk);
1578 return true;
1579 }
1563 1580
1564 if (unlikely(msg_errcode(hdr))) { 1581 if (unlikely(msg_errcode(hdr))) {
1565 tipc_set_sk_state(sk, TIPC_DISCONNECTING); 1582 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
1566 sk->sk_err = ECONNREFUSED; 1583 sk->sk_err = ECONNREFUSED;
1584 sk->sk_state_change(sk);
1567 return true; 1585 return true;
1568 } 1586 }
1569 1587
1570 if (unlikely(!msg_isdata(hdr))) { 1588 if (unlikely(!msg_isdata(hdr))) {
1571 tipc_set_sk_state(sk, TIPC_DISCONNECTING); 1589 tipc_set_sk_state(sk, TIPC_DISCONNECTING);
1572 sk->sk_err = EINVAL; 1590 sk->sk_err = EINVAL;
1591 sk->sk_state_change(sk);
1573 return true; 1592 return true;
1574 } 1593 }
1575 1594