mptcp.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH mptcp 0/2] mptcp: a couple of fix - almost
@ 2021-08-20 17:44 Paolo Abeni
  2021-08-20 17:44 ` [PATCH mptcp 1/2] mptcp: fix possible divide by zero Paolo Abeni
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Paolo Abeni @ 2021-08-20 17:44 UTC (permalink / raw)
  To: mptcp

This are couple of changes poped-up while investigating
issues/219. They does not address the mentioned issue,
but the first one should fix an actual bug, the other
is more a cleanup, so the target tree is undefined ;)

Paolo Abeni (2):
  mptcp: fix possible divide by zero
  mptcp: make the locking tx schema more readable

 net/mptcp/protocol.c | 73 +++++++++++++++++++++-----------------------
 1 file changed, 35 insertions(+), 38 deletions(-)

-- 
2.26.3


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

* [PATCH mptcp 1/2] mptcp: fix possible divide by zero
  2021-08-20 17:44 [PATCH mptcp 0/2] mptcp: a couple of fix - almost Paolo Abeni
@ 2021-08-20 17:44 ` Paolo Abeni
  2021-08-20 17:53   ` Mat Martineau
  2021-08-24  7:28   ` Matthieu Baerts
  2021-08-20 17:44 ` [PATCH mptcp 2/2] mptcp: make the locking tx schema more readable Paolo Abeni
  2021-08-20 23:02 ` [PATCH mptcp 0/2] mptcp: a couple of fix - almost Mat Martineau
  2 siblings, 2 replies; 7+ messages in thread
From: Paolo Abeni @ 2021-08-20 17:44 UTC (permalink / raw)
  To: mptcp

Florian noted that if mptcp_alloc_tx_skb() allocation fails
in __mptcp_push_pending(), we can end-up invoking
mptcp_push_release()/tcp_push() with a zero mss, causing
a divide by 0 error.

This change addresses the issue refactoring the skb allocation
code so that skb allocation always happens after the call
to tcp_send_mss() correctly initialize mss_now.

As side bonuses we now fill the skb tx cache only when needed,
and this also clean-up a bit the output path.

Reported-by: Florian Westphal <fw@strlen.de>
Fixes: 724cfd2ee8aa ("mptcp: allocate TX skbs in msk context")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/mptcp/protocol.c | 63 ++++++++++++++++++++------------------------
 1 file changed, 28 insertions(+), 35 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index b5f8ad634571..84aa11a0b2d5 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1003,6 +1003,15 @@ static void mptcp_wmem_uncharge(struct sock *sk, int size)
 	msk->wmem_reserved += size;
 }
 
+static void __mptcp_mem_reclaim_partial(struct sock *sk)
+{
+#ifdef CONFIG_LOCKDEP
+	WARN_ON_ONCE(!lockdep_is_held(&sk->sk_lock.slock));
+#endif
+	__mptcp_update_wmem(sk);
+	sk_mem_reclaim_partial(sk);
+}
+
 static void mptcp_mem_reclaim_partial(struct sock *sk)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1094,12 +1103,8 @@ static void __mptcp_clean_una(struct sock *sk)
 		msk->recovery = false;
 
 out:
-	if (cleaned) {
-		if (tcp_under_memory_pressure(sk)) {
-			__mptcp_update_wmem(sk);
-			sk_mem_reclaim_partial(sk);
-		}
-	}
+	if (cleaned && tcp_under_memory_pressure(sk))
+		__mptcp_mem_reclaim_partial(sk);
 
 	if (snd_una == READ_ONCE(msk->snd_nxt) && !msk->recovery) {
 		if (mptcp_timer_pending(sk) && !mptcp_data_fin_enabled(msk))
@@ -1179,6 +1184,7 @@ struct mptcp_sendmsg_info {
 	u16 limit;
 	u16 sent;
 	unsigned int flags;
+	bool data_lock_held;
 };
 
 static int mptcp_check_allowed_size(struct mptcp_sock *msk, u64 data_seq,
@@ -1250,17 +1256,17 @@ static bool __mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, gfp_t gfp)
 	return false;
 }
 
-static bool mptcp_must_reclaim_memory(struct sock *sk, struct sock *ssk)
+static bool mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk, bool data_lock_held)
 {
-	return !ssk->sk_tx_skb_cache &&
-	       tcp_under_memory_pressure(sk);
-}
+	gfp_t gfp = data_lock_held ? GFP_ATOMIC : sk->sk_allocation;
 
-static bool mptcp_alloc_tx_skb(struct sock *sk, struct sock *ssk)
-{
-	if (unlikely(mptcp_must_reclaim_memory(sk, ssk)))
-		mptcp_mem_reclaim_partial(sk);
-	return __mptcp_alloc_tx_skb(sk, ssk, sk->sk_allocation);
+	if (unlikely(tcp_under_memory_pressure(sk))) {
+		if (data_lock_held)
+			__mptcp_mem_reclaim_partial(sk);
+		else
+			mptcp_mem_reclaim_partial(sk);
+	}
+	return __mptcp_alloc_tx_skb(sk, ssk, gfp);
 }
 
 /* note: this always recompute the csum on the whole skb, even
@@ -1314,6 +1320,10 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 		}
 	}
 
+	if (!can_collapse && !ssk->sk_tx_skb_cache &&
+	    !mptcp_alloc_tx_skb(sk, ssk, info->data_lock_held))
+		return 0;
+
 	/* Zero window and all data acked? Probe. */
 	avail_size = mptcp_check_allowed_size(msk, data_seq, avail_size);
 	if (avail_size == 0) {
@@ -1526,15 +1536,6 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 			if (ssk != prev_ssk || !prev_ssk)
 				lock_sock(ssk);
 
-			/* keep it simple and always provide a new skb for the
-			 * subflow, even if we will not use it when collapsing
-			 * on the pending one
-			 */
-			if (!mptcp_alloc_tx_skb(sk, ssk)) {
-				mptcp_push_release(sk, ssk, &info);
-				goto out;
-			}
-
 			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
 			if (ret <= 0) {
 				mptcp_push_release(sk, ssk, &info);
@@ -1567,7 +1568,9 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
-	struct mptcp_sendmsg_info info;
+	struct mptcp_sendmsg_info info = {
+				 .data_lock_held = true,
+	};
 	struct mptcp_data_frag *dfrag;
 	struct sock *xmit_ssk;
 	int len, copied = 0;
@@ -1593,13 +1596,6 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
 				goto out;
 			}
 
-			if (unlikely(mptcp_must_reclaim_memory(sk, ssk))) {
-				__mptcp_update_wmem(sk);
-				sk_mem_reclaim_partial(sk);
-			}
-			if (!__mptcp_alloc_tx_skb(sk, ssk, GFP_ATOMIC))
-				goto out;
-
 			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
 			if (ret <= 0)
 				goto out;
@@ -2405,9 +2401,6 @@ static void __mptcp_retrans(struct sock *sk)
 	info.sent = 0;
 	info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len : dfrag->already_sent;
 	while (info.sent < info.limit) {
-		if (!mptcp_alloc_tx_skb(sk, ssk))
-			break;
-
 		ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
 		if (ret <= 0)
 			break;
-- 
2.26.3


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

* [PATCH mptcp 2/2] mptcp: make the locking tx schema more readable
  2021-08-20 17:44 [PATCH mptcp 0/2] mptcp: a couple of fix - almost Paolo Abeni
  2021-08-20 17:44 ` [PATCH mptcp 1/2] mptcp: fix possible divide by zero Paolo Abeni
@ 2021-08-20 17:44 ` Paolo Abeni
  2021-08-20 23:02 ` [PATCH mptcp 0/2] mptcp: a couple of fix - almost Mat Martineau
  2 siblings, 0 replies; 7+ messages in thread
From: Paolo Abeni @ 2021-08-20 17:44 UTC (permalink / raw)
  To: mptcp

Florian noted the locking schema used by __mptcp_push_pending()
is hard to follow, let's add some more descriptive comments
and drop an unneeded and confusing check.

Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/mptcp/protocol.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 84aa11a0b2d5..cd690794e22b 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1525,15 +1525,19 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 			mptcp_flush_join_list(msk);
 			ssk = mptcp_subflow_get_send(msk);
 
-			/* try to keep the subflow socket lock across
-			 * consecutive xmit on the same socket
+			/* First check. If the ssk has changed since
+			 * the last round, release prev_ssk
 			 */
 			if (ssk != prev_ssk && prev_ssk)
 				mptcp_push_release(sk, prev_ssk, &info);
 			if (!ssk)
 				goto out;
 
-			if (ssk != prev_ssk || !prev_ssk)
+			/* Need to lock the new subflow only if different
+			 * from the previous one, otherwise we are still
+			 * helding the relevant lock
+			 */
+			if (ssk != prev_ssk)
 				lock_sock(ssk);
 
 			ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
-- 
2.26.3


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

* Re: [PATCH mptcp 1/2] mptcp: fix possible divide by zero
  2021-08-20 17:44 ` [PATCH mptcp 1/2] mptcp: fix possible divide by zero Paolo Abeni
@ 2021-08-20 17:53   ` Mat Martineau
  2021-08-24  7:28   ` Matthieu Baerts
  1 sibling, 0 replies; 7+ messages in thread
From: Mat Martineau @ 2021-08-20 17:53 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp


On Fri, 20 Aug 2021, Paolo Abeni wrote:

> Florian noted that if mptcp_alloc_tx_skb() allocation fails
> in __mptcp_push_pending(), we can end-up invoking
> mptcp_push_release()/tcp_push() with a zero mss, causing
> a divide by 0 error.
>

I'll start running this in syzkaller now and then follow up later with 
review comments - thanks!


- Mat

> This change addresses the issue refactoring the skb allocation
> code so that skb allocation always happens after the call
> to tcp_send_mss() correctly initialize mss_now.
>
> As side bonuses we now fill the skb tx cache only when needed,
> and this also clean-up a bit the output path.
>
> Reported-by: Florian Westphal <fw@strlen.de>
> Fixes: 724cfd2ee8aa ("mptcp: allocate TX skbs in msk context")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
> net/mptcp/protocol.c | 63 ++++++++++++++++++++------------------------
> 1 file changed, 28 insertions(+), 35 deletions(-)

--
Mat Martineau
Intel

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

* Re: [PATCH mptcp 0/2] mptcp: a couple of fix - almost
  2021-08-20 17:44 [PATCH mptcp 0/2] mptcp: a couple of fix - almost Paolo Abeni
  2021-08-20 17:44 ` [PATCH mptcp 1/2] mptcp: fix possible divide by zero Paolo Abeni
  2021-08-20 17:44 ` [PATCH mptcp 2/2] mptcp: make the locking tx schema more readable Paolo Abeni
@ 2021-08-20 23:02 ` Mat Martineau
  2021-08-23  7:16   ` Matthieu Baerts
  2 siblings, 1 reply; 7+ messages in thread
From: Mat Martineau @ 2021-08-20 23:02 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: mptcp

On Fri, 20 Aug 2021, Paolo Abeni wrote:

> This are couple of changes poped-up while investigating
> issues/219. They does not address the mentioned issue,
> but the first one should fix an actual bug, the other
> is more a cleanup, so the target tree is undefined ;)
>
> Paolo Abeni (2):
>  mptcp: fix possible divide by zero
>  mptcp: make the locking tx schema more readable
>
> net/mptcp/protocol.c | 73 +++++++++++++++++++++-----------------------
> 1 file changed, 35 insertions(+), 38 deletions(-)
>
> -- 
> 2.26.3

So far my syzkaller setup hasn't seen the div-by-0 again, but it was 
typically taking days to show up. I'll leave that running over the 
weekend.

Changes look good to me - mptcp_push_release() is now only called from 
places where info->mss_now is non-zero.

Patch 1 for -net, patch 2 for net-next seems appropriate.

Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>

--
Mat Martineau
Intel

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

* Re: [PATCH mptcp 0/2] mptcp: a couple of fix - almost
  2021-08-20 23:02 ` [PATCH mptcp 0/2] mptcp: a couple of fix - almost Mat Martineau
@ 2021-08-23  7:16   ` Matthieu Baerts
  0 siblings, 0 replies; 7+ messages in thread
From: Matthieu Baerts @ 2021-08-23  7:16 UTC (permalink / raw)
  To: Mat Martineau, Paolo Abeni; +Cc: mptcp

Hi Paolo, Florian, Mat,

On 21/08/2021 01:02, Mat Martineau wrote:
> On Fri, 20 Aug 2021, Paolo Abeni wrote:
> 
>> This are couple of changes poped-up while investigating
>> issues/219. They does not address the mentioned issue,
>> but the first one should fix an actual bug, the other
>> is more a cleanup, so the target tree is undefined ;)
> 
> So far my syzkaller setup hasn't seen the div-by-0 again, but it was
> typically taking days to show up. I'll leave that running over the weekend.
> 
> Changes look good to me - mptcp_push_release() is now only called from
> places where info->mss_now is non-zero.
> 
> Patch 1 for -net, patch 2 for net-next seems appropriate.

Thank you for the patches, the suggestions and the reviews!

These two patches are now in our tree (net and net-next) with Mat's RvB tag:

- 5d8855f6a71f: mptcp: fix possible divide by zero
- Results: 84fc11b83a29..653135eedf64
- 33708631c1fd: mptcp: make the locking tx schema more readable
- Results: 653135eedf64..ebac4c6745a4

Builds and tests are now in progress:

https://cirrus-ci.com/github/multipath-tcp/mptcp_net-next/export/20210823T071618
https://github.com/multipath-tcp/mptcp_net-next/actions/workflows/build-validation.yml?query=branch:export/20210823T071618

Cheers,
Matt
-- 
Tessares | Belgium | Hybrid Access Solutions
www.tessares.net

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

* Re: [PATCH mptcp 1/2] mptcp: fix possible divide by zero
  2021-08-20 17:44 ` [PATCH mptcp 1/2] mptcp: fix possible divide by zero Paolo Abeni
  2021-08-20 17:53   ` Mat Martineau
@ 2021-08-24  7:28   ` Matthieu Baerts
  1 sibling, 0 replies; 7+ messages in thread
From: Matthieu Baerts @ 2021-08-24  7:28 UTC (permalink / raw)
  To: mptcp; +Cc: Paolo Abeni

Hello

On 20/08/2021 19:44, Paolo Abeni wrote:
> Florian noted that if mptcp_alloc_tx_skb() allocation fails
> in __mptcp_push_pending(), we can end-up invoking
> mptcp_push_release()/tcp_push() with a zero mss, causing
> a divide by 0 error.
> 
> This change addresses the issue refactoring the skb allocation
> code so that skb allocation always happens after the call
> to tcp_send_mss() correctly initialize mss_now.
> 
> As side bonuses we now fill the skb tx cache only when needed,
> and this also clean-up a bit the output path.

For those who might have missed the info, a regression has been
introduced by this patch.

This is tracked on Github:

  https://github.com/multipath-tcp/mptcp_net-next/issues/227

(Paolo already shared a patch that seems fixing the issue)

Cheers,
Matt
-- 
Tessares | Belgium | Hybrid Access Solutions
www.tessares.net

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

end of thread, other threads:[~2021-08-24  7:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-20 17:44 [PATCH mptcp 0/2] mptcp: a couple of fix - almost Paolo Abeni
2021-08-20 17:44 ` [PATCH mptcp 1/2] mptcp: fix possible divide by zero Paolo Abeni
2021-08-20 17:53   ` Mat Martineau
2021-08-24  7:28   ` Matthieu Baerts
2021-08-20 17:44 ` [PATCH mptcp 2/2] mptcp: make the locking tx schema more readable Paolo Abeni
2021-08-20 23:02 ` [PATCH mptcp 0/2] mptcp: a couple of fix - almost Mat Martineau
2021-08-23  7:16   ` Matthieu Baerts

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).