Skip to content

Commit 69800e5

Browse files
Paolo Abenidavem330
authored andcommitted
mptcp: propagate fastclose error
When an mptcp socket is closed due to an incoming FASTCLOSE option, so specific sk_err is set and later syscall will fail usually with EPIPE. Align the current fastclose error handling with TCP reset, properly setting the socket error according to the current msk state and propagating such error. Additionally sendmsg() is currently not handling properly the sk_err, always returning EPIPE. Reviewed-by: Matthieu Baerts <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7171e8a commit 69800e5

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

net/mptcp/protocol.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
17071707
goto out;
17081708
} else if (ret) {
17091709
release_sock(ssk);
1710-
goto out;
1710+
goto do_error;
17111711
}
17121712
release_sock(ssk);
17131713
}
@@ -1717,9 +1717,13 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
17171717
if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
17181718
ret = sk_stream_wait_connect(sk, &timeo);
17191719
if (ret)
1720-
goto out;
1720+
goto do_error;
17211721
}
17221722

1723+
ret = -EPIPE;
1724+
if (unlikely(sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)))
1725+
goto do_error;
1726+
17231727
pfrag = sk_page_frag(sk);
17241728

17251729
while (msg_data_left(msg)) {
@@ -1728,11 +1732,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
17281732
bool dfrag_collapsed;
17291733
size_t psize, offset;
17301734

1731-
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) {
1732-
ret = -EPIPE;
1733-
goto out;
1734-
}
1735-
17361735
/* reuse tail pfrag, if possible, or carve a new one from the
17371736
* page allocator
17381737
*/
@@ -1764,7 +1763,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
17641763
if (copy_page_from_iter(dfrag->page, offset, psize,
17651764
&msg->msg_iter) != psize) {
17661765
ret = -EFAULT;
1767-
goto out;
1766+
goto do_error;
17681767
}
17691768

17701769
/* data successfully copied into the write queue */
@@ -1796,15 +1795,22 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
17961795
__mptcp_push_pending(sk, msg->msg_flags);
17971796
ret = sk_stream_wait_memory(sk, &timeo);
17981797
if (ret)
1799-
goto out;
1798+
goto do_error;
18001799
}
18011800

18021801
if (copied)
18031802
__mptcp_push_pending(sk, msg->msg_flags);
18041803

18051804
out:
18061805
release_sock(sk);
1807-
return copied ? : ret;
1806+
return copied;
1807+
1808+
do_error:
1809+
if (copied)
1810+
goto out;
1811+
1812+
copied = sk_stream_error(sk, msg->msg_flags, ret);
1813+
goto out;
18081814
}
18091815

18101816
static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
@@ -2441,12 +2447,31 @@ static void mptcp_check_fastclose(struct mptcp_sock *msk)
24412447
unlock_sock_fast(tcp_sk, slow);
24422448
}
24432449

2450+
/* Mirror the tcp_reset() error propagation */
2451+
switch (sk->sk_state) {
2452+
case TCP_SYN_SENT:
2453+
sk->sk_err = ECONNREFUSED;
2454+
break;
2455+
case TCP_CLOSE_WAIT:
2456+
sk->sk_err = EPIPE;
2457+
break;
2458+
case TCP_CLOSE:
2459+
return;
2460+
default:
2461+
sk->sk_err = ECONNRESET;
2462+
}
2463+
24442464
inet_sk_state_store(sk, TCP_CLOSE);
24452465
sk->sk_shutdown = SHUTDOWN_MASK;
24462466
smp_mb__before_atomic(); /* SHUTDOWN must be visible first */
24472467
set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags);
24482468

2449-
mptcp_close_wake_up(sk);
2469+
/* the calling mptcp_worker will properly destroy the socket */
2470+
if (sock_flag(sk, SOCK_DEAD))
2471+
return;
2472+
2473+
sk->sk_state_change(sk);
2474+
sk_error_report(sk);
24502475
}
24512476

24522477
static void __mptcp_retrans(struct sock *sk)

0 commit comments

Comments
 (0)