DF-3361 / fix.diff
--- a/sys/net/pf/pf_norm.c +++ b/sys/net/pf/pf_norm.c @@ -962,6 +962,22 @@ max > frag->fr_max) goto bad; + /* NOTE (DF-3361): enforce the registered fragment pool + * limit (pfctl set limit frags; default + * PFFRAG_FRENT_HIWAT). The pool_sethardlimit() calls + * were disabled in the DragonFly port, so nothing ever + * checked it and a fragment flood grew the pools without + * bound. + */ + if (pf_nfrents >= pf_pool_limits[PF_LIMIT_FRAGS].limit) { + pf_flush_fragments(); + if (pf_nfrents >= + pf_pool_limits[PF_LIMIT_FRAGS].limit) { + REASON_SET(reason, PFRES_MEMORY); + return (PF_DROP); + } + } + /* Get an entry for the fragment queue */ frent = kmalloc(sizeof(struct pf_frent), M_PFFRENTPL, M_NOWAIT); if (frent == NULL) { @@ -998,6 +1014,17 @@ frag = pf_find_fragment(h, &pf_cache_tree[cpu]); + /* NOTE (DF-3361): same as above for the non-buffering + * fragment cache descriptors. + */ + if (pf_ncache >= PFFRAG_FRCACHE_HIWAT) { + pf_flush_fragments(); + if (pf_ncache >= PFFRAG_FRCACHE_HIWAT) { + REASON_SET(reason, PFRES_MEMORY); + return (PF_DROP); + } + } + /* Check if we saw the last fragment already */ if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) && max > frag->fr_max) { |