| From a1bbb421a282c3c5d1f7b647677e2132296a8c81 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 19 Jul 2021 02:12:18 -0700 |
| Subject: net/tcp_fastopen: fix data races around tfo_active_disable_stamp |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| [ 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: cf1ef3f0719b ("net/tcp_fastopen: Disable active side TFO in certain scenarios") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Cc: Wei Wang <weiwan@google.com> |
| Cc: Yuchung Cheng <ycheng@google.com> |
| Cc: Neal Cardwell <ncardwell@google.com> |
| Acked-by: Wei Wang <weiwan@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/ipv4/tcp_fastopen.c | 19 ++++++++++++++++--- |
| 1 file changed, 16 insertions(+), 3 deletions(-) |
| |
| diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c |
| index af2814c9342a..08548ff23d83 100644 |
| --- a/net/ipv4/tcp_fastopen.c |
| +++ b/net/ipv4/tcp_fastopen.c |
| @@ -507,8 +507,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); |
| } |
| |
| @@ -526,10 +533,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 |
| -- |
| 2.30.2 |
| |