Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
mptcp: handle correctly disconnect() failures
Browse files Browse the repository at this point in the history
commit c2b2ae3 upstream.

Currently the mptcp code has assumes that disconnect() can fail only
at mptcp_sendmsg_fastopen() time - to avoid a deadlock scenario - and
don't even bother returning an error code.

Soon mptcp_disconnect() will handle more error conditions: let's track
them explicitly.

As a bonus, explicitly annotate TCP-level disconnect as not failing:
the mptcp code never blocks for event on the subflows.

Fixes: 7d80334 ("mptcp: fix deadlock in fastopen error path")
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Tested-by: Christoph Paasch <cpaasch@apple.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Paolo Abeni authored and gregkh committed Jun 26, 2023
1 parent b9b830e commit c85b782
Showing 1 changed file with 14 additions and 6 deletions.
20 changes: 14 additions & 6 deletions net/mptcp/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1708,7 +1708,13 @@ static int mptcp_sendmsg_fastopen(struct sock *sk, struct sock *ssk, struct msgh
if (ret && ret != -EINPROGRESS && ret != -ERESTARTSYS && ret != -EINTR)
*copied_syn = 0;
} else if (ret && ret != -EINPROGRESS) {
mptcp_disconnect(sk, 0);
/* The disconnect() op called by tcp_sendmsg_fastopen()/
* __inet_stream_connect() can fail, due to looking check,
* see mptcp_disconnect().
* Attempt it again outside the problematic scope.
*/
if (!mptcp_disconnect(sk, 0))
sk->sk_socket->state = SS_UNCONNECTED;
}

return ret;
Expand Down Expand Up @@ -2375,7 +2381,10 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,

need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
if (!dispose_it) {
tcp_disconnect(ssk, 0);
/* The MPTCP code never wait on the subflow sockets, TCP-level
* disconnect should never fail
*/
WARN_ON_ONCE(tcp_disconnect(ssk, 0));
msk->subflow->state = SS_UNCONNECTED;
mptcp_subflow_ctx_reset(subflow);
release_sock(ssk);
Expand Down Expand Up @@ -2799,7 +2808,7 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
break;
fallthrough;
case TCP_SYN_SENT:
tcp_disconnect(ssk, O_NONBLOCK);
WARN_ON_ONCE(tcp_disconnect(ssk, O_NONBLOCK));
break;
default:
if (__mptcp_check_fallback(mptcp_sk(sk))) {
Expand Down Expand Up @@ -3053,11 +3062,10 @@ static int mptcp_disconnect(struct sock *sk, int flags)

/* We are on the fastopen error path. We can't call straight into the
* subflows cleanup code due to lock nesting (we are already under
* msk->firstsocket lock). Do nothing and leave the cleanup to the
* caller.
* msk->firstsocket lock).
*/
if (msk->fastopening)
return 0;
return -EBUSY;

inet_sk_state_store(sk, TCP_CLOSE);

Expand Down

0 comments on commit c85b782

Please sign in to comment.