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
next prev parent 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