diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9401aa43b814..8fdd27b17306 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3322,13 +3322,22 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 | |||
3322 | } | 3322 | } |
3323 | 3323 | ||
3324 | /* RFC 5961 7 [ACK Throttling] */ | 3324 | /* RFC 5961 7 [ACK Throttling] */ |
3325 | static void tcp_send_challenge_ack(struct sock *sk) | 3325 | static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) |
3326 | { | 3326 | { |
3327 | /* unprotected vars, we dont care of overwrites */ | 3327 | /* unprotected vars, we dont care of overwrites */ |
3328 | static u32 challenge_timestamp; | 3328 | static u32 challenge_timestamp; |
3329 | static unsigned int challenge_count; | 3329 | static unsigned int challenge_count; |
3330 | u32 now = jiffies / HZ; | 3330 | struct tcp_sock *tp = tcp_sk(sk); |
3331 | u32 now; | ||
3332 | |||
3333 | /* First check our per-socket dupack rate limit. */ | ||
3334 | if (tcp_oow_rate_limited(sock_net(sk), skb, | ||
3335 | LINUX_MIB_TCPACKSKIPPEDCHALLENGE, | ||
3336 | &tp->last_oow_ack_time)) | ||
3337 | return; | ||
3331 | 3338 | ||
3339 | /* Then check the check host-wide RFC 5961 rate limit. */ | ||
3340 | now = jiffies / HZ; | ||
3332 | if (now != challenge_timestamp) { | 3341 | if (now != challenge_timestamp) { |
3333 | challenge_timestamp = now; | 3342 | challenge_timestamp = now; |
3334 | challenge_count = 0; | 3343 | challenge_count = 0; |
@@ -3424,7 +3433,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3424 | if (before(ack, prior_snd_una)) { | 3433 | if (before(ack, prior_snd_una)) { |
3425 | /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ | 3434 | /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ |
3426 | if (before(ack, prior_snd_una - tp->max_window)) { | 3435 | if (before(ack, prior_snd_una - tp->max_window)) { |
3427 | tcp_send_challenge_ack(sk); | 3436 | tcp_send_challenge_ack(sk, skb); |
3428 | return -1; | 3437 | return -1; |
3429 | } | 3438 | } |
3430 | goto old_ack; | 3439 | goto old_ack; |
@@ -4993,7 +5002,10 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
4993 | tcp_paws_discard(sk, skb)) { | 5002 | tcp_paws_discard(sk, skb)) { |
4994 | if (!th->rst) { | 5003 | if (!th->rst) { |
4995 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); | 5004 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); |
4996 | tcp_send_dupack(sk, skb); | 5005 | if (!tcp_oow_rate_limited(sock_net(sk), skb, |
5006 | LINUX_MIB_TCPACKSKIPPEDPAWS, | ||
5007 | &tp->last_oow_ack_time)) | ||
5008 | tcp_send_dupack(sk, skb); | ||
4997 | goto discard; | 5009 | goto discard; |
4998 | } | 5010 | } |
4999 | /* Reset is accepted even if it did not pass PAWS. */ | 5011 | /* Reset is accepted even if it did not pass PAWS. */ |
@@ -5010,7 +5022,10 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
5010 | if (!th->rst) { | 5022 | if (!th->rst) { |
5011 | if (th->syn) | 5023 | if (th->syn) |
5012 | goto syn_challenge; | 5024 | goto syn_challenge; |
5013 | tcp_send_dupack(sk, skb); | 5025 | if (!tcp_oow_rate_limited(sock_net(sk), skb, |
5026 | LINUX_MIB_TCPACKSKIPPEDSEQ, | ||
5027 | &tp->last_oow_ack_time)) | ||
5028 | tcp_send_dupack(sk, skb); | ||
5014 | } | 5029 | } |
5015 | goto discard; | 5030 | goto discard; |
5016 | } | 5031 | } |
@@ -5026,7 +5041,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
5026 | if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) | 5041 | if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) |
5027 | tcp_reset(sk); | 5042 | tcp_reset(sk); |
5028 | else | 5043 | else |
5029 | tcp_send_challenge_ack(sk); | 5044 | tcp_send_challenge_ack(sk, skb); |
5030 | goto discard; | 5045 | goto discard; |
5031 | } | 5046 | } |
5032 | 5047 | ||
@@ -5040,7 +5055,7 @@ syn_challenge: | |||
5040 | if (syn_inerr) | 5055 | if (syn_inerr) |
5041 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); | 5056 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); |
5042 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); | 5057 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); |
5043 | tcp_send_challenge_ack(sk); | 5058 | tcp_send_challenge_ack(sk, skb); |
5044 | goto discard; | 5059 | goto discard; |
5045 | } | 5060 | } |
5046 | 5061 | ||