git: 130b5e3f536e - main - pf: be more strict about IPv6 fragments

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Fri, 09 May 2025 22:16:17 UTC
The branch main has been updated by kp:

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

commit 130b5e3f536e322f3e96ad1d786cbac3592f10c3
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-05-08 14:52:53 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-05-09 20:49:28 +0000

    pf: be more strict about IPv6 fragments
    
    Follow RFC 5722 more strictly when handling overlapping fragments
    in pf.  Drop the whole fragment state if IPv6 fragments appear which
    have invalid length or fragment-offset or more-fragment-bit.  In
    IPv4 they are considered invalid and just dropped like before.
    Found by Antonios Atlasis; OK sashan@ sthen@
    
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, f0f63321f2
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf_norm.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index c77895d1829d..8157ea556591 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -603,16 +603,16 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
 
 	/* Non terminal fragments must have more fragments flag. */
 	if (frent->fe_off + frent->fe_len < total && !frent->fe_mff)
-		goto bad_fragment;
+		goto free_ipv6_fragment;
 
 	/* Check if we saw the last fragment already. */
 	if (!TAILQ_LAST(&frag->fr_queue, pf_fragq)->fe_mff) {
 		if (frent->fe_off + frent->fe_len > total ||
 		    (frent->fe_off + frent->fe_len == total && frent->fe_mff))
-			goto bad_fragment;
+			goto free_ipv6_fragment;
 	} else {
 		if (frent->fe_off + frent->fe_len == total && !frent->fe_mff)
-			goto bad_fragment;
+			goto free_ipv6_fragment;
 	}
 
 	/* Find neighbors for newly inserted fragment */
@@ -680,6 +680,9 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
 
 	return (frag);
 
+free_ipv6_fragment:
+	if (frag->fr_af == AF_INET)
+		goto bad_fragment;
 free_fragment:
 	/*
 	 * RFC 5722, Errata 3089:  When reassembling an IPv6 datagram, if one