netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] mptcp: fix 'attempt to release socket in state...' splats
@ 2020-04-17  7:28 Florian Westphal
  2020-04-17  7:28 ` [PATCH net 1/2] mptcp: fix splat when incoming connection is never accepted before exit/close Florian Westphal
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Florian Westphal @ 2020-04-17  7:28 UTC (permalink / raw)
  To: netdev

These two patches fix error handling corner-cases where
inet_sock_destruct gets called for a mptcp_sk that is not in TCP_CLOSE
state.  This results in unwanted error printks from the network stack.

 protocol.c |    8 ++++++--
 subflow.c  |   33 +++++++++++++++++++++++++++++++--
 2 files changed, 37 insertions(+), 4 deletions(-)



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

* [PATCH net 1/2] mptcp: fix splat when incoming connection is never accepted before exit/close
  2020-04-17  7:28 [PATCH net] mptcp: fix 'attempt to release socket in state...' splats Florian Westphal
@ 2020-04-17  7:28 ` Florian Westphal
  2020-04-17  7:28 ` [PATCH net 2/2] mptcp: fix 'Attempt to release TCP socket in state' warnings Florian Westphal
  2020-04-18 22:44 ` [PATCH net] mptcp: fix 'attempt to release socket in state...' splats David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2020-04-17  7:28 UTC (permalink / raw)
  To: netdev; +Cc: Florian Westphal

Following snippet (replicated from syzkaller reproducer) generates
warning: "IPv4: Attempt to release TCP socket in state 1".

int main(void) {
 struct sockaddr_in sin1 = { .sin_family = 2, .sin_port = 0x4e20,
                             .sin_addr.s_addr = 0x010000e0, };
 struct sockaddr_in sin2 = { .sin_family = 2,
	                     .sin_addr.s_addr = 0x0100007f, };
 struct sockaddr_in sin3 = { .sin_family = 2, .sin_port = 0x4e20,
	                     .sin_addr.s_addr = 0x0100007f, };
 int r0 = socket(0x2, 0x1, 0x106);
 int r1 = socket(0x2, 0x1, 0x106);

 bind(r1, (void *)&sin1, sizeof(sin1));
 connect(r1, (void *)&sin2, sizeof(sin2));
 listen(r1, 3);
 return connect(r0, (void *)&sin3, 0x4d);
}

Reason is that the newly generated mptcp socket is closed via the ulp
release of the tcp listener socket when its accept backlog gets purged.

To fix this, delay setting the ESTABLISHED state until after userspace
calls accept and via mptcp specific destructor.

Fixes: 58b09919626bf ("mptcp: create msk early")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/9
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/mptcp/protocol.c |  1 +
 net/mptcp/subflow.c  | 25 ++++++++++++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 9936e33ac351..1c8b021b4537 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1431,6 +1431,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
 		newsk = new_mptcp_sock;
 		mptcp_copy_inaddrs(newsk, ssk);
 		list_add(&subflow->node, &msk->conn_list);
+		inet_sk_state_store(newsk, TCP_ESTABLISHED);
 
 		bh_unlock_sock(new_mptcp_sock);
 
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 50a8bea987c6..57a836fe4988 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -347,6 +347,29 @@ static bool subflow_hmac_valid(const struct request_sock *req,
 	return ret;
 }
 
+static void mptcp_sock_destruct(struct sock *sk)
+{
+	/* if new mptcp socket isn't accepted, it is free'd
+	 * from the tcp listener sockets request queue, linked
+	 * from req->sk.  The tcp socket is released.
+	 * This calls the ULP release function which will
+	 * also remove the mptcp socket, via
+	 * sock_put(ctx->conn).
+	 *
+	 * Problem is that the mptcp socket will not be in
+	 * SYN_RECV state and doesn't have SOCK_DEAD flag.
+	 * Both result in warnings from inet_sock_destruct.
+	 */
+
+	if (sk->sk_state == TCP_SYN_RECV) {
+		sk->sk_state = TCP_CLOSE;
+		WARN_ON_ONCE(sk->sk_socket);
+		sock_orphan(sk);
+	}
+
+	inet_sock_destruct(sk);
+}
+
 static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 					  struct sk_buff *skb,
 					  struct request_sock *req,
@@ -422,7 +445,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 			/* new mpc subflow takes ownership of the newly
 			 * created mptcp socket
 			 */
-			inet_sk_state_store(new_msk, TCP_ESTABLISHED);
+			new_msk->sk_destruct = mptcp_sock_destruct;
 			mptcp_pm_new_connection(mptcp_sk(new_msk), 1);
 			ctx->conn = new_msk;
 			new_msk = NULL;
-- 
2.25.3


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

* [PATCH net 2/2] mptcp: fix 'Attempt to release TCP socket in state' warnings
  2020-04-17  7:28 [PATCH net] mptcp: fix 'attempt to release socket in state...' splats Florian Westphal
  2020-04-17  7:28 ` [PATCH net 1/2] mptcp: fix splat when incoming connection is never accepted before exit/close Florian Westphal
@ 2020-04-17  7:28 ` Florian Westphal
  2020-04-18 22:44 ` [PATCH net] mptcp: fix 'attempt to release socket in state...' splats David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2020-04-17  7:28 UTC (permalink / raw)
  To: netdev; +Cc: Florian Westphal

We need to set sk_state to CLOSED, else we will get following:

IPv4: Attempt to release TCP socket in state 3 00000000b95f109e
IPv4: Attempt to release TCP socket in state 10 00000000b95f109e

First one is from inet_sock_destruct(), second one from
mptcp_sk_clone failure handling.  Setting sk_state to CLOSED isn't
enough, we also need to orphan sk so it has DEAD flag set.
Otherwise, a very similar warning is printed from inet_sock_destruct().

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/mptcp/protocol.c | 7 +++++--
 net/mptcp/subflow.c  | 8 +++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 1c8b021b4537..7e816c733ccb 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1355,12 +1355,15 @@ struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req)
 	msk->subflow = NULL;
 
 	if (unlikely(mptcp_token_new_accept(subflow_req->token, nsk))) {
+		nsk->sk_state = TCP_CLOSE;
 		bh_unlock_sock(nsk);
 
 		/* we can't call into mptcp_close() here - possible BH context
-		 * free the sock directly
+		 * free the sock directly.
+		 * sk_clone_lock() sets nsk refcnt to two, hence call sk_free()
+		 * too.
 		 */
-		nsk->sk_prot->destroy(nsk);
+		sk_common_release(nsk);
 		sk_free(nsk);
 		return NULL;
 	}
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 57a836fe4988..bc46b5091b9d 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -370,6 +370,12 @@ static void mptcp_sock_destruct(struct sock *sk)
 	inet_sock_destruct(sk);
 }
 
+static void mptcp_force_close(struct sock *sk)
+{
+	inet_sk_state_store(sk, TCP_CLOSE);
+	sk_common_release(sk);
+}
+
 static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 					  struct sk_buff *skb,
 					  struct request_sock *req,
@@ -467,7 +473,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
 out:
 	/* dispose of the left over mptcp master, if any */
 	if (unlikely(new_msk))
-		sock_put(new_msk);
+		mptcp_force_close(new_msk);
 	return child;
 
 close_child:
-- 
2.25.3


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

* Re: [PATCH net] mptcp: fix 'attempt to release socket in state...' splats
  2020-04-17  7:28 [PATCH net] mptcp: fix 'attempt to release socket in state...' splats Florian Westphal
  2020-04-17  7:28 ` [PATCH net 1/2] mptcp: fix splat when incoming connection is never accepted before exit/close Florian Westphal
  2020-04-17  7:28 ` [PATCH net 2/2] mptcp: fix 'Attempt to release TCP socket in state' warnings Florian Westphal
@ 2020-04-18 22:44 ` David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2020-04-18 22:44 UTC (permalink / raw)
  To: fw; +Cc: netdev

From: Florian Westphal <fw@strlen.de>
Date: Fri, 17 Apr 2020 09:28:21 +0200

> These two patches fix error handling corner-cases where
> inet_sock_destruct gets called for a mptcp_sk that is not in TCP_CLOSE
> state.  This results in unwanted error printks from the network stack.

Series applied, thanks Florian.

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

end of thread, other threads:[~2020-04-18 22:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-17  7:28 [PATCH net] mptcp: fix 'attempt to release socket in state...' splats Florian Westphal
2020-04-17  7:28 ` [PATCH net 1/2] mptcp: fix splat when incoming connection is never accepted before exit/close Florian Westphal
2020-04-17  7:28 ` [PATCH net 2/2] mptcp: fix 'Attempt to release TCP socket in state' warnings Florian Westphal
2020-04-18 22:44 ` [PATCH net] mptcp: fix 'attempt to release socket in state...' splats David Miller

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).