untrusted comment: verify with openbsd-76-base.pub RWTkuwn4mbq8otkice67Au+qa46kleyAePGu+I4hLM1qXHhaGRct3M8ZlT+TTajWJwWpqA2jexBW6MWGVmekhVdgzT8pi2KIiQo= OpenBSD 7.6 errata 007, February 10, 2025: pf(4) could reassemble overlapping fragments into an incorrect IP packet that was too short. Apply by doing: signify -Vep /etc/signify/openbsd-76-base.pub -x 007_pffrag.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/net/pf_norm.c =================================================================== RCS file: /cvs/src/sys/net/pf_norm.c,v diff -u -p -r1.233 pf_norm.c --- sys/net/pf_norm.c 14 Jul 2024 18:53:39 -0000 1.233 +++ sys/net/pf_norm.c 1 Feb 2025 22:14:25 -0000 @@ -667,34 +667,21 @@ pf_fillup_fragment(struct pf_frnode *key aftercut = frent->fe_off + frent->fe_len - after->fe_off; if (aftercut < after->fe_len) { - int old_index, new_index; - DPFPRINTF(LOG_NOTICE, "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(LOG_DEBUG, "frag index %d, new %d", - 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(LOG_WARNING, - "fragment requeue limit exceeded"); - m_freem(after->fe_m); - pool_put(&pf_frent_pl, after); - pf_status.fragments--; - /* There is not way to recover */ - goto free_fragment; - } + /* Insert into correct queue */ + if (pf_frent_insert(frag, after, prev)) { + DPFPRINTF(LOG_WARNING, + "fragment requeue limit exceeded"); + m_freem(after->fe_m); + pool_put(&pf_frent_pl, after); + pf_status.fragments--; + /* There is not way to recover */ + goto free_fragment; } break; }