mptcp: process pending subflow error on close

commit 9f1a98813b upstream.

On incoming TCP reset, subflow closing could happen before error
propagation. That in turn could cause the socket error being ignored,
and a missing socket state transition, as reported by Daire-Byrne.

Address the issues explicitly checking for subflow socket error at
close time. To avoid code duplication, factor-out of __mptcp_error_report()
a new helper implementing the relevant bits.

Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/429
Fixes: 15cc104533 ("mptcp: deliver ssk errors to msk")
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Paolo Abeni 2024-02-28 18:33:18 +01:00 коммит произвёл Greg Kroah-Hartman
Родитель 305078c274
Коммит 833d068e77
1 изменённых файлов: 34 добавлений и 29 удалений

Просмотреть файл

@ -688,24 +688,19 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk)
return moved; return moved;
} }
void __mptcp_error_report(struct sock *sk) static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
{ {
struct mptcp_subflow_context *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
int err = sock_error(ssk); int err = sock_error(ssk);
int ssk_state; int ssk_state;
if (!err) if (!err)
continue; return false;
/* only propagate errors on fallen-back sockets or /* only propagate errors on fallen-back sockets or
* on MPC connect * on MPC connect
*/ */
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk)) if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk)))
continue; return false;
/* We need to propagate only transition to CLOSE state. /* We need to propagate only transition to CLOSE state.
* Orphaned socket will see such state change via * Orphaned socket will see such state change via
@ -720,8 +715,17 @@ void __mptcp_error_report(struct sock *sk)
/* This barrier is coupled with smp_rmb() in mptcp_poll() */ /* This barrier is coupled with smp_rmb() in mptcp_poll() */
smp_wmb(); smp_wmb();
sk_error_report(sk); sk_error_report(sk);
return true;
}
void __mptcp_error_report(struct sock *sk)
{
struct mptcp_subflow_context *subflow;
struct mptcp_sock *msk = mptcp_sk(sk);
mptcp_for_each_subflow(msk, subflow)
if (__mptcp_subflow_error_report(sk, mptcp_subflow_tcp_sock(subflow)))
break; break;
}
} }
/* In most cases we will be able to lock the mptcp socket. If its already /* In most cases we will be able to lock the mptcp socket. If its already
@ -2309,6 +2313,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
/* close acquired an extra ref */ /* close acquired an extra ref */
__sock_put(ssk); __sock_put(ssk);
} }
__mptcp_subflow_error_report(sk, ssk);
release_sock(ssk); release_sock(ssk);
sock_put(ssk); sock_put(ssk);