summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2023-02-07 14:04:16 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-02-14 19:18:02 +0100
commit8d13f2c3e2ba1d6e4d6daf5993de3d6d4e15693f (patch)
treecd3133954ab23868803e821cf06b2faaf2c72e05
parent25141fb4119112f4ebf8f00cf52014abbc8020b1 (diff)
downloadlinux-8d13f2c3e2ba1d6e4d6daf5993de3d6d4e15693f.tar.gz
linux-8d13f2c3e2ba1d6e4d6daf5993de3d6d4e15693f.tar.bz2
linux-8d13f2c3e2ba1d6e4d6daf5993de3d6d4e15693f.zip
mptcp: be careful on subflow status propagation on errors
commit 1249db44a102d9d3541ed7798d4b01ffdcf03524 upstream. Currently the subflow error report callback unconditionally propagates the fallback subflow status to the owning msk. If the msk is already orphaned, the above prevents the code from correctly tracking the msk moving to the TCP_CLOSE state and doing the appropriate cleanup. All the above causes increasing memory usage over time and sporadic self-tests failures. There is a great deal of infrastructure trying to propagate correctly the fallback subflow status to the owning mptcp socket, e.g. via mptcp_subflow_eof() and subflow_sched_work_if_closed(): in the error propagation path we need only to cope with unorphaned sockets. Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/339 Fixes: 15cc10453398 ("mptcp: deliver ssk errors to msk") Cc: stable@vger.kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com> Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/mptcp/subflow.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index ba4241d7c5ef..15dbaa202c7c 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1284,6 +1284,7 @@ void __mptcp_error_report(struct sock *sk)
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
int err = sock_error(ssk);
+ int ssk_state;
if (!err)
continue;
@@ -1294,7 +1295,14 @@ void __mptcp_error_report(struct sock *sk)
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk))
continue;
- inet_sk_state_store(sk, inet_sk_state_load(ssk));
+ /* We need to propagate only transition to CLOSE state.
+ * Orphaned socket will see such state change via
+ * subflow_sched_work_if_closed() and that path will properly
+ * destroy the msk as needed.
+ */
+ ssk_state = inet_sk_state_load(ssk);
+ if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD))
+ inet_sk_state_store(sk, ssk_state);
sk->sk_err = -err;
/* This barrier is coupled with smp_rmb() in mptcp_poll() */