All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: matttbe@kernel.org
Cc: Jakub Kicinski <kuba@kernel.org>,
	martineau@kernel.org, geliang@kernel.org, davem@davemloft.net,
	edumazet@google.com, pabeni@redhat.com, horms@kernel.org,
	netdev@vger.kernel.org, mptcp@lists.linux.dev,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH net 08/14] mptcp: pm: reset retrans_time when ADD_ADDR entry is reused
Date: Thu, 27 Aug 2026 12:07:28 -0700	[thread overview]
Message-ID: <20260827190728.3998323-1-kuba@kernel.org> (raw)
In-Reply-To: <20260824-net-mptcp-misc-fixes-7-3-rc1-v1-8-a92309d121ca@kernel.org>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
mptcp: pm: reset retrans_time when ADD_ADDR entry is reused

This moves the retrans_times reset from the fresh-allocation path into the
shared reset_timer block of mptcp_pm_announced_alloc(), so a reused
ADD_ADDR entry gets its retransmission budget back when the timer is
re-armed.

Link: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260803-net-mptcp-misc-fixes-7-2-rc6-v2-0-b8f496d71664%40kernel.org?part=4

> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index 8b68868255c50..b0b71adefb8fe 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -462,10 +462,10 @@ bool mptcp_pm_announced_alloc(struct mptcp_sock *msk,
>  
>  	add_entry->addr = *addr;
>  	add_entry->sock = msk;
> -	add_entry->retrans_times = 0;
>  
>  	timer_setup(&add_entry->timer, mptcp_pm_add_addr_timer, 0);
>  reset_timer:
> +	add_entry->retrans_times = 0;
>  	add_entry->timer_done = false;
>  	timeout = mptcp_adjust_add_addr_timeout(msk);
>  	if (timeout)

[Severity: High]
This isn't a bug introduced by this patch, since the reset_timer block
already contained the timer_done = false plus sk_reset_timer() pair, but
since the patch adds another store into exactly this block, is the block
sufficiently serialized against the timer callback?

The reuse path runs from mptcp_pm_nl_announce_doit(), which holds
lock_sock(sk) and msk->pm.lock:

net/mptcp/pm_userspace.c:mptcp_pm_nl_announce_doit() {
	lock_sock(sk);
	spin_lock_bh(&msk->pm.lock);

	if (mptcp_pm_announced_alloc(msk, &addr_val.addr)) {
	...
}

mptcp_pm_add_addr_timer() writes timer_done under bh_lock_sock() only, and
its TCP_CLOSE early-out comes before the sock_owned_by_user() deferral:

net/mptcp/pm.c:mptcp_pm_add_addr_timer() {
	bh_lock_sock(sk);
	if (unlikely(inet_sk_state_load(sk) == TCP_CLOSE))
		goto out;

	if (sock_owned_by_user(sk)) {
		/* Try again later. */
		timeout = HZ / 20;
		goto out;
	}
	...
out:
	if (timeout)
		sk_reset_timer(sk, timer, jiffies + timeout);
	else
		/* if sock_put calls sk_free: avoid waiting for this timer */
		entry->timer_done = true;
	bh_unlock_sock(sk);
	sock_put(sk);
}

In TCP_CLOSE the callback reaches out: with timeout == 0 and stores
timer_done = true even when a process-context task owns the socket, since
lock_sock() only sets the owned flag and bh_lock_sock() still succeeds.
The reuse path does not take slock and the callback does not take pm.lock
around that store, so can the two stores interleave like this?

CPU0 (MPTCP_PM_CMD_ANNOUNCE re-announce, msk in TCP_CLOSE)
mptcp_pm_announced_alloc()
    add_entry->timer_done = false;
    sk_reset_timer()   /* timer becomes pending again */

CPU1 (previously armed timer expiring)
mptcp_pm_add_addr_timer()
    bh_lock_sock(sk);
    inet_sk_state_load(sk) == TCP_CLOSE -> goto out
    entry->timer_done = true;   /* lands after CPU0 re-armed */

That would leave the timer pending with timer_done == true, and teardown
via mptcp_pm_destroy()->mptcp_pm_free_announced_list() skips the sync stop
in that case:

net/mptcp/pm.c:mptcp_pm_free_announced_list() {
	list_for_each_entry_safe(entry, tmp, &free_list, list) {
		if (!entry->timer_done)
			sk_stop_timer_sync(sk, &entry->timer);
		kfree_rcu(entry, rcu);
	}
}

Can the still-queued timer then fire on the freed entry after the RCU
grace period, reading entry->sock and calling sock_put() on it? The
remaining expiry can be as long as the add_addr_timeout value, which is
much longer than a grace period.

For reachability, mptcp_pm_announced_alloc() only rejects
MPTCP_PM_DESTROYING, and mptcp_pm_nl_announce_doit() does no socket-state
check, so an msk sitting in TCP_CLOSE with a live token and an open fd
still reaches the reuse path.

Would stopping the timer (or taking bh_lock_sock()) before re-arming in
the reset_timer block, or moving the TCP_CLOSE check after the
sock_owned_by_user() check in mptcp_pm_add_addr_timer(), close this?

Also noting that no later patch in this series touches net/mptcp/pm.c, so
this state persists at the end of the series.

  reply	other threads:[~2026-08-27 19:07 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-24 16:48 [PATCH net 00/14] mptcp: misc fixes for v7.3-rc1 Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 01/14] mptcp: do not reschedule the RTX timer for fallback sockets Matthieu Baerts (NGI0)
2026-08-25 16:49   ` sashiko-bot
2026-08-27 19:07   ` Jakub Kicinski
2026-08-28  6:35     ` Paolo Abeni
2026-08-24 16:48 ` [PATCH net 02/14] mptcp: subflow: no need to copy thmac during ulp_clone Matthieu Baerts (NGI0)
2026-08-27 19:07   ` Jakub Kicinski
2026-08-28  9:58     ` Matthieu Baerts
2026-08-24 16:48 ` [PATCH net 03/14] mptcp: syncookies: remember the request backup flag Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 04/14] mptcp: pm: kernel: drop pending ADD_ADDR when removing ID0 Matthieu Baerts (NGI0)
2026-08-25 16:49   ` sashiko-bot
2026-08-27 19:07   ` Jakub Kicinski
2026-08-24 16:48 ` [PATCH net 05/14] mptcp: options: handle MPC data + csum reqd + no csum Matthieu Baerts (NGI0)
2026-08-27 19:07   ` Jakub Kicinski
2026-08-24 16:48 ` [PATCH net 06/14] selftests: mptcp: fix an UAF in mptcp_connect.c Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 07/14] mptcp: pm: userspace: fix address ID overflow Matthieu Baerts (NGI0)
2026-08-25 16:49   ` sashiko-bot
2026-08-24 16:48 ` [PATCH net 08/14] mptcp: pm: reset retrans_time when ADD_ADDR entry is reused Matthieu Baerts (NGI0)
2026-08-27 19:07   ` Jakub Kicinski [this message]
2026-08-24 16:48 ` [PATCH net 09/14] mptcp: remove unneeded READ_ONCE() annotation Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 10/14] selftests: mptcp: lib: dump nstat for the right test Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 11/14] selftests: mptcp: lib: get counters " Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 12/14] mptcp: options: fix uninit-value in mptcp_write_data_fin Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 13/14] mptcp: being below memory limit is a likely() condition Matthieu Baerts (NGI0)
2026-08-24 16:48 ` [PATCH net 14/14] mptcp: avoid pruning for OoW data Matthieu Baerts (NGI0)

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=20260827190728.3998323-1-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=geliang@kernel.org \
    --cc=horms@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martineau@kernel.org \
    --cc=matttbe@kernel.org \
    --cc=mptcp@lists.linux.dev \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=stable@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.