git: 07ed2396985f - main - pf: make TCP sequence number tracking less strict by one octet for FIN packets

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 12 Jun 2024 21:33:44 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=07ed2396985f211a1f9c2f84da99f955650df696

commit 07ed2396985f211a1f9c2f84da99f955650df696
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-06-12 18:05:22 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-06-12 21:33:11 +0000

    pf: make TCP sequence number tracking less strict by one octet for FIN packets
    
    The data of a TCP packet must fit into the announced window, but this is not
    required for the sequence number of the FIN.  A packet with the FIN bit set and
    containing data that fits exactly into the announced window was blocked. Our
    stack generates such packets when the receive buffer size is set to 1024. Now
    pf uses only the data lenght for window comparison.
    OK henning@
    
    Obtained From:  OpenBSD
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index c635251c3490..edb95d7ef0ec 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -5246,7 +5246,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 	struct tcphdr		*th = &pd->hdr.tcp;
 	struct pf_state_peer	*src, *dst;
 	u_int16_t		 win = ntohs(th->th_win);
-	u_int32_t		 ack, end, seq, orig_seq;
+	u_int32_t		 ack, end, data_end, seq, orig_seq;
 	u_int8_t		 sws, dws, psrc, pdst;
 	int			 ackskew;
 
@@ -5323,6 +5323,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 				}
 			}
 		}
+		data_end = end;
 		if (th->th_flags & TH_FIN)
 			end++;
 
@@ -5353,6 +5354,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 		end = seq + pd->p_len;
 		if (th->th_flags & TH_SYN)
 			end++;
+		data_end = end;
 		if (th->th_flags & TH_FIN)
 			end++;
 	}
@@ -5374,7 +5376,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 	if (seq == end) {
 		/* Ease sequencing restrictions on no data packets */
 		seq = src->seqlo;
-		end = seq;
+		data_end = end = seq;
 	}
 
 	ackskew = dst->seqlo - ack;
@@ -5397,7 +5399,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 	}
 
 #define	MAXACKWINDOW (0xffff + 1500)	/* 1500 is an arbitrary fudge factor */
-	if (SEQ_GEQ(src->seqhi, end) &&
+	if (SEQ_GEQ(src->seqhi, data_end) &&
 	    /* Last octet inside other's window space */
 	    SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) &&
 	    /* Retrans: not more than one window back */
@@ -5471,7 +5473,7 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 	} else if ((dst->state < TCPS_SYN_SENT ||
 		dst->state >= TCPS_FIN_WAIT_2 ||
 		src->state >= TCPS_FIN_WAIT_2) &&
-	    SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) &&
+	    SEQ_GEQ(src->seqhi + MAXACKWINDOW, data_end) &&
 	    /* Within a window forward of the originating packet */
 	    SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {
 	    /* Within a window backward of the originating packet */
@@ -5564,12 +5566,12 @@ pf_tcp_track_full(struct pf_kstate **state, struct pfi_kkif *kif,
 			    pd->dir == PF_IN ? "in" : "out",
 			    pd->dir == (*state)->direction ? "fwd" : "rev");
 			printf("pf: State failure on: %c %c %c %c | %c %c\n",
-			    SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
+			    SEQ_GEQ(src->seqhi, data_end) ? ' ' : '1',
 			    SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ?
 			    ' ': '2',
 			    (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
 			    (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4',
-			    SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5',
+			    SEQ_GEQ(src->seqhi + MAXACKWINDOW, data_end) ?' ' :'5',
 			    SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6');
 		}
 		REASON_SET(reason, PFRES_BADSTATE);