tcp: do not accept ACK of bytes we never sent
[platform/kernel/linux-rpi.git] / net / ipv4 / tcp_input.c
index 804821d..e6c4929 100644 (file)
@@ -3809,8 +3809,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
         * then we can probably ignore it.
         */
        if (before(ack, prior_snd_una)) {
+               u32 max_window;
+
+               /* do not accept ACK for bytes we never sent. */
+               max_window = min_t(u64, tp->max_window, tp->bytes_acked);
                /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
-               if (before(ack, prior_snd_una - tp->max_window)) {
+               if (before(ack, prior_snd_una - max_window)) {
                        if (!(flag & FLAG_NO_CHALLENGE_ACK))
                                tcp_send_challenge_ack(sk);
                        return -SKB_DROP_REASON_TCP_TOO_OLD_ACK;
@@ -6450,22 +6454,23 @@ reset_and_undo:
 
 static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
 {
+       struct tcp_sock *tp = tcp_sk(sk);
        struct request_sock *req;
 
        /* If we are still handling the SYNACK RTO, see if timestamp ECR allows
         * undo. If peer SACKs triggered fast recovery, we can't undo here.
         */
-       if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
-               tcp_try_undo_loss(sk, false);
+       if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss && !tp->packets_out)
+               tcp_try_undo_recovery(sk);
 
        /* Reset rtx states to prevent spurious retransmits_timed_out() */
-       tcp_sk(sk)->retrans_stamp = 0;
+       tp->retrans_stamp = 0;
        inet_csk(sk)->icsk_retransmits = 0;
 
        /* Once we leave TCP_SYN_RECV or TCP_FIN_WAIT_1,
         * we no longer need req so release it.
         */
-       req = rcu_dereference_protected(tcp_sk(sk)->fastopen_rsk,
+       req = rcu_dereference_protected(tp->fastopen_rsk,
                                        lockdep_sock_is_held(sk));
        reqsk_fastopen_remove(sk, req, false);