Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 006ed6f4 authored by Eric Dumazet's avatar Eric Dumazet Committed by Greg Kroah-Hartman
Browse files

net/tcp_fastopen: fix data races around tfo_active_disable_stamp



[ Upstream commit 6f20c8adb1813467ea52c1296d52c4e95978cb2f ]

tfo_active_disable_stamp is read and written locklessly.
We need to annotate these accesses appropriately.

Then, we need to perform the atomic_inc(tfo_active_disable_times)
after the timestamp has been updated, and thus add barriers
to make sure tcp_fastopen_active_should_disable() wont read
a stale timestamp.

Fixes: cf1ef3f0 ("net/tcp_fastopen: Disable active side TFO in certain scenarios")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Wei Wang <weiwan@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Acked-by: default avatarWei Wang <weiwan@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 3942ba23
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -504,8 +504,15 @@ void tcp_fastopen_active_disable(struct sock *sk)
{
	struct net *net = sock_net(sk);

	/* Paired with READ_ONCE() in tcp_fastopen_active_should_disable() */
	WRITE_ONCE(net->ipv4.tfo_active_disable_stamp, jiffies);

	/* Paired with smp_rmb() in tcp_fastopen_active_should_disable().
	 * We want net->ipv4.tfo_active_disable_stamp to be updated first.
	 */
	smp_mb__before_atomic();
	atomic_inc(&net->ipv4.tfo_active_disable_times);
	net->ipv4.tfo_active_disable_stamp = jiffies;

	NET_INC_STATS(net, LINUX_MIB_TCPFASTOPENBLACKHOLE);
}

@@ -523,10 +530,16 @@ bool tcp_fastopen_active_should_disable(struct sock *sk)
	if (!tfo_da_times)
		return false;

	/* Paired with smp_mb__before_atomic() in tcp_fastopen_active_disable() */
	smp_rmb();

	/* Limit timout to max: 2^6 * initial timeout */
	multiplier = 1 << min(tfo_da_times - 1, 6);
	timeout = multiplier * tfo_bh_timeout * HZ;
	if (time_before(jiffies, sock_net(sk)->ipv4.tfo_active_disable_stamp + timeout))

	/* Paired with the WRITE_ONCE() in tcp_fastopen_active_disable(). */
	timeout = READ_ONCE(sock_net(sk)->ipv4.tfo_active_disable_stamp) +
		  multiplier * tfo_bh_timeout * HZ;
	if (time_before(jiffies, timeout))
		return true;

	/* Mark check bit so we can check for successful active TFO