Skip to content

Commit 3a13454

Browse files
Paolo Abenigregkh
authored andcommitted
mptcp: fix duplicate reset on fastclose
commit ae15506 upstream. The CI reports sporadic failures of the fastclose self-tests. The root cause is a duplicate reset, not carrying the relevant MPTCP option. In the failing scenario the bad reset is received by the peer before the fastclose one, preventing the reception of the latter. Indeed there is window of opportunity at fastclose time for the following race: mptcp_do_fastclose __mptcp_close_ssk __tcp_close() tcp_set_state() [1] tcp_send_active_reset() [2] After [1] the stack will send reset to in-flight data reaching the now closed port. Such reset may race with [2]. Address the issue explicitly sending a single reset on fastclose before explicitly moving the subflow to close status. Fixes: d21f834 ("mptcp: use fastclose on more edge scenarios") Cc: stable@vger.kernel.org Closes: multipath-tcp/mptcp_net-next#596 Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Geliang Tang <geliang@kernel.org> Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Link: https://patch.msgid.link/20251118-net-mptcp-misc-fixes-6-18-rc6-v1-6-806d3781c95f@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> [ No conflicts, but tcp_send_active_reset() doesn't take a 3rd argument (sk_rst_reason) in this version, see commit 5691276 ("rstreason: prepare for active reset"). This argument is only helpful for tracing, it is fine to drop it. ] Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b77075c commit 3a13454

1 file changed

Lines changed: 22 additions & 13 deletions

File tree

net/mptcp/protocol.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,7 +2431,6 @@ bool __mptcp_retransmit_pending_data(struct sock *sk)
24312431

24322432
/* flags for __mptcp_close_ssk() */
24332433
#define MPTCP_CF_PUSH BIT(1)
2434-
#define MPTCP_CF_FASTCLOSE BIT(2)
24352434

24362435
/* be sure to send a reset only if the caller asked for it, also
24372436
* clean completely the subflow status when the subflow reaches
@@ -2442,7 +2441,7 @@ static void __mptcp_subflow_disconnect(struct sock *ssk,
24422441
unsigned int flags)
24432442
{
24442443
if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
2445-
(flags & MPTCP_CF_FASTCLOSE)) {
2444+
subflow->send_fastclose) {
24462445
/* The MPTCP code never wait on the subflow sockets, TCP-level
24472446
* disconnect should never fail
24482447
*/
@@ -2489,14 +2488,8 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
24892488

24902489
lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
24912490

2492-
if ((flags & MPTCP_CF_FASTCLOSE) && !__mptcp_check_fallback(msk)) {
2493-
/* be sure to force the tcp_close path
2494-
* to generate the egress reset
2495-
*/
2496-
ssk->sk_lingertime = 0;
2497-
sock_set_flag(ssk, SOCK_LINGER);
2498-
subflow->send_fastclose = 1;
2499-
}
2491+
if (subflow->send_fastclose && ssk->sk_state != TCP_CLOSE)
2492+
tcp_set_state(ssk, TCP_CLOSE);
25002493

25012494
need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
25022495
if (!dispose_it) {
@@ -2809,9 +2802,25 @@ static void mptcp_do_fastclose(struct sock *sk)
28092802
struct mptcp_sock *msk = mptcp_sk(sk);
28102803

28112804
mptcp_set_state(sk, TCP_CLOSE);
2812-
mptcp_for_each_subflow_safe(msk, subflow, tmp)
2813-
__mptcp_close_ssk(sk, mptcp_subflow_tcp_sock(subflow),
2814-
subflow, MPTCP_CF_FASTCLOSE);
2805+
2806+
/* Explicitly send the fastclose reset as need */
2807+
if (__mptcp_check_fallback(msk))
2808+
return;
2809+
2810+
mptcp_for_each_subflow_safe(msk, subflow, tmp) {
2811+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
2812+
2813+
lock_sock(ssk);
2814+
2815+
/* Some subflow socket states don't allow/need a reset.*/
2816+
if ((1 << ssk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
2817+
goto unlock;
2818+
2819+
subflow->send_fastclose = 1;
2820+
tcp_send_active_reset(ssk, ssk->sk_allocation);
2821+
unlock:
2822+
release_sock(ssk);
2823+
}
28152824
}
28162825

28172826
static void mptcp_worker(struct work_struct *work)

0 commit comments

Comments
 (0)