The branch main has been updated by kp:

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

commit 7d810f27c16b1bb151ed701b040febef8f8909fe
Author:     Kristof Provost <[email protected]>
AuthorDate: 2026-09-03 13:57:58 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2026-09-07 08:37:46 +0000

    pf: Prevent pf dropping TCP state with crafted reset packet.
    
    Revision 1.1212 of pf.c weakened the TCP reset check in stateful
    connection tracking to let legitimate resets pass in the backwards
    window.  Such a reset is accepted only if its acknowledgment number
    matches perfectly.  But as a workaround for broken stacks, pf
    replaces an acknowledgment number of 0 in a reset with the tracked
    sequence of the peer.  Then the perfect match always succeeds, and
    an attacker can spoof resets more easily than intended.  Use the
    acknowledgment number from the wire, before the workaround has
    modified it.
    
    discovered by Minghao Zhang; OK sashan@
    
    Obtained from:  OpenBSD, bluhm <[email protected]>, 1e0a1f4b82
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 322b10c3fce6..9c9509900ea9 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -7290,7 +7290,7 @@ pf_tcp_track_full(struct pf_kstate *state, struct 
pf_pdesc *pd,
 {
        struct tcphdr           *th = &pd->hdr.tcp;
        u_int16_t                win = ntohs(th->th_win);
-       u_int32_t                ack, end, data_end, seq, orig_seq;
+       u_int32_t                ack, orig_ack, end, data_end, seq, orig_seq;
        u_int8_t                 sws, dws;
        int                      ackskew;
 
@@ -7389,6 +7389,7 @@ pf_tcp_track_full(struct pf_kstate *state, struct 
pf_pdesc *pd,
                if (tcp_get_flags(th) & TH_FIN)
                        end++;
        }
+       orig_ack = ack;
 
        if ((tcp_get_flags(th) & TH_ACK) == 0) {
                /* Let it pass through the ack skew check */
@@ -7442,7 +7443,7 @@ pf_tcp_track_full(struct pf_kstate *state, struct 
pf_pdesc *pd,
            (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 &&
+           SEQ_LEQ(orig_seq, src->seqlo + 1) && orig_ack == dst->seqlo &&
            (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)))) {
                /* Allow resets to match sequence window if ack is perfect 
match */
 

Reply via email to