Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Feb 2025 17:43:15 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 2e0f053ad52b - stable/14 - pf: fix fragment hole count
Message-ID:  <202502181743.51IHhF2M021363@gitrepo.freebsd.org>

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

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

commit 2e0f053ad52b38bd8bca72f817d7347df87dbe98
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-02-04 16:19:55 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-02-18 17:40:26 +0000

    pf: fix fragment hole count
    
    Fragment reassembly finishes when no holes are left in the fragment
    queue.  In certain overlap conditions, the hole counter was wrong
    and pf(4) created an incomplete IP packet.  Before adjusting the
    length, remove the overlapping fragment from the queue and insert
    it again afterwards.  pf_frent_remove() and pf_frent_insert() adjust
    the hole counter automatically.
    
    bug reported and fix tested by Lucas Aubard with Johan Mazel, Gilles
    Guette and Pierre Chifflier; OK claudio@
    
    MFC after:      1 week
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, 9915416fe8
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    
    (cherry picked from commit 8b2feafb535d10a559b995c6fc2529715f927e2a)
---
 sys/netpfil/pf/pf_norm.c | 33 ++++++++++-----------------------
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index e6e1549d3689..414dc258cfa5 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -547,7 +547,6 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
 	struct pf_frent		*after, *next, *prev;
 	struct pf_fragment	*frag;
 	uint16_t		total;
-	int			old_index, new_index;
 
 	PF_FRAG_ASSERT();
 
@@ -661,32 +660,20 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
 		uint16_t aftercut;
 
 		aftercut = frent->fe_off + frent->fe_len - after->fe_off;
-		DPFPRINTF(("adjust overlap %d\n", aftercut));
 		if (aftercut < after->fe_len) {
+			DPFPRINTF(("frag tail overlap %d", aftercut));
 			m_adj(after->fe_m, aftercut);
-			old_index = pf_frent_index(after);
+			/* Fragment may switch queue as fe_off changes */
+			pf_frent_remove(frag, after);
 			after->fe_off += aftercut;
 			after->fe_len -= aftercut;
-			new_index = pf_frent_index(after);
-			if (old_index != new_index) {
-				DPFPRINTF(("frag index %d, new %d\n",
-				    old_index, new_index));
-				/* Fragment switched queue as fe_off changed */
-				after->fe_off -= aftercut;
-				after->fe_len += aftercut;
-				/* Remove restored fragment from old queue */
-				pf_frent_remove(frag, after);
-				after->fe_off += aftercut;
-				after->fe_len -= aftercut;
-				/* Insert into correct queue */
-				if (pf_frent_insert(frag, after, prev)) {
-					DPFPRINTF(
-					    ("fragment requeue limit exceeded\n"));
-					m_freem(after->fe_m);
-					uma_zfree(V_pf_frent_z, after);
-					/* There is not way to recover */
-					goto bad_fragment;
-				}
+			/* Insert into correct queue */
+			if (pf_frent_insert(frag, after, prev)) {
+				DPFPRINTF(("fragment requeue limit exceeded"));
+				m_freem(after->fe_m);
+				uma_zfree(V_pf_frent_z, after);
+				/* There is not way to recover */
+				goto free_fragment;
 			}
 			break;
 		}



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