From cdeb50685b44bea985c9ab3d48a632696d0c5508 Mon Sep 17 00:00:00 2001 From: Gang Yan Date: Thu, 9 Jan 2025 21:32:07 +0800 Subject: [PATCH] mptcp: fix invalid addr occupy 'add_addr_accepted' This patch fixes an issue where an invalid address is announced as a signal, the 'add_addr_accepted' is incorrectly added twice. If reach the limits, even the invalid connection is removed from conn_list by mptcp_worker, the variable is not updated, so the available address can not be added. When 'ADD_ADDR' adds an invalid address in the LAN, it will trigger the 'tcp_done_with_error' at the TCP level due to 'icmp_unreach'. At this point, 'RETRANS_ADDR' will increment 'add_addr_accepted' again. This patch is also helpful for issue#498. Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/498 Signed-off-by: Gang Yan --- net/mptcp/pm_netlink.c | 25 +++++++++++++++++++++++++ net/mptcp/protocol.c | 3 +++ net/mptcp/protocol.h | 2 ++ 3 files changed, 30 insertions(+) diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index 98ac73938bd819..cb5a609ae218c5 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -960,6 +960,31 @@ void mptcp_pm_nl_work(struct mptcp_sock *msk) spin_unlock_bh(&msk->pm.lock); } +void mptcp_pm_subflow_closed_external(struct mptcp_sock *msk, + struct mptcp_subflow_context *subflow) +{ + u8 remote_id = READ_ONCE(subflow->remote_id); + s16 local_id = READ_ONCE(subflow->local_id); + struct mptcp_subflow_context *iter; + + if (!subflow->request_join || !remote_id) + return; + + mptcp_for_each_subflow(msk, iter) { + u8 iter_rmtid = READ_ONCE(iter->remote_id); + s16 iter_locid = READ_ONCE(iter->local_id); + + if (remote_id == iter_rmtid && iter->request_join && + local_id != iter_locid) + return; + } + + spin_lock_bh(&msk->pm.lock); + if (--msk->pm.add_addr_accepted < mptcp_pm_get_add_addr_accept_max(msk)) + WRITE_ONCE(msk->pm.accept_addr, true); + spin_unlock_bh(&msk->pm.lock); +} + static bool address_use_port(struct mptcp_pm_addr_entry *entry) { return (entry->flags & diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 398ab465c256fd..acb618fd91dfe0 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2472,6 +2472,9 @@ static void __mptcp_close_subflow(struct sock *sk) continue; mptcp_close_ssk(sk, ssk, subflow); + + if (mptcp_pm_is_kernel(msk)) + mptcp_pm_subflow_closed_external(msk, subflow); } } diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 891ffcfd108877..653695956ab5a9 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -1146,6 +1146,8 @@ unsigned int mptcp_pm_get_add_addr_signal_max(const struct mptcp_sock *msk); unsigned int mptcp_pm_get_add_addr_accept_max(const struct mptcp_sock *msk); unsigned int mptcp_pm_get_subflows_max(const struct mptcp_sock *msk); unsigned int mptcp_pm_get_local_addr_max(const struct mptcp_sock *msk); +void mptcp_pm_subflow_closed_external(struct mptcp_sock *msk, + struct mptcp_subflow_context *closed_subflow); /* called under PM lock */ static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)