mptcp: set msk local address earlier
authorPaolo Abeni <pabeni@redhat.com>
Fri, 21 Oct 2022 22:58:54 +0000 (15:58 -0700)
committerJakub Kicinski <kuba@kernel.org>
Tue, 25 Oct 2022 04:13:55 +0000 (21:13 -0700)
The mptcp_pm_nl_get_local_id() code assumes that the msk local address
is available at that point. For passive sockets, we initialize such
address at accept() time.

Depending on the running configuration and the user-space timing, a
passive MPJ subflow can join the msk socket before accept() completes.

In such case, the PM assigns a wrong local id to the MPJ subflow
and later PM netlink operations will end-up touching the wrong/unexpected
subflow.

All the above causes sporadic self-tests failures, especially when
the host is heavy loaded.

Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/308
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
Fixes: d045b9eb95a9 ("mptcp: introduce implicit endpoints")
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c

index f599ad44ed24c4819ed7d9874def00fe0ad71e00..e33f9caf409d6c16bbc10396f9e381ced5a15f45 100644 (file)
@@ -2952,7 +2952,7 @@ static void mptcp_close(struct sock *sk, long timeout)
        sock_put(sk);
 }
 
-static void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
+void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk)
 {
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
        const struct ipv6_pinfo *ssk6 = inet6_sk(ssk);
@@ -3699,7 +3699,6 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
                if (mptcp_is_fully_established(newsk))
                        mptcp_pm_fully_established(msk, msk->first, GFP_KERNEL);
 
-               mptcp_copy_inaddrs(newsk, msk->first);
                mptcp_rcv_space_init(msk, msk->first);
                mptcp_propagate_sndbuf(newsk, msk->first);
 
index c0b5b4628f65018d02ffb4dcdd1f632828e1865c..be19592441df9d45dc95037569baafc6b78399db 100644 (file)
@@ -599,6 +599,7 @@ int mptcp_is_checksum_enabled(const struct net *net);
 int mptcp_allow_join_id0(const struct net *net);
 unsigned int mptcp_stale_loss_cnt(const struct net *net);
 int mptcp_get_pm_type(const struct net *net);
+void mptcp_copy_inaddrs(struct sock *msk, const struct sock *ssk);
 void mptcp_subflow_fully_established(struct mptcp_subflow_context *subflow,
                                     struct mptcp_options_received *mp_opt);
 bool __mptcp_retransmit_pending_data(struct sock *sk);
index 07dd23d0fe04ac37f4cc66c0c21d4d41f50fb3f4..02a54d59697b51450b61d79f1e77f3fd5523e4fb 100644 (file)
@@ -723,6 +723,8 @@ create_child:
                                goto dispose_child;
                        }
 
+                       if (new_msk)
+                               mptcp_copy_inaddrs(new_msk, child);
                        subflow_drop_ctx(child);
                        goto out;
                }
@@ -750,6 +752,11 @@ create_child:
                        ctx->conn = new_msk;
                        new_msk = NULL;
 
+                       /* set msk addresses early to ensure mptcp_pm_get_local_id()
+                        * uses the correct data
+                        */
+                       mptcp_copy_inaddrs(ctx->conn, child);
+
                        /* with OoO packets we can reach here without ingress
                         * mpc option
                         */