All of lore.kernel.org
 help / color / mirror / Atom feed
* [MPTCP] [PATCH 2/3] mptcp: avoid data stream corruption on allocation failure.
@ 2019-12-02 10:24 Paolo Abeni
  0 siblings, 0 replies; only message in thread
From: Paolo Abeni @ 2019-12-02 10:24 UTC (permalink / raw)
  To: mptcp

[-- Attachment #1: Type: text/plain, Size: 3441 bytes --]

Currently, when if mpext allocation fails, the data stream
is corrupted, as we can add the required DSS nor roll-back
the TCP status.

Allocate a skb_ext before the actuall skb_buff creation/TCP
status update: in case of memory allocation failure we can
bail early, avoiding the above condition.

Additionally, if the ext is unused to to skb collapsing,
cache the ext in the msk for the next send.

Squash-to: "mptcp: Write MPTCP DSS headers to outgoing data packets"
Signed-off-by: Paolo Abeni <pabeni(a)redhat.com>
---
 net/mptcp/protocol.c | 39 +++++++++++++++++++++++++--------------
 net/mptcp/protocol.h |  1 +
 2 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 3180202e56b4..ae158ab08101 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -55,6 +55,14 @@ static struct sock *mptcp_subflow_get(const struct mptcp_sock *msk)
 	return NULL;
 }
 
+static bool mptcp_ext_cache_refill(struct mptcp_sock *msk)
+{
+	if (!msk->cached_ext)
+		msk->cached_ext = skb_ext_alloc();
+
+	return msk->cached_ext;
+}
+
 static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 			      struct msghdr *msg, long *timeo)
 {
@@ -69,7 +77,8 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 	 * from one substream to another, but do per subflow memory accounting
 	 */
 	pfrag = sk_page_frag(sk);
-	while (!sk_page_frag_refill(ssk, pfrag)) {
+	while (!sk_page_frag_refill(ssk, pfrag) ||
+	       !mptcp_ext_cache_refill(msk)) {
 		ret = sk_stream_wait_memory(ssk, timeo);
 		if (ret)
 			return ret;
@@ -103,19 +112,19 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 		iov_iter_revert(&msg->msg_iter, psize - ret);
 
 	skb = tcp_write_queue_tail(ssk);
-	mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
-	if (mpext) {
-		memset(mpext, 0, sizeof(*mpext));
-		mpext->data_seq = msk->write_seq;
-		mpext->subflow_seq = mptcp_subflow_ctx(ssk)->rel_write_seq;
-		mpext->data_len = ret;
-		mpext->use_map = 1;
-		mpext->dsn64 = 1;
-
-		pr_debug("data_seq=%llu subflow_seq=%u data_len=%u dsn64=%d",
-			 mpext->data_seq, mpext->subflow_seq, mpext->data_len,
-			 mpext->dsn64);
-	} /* TODO: else fallback */
+	mpext = __skb_ext_add(skb, SKB_EXT_MPTCP, msk->cached_ext);
+	msk->cached_ext = NULL;
+
+	memset(mpext, 0, sizeof(*mpext));
+	mpext->data_seq = msk->write_seq;
+	mpext->subflow_seq = mptcp_subflow_ctx(ssk)->rel_write_seq;
+	mpext->data_len = ret;
+	mpext->use_map = 1;
+	mpext->dsn64 = 1;
+
+	pr_debug("data_seq=%llu subflow_seq=%u data_len=%u dsn64=%d",
+		 mpext->data_seq, mpext->subflow_seq, mpext->data_len,
+		 mpext->dsn64);
 
 	pfrag->offset += ret;
 	msk->write_seq += ret;
@@ -242,6 +251,8 @@ static void mptcp_close(struct sock *sk, long timeout)
 		sock_release(mptcp_subflow_tcp_socket(subflow));
 	}
 
+	if (msk->cached_ext)
+		__skb_ext_put(msk->cached_ext);
 	release_sock(sk);
 	sk_common_release(sk);
 }
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 412718c1ae5c..3b8d1548dda1 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -58,6 +58,7 @@ struct mptcp_sock {
 	u64		write_seq;
 	u64		ack_seq;
 	u32		token;
+	struct	skb_ext *cached_ext;	/* for the next sendmsg */
 	struct list_head conn_list;
 	struct socket	*subflow; /* outgoing connect/listener/!mp_capable */
 };
-- 
2.21.0

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2019-12-02 10:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-02 10:24 [MPTCP] [PATCH 2/3] mptcp: avoid data stream corruption on allocation failure Paolo Abeni

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.