| From dce1c6d1e92535f165219695a826caedcca4e9b9 Mon Sep 17 00:00:00 2001 |
| From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org> |
| Date: Wed, 28 Aug 2024 08:14:29 +0200 |
| Subject: mptcp: pm: reset MPC endp ID when re-added |
| |
| From: Matthieu Baerts (NGI0) <matttbe@kernel.org> |
| |
| commit dce1c6d1e92535f165219695a826caedcca4e9b9 upstream. |
| |
| The initial subflow has a special local ID: 0. It is specific per |
| connection. |
| |
| When a global endpoint is deleted and re-added later, it can have a |
| different ID -- most services managing the endpoints automatically don't |
| force the ID to be the same as before. It is then important to track |
| these modifications to be consistent with the ID being used for the |
| address used by the initial subflow, not to confuse the other peer or to |
| send the ID 0 for the wrong address. |
| |
| Now when removing an endpoint, msk->mpc_endpoint_id is reset if it |
| corresponds to this endpoint. When adding a new endpoint, the same |
| variable is updated if the address match the one of the initial subflow. |
| |
| Fixes: 3ad14f54bd74 ("mptcp: more accurate MPC endpoint tracking") |
| Cc: stable@vger.kernel.org |
| Reviewed-by: Mat Martineau <martineau@kernel.org> |
| Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> |
| Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/mptcp/pm_netlink.c | 13 +++++++++++-- |
| 1 file changed, 11 insertions(+), 2 deletions(-) |
| |
| --- a/net/mptcp/pm_netlink.c |
| +++ b/net/mptcp/pm_netlink.c |
| @@ -1351,20 +1351,27 @@ static struct pm_nl_pernet *genl_info_pm |
| return pm_nl_get_pernet(genl_info_net(info)); |
| } |
| |
| -static int mptcp_nl_add_subflow_or_signal_addr(struct net *net) |
| +static int mptcp_nl_add_subflow_or_signal_addr(struct net *net, |
| + struct mptcp_addr_info *addr) |
| { |
| struct mptcp_sock *msk; |
| long s_slot = 0, s_num = 0; |
| |
| while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) { |
| struct sock *sk = (struct sock *)msk; |
| + struct mptcp_addr_info mpc_addr; |
| |
| if (!READ_ONCE(msk->fully_established) || |
| mptcp_pm_is_userspace(msk)) |
| goto next; |
| |
| + /* if the endp linked to the init sf is re-added with a != ID */ |
| + mptcp_local_address((struct sock_common *)msk, &mpc_addr); |
| + |
| lock_sock(sk); |
| spin_lock_bh(&msk->pm.lock); |
| + if (mptcp_addresses_equal(addr, &mpc_addr, addr->port)) |
| + msk->mpc_endpoint_id = addr->id; |
| mptcp_pm_create_subflow_or_signal_addr(msk); |
| spin_unlock_bh(&msk->pm.lock); |
| release_sock(sk); |
| @@ -1437,7 +1444,7 @@ static int mptcp_nl_cmd_add_addr(struct |
| goto out_free; |
| } |
| |
| - mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk)); |
| + mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk), &entry->addr); |
| return 0; |
| |
| out_free: |
| @@ -1553,6 +1560,8 @@ static int mptcp_nl_remove_subflow_and_s |
| spin_unlock_bh(&msk->pm.lock); |
| } |
| |
| + if (msk->mpc_endpoint_id == entry->addr.id) |
| + msk->mpc_endpoint_id = 0; |
| release_sock(sk); |
| |
| next: |