Commit 837cf45d authored by Paolo Abeni's avatar Paolo Abeni Committed by David S. Miller
Browse files

mptcp: fix race in incoming ADD_ADDR option processing



If an MPTCP endpoint received multiple consecutive incoming
ADD_ADDR options, mptcp_pm_add_addr_received() can overwrite
the current remote address value after the PM lock is released
in mptcp_pm_nl_add_addr_received() and before such address
is echoed.

Fix the issue caching the remote address value a little earlier
and always using the cached value after releasing the PM lock.

Fixes: f7efc777 ("mptcp: drop argument port from mptcp_pm_announce_addr")
Reviewed-by: default avatarMatthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 98247bc1
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -660,6 +660,7 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
	unsigned int add_addr_accept_max;
	struct mptcp_addr_info remote;
	unsigned int subflows_max;
	bool reset_port = false;
	int i, nr;

	add_addr_accept_max = mptcp_pm_get_add_addr_accept_max(msk);
@@ -669,15 +670,19 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
		 msk->pm.add_addr_accepted, add_addr_accept_max,
		 msk->pm.remote.family);

	if (lookup_subflow_by_daddr(&msk->conn_list, &msk->pm.remote))
	remote = msk->pm.remote;
	if (lookup_subflow_by_daddr(&msk->conn_list, &remote))
		goto add_addr_echo;

	/* pick id 0 port, if none is provided the remote address */
	if (!remote.port) {
		reset_port = true;
		remote.port = sk->sk_dport;
	}

	/* connect to the specified remote address, using whatever
	 * local address the routing configuration will pick.
	 */
	remote = msk->pm.remote;
	if (!remote.port)
		remote.port = sk->sk_dport;
	nr = fill_local_addresses_vec(msk, addrs);

	msk->pm.add_addr_accepted++;
@@ -690,8 +695,12 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
		__mptcp_subflow_connect(sk, &addrs[i], &remote);
	spin_lock_bh(&msk->pm.lock);

	/* be sure to echo exactly the received address */
	if (reset_port)
		remote.port = 0;

add_addr_echo:
	mptcp_pm_announce_addr(msk, &msk->pm.remote, true);
	mptcp_pm_announce_addr(msk, &remote, true);
	mptcp_pm_nl_addr_send_ack(msk);
}