Skip to content

Commit

Permalink
pf: do not keep state when dropping overlapping IPv6 fragments
Browse files Browse the repository at this point in the history
ok sperreault@

Obtained from:	OpenBSD, bluhm <bluhm@openbsd.org>, cd45765685
Sponsored by:	Rubicon Communications, LLC ("Netgate")

(cherry picked from commit 3b79f6d2d39405bcac395dc036ceb6f8fd09ce99)
  • Loading branch information
kprovost authored and fichtner committed Feb 25, 2025
1 parent 7386d91 commit ebfe6da
Showing 1 changed file with 8 additions and 22 deletions.
30 changes: 8 additions & 22 deletions sys/netpfil/pf/pf_norm.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,15 +606,7 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
return (frag);
}

if (TAILQ_EMPTY(&frag->fr_queue)) {
/*
* Overlapping IPv6 fragments have been detected. Do not
* reassemble packet but also drop future fragments.
* This will be done for this ident/src/dst combination
* until fragment queue timeout.
*/
goto drop_fragment;
}
KASSERT(!TAILQ_EMPTY(&frag->fr_queue), ("!TAILQ_EMPTY()->fr_queue"));

/* Remember maximum fragment len for refragmentation. */
if (frent->fe_len > frag->fr_maxlen)
Expand Down Expand Up @@ -651,7 +643,7 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
uint16_t precut;

if (frag->fr_af == AF_INET6)
goto flush_fragentries;
goto free_fragment;

precut = prev->fe_off + prev->fe_len - frent->fe_off;
if (precut >= frent->fe_len) {
Expand Down Expand Up @@ -715,21 +707,15 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,

return (frag);

flush_fragentries:
free_fragment:
/*
* RFC5722: When reassembling an IPv6 datagram, if one or
* more its constituent fragments is determined to be an
* overlapping fragment, the entire datagram (and any constituent
* fragments, including those not yet received) MUST be
* silently discarded.
* RFC 5722, Errata 3089: When reassembling an IPv6 datagram, if one
* or more its constituent fragments is determined to be an overlapping
* fragment, the entire datagram (and any constituent fragments) MUST
* be silently discarded.
*/
DPFPRINTF(("flush overlapping fragments\n"));
while ((prev = TAILQ_FIRST(&frag->fr_queue)) != NULL) {
TAILQ_REMOVE(&frag->fr_queue, prev, fr_next);

m_freem(prev->fe_m);
uma_zfree(V_pf_frent_z, prev);
}
pf_free_fragment(frag);

bad_fragment:
REASON_SET(reason, PFRES_FRAG);
Expand Down

0 comments on commit ebfe6da

Please sign in to comment.