FN(TCP_LISTEN_OVERFLOW)         \
        FN(TCP_OLD_SEQUENCE)            \
        FN(TCP_INVALID_SEQUENCE)        \
+       FN(TCP_INVALID_END_SEQUENCE)    \
        FN(TCP_INVALID_ACK_SEQUENCE)    \
        FN(TCP_RESET)                   \
        FN(TCP_INVALID_SYN)             \
        SKB_DROP_REASON_TCP_LISTEN_OVERFLOW,
        /** @SKB_DROP_REASON_TCP_OLD_SEQUENCE: Old SEQ field (duplicate packet) */
        SKB_DROP_REASON_TCP_OLD_SEQUENCE,
-       /** @SKB_DROP_REASON_TCP_INVALID_SEQUENCE: Not acceptable SEQ field */
+       /** @SKB_DROP_REASON_TCP_INVALID_SEQUENCE: Not acceptable SEQ field. */
        SKB_DROP_REASON_TCP_INVALID_SEQUENCE,
+       /**
+        * @SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE:
+        * Not acceptable END_SEQ field.
+        */
+       SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE,
        /**
         * @SKB_DROP_REASON_TCP_INVALID_ACK_SEQUENCE: Not acceptable ACK SEQ
         * field because ack sequence is not in the window between snd_una
 
  * (borrowed from freebsd)
  */
 
-static enum skb_drop_reason tcp_sequence(const struct tcp_sock *tp,
+static enum skb_drop_reason tcp_sequence(const struct sock *sk,
                                         u32 seq, u32 end_seq)
 {
+       const struct tcp_sock *tp = tcp_sk(sk);
+
        if (before(end_seq, tp->rcv_wup))
                return SKB_DROP_REASON_TCP_OLD_SEQUENCE;
 
-       if (after(seq, tp->rcv_nxt + tcp_receive_window(tp)))
-               return SKB_DROP_REASON_TCP_INVALID_SEQUENCE;
+       if (after(end_seq, tp->rcv_nxt + tcp_receive_window(tp))) {
+               if (after(seq, tp->rcv_nxt + tcp_receive_window(tp)))
+                       return SKB_DROP_REASON_TCP_INVALID_SEQUENCE;
+
+               /* Only accept this packet if receive queue is empty. */
+               if (skb_queue_len(&sk->sk_receive_queue))
+                       return SKB_DROP_REASON_TCP_INVALID_END_SEQUENCE;
+       }
 
        return SKB_NOT_DROPPED_YET;
 }
 
 step1:
        /* Step 1: check sequence number */
-       reason = tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+       reason = tcp_sequence(sk, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
        if (reason) {
                /* RFC793, page 37: "In all states except SYN-SENT, all reset
                 * (RST) segments are validated by checking their SEQ-fields."
                        if (tcp_checksum_complete(skb))
                                goto csum_error;
 
+                       if (after(TCP_SKB_CB(skb)->end_seq,
+                                 tp->rcv_nxt + tcp_receive_window(tp)))
+                               goto validate;
+
                        if ((int)skb->truesize > sk->sk_forward_alloc)
                                goto step5;
 
        /*
         *      Standard slow path.
         */
-
+validate:
        if (!tcp_validate_incoming(sk, skb, th, 1))
                return;