Date: Mon, 1 Mar 2021 07:05:18 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: a7926435c12e - releng/13.0 - pf: Fix incorrect fragment handling Message-ID: <202103010705.12175IBs086695@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch releng/13.0 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=a7926435c12e2304f46c9efadd4216f469f68acc commit a7926435c12e2304f46c9efadd4216f469f68acc Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2021-02-25 07:07:36 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2021-03-01 07:04:47 +0000 pf: Fix incorrect fragment handling A sequence of overlapping IPv4 fragments could crash the kernel in pf due to an assertion. Approved by: re (gjb) Reported by: Alexander Bluhm Obtained from: OpenBSD MFC after: 3 days Sponsored by: Rubicon Communications, LLC ("Netgate") (cherry picked from commit 5f1b1f184b7f12330cf4a027e3db7c6700c67640) (cherry picked from commit 86ebf4d3e12c3eae94d3e9a8dcf5bd5741889b58) --- sys/netpfil/pf/pf_norm.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index b7a84437630b..d7310c7bccb4 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -549,6 +549,7 @@ 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(); @@ -660,8 +661,30 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent, DPFPRINTF(("adjust overlap %d\n", aftercut)); if (aftercut < after->fe_len) { m_adj(after->fe_m, aftercut); + old_index = pf_frent_index(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", + 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")); + m_freem(after->fe_m); + uma_zfree(V_pf_frent_z, after); + /* There is not way to recover */ + goto bad_fragment; + } + } break; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202103010705.12175IBs086695>