All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation
@ 2024-02-08 20:42 Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 1/4] mptcp: fix lockless access in subflow ULP diag Paolo Abeni
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Paolo Abeni @ 2024-02-08 20:42 UTC (permalink / raw)
  To: mptcp

As reported by Mat, the in kernel PM can, in some edge scenarios,
unexpectedly create multiple subflows with the same local and remote
address.

The real fix is implemented by patch 4/4 with some more accurate check
at subflow creation time.

Patches 1-3 are roughly optional pre-requisities, added to avoid
introducing more data-races with the actual fix. Patch 1/4 is a bit
debatable, as it changes the existing ULP API, but I could not find a
better solution and there is some similar prior art:
commit 0df48c26d841 ("tcp: add tcpi_bytes_acked to tcp_info")

This address feedback from Mat on v1, see the patches changelog for 
the details (no changes in patch 1/4).

Paolo Abeni (4):
  mptcp: fix lockless access in subflow ULP diag
  mptcp: fix data races on local_id
  mptcp: fix data races on remote_id
  mptcp: fix duplicate subflow creation

 include/net/tcp.h        |  2 +-
 net/mptcp/diag.c         |  8 +++++--
 net/mptcp/pm_netlink.c   | 45 +++++++++++++++++++++-------------------
 net/mptcp/pm_userspace.c |  2 +-
 net/mptcp/protocol.c     |  2 +-
 net/mptcp/protocol.h     | 15 +++++++++++---
 net/mptcp/subflow.c      | 15 +++++++-------
 net/tls/tls_main.c       |  2 +-
 8 files changed, 54 insertions(+), 37 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH mptcp-net v2 1/4] mptcp: fix lockless access in subflow ULP diag
  2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
@ 2024-02-08 20:42 ` Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 2/4] mptcp: fix data races on local_id Paolo Abeni
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Paolo Abeni @ 2024-02-08 20:42 UTC (permalink / raw)
  To: mptcp

Since the introduction of the subflow ULP diag interface, the
dump callback accessed all the subflow data with lockless.

We need either to annotate all the read and write operation accordingly,
or acquire the subflow socket lock. Let's do latter, even if slower, to
avoid a diffstat havoc.

Fixes: 5147dfb50832 ("mptcp: allow dumping subflow context to userspace")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
note: tls ulp diag has likely the same issue.
---
 include/net/tcp.h  | 2 +-
 net/mptcp/diag.c   | 6 +++++-
 net/tls/tls_main.c | 2 +-
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 58e65af74ad1..33bf92dff0af 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -2551,7 +2551,7 @@ struct tcp_ulp_ops {
 	/* cleanup ulp */
 	void (*release)(struct sock *sk);
 	/* diagnostic */
-	int (*get_info)(const struct sock *sk, struct sk_buff *skb);
+	int (*get_info)(struct sock *sk, struct sk_buff *skb);
 	size_t (*get_info_size)(const struct sock *sk);
 	/* clone ulp */
 	void (*clone)(const struct request_sock *req, struct sock *newsk,
diff --git a/net/mptcp/diag.c b/net/mptcp/diag.c
index a536586742f2..e57c5f47f035 100644
--- a/net/mptcp/diag.c
+++ b/net/mptcp/diag.c
@@ -13,17 +13,19 @@
 #include <uapi/linux/mptcp.h>
 #include "protocol.h"
 
-static int subflow_get_info(const struct sock *sk, struct sk_buff *skb)
+static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
 {
 	struct mptcp_subflow_context *sf;
 	struct nlattr *start;
 	u32 flags = 0;
+	bool slow;
 	int err;
 
 	start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP);
 	if (!start)
 		return -EMSGSIZE;
 
+	slow = lock_sock_fast(sk);
 	rcu_read_lock();
 	sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data);
 	if (!sf) {
@@ -69,11 +71,13 @@ static int subflow_get_info(const struct sock *sk, struct sk_buff *skb)
 	}
 
 	rcu_read_unlock();
+	unlock_sock_fast(sk, slow);
 	nla_nest_end(skb, start);
 	return 0;
 
 nla_failure:
 	rcu_read_unlock();
+	unlock_sock_fast(sk, slow);
 	nla_nest_cancel(skb, start);
 	return err;
 }
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 1c2c6800949d..b4674f03d71a 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -1003,7 +1003,7 @@ static u16 tls_user_config(struct tls_context *ctx, bool tx)
 	return 0;
 }
 
-static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
+static int tls_get_info(struct sock *sk, struct sk_buff *skb)
 {
 	u16 version, cipher_type;
 	struct tls_context *ctx;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH mptcp-net v2 2/4] mptcp: fix data races on local_id
  2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 1/4] mptcp: fix lockless access in subflow ULP diag Paolo Abeni
@ 2024-02-08 20:42 ` Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 3/4] mptcp: fix data races on remote_id Paolo Abeni
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Paolo Abeni @ 2024-02-08 20:42 UTC (permalink / raw)
  To: mptcp

The local address id is accessed lockless by the NL PM, add
all the required ONCE annotation. There is a caveat: the local
id can be initialized late in the subflow life-cycle, and its
validity is controlled by the local_id_valid flag.

Remove such flag and encode the validity in the local_id field
itself with negative value before initialization. That allows
accessing the field consistently with a single read operation.

Fixes: 0ee4261a3681 ("mptcp: implement mptcp_pm_remove_subflow")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
v1 -> v2:
 - get_local_id() return u8
 - use extend helper usage in more places
 - READ_ONCE() in pm_userspace
---
 net/mptcp/diag.c         |  2 +-
 net/mptcp/pm_netlink.c   |  6 +++---
 net/mptcp/pm_userspace.c |  2 +-
 net/mptcp/protocol.c     |  2 +-
 net/mptcp/protocol.h     | 15 ++++++++++++---
 net/mptcp/subflow.c      |  9 +++++----
 6 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/net/mptcp/diag.c b/net/mptcp/diag.c
index e57c5f47f035..6ff6f14674aa 100644
--- a/net/mptcp/diag.c
+++ b/net/mptcp/diag.c
@@ -65,7 +65,7 @@ static int subflow_get_info(struct sock *sk, struct sk_buff *skb)
 			sf->map_data_len) ||
 	    nla_put_u32(skb, MPTCP_SUBFLOW_ATTR_FLAGS, flags) ||
 	    nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_REM, sf->remote_id) ||
-	    nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, sf->local_id)) {
+	    nla_put_u8(skb, MPTCP_SUBFLOW_ATTR_ID_LOC, subflow_get_local_id(sf))) {
 		err = -EMSGSIZE;
 		goto nla_failure;
 	}
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index d9ad45959219..1745678d3009 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -800,7 +800,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
 		mptcp_for_each_subflow_safe(msk, subflow, tmp) {
 			struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
 			int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
-			u8 id = subflow->local_id;
+			u8 id = subflow_get_local_id(subflow);
 
 			if (rm_type == MPTCP_MIB_RMADDR && subflow->remote_id != rm_id)
 				continue;
@@ -809,7 +809,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
 
 			pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u",
 				 rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow",
-				 i, rm_id, subflow->local_id, subflow->remote_id,
+				 i, rm_id, id, subflow->remote_id,
 				 msk->mpc_endpoint_id);
 			spin_unlock_bh(&msk->pm.lock);
 			mptcp_subflow_shutdown(sk, ssk, how);
@@ -1980,7 +1980,7 @@ static int mptcp_event_add_subflow(struct sk_buff *skb, const struct sock *ssk)
 	if (WARN_ON_ONCE(!sf))
 		return -EINVAL;
 
-	if (nla_put_u8(skb, MPTCP_ATTR_LOC_ID, sf->local_id))
+	if (nla_put_u8(skb, MPTCP_ATTR_LOC_ID, subflow_get_local_id(sf)))
 		return -EMSGSIZE;
 
 	if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, sf->remote_id))
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 4f3901d5b8ef..70cca1318575 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -233,7 +233,7 @@ static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk,
 
 	lock_sock(sk);
 	mptcp_for_each_subflow(msk, subflow) {
-		if (subflow->local_id == 0) {
+		if (READ_ONCE(subflow->local_id) == 0) {
 			has_id_0 = true;
 			break;
 		}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index a8a94b34a51e..626fb4907381 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -85,7 +85,7 @@ static int __mptcp_socket_create(struct mptcp_sock *msk)
 	subflow->subflow_id = msk->subflow_id++;
 
 	/* This is the first subflow, always with id 0 */
-	subflow->local_id_valid = 1;
+	WRITE_ONCE(subflow->local_id, 0);
 	mptcp_sock_graft(msk->first, sk->sk_socket);
 	iput(SOCK_INODE(ssock));
 
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index de04b97e8dd1..62b84cc6f35e 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -493,10 +493,9 @@ struct mptcp_subflow_context {
 		remote_key_valid : 1,        /* received the peer key from */
 		disposable : 1,	    /* ctx can be free at ulp release time */
 		stale : 1,	    /* unable to snd/rcv data, do not use for xmit */
-		local_id_valid : 1, /* local_id is correctly initialized */
 		valid_csum_seen : 1,        /* at least one csum validated */
 		is_mptfo : 1,	    /* subflow is doing TFO */
-		__unused : 9;
+		__unused : 10;
 	bool	data_avail;
 	bool	scheduled;
 	u32	remote_nonce;
@@ -507,7 +506,7 @@ struct mptcp_subflow_context {
 		u8	hmac[MPTCPOPT_HMAC_LEN]; /* MPJ subflow only */
 		u64	iasn;	    /* initial ack sequence number, MPC subflows only */
 	};
-	u8	local_id;
+	s16	local_id;	    /* if negative not initialized yet */
 	u8	remote_id;
 	u8	reset_seen:1;
 	u8	reset_transient:1;
@@ -558,6 +557,7 @@ mptcp_subflow_ctx_reset(struct mptcp_subflow_context *subflow)
 {
 	memset(&subflow->reset, 0, sizeof(subflow->reset));
 	subflow->request_mptcp = 1;
+	WRITE_ONCE(subflow->local_id, -1);
 }
 
 static inline u64
@@ -1064,6 +1064,15 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
 int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
 int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
 
+static inline u8 subflow_get_local_id(const struct mptcp_subflow_context *subflow)
+{
+	int local_id = READ_ONCE(subflow->local_id);
+
+	if (local_id < 0)
+		return 0;
+	return local_id;
+}
+
 void __init mptcp_pm_nl_init(void);
 void mptcp_pm_nl_work(struct mptcp_sock *msk);
 void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 02dab0669cfc..068784d3e748 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -578,8 +578,8 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 
 static void subflow_set_local_id(struct mptcp_subflow_context *subflow, int local_id)
 {
-	subflow->local_id = local_id;
-	subflow->local_id_valid = 1;
+	WARN_ON_ONCE(local_id < 0 || local_id > 255);
+	WRITE_ONCE(subflow->local_id, local_id);
 }
 
 static int subflow_chk_local_id(struct sock *sk)
@@ -588,7 +588,7 @@ static int subflow_chk_local_id(struct sock *sk)
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 	int err;
 
-	if (likely(subflow->local_id_valid))
+	if (likely(subflow->local_id >= 0))
 		return 0;
 
 	err = mptcp_pm_get_local_id(msk, (struct sock_common *)sk);
@@ -1733,6 +1733,7 @@ static struct mptcp_subflow_context *subflow_create_ctx(struct sock *sk,
 	pr_debug("subflow=%p", ctx);
 
 	ctx->tcp_sock = sk;
+	WRITE_ONCE(ctx->local_id, -1);
 
 	return ctx;
 }
@@ -1968,7 +1969,7 @@ static void subflow_ulp_clone(const struct request_sock *req,
 		new_ctx->idsn = subflow_req->idsn;
 
 		/* this is the first subflow, id is always 0 */
-		new_ctx->local_id_valid = 1;
+		subflow_set_local_id(new_ctx, 0);
 	} else if (subflow_req->mp_join) {
 		new_ctx->ssn_offset = subflow_req->ssn_offset;
 		new_ctx->mp_join = 1;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH mptcp-net v2 3/4] mptcp: fix data races on remote_id
  2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 1/4] mptcp: fix lockless access in subflow ULP diag Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 2/4] mptcp: fix data races on local_id Paolo Abeni
@ 2024-02-08 20:42 ` Paolo Abeni
  2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Paolo Abeni @ 2024-02-08 20:42 UTC (permalink / raw)
  To: mptcp

Similar to the previous patch, address the data race on
remote_id, adding the suitable ONCE annotations.

Fixes: bedee0b56113 ("mptcp: address lookup improvements")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
v1 -> v2:
 - srm_id -> remote_id
---
 net/mptcp/pm_netlink.c | 8 ++++----
 net/mptcp/subflow.c    | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 1745678d3009..a88cbe266a90 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -443,7 +443,7 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk,
 		mptcp_for_each_subflow(msk, subflow) {
 			ssk = mptcp_subflow_tcp_sock(subflow);
 			remote_address((struct sock_common *)ssk, &addrs[i]);
-			addrs[i].id = subflow->remote_id;
+			addrs[i].id = READ_ONCE(subflow->remote_id);
 			if (deny_id0 && !addrs[i].id)
 				continue;
 
@@ -799,18 +799,18 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
 
 		mptcp_for_each_subflow_safe(msk, subflow, tmp) {
 			struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+			u8 remote_id = READ_ONCE(subflow->remote_id);
 			int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
 			u8 id = subflow_get_local_id(subflow);
 
-			if (rm_type == MPTCP_MIB_RMADDR && subflow->remote_id != rm_id)
+			if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
 				continue;
 			if (rm_type == MPTCP_MIB_RMSUBFLOW && !mptcp_local_id_match(msk, id, rm_id))
 				continue;
 
 			pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u",
 				 rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow",
-				 i, rm_id, id, subflow->remote_id,
-				 msk->mpc_endpoint_id);
+				 i, rm_id, id, remote_id, msk->mpc_endpoint_id);
 			spin_unlock_bh(&msk->pm.lock);
 			mptcp_subflow_shutdown(sk, ssk, how);
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 068784d3e748..6403c56f2902 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -536,7 +536,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
 		subflow->backup = mp_opt.backup;
 		subflow->thmac = mp_opt.thmac;
 		subflow->remote_nonce = mp_opt.nonce;
-		subflow->remote_id = mp_opt.join_id;
+		WRITE_ONCE(subflow->remote_id, mp_opt.join_id);
 		pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u backup=%d",
 			 subflow, subflow->thmac, subflow->remote_nonce,
 			 subflow->backup);
@@ -1569,7 +1569,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
 	pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d", msk,
 		 remote_token, local_id, remote_id);
 	subflow->remote_token = remote_token;
-	subflow->remote_id = remote_id;
+	WRITE_ONCE(subflow->remote_id, remote_id);
 	subflow->request_join = 1;
 	subflow->request_bkup = !!(flags & MPTCP_PM_ADDR_FLAG_BACKUP);
 	subflow->subflow_id = msk->subflow_id++;
@@ -1976,7 +1976,7 @@ static void subflow_ulp_clone(const struct request_sock *req,
 		new_ctx->fully_established = 1;
 		new_ctx->remote_key_valid = 1;
 		new_ctx->backup = subflow_req->backup;
-		new_ctx->remote_id = subflow_req->remote_id;
+		WRITE_ONCE(new_ctx->remote_id, subflow_req->remote_id);
 		new_ctx->token = subflow_req->token;
 		new_ctx->thmac = subflow_req->thmac;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation
  2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
                   ` (2 preceding siblings ...)
  2024-02-08 20:42 ` [PATCH mptcp-net v2 3/4] mptcp: fix data races on remote_id Paolo Abeni
@ 2024-02-08 20:42 ` Paolo Abeni
  2024-02-08 21:34   ` mptcp: fix duplicate subflow creation: Tests Results MPTCP CI
                     ` (3 more replies)
  2024-02-09  0:23 ` [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Mat Martineau
  2024-02-09 14:20 ` Matthieu Baerts
  5 siblings, 4 replies; 13+ messages in thread
From: Paolo Abeni @ 2024-02-08 20:42 UTC (permalink / raw)
  To: mptcp

Fullmesh endpoints could end-up unexpectedly generating duplicate
subflows - same local and remote addresses - when multiple incoming
ADD_ADDR are processed before the PM creates the subflow for the local
endpoints.

Address the issue explicitly checking for duplicates at subflow
creation time.

To avoid a quadratic computational complexity, track the unavailable
remote address ids in a temporary bitmap and initialize such bitmap
with the remote ids of all the existing subflows matching the local
address currently processed.

The above allows additionally replacing the existing code checking
for duplicate entry in the current set with a simple bit test
operation.

Fixes: 2843ff6f36db ("mptcp: remote addresses fullmesh")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/435
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
v1 -> v2:
 - forbit -> forbid

Note that there is no problem for the opposite event sequence.
---
 net/mptcp/pm_netlink.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index a88cbe266a90..b87d802da028 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -396,19 +396,6 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
 	}
 }
 
-static bool lookup_address_in_vec(const struct mptcp_addr_info *addrs, unsigned int nr,
-				  const struct mptcp_addr_info *addr)
-{
-	int i;
-
-	for (i = 0; i < nr; i++) {
-		if (addrs[i].id == addr->id)
-			return true;
-	}
-
-	return false;
-}
-
 /* Fill all the remote addresses into the array addrs[],
  * and return the array size.
  */
@@ -440,6 +427,16 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk,
 		msk->pm.subflows++;
 		addrs[i++] = remote;
 	} else {
+		DECLARE_BITMAP(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1);
+
+		/* Forbid creation of new subflows matching existing
+		 * ones, possibly already created by incoming ADD_ADDR
+		 */
+		bitmap_zero(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1);
+		mptcp_for_each_subflow(msk, subflow)
+			if (READ_ONCE(subflow->local_id) == local->id)
+				__set_bit(subflow->remote_id, unavail_id);
+
 		mptcp_for_each_subflow(msk, subflow) {
 			ssk = mptcp_subflow_tcp_sock(subflow);
 			remote_address((struct sock_common *)ssk, &addrs[i]);
@@ -447,11 +444,17 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk,
 			if (deny_id0 && !addrs[i].id)
 				continue;
 
+			if (test_bit(addrs[i].id, unavail_id))
+				continue;
+
 			if (!mptcp_pm_addr_families_match(sk, local, &addrs[i]))
 				continue;
 
-			if (!lookup_address_in_vec(addrs, i, &addrs[i]) &&
-			    msk->pm.subflows < subflows_max) {
+			if (msk->pm.subflows < subflows_max) {
+				/* forbid creating multiple address towards
+				 * this id
+				 */
+				__set_bit(addrs[i].id, unavail_id);
 				msk->pm.subflows++;
 				i++;
 			}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: mptcp: fix duplicate subflow creation: Tests Results
  2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
@ 2024-02-08 21:34   ` MPTCP CI
  2024-02-08 21:57   ` MPTCP CI
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2024-02-08 21:34 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

Hi Paolo,

Thank you for your modifications, that's great!

Our CI (GitHub Action) did some validations and here is its report:

- KVM Validation: normal:
  - Success! ✅:
  - Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/7835837100

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/2770999be5bd


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-normal

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: mptcp: fix duplicate subflow creation: Tests Results
  2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
  2024-02-08 21:34   ` mptcp: fix duplicate subflow creation: Tests Results MPTCP CI
@ 2024-02-08 21:57   ` MPTCP CI
  2024-02-09  1:17   ` MPTCP CI
  2024-02-09  1:54   ` MPTCP CI
  3 siblings, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2024-02-08 21:57 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

Hi Paolo,

Thank you for your modifications, that's great!

Our CI (Cirrus) did some validations with a debug kernel and here is its report:

- KVM Validation: debug (except selftest_mptcp_join):
  - Success! ✅:
  - Task: https://cirrus-ci.com/task/4813501529587712
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/4813501529587712/summary/summary.txt

- KVM Validation: debug (only selftest_mptcp_join):
  - Success! ✅:
  - Task: https://cirrus-ci.com/task/5939401436430336
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/5939401436430336/summary/summary.txt

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/2770999be5bd


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-debug

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation
  2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
                   ` (3 preceding siblings ...)
  2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
@ 2024-02-09  0:23 ` Mat Martineau
  2024-02-09 14:20 ` Matthieu Baerts
  5 siblings, 0 replies; 13+ messages in thread
From: Mat Martineau @ 2024-02-09  0:23 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

On Thu, 8 Feb 2024, Paolo Abeni wrote:

> As reported by Mat, the in kernel PM can, in some edge scenarios,
> unexpectedly create multiple subflows with the same local and remote
> address.
>
> The real fix is implemented by patch 4/4 with some more accurate check
> at subflow creation time.
>
> Patches 1-3 are roughly optional pre-requisities, added to avoid
> introducing more data-races with the actual fix. Patch 1/4 is a bit
> debatable, as it changes the existing ULP API, but I could not find a
> better solution and there is some similar prior art:
> commit 0df48c26d841 ("tcp: add tcpi_bytes_acked to tcp_info")
>
> This address feedback from Mat on v1, see the patches changelog for
> the details (no changes in patch 1/4).
>
> Paolo Abeni (4):
>  mptcp: fix lockless access in subflow ULP diag
>  mptcp: fix data races on local_id
>  mptcp: fix data races on remote_id
>  mptcp: fix duplicate subflow creation
>

Hi Paolo -

v2 LGTM, thanks:

Reviewed-by: Mat Martineau <martineau@kernel.org>

> include/net/tcp.h        |  2 +-
> net/mptcp/diag.c         |  8 +++++--
> net/mptcp/pm_netlink.c   | 45 +++++++++++++++++++++-------------------
> net/mptcp/pm_userspace.c |  2 +-
> net/mptcp/protocol.c     |  2 +-
> net/mptcp/protocol.h     | 15 +++++++++++---
> net/mptcp/subflow.c      | 15 +++++++-------
> net/tls/tls_main.c       |  2 +-
> 8 files changed, 54 insertions(+), 37 deletions(-)
>
> -- 
> 2.43.0
>
>
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: mptcp: fix duplicate subflow creation: Tests Results
  2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
  2024-02-08 21:34   ` mptcp: fix duplicate subflow creation: Tests Results MPTCP CI
  2024-02-08 21:57   ` MPTCP CI
@ 2024-02-09  1:17   ` MPTCP CI
  2024-02-09  1:54   ` MPTCP CI
  3 siblings, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2024-02-09  1:17 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

Hi Paolo,

Thank you for your modifications, that's great!

Our CI (GitHub Action) did some validations and here is its report:

- KVM Validation: normal:
  - Success! ✅:
  - Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/7837946973

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/57268e5e5c3c


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-normal

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: mptcp: fix duplicate subflow creation: Tests Results
  2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
                     ` (2 preceding siblings ...)
  2024-02-09  1:17   ` MPTCP CI
@ 2024-02-09  1:54   ` MPTCP CI
  3 siblings, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2024-02-09  1:54 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

Hi Paolo,

Thank you for your modifications, that's great!

Our CI (Cirrus) did some validations with a debug kernel and here is its report:

- KVM Validation: debug (except selftest_mptcp_join):
  - Success! ✅:
  - Task: https://cirrus-ci.com/task/5931257842892800
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/5931257842892800/summary/summary.txt

- KVM Validation: debug (only selftest_mptcp_join):
  - Success! ✅:
  - Task: https://cirrus-ci.com/task/5109398167617536
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/5109398167617536/summary/summary.txt

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/57268e5e5c3c


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-debug

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation
  2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
                   ` (4 preceding siblings ...)
  2024-02-09  0:23 ` [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Mat Martineau
@ 2024-02-09 14:20 ` Matthieu Baerts
  5 siblings, 0 replies; 13+ messages in thread
From: Matthieu Baerts @ 2024-02-09 14:20 UTC (permalink / raw)
  To: Paolo Abeni, Mat Martineau; +Cc: mptcp

Hi Paolo, Mat,

On 08/02/2024 21:42, Paolo Abeni wrote:
> As reported by Mat, the in kernel PM can, in some edge scenarios,
> unexpectedly create multiple subflows with the same local and remote
> address.
> 
> The real fix is implemented by patch 4/4 with some more accurate check
> at subflow creation time.
> 
> Patches 1-3 are roughly optional pre-requisities, added to avoid
> introducing more data-races with the actual fix. Patch 1/4 is a bit
> debatable, as it changes the existing ULP API, but I could not find a
> better solution and there is some similar prior art:
> commit 0df48c26d841 ("tcp: add tcpi_bytes_acked to tcp_info")
> 
> This address feedback from Mat on v1, see the patches changelog for 
> the details (no changes in patch 1/4).

Thank you for the modifications and the reviews!

Now in our tree (fixes for -net):

New patches for t/upstream-net and t/upstream:
- ce4271cba41b: mptcp: fix lockless access in subflow ULP diag
- bb35405f2e28: mptcp: fix data races on local_id
- ed0e0e7b2325: mptcp: fix data races on remote_id
- 22e3b19337f7: mptcp: fix duplicate subflow creation
- Results: bef0b46af378..8abab82d59f2 (export-net)
- Results: 78a4d8e40bf5..0c8d1475f726 (export)

Tests are now in progress:

https://cirrus-ci.com/github/multipath-tcp/mptcp_net-next/export-net/20240209T141835
https://cirrus-ci.com/github/multipath-tcp/mptcp_net-next/export/20240209T141835

Cheers,
Matt
-- 
Sponsored by the NGI0 Core fund.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: mptcp: fix duplicate subflow creation: Tests Results
  2024-02-05 15:51 [PATCH mptcp-net 4/4] " Paolo Abeni
  2024-02-05 16:50 ` mptcp: fix duplicate subflow creation: Tests Results MPTCP CI
@ 2024-02-05 17:08 ` MPTCP CI
  1 sibling, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2024-02-05 17:08 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

Hi Paolo,

Thank you for your modifications, that's great!

Our CI (Cirrus) did some validations with a debug kernel and here is its report:

- KVM Validation: debug (except selftest_mptcp_join):
  - Unstable: 1 failed test(s): packetdrill_regressions 🔴:
  - Task: https://cirrus-ci.com/task/5560160119160832
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/5560160119160832/summary/summary.txt

- KVM Validation: debug (only selftest_mptcp_join):
  - Success! ✅:
  - Task: https://cirrus-ci.com/task/6686060026003456
  - Summary: https://api.cirrus-ci.com/v1/artifact/task/6686060026003456/summary/summary.txt

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/75f455f724d8


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-debug

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: mptcp: fix duplicate subflow creation: Tests Results
  2024-02-05 15:51 [PATCH mptcp-net 4/4] " Paolo Abeni
@ 2024-02-05 16:50 ` MPTCP CI
  2024-02-05 17:08 ` MPTCP CI
  1 sibling, 0 replies; 13+ messages in thread
From: MPTCP CI @ 2024-02-05 16:50 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

Hi Paolo,

Thank you for your modifications, that's great!

Our CI (GitHub Action) did some validations and here is its report:

- KVM Validation: normal:
  - Success! ✅:
  - Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/7787400213

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/75f455f724d8


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-normal

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-02-09 14:20 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-08 20:42 [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Paolo Abeni
2024-02-08 20:42 ` [PATCH mptcp-net v2 1/4] mptcp: fix lockless access in subflow ULP diag Paolo Abeni
2024-02-08 20:42 ` [PATCH mptcp-net v2 2/4] mptcp: fix data races on local_id Paolo Abeni
2024-02-08 20:42 ` [PATCH mptcp-net v2 3/4] mptcp: fix data races on remote_id Paolo Abeni
2024-02-08 20:42 ` [PATCH mptcp-net v2 4/4] mptcp: fix duplicate subflow creation Paolo Abeni
2024-02-08 21:34   ` mptcp: fix duplicate subflow creation: Tests Results MPTCP CI
2024-02-08 21:57   ` MPTCP CI
2024-02-09  1:17   ` MPTCP CI
2024-02-09  1:54   ` MPTCP CI
2024-02-09  0:23 ` [PATCH mptcp-net v2 0/4] mptcp: fix duplicate subflow creation Mat Martineau
2024-02-09 14:20 ` Matthieu Baerts
  -- strict thread matches above, loose matches on Subject: below --
2024-02-05 15:51 [PATCH mptcp-net 4/4] " Paolo Abeni
2024-02-05 16:50 ` mptcp: fix duplicate subflow creation: Tests Results MPTCP CI
2024-02-05 17:08 ` MPTCP CI

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.