Commit a3daac63 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'tcp-tcp-challenge-ack-fixes'

Eric Dumazet says:

====================
tcp: tcp challenge ack fixes

syzbot found a typical data-race addressed in the first patch.

While we are at it, second patch makes the global rate limit
per net-ns and disabled by default.
====================

Link: https://lore.kernel.org/r/20220830185656.268523-1-eric.dumazet@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 52267ce2 79e3602c
...@@ -1035,7 +1035,10 @@ tcp_limit_output_bytes - INTEGER ...@@ -1035,7 +1035,10 @@ tcp_limit_output_bytes - INTEGER
tcp_challenge_ack_limit - INTEGER tcp_challenge_ack_limit - INTEGER
Limits number of Challenge ACK sent per second, as recommended Limits number of Challenge ACK sent per second, as recommended
in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks) in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
Default: 1000 Note that this per netns rate limit can allow some side channel
attacks and probably should not be enabled.
TCP stack implements per TCP socket limits anyway.
Default: INT_MAX (unlimited)
UDP variables UDP variables
============= =============
......
...@@ -179,6 +179,8 @@ struct netns_ipv4 { ...@@ -179,6 +179,8 @@ struct netns_ipv4 {
unsigned int sysctl_tcp_fastopen_blackhole_timeout; unsigned int sysctl_tcp_fastopen_blackhole_timeout;
atomic_t tfo_active_disable_times; atomic_t tfo_active_disable_times;
unsigned long tfo_active_disable_stamp; unsigned long tfo_active_disable_stamp;
u32 tcp_challenge_timestamp;
u32 tcp_challenge_count;
int sysctl_udp_wmem_min; int sysctl_udp_wmem_min;
int sysctl_udp_rmem_min; int sysctl_udp_rmem_min;
......
...@@ -3614,12 +3614,9 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, ...@@ -3614,12 +3614,9 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb,
/* RFC 5961 7 [ACK Throttling] */ /* RFC 5961 7 [ACK Throttling] */
static void tcp_send_challenge_ack(struct sock *sk) static void tcp_send_challenge_ack(struct sock *sk)
{ {
/* unprotected vars, we dont care of overwrites */
static u32 challenge_timestamp;
static unsigned int challenge_count;
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
u32 count, now; u32 count, now, ack_limit;
/* First check our per-socket dupack rate limit. */ /* First check our per-socket dupack rate limit. */
if (__tcp_oow_rate_limited(net, if (__tcp_oow_rate_limited(net,
...@@ -3627,18 +3624,22 @@ static void tcp_send_challenge_ack(struct sock *sk) ...@@ -3627,18 +3624,22 @@ static void tcp_send_challenge_ack(struct sock *sk)
&tp->last_oow_ack_time)) &tp->last_oow_ack_time))
return; return;
ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
if (ack_limit == INT_MAX)
goto send_ack;
/* Then check host-wide RFC 5961 rate limit. */ /* Then check host-wide RFC 5961 rate limit. */
now = jiffies / HZ; now = jiffies / HZ;
if (now != challenge_timestamp) { if (now != READ_ONCE(net->ipv4.tcp_challenge_timestamp)) {
u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
u32 half = (ack_limit + 1) >> 1; u32 half = (ack_limit + 1) >> 1;
challenge_timestamp = now; WRITE_ONCE(net->ipv4.tcp_challenge_timestamp, now);
WRITE_ONCE(challenge_count, half + prandom_u32_max(ack_limit)); WRITE_ONCE(net->ipv4.tcp_challenge_count, half + prandom_u32_max(ack_limit));
} }
count = READ_ONCE(challenge_count); count = READ_ONCE(net->ipv4.tcp_challenge_count);
if (count > 0) { if (count > 0) {
WRITE_ONCE(challenge_count, count - 1); WRITE_ONCE(net->ipv4.tcp_challenge_count, count - 1);
send_ack:
NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK); NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);
tcp_send_ack(sk); tcp_send_ack(sk);
} }
......
...@@ -3139,8 +3139,10 @@ static int __net_init tcp_sk_init(struct net *net) ...@@ -3139,8 +3139,10 @@ static int __net_init tcp_sk_init(struct net *net)
net->ipv4.sysctl_tcp_tso_win_divisor = 3; net->ipv4.sysctl_tcp_tso_win_divisor = 3;
/* Default TSQ limit of 16 TSO segments */ /* Default TSQ limit of 16 TSO segments */
net->ipv4.sysctl_tcp_limit_output_bytes = 16 * 65536; net->ipv4.sysctl_tcp_limit_output_bytes = 16 * 65536;
/* rfc5961 challenge ack rate limiting */
net->ipv4.sysctl_tcp_challenge_ack_limit = 1000; /* rfc5961 challenge ack rate limiting, per net-ns, disabled by default. */
net->ipv4.sysctl_tcp_challenge_ack_limit = INT_MAX;
net->ipv4.sysctl_tcp_min_tso_segs = 2; net->ipv4.sysctl_tcp_min_tso_segs = 2;
net->ipv4.sysctl_tcp_tso_rtt_log = 9; /* 2^9 = 512 usec */ net->ipv4.sysctl_tcp_tso_rtt_log = 9; /* 2^9 = 512 usec */
net->ipv4.sysctl_tcp_min_rtt_wlen = 300; net->ipv4.sysctl_tcp_min_rtt_wlen = 300;
......
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