Commit 56e639e6 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mptcp-fixes'



Florian Westphal says:

====================
mptcp: fix 'attempt to release socket in state...' splats

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

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 310660a1 9f5ca6a5
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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;
	}
@@ -1431,6 +1434,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);

+31 −2
Original line number Diff line number Diff line
@@ -347,6 +347,35 @@ 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 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,
@@ -422,7 +451,7 @@ create_child:
			/* 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;
@@ -444,7 +473,7 @@ create_child:
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: