diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/socket.c | 25 |
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 | ||