Commit 6f20c8ad authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net/tcp_fastopen: fix data races around tfo_active_disable_stamp

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>
parent a0050653
...@@ -507,8 +507,15 @@ void tcp_fastopen_active_disable(struct sock *sk) ...@@ -507,8 +507,15 @@ void tcp_fastopen_active_disable(struct sock *sk)
{ {
struct net *net = sock_net(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); atomic_inc(&net->ipv4.tfo_active_disable_times);
net->ipv4.tfo_active_disable_stamp = jiffies;
NET_INC_STATS(net, LINUX_MIB_TCPFASTOPENBLACKHOLE); NET_INC_STATS(net, LINUX_MIB_TCPFASTOPENBLACKHOLE);
} }
...@@ -526,10 +533,16 @@ bool tcp_fastopen_active_should_disable(struct sock *sk) ...@@ -526,10 +533,16 @@ bool tcp_fastopen_active_should_disable(struct sock *sk)
if (!tfo_da_times) if (!tfo_da_times)
return false; return false;
/* Paired with smp_mb__before_atomic() in tcp_fastopen_active_disable() */
smp_rmb();
/* Limit timeout to max: 2^6 * initial timeout */ /* Limit timeout to max: 2^6 * initial timeout */
multiplier = 1 << min(tfo_da_times - 1, 6); 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; return true;
/* Mark check bit so we can check for successful active TFO /* Mark check bit so we can check for successful active TFO
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment