MPTCP Linux Development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Anil Kaushik" <anilkaushikwireless@gmail.com>, mptcp@lists.linux.dev
Subject: Re: [PATCH mptcp-next v8 4/6] mptcp: pm: in-kernel: retry subflows closed after an error
Date: Thu, 22 Oct 2026 15:49:40 +0000	[thread overview]
Message-ID: <sashiko-outbox-181728@kernel.org> (raw)
In-Reply-To: <20261022151130.2285198-5-anilkaushikwireless@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] mptcp: race in mptcp_close_retry_subflows() due to unlocked ssk state check
--

commit c03fc05db7095624e90e910918ec9a00af7081a3
Author: Anil Kaushik <anilkaushikwireless@gmail.com>

mptcp: pm: in-kernel: retry subflows closed after an error

This commit teaches the in-kernel path manager to re-create established
client-initiated or joined subflows that were closed by TCP after a path
timeout error. It also closes any re-created subflows that are still
connecting when the parent MPTCP socket is closed.

> diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
> index 02a4f479d9d8c..f941533a1eb48 100644
> --- a/net/mptcp/protocol.c
> +++ b/net/mptcp/protocol.c

[ ... ]

> @@ -3501,6 +3506,34 @@ static void mptcp_check_listen_stop(struct sock *sk)
>  	release_sock(ssk);
>  }
>  
> +/* Re-created subflows still connecting are useless once the msk is closed,
> + * and their SYN retransmissions could keep them around for a long time.
> + */
> +static void mptcp_close_retry_subflows(struct sock *sk)
> +{
> +	struct mptcp_subflow_context *subflow, *tmp;
> +	struct mptcp_sock *msk = mptcp_sk(sk);
> +
> +	mptcp_for_each_subflow_safe(msk, subflow, tmp) {
> +		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
> +		int state;
> +
> +		if (!subflow->retry || READ_ONCE(subflow->fully_established))
> +			continue;
> +
> +		/* still connecting, or already disconnected by
> +		 * mptcp_subflow_shutdown(), e.g. after shutdown(SHUT_WR)
> +		 */
> +		state = inet_sk_state_load(ssk);
> +		if (state != TCP_SYN_SENT && state != TCP_CLOSE)
> +			continue;
> +
> +		/* it never carried data: nothing to push or re-inject */
> +		mptcp_pm_subflow_check_next(msk, subflow);
> +		__mptcp_close_ssk(sk, ssk, subflow, 0);
> +	}
> +}

[Severity: High]
Can mptcp_close_retry_subflows() in net/mptcp/protocol.c race with softirq
packet processing on ssk because subflow->fully_established and
inet_sk_state_load(ssk) are checked before ssk is locked in
__mptcp_close_ssk()?

When __mptcp_close() calls mptcp_close_retry_subflows(sk), the msk socket
lock is held, sk->sk_state is still TCP_ESTABLISHED, and msk->allow_subflows
is true, while ssk is not locked until __mptcp_close_ssk() runs:

net/mptcp/protocol.c:__mptcp_close_ssk() {
    lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
    subflow->closing = 1;

    if (flags & MPTCP_CF_PUSH)
        mptcp_cleanup_ssk_backlog(sk, ssk);
    ...
}

Between the lockless checks in mptcp_close_retry_subflows() and
lock_sock_nested(ssk) in __mptcp_close_ssk(), TCP softirq on another CPU can
process incoming packets under bh_lock_sock_nested(ssk):

1. If ssk is observed in TCP_SYN_SENT, an incoming MP_JOIN handshake can
transition ssk to TCP_ESTABLISHED via:

  tcp_rcv_synsent_state_process()
    -> subflow_finish_connect()
      -> mptcp_finish_join()

which succeeds without acquiring the msk socket lock because subflow->node
is on msk->conn_list and msk->allow_subflows is true. A subsequent packet
carrying the 4th ACK and DSS data can then set subflow->fully_established =
true in check_fully_established() and queue skbs onto msk->backlog_list via:

  subflow_data_ready()
    -> mptcp_data_ready()
      -> __mptcp_move_skbs_from_subflow(msk, ssk, false)
        -> __mptcp_add_backlog()

which sets skb->destructor = NULL and skb->sk = ssk while leaving
skb->truesize charged to ssk->sk_rmem_alloc.

2. Similarly, if ssk already completed the 3-way handshake
(TCP_ESTABLISHED, subflow->fully_established == false) when
READ_ONCE(subflow->fully_established) is checked, softirq can process the
4th ACK with DSS data (queuing skbs onto msk->backlog_list) and then a
subsequent FIN or RST transitioning ssk to TCP_CLOSE before
inet_sk_state_load(ssk) is read.

When __mptcp_close_ssk(sk, ssk, subflow, 0) then runs without MPTCP_CF_PUSH,
it skips mptcp_cleanup_ssk_backlog(sk, ssk) and destroys ssk while skbs on
msk->backlog_list still hold skb->sk = ssk:

net/mptcp/protocol.h:mptcp_borrow_fwdmem() {
    struct sock *ssk = skb->sk;
    ...
    if (!ssk)
        return;

    atomic_sub(skb->truesize, &ssk->sk_rmem_alloc);
    skb->sk = NULL;
}

Wouldn't this trigger the sk->sk_rmem_alloc warning in inet_sock_destruct()
and a use-after-free atomic_sub() on ssk->sk_rmem_alloc in
mptcp_borrow_fwdmem() when msk->backlog_list is later drained or purged?

不断地

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261022151130.2285198-1-anilkaushikwireless@gmail.com?part=4

  reply	other threads:[~2026-10-22 15:49 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-22 15:11 [PATCH mptcp-next v8 0/6] mptcp: pm: in-kernel: retry subflows closed after an error Anil Kaushik
2026-10-22 15:11 ` [PATCH mptcp-next v8 1/6] selftests: mptcp: connect: retry write() on EAGAIN Anil Kaushik
2026-10-22 15:11 ` [PATCH mptcp-next v8 2/6] netlink: specs: mptcp: add the subflow-retries attribute Anil Kaushik
2026-10-24  6:11   ` netdev-bot+sashiko
2026-10-22 15:11 ` [PATCH mptcp-next v8 3/6] mptcp: pm: in-kernel: add the subflow-retries limit Anil Kaushik
2026-10-22 15:11 ` [PATCH mptcp-next v8 4/6] mptcp: pm: in-kernel: retry subflows closed after an error Anil Kaushik
2026-10-22 15:49   ` sashiko-bot [this message]
2026-10-24  6:11   ` netdev-bot+sashiko
2026-10-22 15:11 ` [PATCH mptcp-next v8 5/6] selftests: mptcp: pm_nl_ctl: support the subflow-retries limit Anil Kaushik
2026-10-24  6:11   ` netdev-bot+sashiko
2026-10-22 15:11 ` [PATCH mptcp-next v8 6/6] selftests: mptcp: join: validate subflow retry after link failure Anil Kaushik
2026-10-22 15:34   ` sashiko-bot
2026-10-24  6:11   ` netdev-bot+sashiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-181728@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=anilkaushikwireless@gmail.com \
    --cc=mptcp@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox