untrusted comment: verify with openbsd-75-base.pub
RWRGj1pRpprAfhbzrw2p5f4eDhdQNLn+P5LCNmWXpahn5n24voyMJcWCM+qoZfspBVSNU6sSQtITOx2V0Tl1Yd5+CA4SV9A4FA8=
OpenBSD 7.5 errata 016, 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-75-base.pub -x 016_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.229 pf_norm.c
--- sys/net/pf_norm.c 10 Oct 2023 11:25:31 -0000 1.229
+++ sys/net/pf_norm.c 1 Feb 2025 21:46:48 -0000
@@ -665,34 +665,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_nfrents--;
- /* 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_nfrents--;
+ /* There is not way to recover */
+ goto free_fragment;
}
break;
}