Commit 0e24d17bd966 ("tcp: implement RFC 7323 window retraction receiver requirements") removed the special FIN case that was added in commit 1e3bb184e941 ("tcp: re-enable acceptance of FIN packets when RWIN is 0"). If a peer sends a segment containing data and a FIN flag before it learns about our window retraction and has a buggy TCP stack, it might place the FIN one byte beyond what it thinks is the right edge of the window (i.e., max_window_edge + 1). The data portion (end_seq - th->fin) will end exactly at max_window_edge. In this case, we will drop the packet if our receive queue is not empty, even though the data was sent within the window we previously allowed. Signed-off-by: Eric Dumazet Cc: Simon Baatz --- net/ipv4/tcp_input.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ab7a4e5435a8a2cbb532d42c54af76d8541c903b..8560a9c6d38207c098d673497caf2c7652c36f5c 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4812,18 +4812,20 @@ static enum skb_drop_reason tcp_sequence(const struct sock *sk, const struct tcphdr *th) { const struct tcp_sock *tp = tcp_sk(sk); + u32 seq_limit; if (before(end_seq, tp->rcv_wup)) return SKB_DROP_REASON_TCP_OLD_SEQUENCE; - if (unlikely(after(end_seq, tp->rcv_nxt + tcp_max_receive_window(tp)))) { + seq_limit = tp->rcv_nxt + tcp_max_receive_window(tp); + if (unlikely(after(end_seq, seq_limit))) { /* Some stacks are known to handle FIN incorrectly; allow the * FIN to extend beyond the window and check it in detail later. */ - if (!after(end_seq - th->fin, tp->rcv_nxt + tcp_receive_window(tp))) + if (!after(end_seq - th->fin, seq_limit)) return SKB_NOT_DROPPED_YET; - if (after(seq, tp->rcv_nxt + tcp_max_receive_window(tp))) + if (after(seq, seq_limit)) return SKB_DROP_REASON_TCP_INVALID_SEQUENCE; /* Only accept this packet if receive queue is empty. */ -- 2.54.0.1032.g2f8565e1d1-goog