[PATCH mptcp-next] Squash-to: "mptcp: cleanup MPJ subflow list handling"

Paolo Abeni posted 1 patch 9 months, 2 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/multipath-tcp/mptcp_net-next tags/patchew/70e15da075bab481ac07ed1ce8c2adc9740403c6.1639665203.git.pabeni@redhat.com
Maintainers: Jakub Kicinski <kuba@kernel.org>, Mat Martineau <mathew.j.martineau@linux.intel.com>, Matthieu Baerts <matthieu.baerts@tessares.net>, "David S. Miller" <davem@davemloft.net>
net/mptcp/protocol.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
[PATCH mptcp-next] Squash-to: "mptcp: cleanup MPJ subflow list handling"
Posted by Paolo Abeni 9 months, 2 weeks ago
The self-tests in a loop triggered a UaF similar to:

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

The critical scenario is actually almost fixed by:

"mptcp: cleanup MPJ subflow list handling"

with a notable exception: if an MPJ handshake races with
mptcp_close(), the subflow enter the join_list and __mptcp_finish_join()
is processed at the msk socket lock release in mptcp_close(),
the subflow will preserver a danfling reference to the msk sk_socket.

Address the issue fragting the subflow only on successful
__mptcp_finish_join()

Note that issues/250 triggers even before
"mptcp: cleanup MPJ subflow list handling", as before such commit the join
list was not spliced by mptcp_close(). We could consider a net-only patch to
address that.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/mptcp/protocol.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index e81fd46a43c4..e89d7741aa7f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -810,9 +810,17 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
 
 static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
 {
-	if (((struct sock *)msk)->sk_state != TCP_ESTABLISHED)
+	struct sock *sk = (struct sock *)msk;
+
+	if (sk->sk_state != TCP_ESTABLISHED)
 		return false;
 
+	/* attach to msk socket only after we are sure we will deal with it
+	 * at close time
+	 */
+	if (sk->sk_socket && !ssk->sk_socket)
+		mptcp_sock_graft(ssk, sk->sk_socket);
+
 	mptcp_propagate_sndbuf((struct sock *)msk, ssk);
 	mptcp_sockopt_sync_locked(msk, ssk);
 	WRITE_ONCE(msk->allow_infinite_fallback, false);
@@ -3234,7 +3242,6 @@ bool mptcp_finish_join(struct sock *ssk)
 	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
 	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
 	struct sock *parent = (void *)msk;
-	struct socket *parent_sock;
 	bool ret = true;
 
 	pr_debug("msk=%p, subflow=%p", msk, subflow);
@@ -3278,13 +3285,6 @@ bool mptcp_finish_join(struct sock *ssk)
 		return false;
 	}
 
-	/* attach to msk socket only after we are sure he will deal with us
-	 * at close time
-	 */
-	parent_sock = READ_ONCE(parent->sk_socket);
-	if (parent_sock && !ssk->sk_socket)
-		mptcp_sock_graft(ssk, parent_sock);
-
 	subflow->map_seq = READ_ONCE(msk->ack_seq);
 
 out:
-- 
2.33.1


Re: [PATCH mptcp-next] Squash-to: "mptcp: cleanup MPJ subflow list handling"
Posted by Mat Martineau 9 months, 2 weeks ago
On Thu, 16 Dec 2021, Paolo Abeni wrote:

> The self-tests in a loop triggered a UaF similar to:
> 
> https://github.com/multipath-tcp/mptcp_net-next/issues/250
> 
> The critical scenario is actually almost fixed by:
> 
> "mptcp: cleanup MPJ subflow list handling"
> 
> with a notable exception: if an MPJ handshake races with
> mptcp_close(), the subflow enter the join_list and __mptcp_finish_join()
> is processed at the msk socket lock release in mptcp_close(),
> the subflow will preserver a danfling reference to the msk sk_socket.
> 
> Address the issue fragting the subflow only on successful
                     ^^^^^^^^ grafting?

Change looks good to squash, and the tests (other than the one ipv6 issue) 
are ok on my local system.

> __mptcp_finish_join()
> 
> Note that issues/250 triggers even before
> "mptcp: cleanup MPJ subflow list handling", as before such commit the join
> list was not spliced by mptcp_close(). We could consider a net-only patch to
> address that.

Yes, definitely need something for #250 in net.


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

> 
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
>  net/mptcp/protocol.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index e81fd46a43c4..e89d7741aa7f 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c
> @@ -810,9 +810,17 @@ void mptcp_data_ready(struct sock *sk, struct sock *ssk)
>
>  static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
>  {
> -	if (((struct sock *)msk)->sk_state != TCP_ESTABLISHED)
> +	struct sock *sk = (struct sock *)msk;
> +
> +	if (sk->sk_state != TCP_ESTABLISHED)
>  		return false;
> 
> +	/* attach to msk socket only after we are sure we will deal with it
> +	 * at close time
> +	 */
> +	if (sk->sk_socket && !ssk->sk_socket)
> +		mptcp_sock_graft(ssk, sk->sk_socket);
> +
>  	mptcp_propagate_sndbuf((struct sock *)msk, ssk);
>  	mptcp_sockopt_sync_locked(msk, ssk);
>  	WRITE_ONCE(msk->allow_infinite_fallback, false);
> @@ -3234,7 +3242,6 @@ bool mptcp_finish_join(struct sock *ssk)
>  	struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
>  	struct mptcp_sock *msk = mptcp_sk(subflow->conn);
>  	struct sock *parent = (void *)msk;
> -	struct socket *parent_sock;
>  	bool ret = true;
>
>  	pr_debug("msk=%p, subflow=%p", msk, subflow);
> @@ -3278,13 +3285,6 @@ bool mptcp_finish_join(struct sock *ssk)
>  		return false;
>  	}
> 
> -	/* attach to msk socket only after we are sure he will deal with us
> -	 * at close time
> -	 */
> -	parent_sock = READ_ONCE(parent->sk_socket);
> -	if (parent_sock && !ssk->sk_socket)
> -		mptcp_sock_graft(ssk, parent_sock);
> -
>  	subflow->map_seq = READ_ONCE(msk->ack_seq);
>
>  out:
> -- 
> 2.33.1
> 
> 
>

--
Mat Martineau
Intel

Re: [PATCH mptcp-next] Squash-to: "mptcp: cleanup MPJ subflow list handling"
Posted by Matthieu Baerts 9 months, 2 weeks ago
Hi Paolo, Mat,

On 16/12/2021 15:33, Paolo Abeni wrote:
> The self-tests in a loop triggered a UaF similar to:
> 
> https://github.com/multipath-tcp/mptcp_net-next/issues/250
> 
> The critical scenario is actually almost fixed by:
> 
> "mptcp: cleanup MPJ subflow list handling"
> 
> with a notable exception: if an MPJ handshake races with
> mptcp_close(), the subflow enter the join_list and __mptcp_finish_join()
> is processed at the msk socket lock release in mptcp_close(),
> the subflow will preserver a danfling reference to the msk sk_socket.
> 
> Address the issue fragting the subflow only on successful
> __mptcp_finish_join()

Thank you for the patch and the review!

Now in our tree:

- 494ff5ec1dd6: "squashed" in "mptcp: cleanup MPJ subflow list handling"
- Results: cabf1e05f011..82c91858f45c

Builds and tests are now in progress:

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

> Note that issues/250 triggers even before
> "mptcp: cleanup MPJ subflow list handling", as before such commit the join
> list was not spliced by mptcp_close(). We could consider a net-only patch to
> address that.
Please note I didn't close issues/250 for this reason.

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