diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
| -rw-r--r-- | net/ipv4/tcp_input.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1db663983587..a13692560e63 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -3552,6 +3552,24 @@ static bool tcp_process_frto(struct sock *sk, int flag) | |||
| 3552 | return false; | 3552 | return false; |
| 3553 | } | 3553 | } |
| 3554 | 3554 | ||
| 3555 | /* RFC 5961 7 [ACK Throttling] */ | ||
| 3556 | static void tcp_send_challenge_ack(struct sock *sk) | ||
| 3557 | { | ||
| 3558 | /* unprotected vars, we dont care of overwrites */ | ||
| 3559 | static u32 challenge_timestamp; | ||
| 3560 | static unsigned int challenge_count; | ||
| 3561 | u32 now = jiffies / HZ; | ||
| 3562 | |||
| 3563 | if (now != challenge_timestamp) { | ||
| 3564 | challenge_timestamp = now; | ||
| 3565 | challenge_count = 0; | ||
| 3566 | } | ||
| 3567 | if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { | ||
| 3568 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); | ||
| 3569 | tcp_send_ack(sk); | ||
| 3570 | } | ||
| 3571 | } | ||
| 3572 | |||
| 3555 | /* This routine deals with incoming acks, but not outgoing ones. */ | 3573 | /* This routine deals with incoming acks, but not outgoing ones. */ |
| 3556 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | 3574 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) |
| 3557 | { | 3575 | { |
| @@ -3571,8 +3589,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3571 | /* If the ack is older than previous acks | 3589 | /* If the ack is older than previous acks |
| 3572 | * then we can probably ignore it. | 3590 | * then we can probably ignore it. |
| 3573 | */ | 3591 | */ |
| 3574 | if (before(ack, prior_snd_una)) | 3592 | if (before(ack, prior_snd_una)) { |
| 3593 | /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ | ||
| 3594 | if (before(ack, prior_snd_una - tp->max_window)) { | ||
| 3595 | tcp_send_challenge_ack(sk); | ||
| 3596 | return -1; | ||
| 3597 | } | ||
| 3575 | goto old_ack; | 3598 | goto old_ack; |
| 3599 | } | ||
| 3576 | 3600 | ||
| 3577 | /* If the ack includes data we haven't sent yet, discard | 3601 | /* If the ack includes data we haven't sent yet, discard |
| 3578 | * this segment (RFC793 Section 3.9). | 3602 | * this segment (RFC793 Section 3.9). |
| @@ -4529,6 +4553,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) | |||
| 4529 | struct tcphdr *th; | 4553 | struct tcphdr *th; |
| 4530 | bool fragstolen; | 4554 | bool fragstolen; |
| 4531 | 4555 | ||
| 4556 | if (size == 0) | ||
| 4557 | return 0; | ||
| 4558 | |||
| 4532 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); | 4559 | skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); |
| 4533 | if (!skb) | 4560 | if (!skb) |
| 4534 | goto err; | 4561 | goto err; |
| @@ -5241,23 +5268,6 @@ out: | |||
| 5241 | } | 5268 | } |
| 5242 | #endif /* CONFIG_NET_DMA */ | 5269 | #endif /* CONFIG_NET_DMA */ |
| 5243 | 5270 | ||
| 5244 | static void tcp_send_challenge_ack(struct sock *sk) | ||
| 5245 | { | ||
| 5246 | /* unprotected vars, we dont care of overwrites */ | ||
| 5247 | static u32 challenge_timestamp; | ||
| 5248 | static unsigned int challenge_count; | ||
| 5249 | u32 now = jiffies / HZ; | ||
| 5250 | |||
| 5251 | if (now != challenge_timestamp) { | ||
| 5252 | challenge_timestamp = now; | ||
| 5253 | challenge_count = 0; | ||
| 5254 | } | ||
| 5255 | if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { | ||
| 5256 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); | ||
| 5257 | tcp_send_ack(sk); | ||
| 5258 | } | ||
| 5259 | } | ||
| 5260 | |||
| 5261 | /* Does PAWS and seqno based validation of an incoming segment, flags will | 5271 | /* Does PAWS and seqno based validation of an incoming segment, flags will |
| 5262 | * play significant role here. | 5272 | * play significant role here. |
| 5263 | */ | 5273 | */ |
| @@ -5310,11 +5320,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
| 5310 | goto discard; | 5320 | goto discard; |
| 5311 | } | 5321 | } |
| 5312 | 5322 | ||
| 5313 | /* ts_recent update must be made after we are sure that the packet | ||
| 5314 | * is in window. | ||
| 5315 | */ | ||
| 5316 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 5317 | |||
| 5318 | /* step 3: check security and precedence [ignored] */ | 5323 | /* step 3: check security and precedence [ignored] */ |
| 5319 | 5324 | ||
| 5320 | /* step 4: Check for a SYN | 5325 | /* step 4: Check for a SYN |
| @@ -5549,6 +5554,11 @@ step5: | |||
| 5549 | if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) | 5554 | if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) |
| 5550 | goto discard; | 5555 | goto discard; |
| 5551 | 5556 | ||
| 5557 | /* ts_recent update must be made after we are sure that the packet | ||
| 5558 | * is in window. | ||
| 5559 | */ | ||
| 5560 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 5561 | |||
| 5552 | tcp_rcv_rtt_measure_ts(sk, skb); | 5562 | tcp_rcv_rtt_measure_ts(sk, skb); |
| 5553 | 5563 | ||
| 5554 | /* Process urgent data. */ | 5564 | /* Process urgent data. */ |
| @@ -5642,7 +5652,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, | |||
| 5642 | tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); | 5652 | tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); |
| 5643 | 5653 | ||
| 5644 | if (data) { /* Retransmit unacked data in SYN */ | 5654 | if (data) { /* Retransmit unacked data in SYN */ |
| 5645 | tcp_retransmit_skb(sk, data); | 5655 | tcp_for_write_queue_from(data, sk) { |
| 5656 | if (data == tcp_send_head(sk) || | ||
| 5657 | __tcp_retransmit_skb(sk, data)) | ||
| 5658 | break; | ||
| 5659 | } | ||
| 5646 | tcp_rearm_rto(sk); | 5660 | tcp_rearm_rto(sk); |
| 5647 | return true; | 5661 | return true; |
| 5648 | } | 5662 | } |
| @@ -5985,7 +5999,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 5985 | */ | 5999 | */ |
| 5986 | if (req) { | 6000 | if (req) { |
| 5987 | tcp_synack_rtt_meas(sk, req); | 6001 | tcp_synack_rtt_meas(sk, req); |
| 5988 | tp->total_retrans = req->retrans; | 6002 | tp->total_retrans = req->num_retrans; |
| 5989 | 6003 | ||
| 5990 | reqsk_fastopen_remove(sk, req, false); | 6004 | reqsk_fastopen_remove(sk, req, false); |
| 5991 | } else { | 6005 | } else { |
| @@ -6127,6 +6141,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 6127 | } else | 6141 | } else |
| 6128 | goto discard; | 6142 | goto discard; |
| 6129 | 6143 | ||
| 6144 | /* ts_recent update must be made after we are sure that the packet | ||
| 6145 | * is in window. | ||
| 6146 | */ | ||
| 6147 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 6148 | |||
| 6130 | /* step 6: check the URG bit */ | 6149 | /* step 6: check the URG bit */ |
| 6131 | tcp_urg(sk, skb, th); | 6150 | tcp_urg(sk, skb, th); |
| 6132 | 6151 | ||
