Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Sep 2025 14:15:46 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: fc63421de9f6 - main - pf: allows TCP RST packets in the backwards window if ACK matches
Message-ID:  <202509171415.58HEFkFC010352@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp:

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

commit fc63421de9f69ed67aad7bae29712fca2f570693
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-08-25 13:49:22 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-09-17 14:15:15 +0000

    pf: allows TCP RST packets in the backwards window if ACK matches
    
    TCP reset packets are generated for the sequence numbers that have
    been acknowledged.  Our pf(4) is quite strict regarding sequence
    numbers of reset packets to avoid evil connection drops.  It expected
    exact match and did not allow a sequence window for resets.  As pf
    tracks neither gaps in the sequence space nor the acknowledged data,
    it does not know where exactly the reset is expected by the TCP
    stack.
    
    Problem was that legit reset packets before a gap but not at the
    highest sequence numbers were blocked by pf.  Solution is to fix
    pf_tcp_track_full().  Now it allows sequence number windows if the
    packet has ACK+RST flags set and the acknowlege number matches
    perfectly.  This still prevents reset number guessing by an attacker.
    
    Curiously the TCP stack behaves correctly and accepts only resets
    before the gap.  pf only allowed resets after the final data.  So
    any reset was ignored by the system.  When the other side processed
    the challenge ACK, the situation could be fixed.
    
    bug reported and fix tested by Lucas Aubard with Johan Mazel, Gilles
    Guette and Pierre Chifflier; OK sashan@
    
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, 12e4c257ea
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index aade1d9ace37..2705df61a1f7 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -6775,8 +6775,12 @@ pf_tcp_track_full(struct pf_kstate *state, struct pf_pdesc *pd,
 	    (ackskew <= (MAXACKWINDOW << sws)) &&
 	    /* Acking not more than one window forward */
 	    ((tcp_get_flags(th) & TH_RST) == 0 || orig_seq == src->seqlo ||
-	    (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo))) {
+	    (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo) ||
 	    /* Require an exact/+1 sequence match on resets when possible */
+	    (SEQ_GEQ(orig_seq, src->seqlo - (dst->max_win << dws)) &&
+	    SEQ_LEQ(orig_seq, src->seqlo + 1) && ackskew == 0 &&
+	    (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)))) {
+		/* Allow resets to match sequence window if ack is perfect match */
 
 		if (dst->scrub || src->scrub) {
 			if (pf_normalize_tcp_stateful(pd, reason, th,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202509171415.58HEFkFC010352>