Skip to content

Commit c518471

Browse files
committed
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>
2 parents f832460 + c1be775 commit c518471

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

net/tipc/socket.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,14 @@ static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
866866
if (!tsk_peer_msg(tsk, hdr))
867867
goto exit;
868868

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+
869877
tsk->probe_unacked = false;
870878

871879
if (mtyp == CONN_PROBE) {
@@ -1259,7 +1267,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
12591267
struct sock *sk = sock->sk;
12601268
DEFINE_WAIT(wait);
12611269
long timeo = *timeop;
1262-
int err;
1270+
int err = sock_error(sk);
1271+
1272+
if (err)
1273+
return err;
12631274

12641275
for (;;) {
12651276
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
@@ -1281,6 +1292,10 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
12811292
err = sock_intr_errno(timeo);
12821293
if (signal_pending(current))
12831294
break;
1295+
1296+
err = sock_error(sk);
1297+
if (err)
1298+
break;
12841299
}
12851300
finish_wait(sk_sleep(sk), &wait);
12861301
*timeop = timeo;
@@ -1551,25 +1566,37 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
15511566
struct sock *sk = &tsk->sk;
15521567
struct net *net = sock_net(sk);
15531568
struct tipc_msg *hdr = buf_msg(skb);
1569+
u32 pport = msg_origport(hdr);
1570+
u32 pnode = msg_orignode(hdr);
15541571

15551572
if (unlikely(msg_mcast(hdr)))
15561573
return false;
15571574

15581575
switch (sk->sk_state) {
15591576
case TIPC_CONNECTING:
15601577
/* Accept only ACK or NACK message */
1561-
if (unlikely(!msg_connected(hdr)))
1562-
return false;
1578+
if (unlikely(!msg_connected(hdr))) {
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+
}
15631588

15641589
if (unlikely(msg_errcode(hdr))) {
15651590
tipc_set_sk_state(sk, TIPC_DISCONNECTING);
15661591
sk->sk_err = ECONNREFUSED;
1592+
sk->sk_state_change(sk);
15671593
return true;
15681594
}
15691595

15701596
if (unlikely(!msg_isdata(hdr))) {
15711597
tipc_set_sk_state(sk, TIPC_DISCONNECTING);
15721598
sk->sk_err = EINVAL;
1599+
sk->sk_state_change(sk);
15731600
return true;
15741601
}
15751602

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

15831610
/* If empty 'ACK-' message, wake up sleeping connect() */
1584-
if (waitqueue_active(sk_sleep(sk)))
1585-
wake_up_interruptible(sk_sleep(sk));
1611+
sk->sk_data_ready(sk);
15861612

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

0 commit comments

Comments
 (0)